rpatricia 0.07 → 0.08
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Changes +4 -0
- data/README +17 -7
- data/ext/rpatricia/patricia.c +86 -437
- data/ext/rpatricia/patricia.h +2 -8
- data/ext/rpatricia/rpatricia.c +90 -44
- data/rpatricia.gemspec +1 -1
- metadata +6 -8
data/Changes
CHANGED
data/README
CHANGED
@@ -60,9 +60,11 @@ new:
|
|
60
60
|
|
61
61
|
pt = Patricia.new
|
62
62
|
|
63
|
-
This is the class' constructor - it returns a Patricia object
|
64
|
-
|
65
|
-
|
63
|
+
This is the class' constructor - it returns a Patricia object for
|
64
|
+
handling IPv4 addresses. To handle IPv6 addresses (only),
|
65
|
+
Patricia.new may be called with an additional argument:
|
66
|
+
|
67
|
+
pt = Patricia.new(:AF_INET6)
|
66
68
|
|
67
69
|
The Patricia object will be destroyed automatically when there are
|
68
70
|
no longer any references to it.
|
@@ -74,7 +76,8 @@ add:
|
|
74
76
|
specification in canonical form, e.g. ``10.0.0.0/8'', where the
|
75
77
|
number after the slash represents the number of bits in the
|
76
78
|
netmask. If no mask width is specified, the longest possible mask
|
77
|
-
is assumed, i.e. 32 bits for AF_INET addresses
|
79
|
+
is assumed, i.e. 32 bits for AF_INET addresses and 128 bits for
|
80
|
+
AF_INET6 addresses.
|
78
81
|
|
79
82
|
The second argument, user_data, is optional. If supplied, it
|
80
83
|
should be a STRING object specifying the user data that will be
|
@@ -89,6 +92,12 @@ add:
|
|
89
92
|
On success, this method returns the object of the Patricia Trie
|
90
93
|
node.
|
91
94
|
|
95
|
+
family:
|
96
|
+
|
97
|
+
Returns either :AF_INET or :AF_INET6 symbol depending on how the
|
98
|
+
object was initialized. A Patricia object may only handle IPv4 or
|
99
|
+
IPv6 addresses.
|
100
|
+
|
92
101
|
add_node: An alias of add.
|
93
102
|
|
94
103
|
search_best:
|
@@ -103,7 +112,7 @@ search_best:
|
|
103
112
|
canonical form, e.g. ``10.0.0.0/8'', where the number after the
|
104
113
|
slash represents the number of bits in the netmask. If no mask
|
105
114
|
width value is specified, the longest mask is assumed, i.e. 32
|
106
|
-
bits for AF_INET addresses.
|
115
|
+
bits for AF_INET addresses and 128 bits for AF_INET6 addresses.
|
107
116
|
|
108
117
|
If a matching node is found in the Patricia Trie, this method
|
109
118
|
returns the object of the node. This method returns nil on
|
@@ -181,6 +190,7 @@ prefixlen:
|
|
181
190
|
This method returns the prefix length of the Patricia Trie
|
182
191
|
node.
|
183
192
|
|
184
|
-
|
185
|
-
|
193
|
+
AUTHORS
|
194
|
+
-------
|
186
195
|
Tatsuya Mori <mori.tatsuya@gmail.com>
|
196
|
+
Eric Wong <normalperson@yhbt.net>
|
data/ext/rpatricia/patricia.c
CHANGED
@@ -67,142 +67,37 @@ comp_with_mask (void *addr, void *dest, u_int mask)
|
|
67
67
|
return (0);
|
68
68
|
}
|
69
69
|
|
70
|
-
/* inet_pton substitute implementation
|
71
|
-
* Uses inet_addr to convert an IP address in dotted decimal notation into
|
72
|
-
* unsigned long and copies the result to dst.
|
73
|
-
* Only supports AF_INET. Follows standard error return conventions of
|
74
|
-
* inet_pton.
|
75
|
-
*/
|
76
|
-
int
|
77
|
-
inet_pton (int af, const char *src, void *dst)
|
78
|
-
{
|
79
|
-
u_long result;
|
80
|
-
|
81
|
-
if (af == AF_INET) {
|
82
|
-
result = inet_addr(src);
|
83
|
-
if (result == -1)
|
84
|
-
return 0;
|
85
|
-
else {
|
86
|
-
memcpy (dst, &result, 4);
|
87
|
-
return 1;
|
88
|
-
}
|
89
|
-
}
|
90
|
-
#ifdef NT
|
91
|
-
#ifdef HAVE_IPV6
|
92
|
-
else if (af == AF_INET6) {
|
93
|
-
struct in6_addr Address;
|
94
|
-
return (inet6_addr(src, &Address));
|
95
|
-
}
|
96
|
-
#endif /* HAVE_IPV6 */
|
97
|
-
#endif /* NT */
|
98
|
-
#ifndef NT
|
99
|
-
else {
|
100
|
-
|
101
|
-
errno = EAFNOSUPPORT;
|
102
|
-
return -1;
|
103
|
-
}
|
104
|
-
#endif /* NT */
|
105
|
-
}
|
106
|
-
|
107
|
-
/* this allows imcomplete prefix */
|
108
|
-
int
|
109
|
-
my_inet_pton (int af, const char *src, void *dst)
|
110
|
-
{
|
111
|
-
if (af == AF_INET) {
|
112
|
-
int i, c, val;
|
113
|
-
u_char xp[4] = {0, 0, 0, 0};
|
114
|
-
|
115
|
-
for (i = 0; ; i++) {
|
116
|
-
c = *src++;
|
117
|
-
if (!isdigit (c))
|
118
|
-
return (-1);
|
119
|
-
val = 0;
|
120
|
-
do {
|
121
|
-
val = val * 10 + c - '0';
|
122
|
-
if (val > 255)
|
123
|
-
return (0);
|
124
|
-
c = *src++;
|
125
|
-
} while (c && isdigit (c));
|
126
|
-
xp[i] = val;
|
127
|
-
if (c == '\0')
|
128
|
-
break;
|
129
|
-
if (c != '.')
|
130
|
-
return (0);
|
131
|
-
if (i >= 3)
|
132
|
-
return (0);
|
133
|
-
}
|
134
|
-
memcpy (dst, xp, 4);
|
135
|
-
return (1);
|
136
|
-
#ifdef HAVE_IPV6
|
137
|
-
} else if (af == AF_INET6) {
|
138
|
-
return (inet_pton (af, src, dst));
|
139
|
-
#endif /* HAVE_IPV6 */
|
140
|
-
} else {
|
141
|
-
#ifndef NT
|
142
|
-
errno = EAFNOSUPPORT;
|
143
|
-
#endif /* NT */
|
144
|
-
return -1;
|
145
|
-
}
|
146
|
-
}
|
147
|
-
|
148
70
|
/*
|
149
71
|
* convert prefix information to ascii string with length
|
150
|
-
* thread safe and
|
72
|
+
* thread safe and re-entrant implementation
|
73
|
+
*
|
74
|
+
* buff must be at least PATRICIA_MAXSTRLEN bytes large if with_len is true
|
75
|
+
* buff must be at least INET6_ADDRSTRLEN bytes large if with_len is false
|
151
76
|
*/
|
152
77
|
char *
|
153
78
|
prefix_toa2x (prefix_t *prefix, char *buff, int with_len)
|
154
79
|
{
|
155
|
-
|
156
|
-
return ("(Null)");
|
157
|
-
assert (prefix->ref_count >= 0);
|
158
|
-
if (buff == NULL) {
|
159
|
-
|
160
|
-
struct buffer {
|
161
|
-
char buffs[16][48+5];
|
162
|
-
u_int i;
|
163
|
-
} *buffp;
|
164
|
-
|
165
|
-
# if 0
|
166
|
-
THREAD_SPECIFIC_DATA (struct buffer, buffp, 1);
|
167
|
-
# else
|
168
|
-
{ /* for scope only */
|
169
|
-
static struct buffer local_buff;
|
170
|
-
buffp = &local_buff;
|
171
|
-
}
|
172
|
-
# endif
|
173
|
-
if (buffp == NULL) {
|
174
|
-
/* XXX should we report an error? */
|
175
|
-
return (NULL);
|
176
|
-
}
|
80
|
+
const char *dst;
|
177
81
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
if (r && with_len) {
|
198
|
-
assert (prefix->bitlen <= 128);
|
199
|
-
sprintf (buff + strlen (buff), "/%d", prefix->bitlen);
|
200
|
-
}
|
201
|
-
return (buff);
|
202
|
-
}
|
203
|
-
#endif /* HAVE_IPV6 */
|
204
|
-
else
|
205
|
-
return (NULL);
|
82
|
+
assert(prefix && "NULL prefix not allowed");
|
83
|
+
assert(prefix->ref_count >= 0);
|
84
|
+
assert(buff != NULL && "buffer must be specified");
|
85
|
+
|
86
|
+
switch (prefix->family) {
|
87
|
+
case AF_INET:
|
88
|
+
assert(prefix->bitlen <= 32 && "bitlen > 32 for AF_INET");
|
89
|
+
break;
|
90
|
+
case AF_INET6:
|
91
|
+
assert(prefix->bitlen <= 128 && "bitlen > 128 for AF_INET6");
|
92
|
+
break;
|
93
|
+
default:
|
94
|
+
assert(0 && "unknown address family (memory corruption?)");
|
95
|
+
}
|
96
|
+
dst = inet_ntop(prefix->family, &prefix->add.sin6, buff, INET6_ADDRSTRLEN);
|
97
|
+
assert(dst && "corrupt address");
|
98
|
+
if (with_len)
|
99
|
+
sprintf(buff + strlen(buff), "/%u", prefix->bitlen);
|
100
|
+
return buff;
|
206
101
|
}
|
207
102
|
|
208
103
|
/* prefix_toa2
|
@@ -214,57 +109,36 @@ prefix_toa2 (prefix_t *prefix, char *buff)
|
|
214
109
|
return (prefix_toa2x (prefix, buff, 0));
|
215
110
|
}
|
216
111
|
|
217
|
-
/* prefix_toa
|
218
|
-
*/
|
219
|
-
char *
|
220
|
-
prefix_toa (prefix_t * prefix)
|
221
|
-
{
|
222
|
-
return (prefix_toa2 (prefix, (char *) NULL));
|
223
|
-
}
|
224
|
-
|
225
112
|
prefix_t *
|
226
113
|
New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix)
|
227
114
|
{
|
228
|
-
|
229
|
-
int default_bitlen
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
#endif /* NT */
|
251
|
-
|
252
|
-
dynamic_allocated++;
|
253
|
-
}
|
254
|
-
memcpy (&prefix->add.sin, dest, 4);
|
255
|
-
}
|
256
|
-
else {
|
257
|
-
return (NULL);
|
258
|
-
}
|
259
|
-
|
260
|
-
prefix->bitlen = (bitlen >= 0)? bitlen: default_bitlen;
|
115
|
+
prefix_t *orig_prefix = prefix;
|
116
|
+
int default_bitlen;
|
117
|
+
size_t size, addr_size;
|
118
|
+
|
119
|
+
switch (family) {
|
120
|
+
case AF_INET6:
|
121
|
+
addr_size = sizeof(struct in6_addr);
|
122
|
+
size = sizeof(prefix_t);
|
123
|
+
break;
|
124
|
+
case AF_INET:
|
125
|
+
addr_size = sizeof(struct in_addr);
|
126
|
+
size = sizeof(prefix4_t);
|
127
|
+
break;
|
128
|
+
default:
|
129
|
+
return NULL;
|
130
|
+
}
|
131
|
+
default_bitlen = addr_size * CHAR_BIT;
|
132
|
+
if (bitlen > default_bitlen)
|
133
|
+
return NULL;
|
134
|
+
if (!orig_prefix)
|
135
|
+
prefix = calloc(1, size);
|
136
|
+
prefix->bitlen = bitlen >= 0 ? bitlen : default_bitlen;
|
261
137
|
prefix->family = family;
|
262
|
-
prefix->ref_count = 0;
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
/* fprintf(stderr, "[C %s, %d]\n", prefix_toa (prefix), prefix->ref_count); */
|
267
|
-
return (prefix);
|
138
|
+
prefix->ref_count = orig_prefix ? 0 : 1;
|
139
|
+
memcpy(&prefix->add.sin6, dest, addr_size);
|
140
|
+
|
141
|
+
return prefix;
|
268
142
|
}
|
269
143
|
|
270
144
|
prefix_t *
|
@@ -276,76 +150,46 @@ New_Prefix (int family, void *dest, int bitlen)
|
|
276
150
|
/* ascii2prefix
|
277
151
|
*/
|
278
152
|
prefix_t *
|
279
|
-
ascii2prefix
|
153
|
+
ascii2prefix(char *string, prefix_t *prefix)
|
280
154
|
{
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
struct in6_addr sin6;
|
286
|
-
#endif /* HAVE_IPV6 */
|
155
|
+
long bitlen;
|
156
|
+
size_t maxbitlen;
|
157
|
+
void *dest;
|
158
|
+
char *slash, *end;
|
287
159
|
int result;
|
288
|
-
char save[
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
160
|
+
char save[INET6_ADDRSTRLEN];
|
161
|
+
size_t len;
|
162
|
+
int family;
|
163
|
+
union {
|
164
|
+
struct in6_addr sin6;
|
165
|
+
struct in_addr sin;
|
166
|
+
} addr;
|
167
|
+
|
168
|
+
assert(string && "string is NULL");
|
169
|
+
len = strlen(string);
|
170
|
+
slash = memchr(string, '/', len);
|
171
|
+
if (slash) {
|
172
|
+
bitlen = strtol(slash + 1, &end, 10);
|
173
|
+
if (*end || (bitlen < 0) || ((slash - string) >= (int)sizeof(save)))
|
174
|
+
return NULL;
|
175
|
+
|
176
|
+
/* copy the string to save. Avoid destroying the string */
|
177
|
+
memcpy(save, string, slash - string);
|
178
|
+
save[slash - string] = '\0';
|
179
|
+
string = save;
|
180
|
+
} else {
|
181
|
+
bitlen = -1;
|
299
182
|
}
|
300
183
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
}
|
308
|
-
#endif /* HAVE_IPV6 */
|
309
|
-
|
310
|
-
if ((cp = strchr (string, '/')) != NULL) {
|
311
|
-
bitlen = atol (cp + 1);
|
312
|
-
/* *cp = '\0'; */
|
313
|
-
/* copy the string to save. Avoid destroying the string */
|
314
|
-
assert (cp - string < MAXLINE);
|
315
|
-
memcpy (save, string, cp - string);
|
316
|
-
save[cp - string] = '\0';
|
317
|
-
string = save;
|
318
|
-
if (bitlen < 0 || bitlen > maxbitlen)
|
319
|
-
bitlen = maxbitlen;
|
320
|
-
}
|
321
|
-
else {
|
322
|
-
bitlen = maxbitlen;
|
323
|
-
}
|
324
|
-
|
325
|
-
if (family == AF_INET) {
|
326
|
-
if ((result = my_inet_pton (AF_INET, string, &sin)) <= 0)
|
327
|
-
return (NULL);
|
328
|
-
return (New_Prefix (AF_INET, &sin, bitlen));
|
329
|
-
}
|
330
|
-
|
331
|
-
#ifdef HAVE_IPV6
|
332
|
-
else if (family == AF_INET6) {
|
333
|
-
// Get rid of this with next IPv6 upgrade
|
334
|
-
#if defined(NT) && !defined(HAVE_INET_NTOP)
|
335
|
-
inet6_addr(string, &sin6);
|
336
|
-
return (New_Prefix (AF_INET6, &sin6, bitlen));
|
337
|
-
#else
|
338
|
-
if ((result = inet_pton (AF_INET6, string, &sin6)) <= 0)
|
339
|
-
return (NULL);
|
340
|
-
#endif /* NT */
|
341
|
-
return (New_Prefix (AF_INET6, &sin6, bitlen));
|
342
|
-
}
|
343
|
-
#endif /* HAVE_IPV6 */
|
344
|
-
else
|
345
|
-
return (NULL);
|
184
|
+
family = memchr(string, ':', len) ? AF_INET6 : AF_INET;
|
185
|
+
result = inet_pton(family, string, &addr);
|
186
|
+
if (result != 1)
|
187
|
+
return NULL;
|
188
|
+
|
189
|
+
return New_Prefix2(family, &addr, bitlen, prefix);
|
346
190
|
}
|
347
191
|
|
348
|
-
prefix_t *
|
192
|
+
static prefix_t *
|
349
193
|
Ref_Prefix (prefix_t * prefix)
|
350
194
|
{
|
351
195
|
if (prefix == NULL)
|
@@ -355,11 +199,10 @@ Ref_Prefix (prefix_t * prefix)
|
|
355
199
|
return (New_Prefix2 (prefix->family, &prefix->add, prefix->bitlen, NULL));
|
356
200
|
}
|
357
201
|
prefix->ref_count++;
|
358
|
-
/* fprintf(stderr, "[A %s, %d]\n", prefix_toa (prefix), prefix->ref_count); */
|
359
202
|
return (prefix);
|
360
203
|
}
|
361
204
|
|
362
|
-
void
|
205
|
+
static void
|
363
206
|
Deref_Prefix (prefix_t * prefix)
|
364
207
|
{
|
365
208
|
if (prefix == NULL)
|
@@ -377,8 +220,6 @@ Deref_Prefix (prefix_t * prefix)
|
|
377
220
|
|
378
221
|
/* } */
|
379
222
|
|
380
|
-
/* #define PATRICIA_DEBUG 1 */
|
381
|
-
|
382
223
|
static int num_active_patricia = 0;
|
383
224
|
|
384
225
|
/* these routines support continuous mask only */
|
@@ -512,27 +353,10 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix)
|
|
512
353
|
bitlen = prefix->bitlen;
|
513
354
|
|
514
355
|
while (node->bit < bitlen) {
|
515
|
-
|
516
356
|
if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) {
|
517
|
-
#ifdef PATRICIA_DEBUG
|
518
|
-
if (node->prefix)
|
519
|
-
fprintf (stderr, "patricia_search_exact: take right %s/%d\n",
|
520
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
521
|
-
else
|
522
|
-
fprintf (stderr, "patricia_search_exact: take right at %d\n",
|
523
|
-
node->bit);
|
524
|
-
#endif /* PATRICIA_DEBUG */
|
525
357
|
node = node->r;
|
526
358
|
}
|
527
359
|
else {
|
528
|
-
#ifdef PATRICIA_DEBUG
|
529
|
-
if (node->prefix)
|
530
|
-
fprintf (stderr, "patricia_search_exact: take left %s/%d\n",
|
531
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
532
|
-
else
|
533
|
-
fprintf (stderr, "patricia_search_exact: take left at %d\n",
|
534
|
-
node->bit);
|
535
|
-
#endif /* PATRICIA_DEBUG */
|
536
360
|
node = node->l;
|
537
361
|
}
|
538
362
|
|
@@ -540,23 +364,12 @@ patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix)
|
|
540
364
|
return (NULL);
|
541
365
|
}
|
542
366
|
|
543
|
-
#ifdef PATRICIA_DEBUG
|
544
|
-
if (node->prefix)
|
545
|
-
fprintf (stderr, "patricia_search_exact: stop at %s/%d\n",
|
546
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
547
|
-
else
|
548
|
-
fprintf (stderr, "patricia_search_exact: stop at %d\n", node->bit);
|
549
|
-
#endif /* PATRICIA_DEBUG */
|
550
367
|
if (node->bit > bitlen || node->prefix == NULL)
|
551
368
|
return (NULL);
|
552
369
|
assert (node->bit == bitlen);
|
553
370
|
assert (node->bit == node->prefix->bitlen);
|
554
371
|
if (comp_with_mask (prefix_tochar (node->prefix), prefix_tochar (prefix),
|
555
372
|
bitlen)) {
|
556
|
-
#ifdef PATRICIA_DEBUG
|
557
|
-
fprintf (stderr, "patricia_search_exact: found %s/%d\n",
|
558
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
559
|
-
#endif /* PATRICIA_DEBUG */
|
560
373
|
return (node);
|
561
374
|
}
|
562
375
|
return (NULL);
|
@@ -587,33 +400,13 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv
|
|
587
400
|
while (node->bit < bitlen) {
|
588
401
|
|
589
402
|
if (node->prefix) {
|
590
|
-
#ifdef PATRICIA_DEBUG
|
591
|
-
fprintf (stderr, "patricia_search_best: push %s/%d\n",
|
592
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
593
|
-
#endif /* PATRICIA_DEBUG */
|
594
403
|
stack[cnt++] = node;
|
595
404
|
}
|
596
405
|
|
597
406
|
if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) {
|
598
|
-
#ifdef PATRICIA_DEBUG
|
599
|
-
if (node->prefix)
|
600
|
-
fprintf (stderr, "patricia_search_best: take right %s/%d\n",
|
601
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
602
|
-
else
|
603
|
-
fprintf (stderr, "patricia_search_best: take right at %d\n",
|
604
|
-
node->bit);
|
605
|
-
#endif /* PATRICIA_DEBUG */
|
606
407
|
node = node->r;
|
607
408
|
}
|
608
409
|
else {
|
609
|
-
#ifdef PATRICIA_DEBUG
|
610
|
-
if (node->prefix)
|
611
|
-
fprintf (stderr, "patricia_search_best: take left %s/%d\n",
|
612
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
613
|
-
else
|
614
|
-
fprintf (stderr, "patricia_search_best: take left at %d\n",
|
615
|
-
node->bit);
|
616
|
-
#endif /* PATRICIA_DEBUG */
|
617
410
|
node = node->l;
|
618
411
|
}
|
619
412
|
|
@@ -624,32 +417,14 @@ patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusiv
|
|
624
417
|
if (inclusive && node && node->prefix)
|
625
418
|
stack[cnt++] = node;
|
626
419
|
|
627
|
-
#ifdef PATRICIA_DEBUG
|
628
|
-
if (node == NULL)
|
629
|
-
fprintf (stderr, "patricia_search_best: stop at null\n");
|
630
|
-
else if (node->prefix)
|
631
|
-
fprintf (stderr, "patricia_search_best: stop at %s/%d\n",
|
632
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
633
|
-
else
|
634
|
-
fprintf (stderr, "patricia_search_best: stop at %d\n", node->bit);
|
635
|
-
#endif /* PATRICIA_DEBUG */
|
636
|
-
|
637
420
|
if (cnt <= 0)
|
638
421
|
return (NULL);
|
639
422
|
|
640
423
|
while (--cnt >= 0) {
|
641
424
|
node = stack[cnt];
|
642
|
-
#ifdef PATRICIA_DEBUG
|
643
|
-
fprintf (stderr, "patricia_search_best: pop %s/%d\n",
|
644
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
645
|
-
#endif /* PATRICIA_DEBUG */
|
646
425
|
if (comp_with_mask (prefix_tochar (node->prefix),
|
647
426
|
prefix_tochar (prefix),
|
648
427
|
node->prefix->bitlen)) {
|
649
|
-
#ifdef PATRICIA_DEBUG
|
650
|
-
fprintf (stderr, "patricia_search_best: found %s/%d\n",
|
651
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
652
|
-
#endif /* PATRICIA_DEBUG */
|
653
428
|
return (node);
|
654
429
|
}
|
655
430
|
}
|
@@ -684,10 +459,6 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
|
|
684
459
|
node->l = node->r = NULL;
|
685
460
|
node->data = NULL;
|
686
461
|
patricia->head = node;
|
687
|
-
#ifdef PATRICIA_DEBUG
|
688
|
-
fprintf (stderr, "patricia_lookup: new_node #0 %s/%d (head)\n",
|
689
|
-
prefix_toa (prefix), prefix->bitlen);
|
690
|
-
#endif /* PATRICIA_DEBUG */
|
691
462
|
patricia->num_active_node++;
|
692
463
|
return (node);
|
693
464
|
}
|
@@ -702,25 +473,11 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
|
|
702
473
|
BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) {
|
703
474
|
if (node->r == NULL)
|
704
475
|
break;
|
705
|
-
#ifdef PATRICIA_DEBUG
|
706
|
-
if (node->prefix)
|
707
|
-
fprintf (stderr, "patricia_lookup: take right %s/%d\n",
|
708
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
709
|
-
else
|
710
|
-
fprintf (stderr, "patricia_lookup: take right at %d\n", node->bit);
|
711
|
-
#endif /* PATRICIA_DEBUG */
|
712
476
|
node = node->r;
|
713
477
|
}
|
714
478
|
else {
|
715
479
|
if (node->l == NULL)
|
716
480
|
break;
|
717
|
-
#ifdef PATRICIA_DEBUG
|
718
|
-
if (node->prefix)
|
719
|
-
fprintf (stderr, "patricia_lookup: take left %s/%d\n",
|
720
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
721
|
-
else
|
722
|
-
fprintf (stderr, "patricia_lookup: take left at %d\n", node->bit);
|
723
|
-
#endif /* PATRICIA_DEBUG */
|
724
481
|
node = node->l;
|
725
482
|
}
|
726
483
|
|
@@ -728,16 +485,12 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
|
|
728
485
|
}
|
729
486
|
|
730
487
|
assert (node->prefix);
|
731
|
-
#ifdef PATRICIA_DEBUG
|
732
|
-
fprintf (stderr, "patricia_lookup: stop at %s/%d\n",
|
733
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
734
|
-
#endif /* PATRICIA_DEBUG */
|
735
488
|
|
736
489
|
test_addr = prefix_touchar (node->prefix);
|
737
490
|
/* find the first bit different */
|
738
491
|
check_bit = (node->bit < bitlen)? node->bit: bitlen;
|
739
492
|
differ_bit = 0;
|
740
|
-
for (i = 0; i*8 < check_bit; i++) {
|
493
|
+
for (i = 0; i*8 < (int)check_bit; i++) {
|
741
494
|
if ((r = (addr[i] ^ test_addr[i])) == 0) {
|
742
495
|
differ_bit = (i + 1) * 8;
|
743
496
|
continue;
|
@@ -754,36 +507,18 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
|
|
754
507
|
}
|
755
508
|
if (differ_bit > check_bit)
|
756
509
|
differ_bit = check_bit;
|
757
|
-
#ifdef PATRICIA_DEBUG
|
758
|
-
fprintf (stderr, "patricia_lookup: differ_bit %d\n", differ_bit);
|
759
|
-
#endif /* PATRICIA_DEBUG */
|
760
510
|
|
761
511
|
parent = node->parent;
|
762
512
|
while (parent && parent->bit >= differ_bit) {
|
763
513
|
node = parent;
|
764
514
|
parent = node->parent;
|
765
|
-
#ifdef PATRICIA_DEBUG
|
766
|
-
if (node->prefix)
|
767
|
-
fprintf (stderr, "patricia_lookup: up to %s/%d\n",
|
768
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
769
|
-
else
|
770
|
-
fprintf (stderr, "patricia_lookup: up to %d\n", node->bit);
|
771
|
-
#endif /* PATRICIA_DEBUG */
|
772
515
|
}
|
773
516
|
|
774
517
|
if (differ_bit == bitlen && node->bit == bitlen) {
|
775
518
|
if (node->prefix) {
|
776
|
-
#ifdef PATRICIA_DEBUG
|
777
|
-
fprintf (stderr, "patricia_lookup: found %s/%d\n",
|
778
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
779
|
-
#endif /* PATRICIA_DEBUG */
|
780
519
|
return (node);
|
781
520
|
}
|
782
521
|
node->prefix = Ref_Prefix (prefix);
|
783
|
-
#ifdef PATRICIA_DEBUG
|
784
|
-
fprintf (stderr, "patricia_lookup: new node #1 %s/%d (glue mod)\n",
|
785
|
-
prefix_toa (prefix), prefix->bitlen);
|
786
|
-
#endif /* PATRICIA_DEBUG */
|
787
522
|
assert (node->data == NULL);
|
788
523
|
return (node);
|
789
524
|
}
|
@@ -807,10 +542,6 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
|
|
807
542
|
assert (node->l == NULL);
|
808
543
|
node->l = new_node;
|
809
544
|
}
|
810
|
-
#ifdef PATRICIA_DEBUG
|
811
|
-
fprintf (stderr, "patricia_lookup: new_node #2 %s/%d (child)\n",
|
812
|
-
prefix_toa (prefix), prefix->bitlen);
|
813
|
-
#endif /* PATRICIA_DEBUG */
|
814
545
|
return (new_node);
|
815
546
|
}
|
816
547
|
|
@@ -834,10 +565,6 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
|
|
834
565
|
node->parent->l = new_node;
|
835
566
|
}
|
836
567
|
node->parent = new_node;
|
837
|
-
#ifdef PATRICIA_DEBUG
|
838
|
-
fprintf (stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n",
|
839
|
-
prefix_toa (prefix), prefix->bitlen);
|
840
|
-
#endif /* PATRICIA_DEBUG */
|
841
568
|
}
|
842
569
|
else {
|
843
570
|
glue = calloc(1, sizeof *glue);
|
@@ -868,10 +595,6 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
|
|
868
595
|
node->parent->l = glue;
|
869
596
|
}
|
870
597
|
node->parent = glue;
|
871
|
-
#ifdef PATRICIA_DEBUG
|
872
|
-
fprintf (stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n",
|
873
|
-
prefix_toa (prefix), prefix->bitlen);
|
874
|
-
#endif /* PATRICIA_DEBUG */
|
875
598
|
}
|
876
599
|
return (new_node);
|
877
600
|
}
|
@@ -886,11 +609,6 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node)
|
|
886
609
|
assert (node);
|
887
610
|
|
888
611
|
if (node->r && node->l) {
|
889
|
-
#ifdef PATRICIA_DEBUG
|
890
|
-
fprintf (stderr, "patricia_remove: #0 %s/%d (r & l)\n",
|
891
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
892
|
-
#endif /* PATRICIA_DEBUG */
|
893
|
-
|
894
612
|
/* this might be a placeholder node -- have to check and make sure
|
895
613
|
* there is a prefix aossciated with it ! */
|
896
614
|
if (node->prefix != NULL)
|
@@ -902,10 +620,6 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node)
|
|
902
620
|
}
|
903
621
|
|
904
622
|
if (node->r == NULL && node->l == NULL) {
|
905
|
-
#ifdef PATRICIA_DEBUG
|
906
|
-
fprintf (stderr, "patricia_remove: #1 %s/%d (!r & !l)\n",
|
907
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
908
|
-
#endif /* PATRICIA_DEBUG */
|
909
623
|
parent = node->parent;
|
910
624
|
Deref_Prefix (node->prefix);
|
911
625
|
Delete (node);
|
@@ -949,10 +663,6 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node)
|
|
949
663
|
return;
|
950
664
|
}
|
951
665
|
|
952
|
-
#ifdef PATRICIA_DEBUG
|
953
|
-
fprintf (stderr, "patricia_remove: #2 %s/%d (r ^ l)\n",
|
954
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
955
|
-
#endif /* PATRICIA_DEBUG */
|
956
666
|
if (node->r) {
|
957
667
|
child = node->r;
|
958
668
|
}
|
@@ -981,64 +691,3 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node)
|
|
981
691
|
parent->l = child;
|
982
692
|
}
|
983
693
|
}
|
984
|
-
|
985
|
-
/* { from demo.c */
|
986
|
-
|
987
|
-
patricia_node_t *
|
988
|
-
make_and_lookup (patricia_tree_t *tree, char *string)
|
989
|
-
{
|
990
|
-
prefix_t *prefix;
|
991
|
-
patricia_node_t *node;
|
992
|
-
|
993
|
-
prefix = ascii2prefix (AF_INET, string);
|
994
|
-
printf ("make_and_lookup: %s/%d\n", prefix_toa (prefix), prefix->bitlen);
|
995
|
-
node = patricia_lookup (tree, prefix);
|
996
|
-
Deref_Prefix (prefix);
|
997
|
-
return (node);
|
998
|
-
}
|
999
|
-
|
1000
|
-
patricia_node_t *
|
1001
|
-
try_search_exact (patricia_tree_t *tree, char *string)
|
1002
|
-
{
|
1003
|
-
prefix_t *prefix;
|
1004
|
-
patricia_node_t *node;
|
1005
|
-
|
1006
|
-
prefix = ascii2prefix (AF_INET, string);
|
1007
|
-
printf ("try_search_exact: %s/%d\n", prefix_toa (prefix), prefix->bitlen);
|
1008
|
-
if ((node = patricia_search_exact (tree, prefix)) == NULL) {
|
1009
|
-
printf ("try_search_exact: not found\n");
|
1010
|
-
}
|
1011
|
-
else {
|
1012
|
-
printf ("try_search_exact: %s/%d found\n",
|
1013
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
1014
|
-
}
|
1015
|
-
Deref_Prefix (prefix);
|
1016
|
-
return (node);
|
1017
|
-
}
|
1018
|
-
|
1019
|
-
void
|
1020
|
-
lookup_then_remove (patricia_tree_t *tree, char *string)
|
1021
|
-
{
|
1022
|
-
patricia_node_t *node;
|
1023
|
-
|
1024
|
-
if (node = try_search_exact (tree, string))
|
1025
|
-
patricia_remove (tree, node);
|
1026
|
-
}
|
1027
|
-
|
1028
|
-
patricia_node_t *
|
1029
|
-
try_search_best (patricia_tree_t *tree, char *string)
|
1030
|
-
{
|
1031
|
-
prefix_t *prefix;
|
1032
|
-
patricia_node_t *node;
|
1033
|
-
|
1034
|
-
prefix = ascii2prefix (AF_INET, string);
|
1035
|
-
printf ("try_search_best: %s/%d\n", prefix_toa (prefix), prefix->bitlen);
|
1036
|
-
if ((node = patricia_search_best (tree, prefix)) == NULL)
|
1037
|
-
printf ("try_search_best: not found\n");
|
1038
|
-
else
|
1039
|
-
printf ("try_search_best: %s/%d found\n",
|
1040
|
-
prefix_toa (node->prefix), node->prefix->bitlen);
|
1041
|
-
Deref_Prefix (prefix);
|
1042
|
-
}
|
1043
|
-
|
1044
|
-
/* } */
|
data/ext/rpatricia/patricia.h
CHANGED
@@ -23,8 +23,6 @@ typedef void (*void_fn_t)();
|
|
23
23
|
#define BIT_TEST(f, b) ((f) & (b))
|
24
24
|
/* } */
|
25
25
|
|
26
|
-
#define addroute make_and_lookup
|
27
|
-
|
28
26
|
#include <sys/types.h> /* for u_* definitions (on FreeBSD 5) */
|
29
27
|
|
30
28
|
#include <errno.h> /* for EAFNOSUPPORT */
|
@@ -52,9 +50,7 @@ typedef struct _prefix_t {
|
|
52
50
|
int ref_count; /* reference count */
|
53
51
|
union {
|
54
52
|
struct in_addr sin;
|
55
|
-
#ifdef HAVE_IPV6
|
56
53
|
struct in6_addr sin6;
|
57
|
-
#endif /* IPV6 */
|
58
54
|
} add;
|
59
55
|
} prefix_t;
|
60
56
|
|
@@ -90,14 +86,12 @@ void patricia_process (patricia_tree_t *patricia, void_fn_t func);
|
|
90
86
|
/* { from demo.c */
|
91
87
|
|
92
88
|
prefix_t *
|
93
|
-
ascii2prefix (
|
94
|
-
|
95
|
-
patricia_node_t *
|
96
|
-
make_and_lookup (patricia_tree_t *tree, char *string);
|
89
|
+
ascii2prefix (char *string, prefix_t *prefix);
|
97
90
|
|
98
91
|
/* } */
|
99
92
|
|
100
93
|
#define PATRICIA_MAXBITS 128
|
94
|
+
#define PATRICIA_MAXSTRLEN (INET6_ADDRSTRLEN + sizeof("/128") - 1)
|
101
95
|
#define PATRICIA_NBIT(x) (0x80 >> ((x) & 0x7f))
|
102
96
|
#define PATRICIA_NBYTE(x) ((x) >> 3)
|
103
97
|
|
data/ext/rpatricia/rpatricia.c
CHANGED
@@ -8,7 +8,12 @@
|
|
8
8
|
#include "patricia.h"
|
9
9
|
#include <assert.h>
|
10
10
|
|
11
|
+
size_t patricia_walk_inorder(patricia_node_t *node, void_fn_t func);
|
12
|
+
char * prefix_toa2x(prefix_t *prefix, char *buff, int with_len);
|
13
|
+
char * prefix_toa2(prefix_t *prefix, char *buff);
|
14
|
+
|
11
15
|
static VALUE cPatricia, cNode;
|
16
|
+
static VALUE sym_AF_INET, sym_AF_INET6;
|
12
17
|
|
13
18
|
static void dummy(void) {}
|
14
19
|
|
@@ -42,16 +47,18 @@ wrap_node(patricia_node_t *orig)
|
|
42
47
|
return Data_Wrap_Struct(cNode, p_node_mark, -1, node);
|
43
48
|
}
|
44
49
|
|
45
|
-
static
|
46
|
-
my_ascii2prefix(
|
50
|
+
static void
|
51
|
+
my_ascii2prefix(patricia_tree_t *tree, VALUE str, prefix_t *prefix)
|
47
52
|
{
|
48
|
-
char *cstr =
|
49
|
-
prefix_t *
|
53
|
+
char *cstr = StringValueCStr(str);
|
54
|
+
prefix_t *ok = ascii2prefix(cstr, prefix);
|
50
55
|
|
51
|
-
if (!
|
56
|
+
if (!ok)
|
52
57
|
rb_raise(rb_eArgError, "invalid prefix: %s", cstr);
|
53
58
|
|
54
|
-
|
59
|
+
if (prefix->bitlen > tree->maxbits)
|
60
|
+
rb_raise(rb_eArgError, "prefix length (%u) larger than maxbits (%u)",
|
61
|
+
prefix->bitlen, tree->maxbits);
|
55
62
|
}
|
56
63
|
|
57
64
|
static VALUE
|
@@ -60,15 +67,14 @@ p_add (int argc, VALUE *argv, VALUE self)
|
|
60
67
|
VALUE user_data;
|
61
68
|
patricia_tree_t *tree;
|
62
69
|
patricia_node_t *node;
|
63
|
-
prefix_t
|
70
|
+
prefix_t prefix;
|
64
71
|
|
65
72
|
if (argc > 2 || argc < 1)
|
66
73
|
return Qnil;
|
67
74
|
|
68
75
|
Data_Get_Struct(self, patricia_tree_t, tree);
|
69
|
-
|
70
|
-
node = patricia_lookup(tree, prefix);
|
71
|
-
Deref_Prefix(prefix);
|
76
|
+
my_ascii2prefix(tree, argv[0], &prefix);
|
77
|
+
node = patricia_lookup(tree, &prefix);
|
72
78
|
|
73
79
|
if (argc == 2) {
|
74
80
|
user_data = argv[1];
|
@@ -90,12 +96,11 @@ p_remove (VALUE self, VALUE r_key)
|
|
90
96
|
{
|
91
97
|
patricia_tree_t *tree;
|
92
98
|
patricia_node_t *node;
|
93
|
-
prefix_t
|
99
|
+
prefix_t prefix;
|
94
100
|
|
95
101
|
Data_Get_Struct(self, patricia_tree_t, tree);
|
96
|
-
|
97
|
-
node = patricia_search_exact(tree, prefix);
|
98
|
-
Deref_Prefix (prefix);
|
102
|
+
my_ascii2prefix(tree, r_key, &prefix);
|
103
|
+
node = patricia_search_exact(tree, &prefix);
|
99
104
|
|
100
105
|
if (node) {
|
101
106
|
patricia_remove (tree, node);
|
@@ -110,12 +115,11 @@ p_match (VALUE self, VALUE r_key)
|
|
110
115
|
{
|
111
116
|
patricia_tree_t *tree;
|
112
117
|
patricia_node_t *node;
|
113
|
-
prefix_t
|
118
|
+
prefix_t prefix;
|
114
119
|
|
115
120
|
Data_Get_Struct(self, patricia_tree_t, tree);
|
116
|
-
|
117
|
-
node = patricia_search_best(tree, prefix);
|
118
|
-
Deref_Prefix (prefix);
|
121
|
+
my_ascii2prefix(tree, r_key, &prefix);
|
122
|
+
node = patricia_search_best(tree, &prefix);
|
119
123
|
|
120
124
|
return node ? wrap_node(node) : Qnil;
|
121
125
|
}
|
@@ -125,12 +129,11 @@ p_include (VALUE self, VALUE r_key)
|
|
125
129
|
{
|
126
130
|
patricia_tree_t *tree;
|
127
131
|
patricia_node_t *node;
|
128
|
-
prefix_t
|
132
|
+
prefix_t prefix;
|
129
133
|
|
130
134
|
Data_Get_Struct(self, patricia_tree_t, tree);
|
131
|
-
|
132
|
-
node = patricia_search_best(tree, prefix);
|
133
|
-
Deref_Prefix (prefix);
|
135
|
+
my_ascii2prefix(tree, r_key, &prefix);
|
136
|
+
node = patricia_search_best(tree, &prefix);
|
134
137
|
|
135
138
|
return node ? Qtrue : Qfalse;
|
136
139
|
}
|
@@ -140,12 +143,11 @@ p_match_exact (VALUE self, VALUE r_key)
|
|
140
143
|
{
|
141
144
|
patricia_tree_t *tree;
|
142
145
|
patricia_node_t *node;
|
143
|
-
prefix_t
|
146
|
+
prefix_t prefix;
|
144
147
|
|
145
148
|
Data_Get_Struct(self, patricia_tree_t, tree);
|
146
|
-
|
147
|
-
node = patricia_search_exact(tree, prefix);
|
148
|
-
Deref_Prefix (prefix);
|
149
|
+
my_ascii2prefix(tree, r_key, &prefix);
|
150
|
+
node = patricia_search_exact(tree, &prefix);
|
149
151
|
|
150
152
|
return node ? wrap_node(node) : Qnil;
|
151
153
|
}
|
@@ -177,7 +179,7 @@ p_print_nodes (int argc, VALUE *argv, VALUE self)
|
|
177
179
|
{
|
178
180
|
ID id_printf = rb_intern("printf");
|
179
181
|
VALUE fmt = rb_str_new2("node: %s\n");
|
180
|
-
VALUE buf =
|
182
|
+
VALUE buf = rb_str_new(0, 0);
|
181
183
|
char *cbuf;
|
182
184
|
patricia_tree_t *tree;
|
183
185
|
patricia_node_t *node;
|
@@ -190,7 +192,7 @@ p_print_nodes (int argc, VALUE *argv, VALUE self)
|
|
190
192
|
|
191
193
|
if (tree->head) {
|
192
194
|
PATRICIA_WALK(tree->head, node) {
|
193
|
-
rb_str_resize(buf,
|
195
|
+
rb_str_resize(buf, PATRICIA_MAXSTRLEN);
|
194
196
|
cbuf = RSTRING_PTR(buf);
|
195
197
|
prefix_toa2x(node->prefix, cbuf, 1);
|
196
198
|
rb_str_set_len(buf, strlen(cbuf));
|
@@ -219,21 +221,29 @@ p_data (VALUE self)
|
|
219
221
|
static VALUE
|
220
222
|
p_network (VALUE self)
|
221
223
|
{
|
222
|
-
char buff[32];
|
223
224
|
patricia_node_t *node;
|
225
|
+
VALUE str = rb_str_new(0, PATRICIA_MAXSTRLEN);
|
226
|
+
char *cstr = RSTRING_PTR(str);
|
227
|
+
|
224
228
|
Data_Get_Struct(self, patricia_node_t, node);
|
225
|
-
prefix_toa2x
|
226
|
-
|
229
|
+
prefix_toa2x(node->prefix, cstr, 0);
|
230
|
+
rb_str_set_len(str, strlen(cstr));
|
231
|
+
|
232
|
+
return str;
|
227
233
|
}
|
228
234
|
|
229
235
|
static VALUE
|
230
236
|
p_prefix (VALUE self)
|
231
237
|
{
|
232
|
-
char buff[32];
|
233
238
|
patricia_node_t *node;
|
239
|
+
VALUE str = rb_str_new(0, INET6_ADDRSTRLEN);
|
240
|
+
char *cstr = RSTRING_PTR(str);
|
241
|
+
|
234
242
|
Data_Get_Struct(self, patricia_node_t, node);
|
235
|
-
prefix_toa2
|
236
|
-
|
243
|
+
prefix_toa2(node->prefix, cstr);
|
244
|
+
rb_str_set_len(str, strlen(cstr));
|
245
|
+
|
246
|
+
return str;
|
237
247
|
}
|
238
248
|
|
239
249
|
static VALUE
|
@@ -258,25 +268,42 @@ p_tree_mark (void *ptr)
|
|
258
268
|
{
|
259
269
|
patricia_tree_t *tree = ptr;
|
260
270
|
|
261
|
-
|
271
|
+
if (tree)
|
272
|
+
patricia_process(tree, p_tree_mark_each);
|
262
273
|
}
|
263
274
|
|
264
275
|
static void
|
265
276
|
p_tree_free (void *ptr)
|
266
277
|
{
|
267
278
|
patricia_tree_t *tree = ptr;
|
268
|
-
|
269
279
|
/* no need to explicitly free each node->data, GC will do it for us */
|
270
|
-
|
280
|
+
if (tree)
|
281
|
+
Destroy_Patricia(tree, NULL);
|
271
282
|
}
|
272
283
|
|
273
284
|
static VALUE
|
274
285
|
p_alloc(VALUE klass)
|
275
286
|
{
|
276
|
-
|
277
|
-
|
287
|
+
return Data_Wrap_Struct(klass, p_tree_mark, p_tree_free, NULL);
|
288
|
+
}
|
289
|
+
|
290
|
+
static VALUE
|
291
|
+
p_init(int argc, VALUE *argv, VALUE self)
|
292
|
+
{
|
293
|
+
VALUE family;
|
294
|
+
int maxbits;
|
295
|
+
|
296
|
+
rb_scan_args(argc, argv, "01", &family);
|
278
297
|
|
279
|
-
|
298
|
+
if (NIL_P(family) || family == sym_AF_INET)
|
299
|
+
maxbits = 32;
|
300
|
+
else if (family == sym_AF_INET6)
|
301
|
+
maxbits = 128;
|
302
|
+
else
|
303
|
+
rb_raise(rb_eArgError, "unknown family (must be :AF_INET6 or :AF_INET)");
|
304
|
+
|
305
|
+
DATA_PTR(self) = New_Patricia(maxbits);
|
306
|
+
return self;
|
280
307
|
}
|
281
308
|
|
282
309
|
static VALUE
|
@@ -288,10 +315,10 @@ p_init_copy(VALUE self, VALUE orig)
|
|
288
315
|
if (orig_tree->head) {
|
289
316
|
patricia_tree_t *tree;
|
290
317
|
patricia_node_t *orig_node, *node;
|
291
|
-
prefix_t prefix;
|
292
318
|
VALUE user_data;
|
293
319
|
|
294
|
-
|
320
|
+
DATA_PTR(self) = tree = New_Patricia(orig_tree->maxbits);
|
321
|
+
|
295
322
|
PATRICIA_WALK(orig_tree->head, orig_node) {
|
296
323
|
node = patricia_lookup(tree, orig_node->prefix);
|
297
324
|
assert(node->prefix == orig_node->prefix);
|
@@ -302,6 +329,23 @@ p_init_copy(VALUE self, VALUE orig)
|
|
302
329
|
PATRICIA_DATA_SET(node, user_data);
|
303
330
|
} PATRICIA_WALK_END;
|
304
331
|
}
|
332
|
+
|
333
|
+
return self;
|
334
|
+
}
|
335
|
+
|
336
|
+
static VALUE
|
337
|
+
p_family(VALUE self)
|
338
|
+
{
|
339
|
+
patricia_tree_t *tree;
|
340
|
+
|
341
|
+
Data_Get_Struct(self, patricia_tree_t, tree);
|
342
|
+
|
343
|
+
switch (tree->maxbits) {
|
344
|
+
case 32: return sym_AF_INET;
|
345
|
+
case 128: return sym_AF_INET6;
|
346
|
+
}
|
347
|
+
assert(0 && "unknown maxbits, corrupt tree");
|
348
|
+
return Qnil;
|
305
349
|
}
|
306
350
|
|
307
351
|
void
|
@@ -309,15 +353,19 @@ Init_rpatricia (void)
|
|
309
353
|
{
|
310
354
|
cPatricia = rb_define_class("Patricia", rb_cObject);
|
311
355
|
cNode = rb_define_class_under(cPatricia, "Node", rb_cObject);
|
356
|
+
sym_AF_INET = ID2SYM(rb_intern("AF_INET"));
|
357
|
+
sym_AF_INET6 = ID2SYM(rb_intern("AF_INET6"));
|
312
358
|
|
313
359
|
/* allocate new Patricia object, called before initialize */
|
314
360
|
rb_define_alloc_func(cPatricia, p_alloc);
|
361
|
+
rb_define_private_method(cPatricia, "initialize", p_init, -1);
|
315
362
|
rb_define_method(cPatricia, "initialize_copy", p_init_copy, 1);
|
316
363
|
|
317
364
|
/*---------- methods to tree ----------*/
|
318
365
|
/* add string */
|
319
366
|
rb_define_method(cPatricia, "add", p_add, -1);
|
320
367
|
rb_define_method(cPatricia, "add_node", p_add, -1);
|
368
|
+
rb_define_method(cPatricia, "family", p_family, 0);
|
321
369
|
|
322
370
|
/* match prefix */
|
323
371
|
rb_define_method(cPatricia, "match_best", p_match, 1);
|
@@ -348,6 +396,4 @@ Init_rpatricia (void)
|
|
348
396
|
rb_define_method(cNode, "network", p_network, 0);
|
349
397
|
rb_define_method(cNode, "prefix", p_prefix, 0);
|
350
398
|
rb_define_method(cNode, "prefixlen", p_prefixlen, 0);
|
351
|
-
// rb_define_method(cPatricia, "family", p_family, 0);
|
352
|
-
|
353
399
|
}
|
data/rpatricia.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = %q{rpatricia}
|
6
|
-
s.version = %q{0.
|
6
|
+
s.version = %q{0.08} # remember to update Changes if this is changed
|
7
7
|
|
8
8
|
s.homepage = "http://www.goto.info.waseda.ac.jp/~tatsuya/rpatricia/"
|
9
9
|
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rpatricia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: "0.
|
8
|
+
- 8
|
9
|
+
version: "0.08"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Tatsuya Mori
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
19
|
-
default_executable:
|
18
|
+
date: 2011-08-13 00:00:00 Z
|
20
19
|
dependencies: []
|
21
20
|
|
22
21
|
description: |-
|
@@ -46,7 +45,6 @@ files:
|
|
46
45
|
- ext/rpatricia/rpatricia.c
|
47
46
|
- rpatricia.gemspec
|
48
47
|
- test.rb
|
49
|
-
has_rdoc: true
|
50
48
|
homepage: http://www.goto.info.waseda.ac.jp/~tatsuya/rpatricia/
|
51
49
|
licenses: []
|
52
50
|
|
@@ -76,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
74
|
requirements: []
|
77
75
|
|
78
76
|
rubyforge_project:
|
79
|
-
rubygems_version: 1.
|
77
|
+
rubygems_version: 1.8.5
|
80
78
|
signing_key:
|
81
79
|
specification_version: 3
|
82
80
|
summary: module for fast IP address/prefix lookups
|