rpatricia 0.07 → 0.08
Sign up to get free protection for your applications and to get access to all the features.
- 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
|