rpatricia 0.04

Sign up to get free protection for your applications and to get access to all the features.
Files changed (10) hide show
  1. data/Changes +16 -0
  2. data/README +179 -0
  3. data/TODO +2 -0
  4. data/copyright +34 -0
  5. data/credits.txt +73 -0
  6. data/extconf.rb +5 -0
  7. data/patricia.c +1038 -0
  8. data/patricia.h +147 -0
  9. data/rpatricia.c +225 -0
  10. 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
+