rpatricia 0.04
Sign up to get free protection for your applications and to get access to all the features.
- data/Changes +16 -0
- data/README +179 -0
- data/TODO +2 -0
- data/copyright +34 -0
- data/credits.txt +73 -0
- data/extconf.rb +5 -0
- data/patricia.c +1038 -0
- data/patricia.h +147 -0
- data/rpatricia.c +225 -0
- metadata +71 -0
data/patricia.h
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
/*
|
2
|
+
* $Id: patricia.h,v 1.6 2005/12/07 20:53:01 dplonka Exp $
|
3
|
+
* Dave Plonka <plonka@doit.wisc.edu>
|
4
|
+
*
|
5
|
+
* This product includes software developed by the University of Michigan,
|
6
|
+
* Merit Network, Inc., and their contributors.
|
7
|
+
*
|
8
|
+
* This file had been called "radix.h" in the MRT sources.
|
9
|
+
*
|
10
|
+
* I renamed it to "patricia.h" since it's not an implementation of a general
|
11
|
+
* radix trie. Also, pulled in various requirements from "mrt.h" and added
|
12
|
+
* some other things it could be used as a standalone API.
|
13
|
+
*/
|
14
|
+
|
15
|
+
#ifndef _PATRICIA_H
|
16
|
+
#define _PATRICIA_H
|
17
|
+
|
18
|
+
/* typedef unsigned int u_int; */
|
19
|
+
typedef void (*void_fn_t)();
|
20
|
+
/* { from defs.h */
|
21
|
+
#define prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin)
|
22
|
+
#define MAXLINE 1024
|
23
|
+
#define BIT_TEST(f, b) ((f) & (b))
|
24
|
+
/* } */
|
25
|
+
|
26
|
+
#define addroute make_and_lookup
|
27
|
+
|
28
|
+
#include <sys/types.h> /* for u_* definitions (on FreeBSD 5) */
|
29
|
+
|
30
|
+
#include <errno.h> /* for EAFNOSUPPORT */
|
31
|
+
#ifndef EAFNOSUPPORT
|
32
|
+
# defined EAFNOSUPPORT WSAEAFNOSUPPORT
|
33
|
+
# include <winsock.h>
|
34
|
+
#else
|
35
|
+
# include <netinet/in.h> /* for struct in_addr */
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#include <sys/socket.h> /* for AF_INET */
|
39
|
+
|
40
|
+
/* { from mrt.h */
|
41
|
+
|
42
|
+
typedef struct _prefix4_t {
|
43
|
+
u_short family; /* AF_INET | AF_INET6 */
|
44
|
+
u_short bitlen; /* same as mask? */
|
45
|
+
int ref_count; /* reference count */
|
46
|
+
struct in_addr sin;
|
47
|
+
} prefix4_t;
|
48
|
+
|
49
|
+
typedef struct _prefix_t {
|
50
|
+
u_short family; /* AF_INET | AF_INET6 */
|
51
|
+
u_short bitlen; /* same as mask? */
|
52
|
+
int ref_count; /* reference count */
|
53
|
+
union {
|
54
|
+
struct in_addr sin;
|
55
|
+
#ifdef HAVE_IPV6
|
56
|
+
struct in6_addr sin6;
|
57
|
+
#endif /* IPV6 */
|
58
|
+
} add;
|
59
|
+
} prefix_t;
|
60
|
+
|
61
|
+
/* } */
|
62
|
+
|
63
|
+
typedef struct _patricia_node_t {
|
64
|
+
u_int bit; /* flag if this node used */
|
65
|
+
prefix_t *prefix; /* who we are in patricia tree */
|
66
|
+
struct _patricia_node_t *l, *r; /* left and right children */
|
67
|
+
struct _patricia_node_t *parent;/* may be used */
|
68
|
+
void *data; /* pointer to data */
|
69
|
+
void *user; /* pointer to usr data (ex. route flap info) */
|
70
|
+
} patricia_node_t;
|
71
|
+
|
72
|
+
typedef struct _patricia_tree_t {
|
73
|
+
patricia_node_t *head;
|
74
|
+
u_int maxbits; /* for IP, 32 bit addresses */
|
75
|
+
int num_active_node; /* for debug purpose */
|
76
|
+
} patricia_tree_t;
|
77
|
+
|
78
|
+
|
79
|
+
patricia_node_t *patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix);
|
80
|
+
patricia_node_t *patricia_search_best (patricia_tree_t *patricia, prefix_t *prefix);
|
81
|
+
patricia_node_t * patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix,
|
82
|
+
int inclusive);
|
83
|
+
patricia_node_t *patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix);
|
84
|
+
void patricia_remove (patricia_tree_t *patricia, patricia_node_t *node);
|
85
|
+
patricia_tree_t *New_Patricia (int maxbits);
|
86
|
+
void Clear_Patricia (patricia_tree_t *patricia, void_fn_t func);
|
87
|
+
void Destroy_Patricia (patricia_tree_t *patricia, void_fn_t func);
|
88
|
+
void patricia_process (patricia_tree_t *patricia, void_fn_t func);
|
89
|
+
|
90
|
+
/* { from demo.c */
|
91
|
+
|
92
|
+
prefix_t *
|
93
|
+
ascii2prefix (int family, char *string);
|
94
|
+
|
95
|
+
patricia_node_t *
|
96
|
+
make_and_lookup (patricia_tree_t *tree, char *string);
|
97
|
+
|
98
|
+
/* } */
|
99
|
+
|
100
|
+
#define PATRICIA_MAXBITS 128
|
101
|
+
#define PATRICIA_NBIT(x) (0x80 >> ((x) & 0x7f))
|
102
|
+
#define PATRICIA_NBYTE(x) ((x) >> 3)
|
103
|
+
|
104
|
+
#define PATRICIA_DATA_GET(node, type) (type *)((node)->data)
|
105
|
+
#define PATRICIA_DATA_SET(node, value) ((node)->data = (void *)(value))
|
106
|
+
|
107
|
+
#define PATRICIA_WALK(Xhead, Xnode) \
|
108
|
+
do { \
|
109
|
+
patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \
|
110
|
+
patricia_node_t **Xsp = Xstack; \
|
111
|
+
patricia_node_t *Xrn = (Xhead); \
|
112
|
+
while ((Xnode = Xrn)) { \
|
113
|
+
if (Xnode->prefix)
|
114
|
+
|
115
|
+
#define PATRICIA_WALK_ALL(Xhead, Xnode) \
|
116
|
+
do { \
|
117
|
+
patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \
|
118
|
+
patricia_node_t **Xsp = Xstack; \
|
119
|
+
patricia_node_t *Xrn = (Xhead); \
|
120
|
+
while ((Xnode = Xrn)) { \
|
121
|
+
if (1)
|
122
|
+
|
123
|
+
#define PATRICIA_WALK_BREAK { \
|
124
|
+
if (Xsp != Xstack) { \
|
125
|
+
Xrn = *(--Xsp); \
|
126
|
+
} else { \
|
127
|
+
Xrn = (patricia_node_t *) 0; \
|
128
|
+
} \
|
129
|
+
continue; }
|
130
|
+
|
131
|
+
#define PATRICIA_WALK_END \
|
132
|
+
if (Xrn->l) { \
|
133
|
+
if (Xrn->r) { \
|
134
|
+
*Xsp++ = Xrn->r; \
|
135
|
+
} \
|
136
|
+
Xrn = Xrn->l; \
|
137
|
+
} else if (Xrn->r) { \
|
138
|
+
Xrn = Xrn->r; \
|
139
|
+
} else if (Xsp != Xstack) { \
|
140
|
+
Xrn = *(--Xsp); \
|
141
|
+
} else { \
|
142
|
+
Xrn = (patricia_node_t *) 0; \
|
143
|
+
} \
|
144
|
+
} \
|
145
|
+
} while (0)
|
146
|
+
|
147
|
+
#endif /* _PATRICIA_H */
|
data/rpatricia.c
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
/*
|
2
|
+
* rpatricia.c - Ruby wrapper of Net::Patricia
|
3
|
+
* Tatsuya Mori <mori.tatsuya@gmail.com>
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include "ruby.h"
|
7
|
+
#include <stdio.h> /* printf */
|
8
|
+
#include <stdlib.h>
|
9
|
+
#include "patricia.h"
|
10
|
+
|
11
|
+
VALUE cPatricia;
|
12
|
+
|
13
|
+
void dummy(void) {}
|
14
|
+
|
15
|
+
static VALUE
|
16
|
+
p_destroy (VALUE self)
|
17
|
+
{
|
18
|
+
patricia_tree_t *tree;
|
19
|
+
Data_Get_Struct(self, patricia_tree_t, tree);
|
20
|
+
Destroy_Patricia(tree, free);
|
21
|
+
return Qtrue;
|
22
|
+
}
|
23
|
+
|
24
|
+
VALUE
|
25
|
+
p_add (int argc, VALUE *argv, VALUE self)
|
26
|
+
{
|
27
|
+
int str_len;
|
28
|
+
char *user_data;
|
29
|
+
patricia_tree_t *tree;
|
30
|
+
patricia_node_t *node;
|
31
|
+
prefix_t *prefix;
|
32
|
+
|
33
|
+
if (argc > 2 || argc < 1)
|
34
|
+
return Qnil;
|
35
|
+
|
36
|
+
Data_Get_Struct(self, patricia_tree_t, tree);
|
37
|
+
prefix = ascii2prefix(AF_INET, STR2CSTR(argv[0]));
|
38
|
+
node = patricia_lookup(tree, prefix);
|
39
|
+
Deref_Prefix(prefix);
|
40
|
+
|
41
|
+
if (argc == 2) {
|
42
|
+
user_data = STR2CSTR(argv[1]);
|
43
|
+
str_len = strlen(user_data);
|
44
|
+
node->data = (char *) malloc((str_len + 1) * sizeof(char));
|
45
|
+
sprintf((char *)node->data, user_data);
|
46
|
+
} else {
|
47
|
+
node->data = (char *) malloc(sizeof(char));
|
48
|
+
sprintf((char *)node->data, "");
|
49
|
+
}
|
50
|
+
return Data_Wrap_Struct(cPatricia, 0, 0, node);
|
51
|
+
}
|
52
|
+
|
53
|
+
static VALUE
|
54
|
+
p_remove (VALUE self, VALUE r_key)
|
55
|
+
{
|
56
|
+
char *c_key;
|
57
|
+
patricia_tree_t *tree;
|
58
|
+
patricia_node_t *node;
|
59
|
+
prefix_t *prefix;
|
60
|
+
|
61
|
+
Data_Get_Struct(self, patricia_tree_t, tree);
|
62
|
+
c_key = STR2CSTR(r_key);
|
63
|
+
prefix = ascii2prefix (AF_INET, c_key);
|
64
|
+
node = patricia_search_exact(tree, prefix);
|
65
|
+
Deref_Prefix (prefix);
|
66
|
+
|
67
|
+
if (node) {
|
68
|
+
patricia_remove (tree, node);
|
69
|
+
return Qtrue;
|
70
|
+
} else {
|
71
|
+
return Qfalse;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
static VALUE
|
76
|
+
p_match (VALUE self, VALUE r_key)
|
77
|
+
{
|
78
|
+
patricia_tree_t *tree;
|
79
|
+
patricia_node_t *node;
|
80
|
+
prefix_t *prefix;
|
81
|
+
|
82
|
+
Data_Get_Struct(self, patricia_tree_t, tree);
|
83
|
+
prefix = ascii2prefix (AF_INET, STR2CSTR(r_key));
|
84
|
+
node = patricia_search_best(tree, prefix);
|
85
|
+
Deref_Prefix (prefix);
|
86
|
+
|
87
|
+
if (node)
|
88
|
+
return Data_Wrap_Struct(cPatricia, 0, 0, node);
|
89
|
+
else
|
90
|
+
return Qfalse;
|
91
|
+
|
92
|
+
}
|
93
|
+
|
94
|
+
static VALUE
|
95
|
+
p_match_exact (VALUE self, VALUE r_key)
|
96
|
+
{
|
97
|
+
patricia_tree_t *tree;
|
98
|
+
patricia_node_t *node;
|
99
|
+
prefix_t *prefix;
|
100
|
+
|
101
|
+
Data_Get_Struct(self, patricia_tree_t, tree);
|
102
|
+
prefix = ascii2prefix (AF_INET, STR2CSTR(r_key));
|
103
|
+
node = patricia_search_exact(tree, prefix);
|
104
|
+
Deref_Prefix (prefix);
|
105
|
+
|
106
|
+
if (node)
|
107
|
+
return Data_Wrap_Struct(cPatricia, 0, 0, node);
|
108
|
+
else
|
109
|
+
return Qfalse;
|
110
|
+
}
|
111
|
+
|
112
|
+
static VALUE
|
113
|
+
p_num_nodes (VALUE self)
|
114
|
+
{
|
115
|
+
int n;
|
116
|
+
patricia_tree_t *tree;
|
117
|
+
|
118
|
+
Data_Get_Struct(self, patricia_tree_t, tree);
|
119
|
+
n = patricia_walk_inorder(tree->head, dummy);
|
120
|
+
|
121
|
+
return INT2NUM(n);
|
122
|
+
}
|
123
|
+
|
124
|
+
static VALUE
|
125
|
+
p_print_nodes (VALUE self)
|
126
|
+
{
|
127
|
+
int n;
|
128
|
+
char buff[32];
|
129
|
+
patricia_tree_t *tree;
|
130
|
+
patricia_node_t *node;
|
131
|
+
Data_Get_Struct(self, patricia_tree_t, tree);
|
132
|
+
|
133
|
+
PATRICIA_WALK(tree->head, node) {
|
134
|
+
prefix_toa2x(node->prefix, buff, 1);
|
135
|
+
printf("node: %s\n", buff);
|
136
|
+
} PATRICIA_WALK_END;
|
137
|
+
return Qtrue;
|
138
|
+
}
|
139
|
+
|
140
|
+
static VALUE
|
141
|
+
p_data (VALUE self)
|
142
|
+
{
|
143
|
+
patricia_node_t *node;
|
144
|
+
Data_Get_Struct(self, patricia_node_t, node);
|
145
|
+
return rb_str_new2((char *)node->data);
|
146
|
+
}
|
147
|
+
|
148
|
+
static VALUE
|
149
|
+
p_network (VALUE self)
|
150
|
+
{
|
151
|
+
char buff[32];
|
152
|
+
patricia_node_t *node;
|
153
|
+
Data_Get_Struct(self, patricia_node_t, node);
|
154
|
+
prefix_toa2x (node->prefix, buff, 0);
|
155
|
+
return rb_str_new2(buff);
|
156
|
+
}
|
157
|
+
|
158
|
+
static VALUE
|
159
|
+
p_prefix (VALUE self)
|
160
|
+
{
|
161
|
+
char buff[32];
|
162
|
+
patricia_node_t *node;
|
163
|
+
Data_Get_Struct(self, patricia_node_t, node);
|
164
|
+
prefix_toa2 (node->prefix, buff);
|
165
|
+
return rb_str_new2(buff);
|
166
|
+
}
|
167
|
+
|
168
|
+
static VALUE
|
169
|
+
p_prefixlen (VALUE self)
|
170
|
+
{
|
171
|
+
patricia_node_t *node;
|
172
|
+
Data_Get_Struct(self, patricia_node_t, node);
|
173
|
+
return INT2NUM(node->prefix->bitlen);
|
174
|
+
}
|
175
|
+
|
176
|
+
static VALUE
|
177
|
+
p_new (VALUE self)
|
178
|
+
{
|
179
|
+
patricia_tree_t *tree;
|
180
|
+
tree = New_Patricia(32); /* assuming only IPv4 */
|
181
|
+
return Data_Wrap_Struct(cPatricia, 0, 0, tree);
|
182
|
+
}
|
183
|
+
|
184
|
+
void
|
185
|
+
Init_rpatricia (void)
|
186
|
+
{
|
187
|
+
cPatricia = rb_define_class("Patricia", rb_cObject);
|
188
|
+
|
189
|
+
/* create new Patricia object */
|
190
|
+
rb_define_singleton_method(cPatricia, "new", p_new, 0);
|
191
|
+
|
192
|
+
/*---------- methods to tree ----------*/
|
193
|
+
/* add string */
|
194
|
+
rb_define_method(cPatricia, "add", p_add, -1);
|
195
|
+
rb_define_method(cPatricia, "add_node", p_add, -1);
|
196
|
+
|
197
|
+
/* match prefix */
|
198
|
+
rb_define_method(cPatricia, "match_best", p_match, 1);
|
199
|
+
rb_define_method(cPatricia, "search_best", p_match, 1);
|
200
|
+
|
201
|
+
/* exact match */
|
202
|
+
rb_define_method(cPatricia, "match_exact", p_match_exact, 1);
|
203
|
+
rb_define_method(cPatricia, "search_exact", p_match_exact, 1);
|
204
|
+
|
205
|
+
/* removal */
|
206
|
+
rb_define_method(cPatricia, "remove", p_remove, 1);
|
207
|
+
rb_define_method(cPatricia, "remove_node", p_remove, 1);
|
208
|
+
|
209
|
+
/* derivatives of climb */
|
210
|
+
rb_define_method(cPatricia, "num_nodes", p_num_nodes, 0);
|
211
|
+
rb_define_method(cPatricia, "show_nodes", p_print_nodes, 0);
|
212
|
+
|
213
|
+
/* destroy tree */
|
214
|
+
rb_define_method(cPatricia, "destroy", p_destroy, 0);
|
215
|
+
rb_define_method(cPatricia, "clear", p_destroy, 0);
|
216
|
+
|
217
|
+
/*---------- methods to node ----------*/
|
218
|
+
rb_define_method(cPatricia, "data", p_data, 0);
|
219
|
+
rb_define_method(cPatricia, "show_data", p_data, 0);
|
220
|
+
rb_define_method(cPatricia, "network", p_network, 0);
|
221
|
+
rb_define_method(cPatricia, "prefix", p_prefix, 0);
|
222
|
+
rb_define_method(cPatricia, "prefixlen", p_prefixlen, 0);
|
223
|
+
// rb_define_method(cPatricia, "family", p_family, 0);
|
224
|
+
|
225
|
+
}
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rpatricia
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.04"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tatsuya Mori
|
8
|
+
- Eric Wong
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2010-03-12 00:00:00 +00:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: |-
|
18
|
+
This is a ruby wrapper of Net::Patricia, which has been developed by
|
19
|
+
Dave Plonka. The original Net::Patricia and its C API are available
|
20
|
+
from:
|
21
|
+
http://net.doit.wisc.edu/~plonka/Net-Patricia/
|
22
|
+
|
23
|
+
Net::Patricia is a module for fast IP address/prefix lookups.
|
24
|
+
I have modified some interfaces for the Ruby wrapper version.
|
25
|
+
email: normalperson@yhbt.net
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions:
|
29
|
+
- extconf.rb
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- Changes
|
34
|
+
- README
|
35
|
+
- TODO
|
36
|
+
- copyright
|
37
|
+
- credits.txt
|
38
|
+
- extconf.rb
|
39
|
+
- patricia.c
|
40
|
+
- patricia.h
|
41
|
+
- rpatricia.c
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://www.goto.info.waseda.ac.jp/~tatsuya/rpatricia/
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- .
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.5
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: module for fast IP address/prefix lookups
|
70
|
+
test_files: []
|
71
|
+
|