stropheruby 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/ext/hash.c ADDED
@@ -0,0 +1,278 @@
1
+ /* hash.c
2
+ ** strophe XMPP client library -- hash table implementation
3
+ **
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
+ **
6
+ ** This software is provided AS-IS with no warranty, either express
7
+ ** or implied.
8
+ **
9
+ ** This software is distributed under license and may not be copied,
10
+ ** modified or distributed except as expressly authorized under the
11
+ ** terms of the license contained in the file LICENSE.txt in this
12
+ ** distribution.
13
+ */
14
+
15
+ /** @file
16
+ * Hash tables.
17
+ */
18
+
19
+ #include <stdlib.h>
20
+ #include <string.h>
21
+
22
+ #include "strophe.h"
23
+ #include "common.h"
24
+ #include "hash.h"
25
+
26
+ /* private types */
27
+ typedef struct _hashentry_t hashentry_t;
28
+
29
+ struct _hashentry_t {
30
+ hashentry_t *next;
31
+ char *key;
32
+ void *value;
33
+ };
34
+
35
+ struct _hash_t {
36
+ unsigned int ref;
37
+ xmpp_ctx_t *ctx;
38
+ hash_free_func free;
39
+ int length;
40
+ int num_keys;
41
+ hashentry_t **entries;
42
+ };
43
+
44
+ struct _hash_iterator_t {
45
+ unsigned int ref;
46
+ hash_t *table;
47
+ hashentry_t *entry;
48
+ int index;
49
+ };
50
+
51
+ /** allocate and initialize a new hash table */
52
+ hash_t *hash_new(xmpp_ctx_t * const ctx, const int size,
53
+ hash_free_func free)
54
+ {
55
+ hash_t *result = NULL;
56
+
57
+ result = xmpp_alloc(ctx, sizeof(hash_t));
58
+ if (result != NULL) {
59
+ result->entries = xmpp_alloc(ctx, size * sizeof(hashentry_t *));
60
+ if (result->entries == NULL) {
61
+ xmpp_free(ctx, result);
62
+ return NULL;
63
+ }
64
+ memset(result->entries, 0, size * sizeof(hashentry_t *));
65
+ result->length = size;
66
+
67
+ result->ctx = ctx;
68
+ result->free = free;
69
+ result->num_keys = 0;
70
+ /* give the caller a reference */
71
+ result->ref = 1;
72
+ }
73
+
74
+ return result;
75
+ }
76
+
77
+ /** obtain a new reference to an existing hash table */
78
+ hash_t *hash_clone(hash_t * const table)
79
+ {
80
+ table->ref++;
81
+ return table;
82
+ }
83
+
84
+ /** release a hash table that is no longer needed */
85
+ void hash_release(hash_t * const table)
86
+ {
87
+ xmpp_ctx_t *ctx = table->ctx;
88
+ hashentry_t *entry, *next;
89
+ int i;
90
+
91
+ if (table->ref > 1)
92
+ table->ref--;
93
+ else {
94
+ for (i = 0; i < table->length; i++) {
95
+ entry = table->entries[i];
96
+ while (entry != NULL) {
97
+ next = entry->next;
98
+ xmpp_free(ctx, entry->key);
99
+ if (table->free) table->free(ctx, entry->value);
100
+ xmpp_free(ctx, entry);
101
+ entry = next;
102
+ }
103
+ }
104
+ xmpp_free(ctx, table->entries);
105
+ xmpp_free(ctx, table);
106
+ }
107
+ }
108
+
109
+ /** hash a key for our table lookup */
110
+ static int _hash_key(hash_t *table, const char *key)
111
+ {
112
+ int hash = 0;
113
+ int shift = 0;
114
+ const char *c = key;
115
+
116
+ while (*c != '\0') {
117
+ /* assume 32 bit ints */
118
+ hash ^= ((int)*c++ << shift);
119
+ shift += 8;
120
+ if (shift > 24) shift = 0;
121
+ }
122
+
123
+ return hash % table->length;
124
+ }
125
+
126
+ /** add a key, value pair to a hash table.
127
+ * each key can appear only once; the value of any
128
+ * identical key will be replaced
129
+ */
130
+ int hash_add(hash_t *table, const char * const key, void *data)
131
+ {
132
+ xmpp_ctx_t *ctx = table->ctx;
133
+ hashentry_t *entry = NULL;
134
+ int index = _hash_key(table, key);
135
+
136
+ /* drop existing entry, if any */
137
+ hash_drop(table, key);
138
+
139
+ /* allocate and fill a new entry */
140
+ entry = xmpp_alloc(ctx, sizeof(hashentry_t));
141
+ if (!entry) return -1;
142
+ entry->key = xmpp_strdup(ctx, key);
143
+ if (!entry->key) {
144
+ xmpp_free(ctx, entry);
145
+ return -1;
146
+ }
147
+ entry->value = data;
148
+ /* insert ourselves in the linked list */
149
+ /* TODO: this leaks duplicate keys */
150
+ entry->next = table->entries[index];
151
+ table->entries[index] = entry;
152
+ table->num_keys++;
153
+
154
+ return 0;
155
+ }
156
+
157
+ /** look up a key in a hash table */
158
+ void *hash_get(hash_t *table, const char *key)
159
+ {
160
+ hashentry_t *entry;
161
+ int index = _hash_key(table, key);
162
+ void *result = NULL;
163
+
164
+ /* look up the hash entry */
165
+ entry = table->entries[index];
166
+ while (entry != NULL) {
167
+ /* traverse the linked list looking for the key */
168
+ if (!strcmp(key, entry->key)) {
169
+ /* match */
170
+ result = entry->value;
171
+ return result;
172
+ }
173
+ entry = entry->next;
174
+ }
175
+ /* no match */
176
+ return result;
177
+ }
178
+
179
+ /** delete a key from a hash table */
180
+ int hash_drop(hash_t *table, const char *key)
181
+ {
182
+ xmpp_ctx_t *ctx = table->ctx;
183
+ hashentry_t *entry, *prev;
184
+ int index = _hash_key(table, key);
185
+
186
+ /* look up the hash entry */
187
+ entry = table->entries[index];
188
+ prev = NULL;
189
+ while (entry != NULL) {
190
+ /* traverse the linked list looking for the key */
191
+ if (!strcmp(key, entry->key)) {
192
+ /* match, remove the entry */
193
+ xmpp_free(ctx, entry->key);
194
+ if (table->free) table->free(ctx, entry->value);
195
+ if (prev == NULL) {
196
+ table->entries[index] = entry->next;
197
+ } else {
198
+ prev->next = entry->next;
199
+ }
200
+ xmpp_free(ctx, entry);
201
+ table->num_keys--;
202
+ return 0;
203
+ }
204
+ prev = entry;
205
+ entry = entry->next;
206
+ }
207
+ /* no match */
208
+ return -1;
209
+ }
210
+
211
+ int hash_num_keys(hash_t *table)
212
+ {
213
+ return table->num_keys;
214
+ }
215
+
216
+ /** allocate and initialize a new iterator */
217
+ hash_iterator_t *hash_iter_new(hash_t *table)
218
+ {
219
+ xmpp_ctx_t *ctx = table->ctx;
220
+ hash_iterator_t *iter;
221
+
222
+ iter = xmpp_alloc(ctx, sizeof(*iter));
223
+ if (iter != NULL) {
224
+ iter->ref = 1;
225
+ iter->table = hash_clone(table);
226
+ iter->entry = NULL;
227
+ iter->index = -1;
228
+ }
229
+
230
+ return iter;
231
+ }
232
+
233
+
234
+ /** release an iterator that is no longer needed */
235
+ void hash_iter_release(hash_iterator_t *iter)
236
+ {
237
+ xmpp_ctx_t *ctx = iter->table->ctx;
238
+
239
+ iter->ref--;
240
+
241
+ if (iter->ref <= 0) {
242
+ hash_release(iter->table);
243
+ xmpp_free(ctx, iter);
244
+ }
245
+ }
246
+
247
+ /** return the next hash table key from the iterator.
248
+ the returned key should not be freed */
249
+ const char * hash_iter_next(hash_iterator_t *iter)
250
+ {
251
+ hash_t *table = iter->table;
252
+ hashentry_t *entry = iter->entry;
253
+ int i = iter->index + 1;
254
+
255
+ /* advance until we find the next entry */
256
+ if (entry != NULL) entry = entry->next;
257
+ if (entry == NULL) {
258
+ /* we're off the end of list, search for a new entry */
259
+ while (i < iter->table->length) {
260
+ entry = table->entries[i];
261
+ if (entry != NULL) {
262
+ iter->index = i;
263
+ break;
264
+ }
265
+ i++;
266
+ }
267
+ }
268
+
269
+ if ((entry == NULL) || (i >= table->length)) {
270
+ /* no more keys! */
271
+ return NULL;
272
+ }
273
+
274
+ /* remember our current match */
275
+ iter->entry = entry;
276
+ return entry->key;
277
+ }
278
+
data/ext/hash.h ADDED
@@ -0,0 +1,64 @@
1
+ /* hash.h
2
+ ** strophe XMPP client library -- hash table interface
3
+ **
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
+ **
6
+ ** This software is provided AS-IS with no warranty, either express
7
+ ** or implied.
8
+ **
9
+ ** This software is distributed under license and may not be copied,
10
+ ** modified or distributed except as expressly authorized under the
11
+ ** terms of the license contained in the file LICENSE.txt in this
12
+ ** distribution.
13
+ */
14
+
15
+ /** @file
16
+ * Hash table API.
17
+ */
18
+
19
+ #ifndef __LIBSTROPHE_HASH_H__
20
+ #define __LIBSTROPHE_HASH_H__
21
+
22
+ typedef struct _hash_t hash_t;
23
+
24
+ typedef void (*hash_free_func)(const xmpp_ctx_t * const ctx, void *p);
25
+
26
+ /** allocate and initialize a new hash table */
27
+ hash_t *hash_new(xmpp_ctx_t * const ctx, const int size,
28
+ hash_free_func free);
29
+
30
+ /** allocate a new reference to an existing hash table */
31
+ hash_t *hash_clone(hash_t * const table);
32
+
33
+ /** release a hash table when no longer needed */
34
+ void hash_release(hash_t * const table);
35
+
36
+ /** add a key, value pair to a hash table.
37
+ * each key can appear only once; the value of any
38
+ * identical key will be replaced
39
+ */
40
+ int hash_add(hash_t *table, const char * const key, void *data);
41
+
42
+ /** look up a key in a hash table */
43
+ void *hash_get(hash_t *table, const char *key);
44
+
45
+ /** delete a key from a hash table */
46
+ int hash_drop(hash_t *table, const char *key);
47
+
48
+ /** return the number of keys in a hash */
49
+ int hash_num_keys(hash_t *table);
50
+
51
+ /** hash key iterator functions */
52
+ typedef struct _hash_iterator_t hash_iterator_t;
53
+
54
+ /** allocate and initialize a new iterator */
55
+ hash_iterator_t *hash_iter_new(hash_t *table);
56
+
57
+ /** release an iterator that is no longer needed */
58
+ void hash_iter_release(hash_iterator_t *iter);
59
+
60
+ /** return the next hash table key from the iterator.
61
+ the returned key should not be freed */
62
+ const char * hash_iter_next(hash_iterator_t *iter);
63
+
64
+ #endif /* __LIBXMPPP_HASH_H__ */
data/ext/jid.c ADDED
@@ -0,0 +1,177 @@
1
+ /* jid.c
2
+ ** strophe XMPP client library -- helper functions for parsing JIDs
3
+ **
4
+ ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
5
+ **
6
+ ** This software is provided AS-IS with no warranty, either express
7
+ ** or implied.
8
+ **
9
+ ** This software is distributed under license and may not be copied,
10
+ ** modified or distributed except as expressly authorized under the
11
+ ** terms of the license contained in the file LICENSE.txt in this
12
+ ** distribution.
13
+ */
14
+
15
+ /** @file
16
+ * JID creation and parsing.
17
+ */
18
+
19
+ #include <string.h>
20
+
21
+ #include "strophe.h"
22
+ #include "common.h"
23
+
24
+ /** Create a JID string from component parts node, domain, and resource.
25
+ *
26
+ * @param ctx the Strophe context object
27
+ * @param node a string representing the node
28
+ * @param domain a string representing the domain. Required.
29
+ * @param resource a string representing the resource
30
+ *
31
+ * @return an allocated string with the full JID or NULL if no domain
32
+ * is specified
33
+ */
34
+ char *xmpp_jid_new(xmpp_ctx_t *ctx, const char *node,
35
+ const char *domain,
36
+ const char *resource)
37
+ {
38
+ char *result;
39
+ int len,nlen,dlen,rlen;
40
+
41
+ /* jid must at least have a domain */
42
+ if (domain == NULL) return NULL;
43
+
44
+ /* accumulate lengths */
45
+ dlen = strlen(domain);
46
+ nlen = (node) ? strlen(node) + 1 : 0;
47
+ rlen = (resource) ? strlen(resource) + 1 : 0;
48
+ len = nlen + dlen + rlen;
49
+
50
+ /* concat components */
51
+ result = xmpp_alloc(ctx, len + 1);
52
+ if (result != NULL) {
53
+ if (node != NULL) {
54
+ memcpy(result, node, nlen - 1);
55
+ result[nlen-1] = '@';
56
+ }
57
+ memcpy(result + nlen, domain, dlen);
58
+ if (resource != NULL) {
59
+ result[nlen+dlen] = '/';
60
+ memcpy(result+nlen+dlen+1, resource, rlen - 1);
61
+ }
62
+ result[nlen+dlen+rlen] = '\0';
63
+ }
64
+
65
+ return result;
66
+ }
67
+
68
+ /** Create a bare JID from a JID.
69
+ *
70
+ * @param ctx the Strophe context object
71
+ * @param jid the JID
72
+ *
73
+ * @return an allocated string with the bare JID or NULL on an error
74
+ */
75
+ char *xmpp_jid_bare(xmpp_ctx_t *ctx, const char *jid)
76
+ {
77
+ char *result;
78
+ const char *c;
79
+
80
+ c = strchr(jid, '/');
81
+ if (c == NULL) return xmpp_strdup(ctx, jid);
82
+
83
+ result = xmpp_alloc(ctx, c-jid+1);
84
+ if (result != NULL) {
85
+ memcpy(result, jid, c-jid);
86
+ result[c-jid] = '\0';
87
+ }
88
+
89
+ return result;
90
+ }
91
+
92
+ /** Create a node string from a JID.
93
+ *
94
+ * @param ctx a Strophe context object
95
+ * @param jid the JID
96
+ *
97
+ * @return an allocated string with the node or NULL if no node is found
98
+ * or an error occurs
99
+ */
100
+ char *xmpp_jid_node(xmpp_ctx_t *ctx, const char *jid)
101
+ {
102
+ char *result = NULL;
103
+ const char *c;
104
+
105
+ c = strchr(jid, '@');
106
+ if (c != NULL) {
107
+ result = xmpp_alloc(ctx, (c-jid) + 1);
108
+ if (result != NULL) {
109
+ memcpy(result, jid, (c-jid));
110
+ result[c-jid] = '\0';
111
+ }
112
+ }
113
+
114
+ return result;
115
+ }
116
+
117
+ /** Create a domain string from a JID.
118
+ *
119
+ * @param ctx the Strophe context object
120
+ * @param jid the JID
121
+ *
122
+ * @return an allocated string with the domain or NULL on an error
123
+ */
124
+ char *xmpp_jid_domain(xmpp_ctx_t *ctx, const char *jid)
125
+ {
126
+ char *result = NULL;
127
+ const char *c,*s;
128
+
129
+ c = strchr(jid, '@');
130
+ if (c == NULL) {
131
+ /* no node, assume domain */
132
+ c = jid;
133
+ } else {
134
+ /* advance past the separator */
135
+ c++;
136
+ }
137
+ s = strchr(c, '/');
138
+ if (s == NULL) {
139
+ /* no resource */
140
+ s = c + strlen(c);
141
+ }
142
+ result = xmpp_alloc(ctx, (s-c) + 1);
143
+ if (result != NULL) {
144
+ memcpy(result, c, (s-c));
145
+ result[s-c] = '\0';
146
+ }
147
+
148
+ return result;
149
+ }
150
+
151
+ /** Create a resource string from a JID.
152
+ *
153
+ * @param ctx a Strophe context object
154
+ * @param jid the JID
155
+ *
156
+ * @return an allocated string with the resource or NULL if no resource
157
+ * is found or an error occurs
158
+ */
159
+ char *xmpp_jid_resource(xmpp_ctx_t *ctx, const char *jid)
160
+ {
161
+ char *result = NULL;
162
+ const char *c;
163
+ int len;
164
+
165
+ c = strchr(jid, '/');
166
+ if (c != NULL) {
167
+ c++;
168
+ len = strlen(c);
169
+ result = xmpp_alloc(ctx, len + 1);
170
+ if (result != NULL) {
171
+ memcpy(result, c, len);
172
+ result[len] = '\0';
173
+ }
174
+ }
175
+
176
+ return result;
177
+ }