ffi-radix_tree 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +19 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/ffi/radixtree/Rakefile +62 -0
- data/ffi-radix_tree.gemspec +40 -0
- data/lib/ffi/radix_tree.rb +129 -0
- data/lib/ffi/radix_tree/version.rb +5 -0
- data/vendor/radixtree/CMakeLists.txt +10 -0
- data/vendor/radixtree/COPYING +21 -0
- data/vendor/radixtree/ffi_radix_tree.cpp +101 -0
- data/vendor/radixtree/radix_tree.hpp +536 -0
- data/vendor/radixtree/radix_tree_it.hpp +117 -0
- data/vendor/radixtree/radix_tree_node.hpp +53 -0
- metadata +134 -0
@@ -0,0 +1,536 @@
|
|
1
|
+
#ifndef RADIX_TREE_HPP
|
2
|
+
#define RADIX_TREE_HPP
|
3
|
+
|
4
|
+
#include <cassert>
|
5
|
+
#include <string>
|
6
|
+
#include <utility>
|
7
|
+
#include <vector>
|
8
|
+
|
9
|
+
#include "radix_tree_it.hpp"
|
10
|
+
#include "radix_tree_node.hpp"
|
11
|
+
|
12
|
+
template<typename K>
|
13
|
+
K radix_substr(const K &key, int begin, int num);
|
14
|
+
|
15
|
+
template<>
|
16
|
+
inline std::string radix_substr<std::string>(const std::string &key, int begin, int num)
|
17
|
+
{
|
18
|
+
return key.substr(begin, num);
|
19
|
+
}
|
20
|
+
|
21
|
+
template<typename K>
|
22
|
+
K radix_join(const K &key1, const K &key2);
|
23
|
+
|
24
|
+
template<>
|
25
|
+
inline std::string radix_join<std::string>(const std::string &key1, const std::string &key2)
|
26
|
+
{
|
27
|
+
return key1 + key2;
|
28
|
+
}
|
29
|
+
|
30
|
+
template<typename K>
|
31
|
+
int radix_length(const K &key);
|
32
|
+
|
33
|
+
template<>
|
34
|
+
inline int radix_length<std::string>(const std::string &key)
|
35
|
+
{
|
36
|
+
return key.size();
|
37
|
+
}
|
38
|
+
|
39
|
+
template <typename K, typename T>
|
40
|
+
class radix_tree {
|
41
|
+
public:
|
42
|
+
typedef K key_type;
|
43
|
+
typedef T mapped_type;
|
44
|
+
typedef std::pair<const K, T> value_type;
|
45
|
+
typedef radix_tree_it<K, T> iterator;
|
46
|
+
typedef std::size_t size_type;
|
47
|
+
|
48
|
+
radix_tree() : m_size(0), m_root(NULL) { }
|
49
|
+
~radix_tree() {
|
50
|
+
delete m_root;
|
51
|
+
}
|
52
|
+
|
53
|
+
size_type size() const {
|
54
|
+
return m_size;
|
55
|
+
}
|
56
|
+
bool empty() const {
|
57
|
+
return m_size == 0;
|
58
|
+
}
|
59
|
+
void clear() {
|
60
|
+
delete m_root;
|
61
|
+
m_root = NULL;
|
62
|
+
m_size = 0;
|
63
|
+
}
|
64
|
+
|
65
|
+
iterator find(const K &key);
|
66
|
+
iterator begin();
|
67
|
+
iterator end();
|
68
|
+
|
69
|
+
std::pair<iterator, bool> insert(const value_type &val);
|
70
|
+
bool erase(const K &key);
|
71
|
+
void erase(iterator it);
|
72
|
+
void prefix_match(const K &key, std::vector<iterator> &vec);
|
73
|
+
void greedy_match(const K &key, std::vector<iterator> &vec);
|
74
|
+
iterator longest_match(const K &key);
|
75
|
+
|
76
|
+
T& operator[] (const K &lhs);
|
77
|
+
|
78
|
+
private:
|
79
|
+
size_type m_size;
|
80
|
+
radix_tree_node<K, T>* m_root;
|
81
|
+
|
82
|
+
radix_tree_node<K, T>* begin(radix_tree_node<K, T> *node);
|
83
|
+
radix_tree_node<K, T>* find_node(const K &key, radix_tree_node<K, T> *node, int depth);
|
84
|
+
radix_tree_node<K, T>* append(radix_tree_node<K, T> *parent, const value_type &val);
|
85
|
+
radix_tree_node<K, T>* prepend(radix_tree_node<K, T> *node, const value_type &val);
|
86
|
+
void greedy_match(radix_tree_node<K, T> *node, std::vector<iterator> &vec);
|
87
|
+
|
88
|
+
radix_tree(const radix_tree& other); // delete
|
89
|
+
radix_tree& operator =(const radix_tree other); // delete
|
90
|
+
};
|
91
|
+
|
92
|
+
template <typename K, typename T>
|
93
|
+
void radix_tree<K, T>::prefix_match(const K &key, std::vector<iterator> &vec)
|
94
|
+
{
|
95
|
+
vec.clear();
|
96
|
+
|
97
|
+
if (m_root == NULL)
|
98
|
+
return;
|
99
|
+
|
100
|
+
radix_tree_node<K, T> *node;
|
101
|
+
K key_sub1, key_sub2;
|
102
|
+
|
103
|
+
node = find_node(key, m_root, 0);
|
104
|
+
|
105
|
+
if (node->m_is_leaf)
|
106
|
+
node = node->m_parent;
|
107
|
+
|
108
|
+
int len = radix_length(key) - node->m_depth;
|
109
|
+
key_sub1 = radix_substr(key, node->m_depth, len);
|
110
|
+
key_sub2 = radix_substr(node->m_key, 0, len);
|
111
|
+
|
112
|
+
if (key_sub1 != key_sub2)
|
113
|
+
return;
|
114
|
+
|
115
|
+
greedy_match(node, vec);
|
116
|
+
}
|
117
|
+
|
118
|
+
template <typename K, typename T>
|
119
|
+
typename radix_tree<K, T>::iterator radix_tree<K, T>::longest_match(const K &key)
|
120
|
+
{
|
121
|
+
if (m_root == NULL)
|
122
|
+
return iterator(NULL);
|
123
|
+
|
124
|
+
radix_tree_node<K, T> *node;
|
125
|
+
K key_sub;
|
126
|
+
|
127
|
+
node = find_node(key, m_root, 0);
|
128
|
+
|
129
|
+
if (node->m_is_leaf)
|
130
|
+
return iterator(node);
|
131
|
+
|
132
|
+
key_sub = radix_substr(key, node->m_depth, radix_length(node->m_key));
|
133
|
+
|
134
|
+
if (! (key_sub == node->m_key))
|
135
|
+
node = node->m_parent;
|
136
|
+
|
137
|
+
K nul = radix_substr(key, 0, 0);
|
138
|
+
|
139
|
+
while (node != NULL) {
|
140
|
+
typename radix_tree_node<K, T>::it_child it;
|
141
|
+
it = node->m_children.find(nul);
|
142
|
+
if (it != node->m_children.end() && it->second->m_is_leaf)
|
143
|
+
return iterator(it->second);
|
144
|
+
|
145
|
+
node = node->m_parent;
|
146
|
+
}
|
147
|
+
|
148
|
+
return iterator(NULL);
|
149
|
+
}
|
150
|
+
|
151
|
+
|
152
|
+
template <typename K, typename T>
|
153
|
+
typename radix_tree<K, T>::iterator radix_tree<K, T>::end()
|
154
|
+
{
|
155
|
+
return iterator(NULL);
|
156
|
+
}
|
157
|
+
|
158
|
+
template <typename K, typename T>
|
159
|
+
typename radix_tree<K, T>::iterator radix_tree<K, T>::begin()
|
160
|
+
{
|
161
|
+
radix_tree_node<K, T> *node;
|
162
|
+
|
163
|
+
if (m_root == NULL)
|
164
|
+
node = NULL;
|
165
|
+
else
|
166
|
+
node = begin(m_root);
|
167
|
+
|
168
|
+
return iterator(node);
|
169
|
+
}
|
170
|
+
|
171
|
+
template <typename K, typename T>
|
172
|
+
radix_tree_node<K, T>* radix_tree<K, T>::begin(radix_tree_node<K, T> *node)
|
173
|
+
{
|
174
|
+
if (node->m_is_leaf)
|
175
|
+
return node;
|
176
|
+
|
177
|
+
assert(!node->m_children.empty());
|
178
|
+
|
179
|
+
return begin(node->m_children.begin()->second);
|
180
|
+
}
|
181
|
+
|
182
|
+
template <typename K, typename T>
|
183
|
+
T& radix_tree<K, T>::operator[] (const K &lhs)
|
184
|
+
{
|
185
|
+
iterator it = find(lhs);
|
186
|
+
|
187
|
+
if (it == end()) {
|
188
|
+
std::pair<K, T> val;
|
189
|
+
val.first = lhs;
|
190
|
+
|
191
|
+
std::pair<iterator, bool> ret;
|
192
|
+
ret = insert(val);
|
193
|
+
|
194
|
+
assert(ret.second == true);
|
195
|
+
|
196
|
+
it = ret.first;
|
197
|
+
}
|
198
|
+
|
199
|
+
return it->second;
|
200
|
+
}
|
201
|
+
|
202
|
+
template <typename K, typename T>
|
203
|
+
void radix_tree<K, T>::greedy_match(const K &key, std::vector<iterator> &vec)
|
204
|
+
{
|
205
|
+
radix_tree_node<K, T> *node;
|
206
|
+
|
207
|
+
vec.clear();
|
208
|
+
|
209
|
+
if (m_root == NULL)
|
210
|
+
return;
|
211
|
+
|
212
|
+
node = find_node(key, m_root, 0);
|
213
|
+
|
214
|
+
if (node->m_is_leaf)
|
215
|
+
node = node->m_parent;
|
216
|
+
|
217
|
+
greedy_match(node, vec);
|
218
|
+
}
|
219
|
+
|
220
|
+
template <typename K, typename T>
|
221
|
+
void radix_tree<K, T>::greedy_match(radix_tree_node<K, T> *node, std::vector<iterator> &vec)
|
222
|
+
{
|
223
|
+
if (node->m_is_leaf) {
|
224
|
+
vec.push_back(iterator(node));
|
225
|
+
return;
|
226
|
+
}
|
227
|
+
|
228
|
+
typename std::map<K, radix_tree_node<K, T>*>::iterator it;
|
229
|
+
|
230
|
+
for (it = node->m_children.begin(); it != node->m_children.end(); ++it) {
|
231
|
+
greedy_match(it->second, vec);
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
template <typename K, typename T>
|
236
|
+
void radix_tree<K, T>::erase(iterator it)
|
237
|
+
{
|
238
|
+
erase(it->first);
|
239
|
+
}
|
240
|
+
|
241
|
+
template <typename K, typename T>
|
242
|
+
bool radix_tree<K, T>::erase(const K &key)
|
243
|
+
{
|
244
|
+
if (m_root == NULL)
|
245
|
+
return 0;
|
246
|
+
|
247
|
+
radix_tree_node<K, T> *child;
|
248
|
+
radix_tree_node<K, T> *parent;
|
249
|
+
radix_tree_node<K, T> *grandparent;
|
250
|
+
K nul = radix_substr(key, 0, 0);
|
251
|
+
|
252
|
+
child = find_node(key, m_root, 0);
|
253
|
+
|
254
|
+
if (! child->m_is_leaf)
|
255
|
+
return 0;
|
256
|
+
|
257
|
+
parent = child->m_parent;
|
258
|
+
parent->m_children.erase(nul);
|
259
|
+
|
260
|
+
delete child;
|
261
|
+
|
262
|
+
m_size--;
|
263
|
+
|
264
|
+
if (parent == m_root)
|
265
|
+
return 1;
|
266
|
+
|
267
|
+
if (parent->m_children.size() > 1)
|
268
|
+
return 1;
|
269
|
+
|
270
|
+
if (parent->m_children.empty()) {
|
271
|
+
grandparent = parent->m_parent;
|
272
|
+
grandparent->m_children.erase(parent->m_key);
|
273
|
+
delete parent;
|
274
|
+
} else {
|
275
|
+
grandparent = parent;
|
276
|
+
}
|
277
|
+
|
278
|
+
if (grandparent == m_root) {
|
279
|
+
return 1;
|
280
|
+
}
|
281
|
+
|
282
|
+
if (grandparent->m_children.size() == 1) {
|
283
|
+
// merge grandparent with the uncle
|
284
|
+
typename std::map<K, radix_tree_node<K, T>*>::iterator it;
|
285
|
+
it = grandparent->m_children.begin();
|
286
|
+
|
287
|
+
radix_tree_node<K, T> *uncle = it->second;
|
288
|
+
|
289
|
+
if (uncle->m_is_leaf)
|
290
|
+
return 1;
|
291
|
+
|
292
|
+
uncle->m_depth = grandparent->m_depth;
|
293
|
+
uncle->m_key = radix_join(grandparent->m_key, uncle->m_key);
|
294
|
+
uncle->m_parent = grandparent->m_parent;
|
295
|
+
|
296
|
+
grandparent->m_children.erase(it);
|
297
|
+
|
298
|
+
grandparent->m_parent->m_children.erase(grandparent->m_key);
|
299
|
+
grandparent->m_parent->m_children[uncle->m_key] = uncle;
|
300
|
+
|
301
|
+
delete grandparent;
|
302
|
+
}
|
303
|
+
|
304
|
+
return 1;
|
305
|
+
}
|
306
|
+
|
307
|
+
|
308
|
+
template <typename K, typename T>
|
309
|
+
radix_tree_node<K, T>* radix_tree<K, T>::append(radix_tree_node<K, T> *parent, const value_type &val)
|
310
|
+
{
|
311
|
+
int depth;
|
312
|
+
int len;
|
313
|
+
K nul = radix_substr(val.first, 0, 0);
|
314
|
+
radix_tree_node<K, T> *node_c, *node_cc;
|
315
|
+
|
316
|
+
depth = parent->m_depth + radix_length(parent->m_key);
|
317
|
+
len = radix_length(val.first) - depth;
|
318
|
+
|
319
|
+
if (len == 0) {
|
320
|
+
node_c = new radix_tree_node<K, T>(val);
|
321
|
+
|
322
|
+
node_c->m_depth = depth;
|
323
|
+
node_c->m_parent = parent;
|
324
|
+
node_c->m_key = nul;
|
325
|
+
node_c->m_is_leaf = true;
|
326
|
+
|
327
|
+
parent->m_children[nul] = node_c;
|
328
|
+
|
329
|
+
return node_c;
|
330
|
+
} else {
|
331
|
+
node_c = new radix_tree_node<K, T>(val);
|
332
|
+
|
333
|
+
K key_sub = radix_substr(val.first, depth, len);
|
334
|
+
|
335
|
+
parent->m_children[key_sub] = node_c;
|
336
|
+
|
337
|
+
node_c->m_depth = depth;
|
338
|
+
node_c->m_parent = parent;
|
339
|
+
node_c->m_key = key_sub;
|
340
|
+
|
341
|
+
|
342
|
+
node_cc = new radix_tree_node<K, T>(val);
|
343
|
+
node_c->m_children[nul] = node_cc;
|
344
|
+
|
345
|
+
node_cc->m_depth = depth + len;
|
346
|
+
node_cc->m_parent = node_c;
|
347
|
+
node_cc->m_key = nul;
|
348
|
+
node_cc->m_is_leaf = true;
|
349
|
+
|
350
|
+
return node_cc;
|
351
|
+
}
|
352
|
+
}
|
353
|
+
|
354
|
+
template <typename K, typename T>
|
355
|
+
radix_tree_node<K, T>* radix_tree<K, T>::prepend(radix_tree_node<K, T> *node, const value_type &val)
|
356
|
+
{
|
357
|
+
int count;
|
358
|
+
int len1, len2;
|
359
|
+
|
360
|
+
len1 = radix_length(node->m_key);
|
361
|
+
len2 = radix_length(val.first) - node->m_depth;
|
362
|
+
|
363
|
+
for (count = 0; count < len1 && count < len2; count++) {
|
364
|
+
if (! (node->m_key[count] == val.first[count + node->m_depth]) )
|
365
|
+
break;
|
366
|
+
}
|
367
|
+
|
368
|
+
assert(count != 0);
|
369
|
+
|
370
|
+
node->m_parent->m_children.erase(node->m_key);
|
371
|
+
|
372
|
+
radix_tree_node<K, T> *node_a = new radix_tree_node<K, T>;
|
373
|
+
|
374
|
+
node_a->m_parent = node->m_parent;
|
375
|
+
node_a->m_key = radix_substr(node->m_key, 0, count);
|
376
|
+
node_a->m_depth = node->m_depth;
|
377
|
+
node_a->m_parent->m_children[node_a->m_key] = node_a;
|
378
|
+
|
379
|
+
|
380
|
+
node->m_depth += count;
|
381
|
+
node->m_parent = node_a;
|
382
|
+
node->m_key = radix_substr(node->m_key, count, len1 - count);
|
383
|
+
node->m_parent->m_children[node->m_key] = node;
|
384
|
+
|
385
|
+
K nul = radix_substr(val.first, 0, 0);
|
386
|
+
if (count == len2) {
|
387
|
+
radix_tree_node<K, T> *node_b;
|
388
|
+
|
389
|
+
node_b = new radix_tree_node<K, T>(val);
|
390
|
+
|
391
|
+
node_b->m_parent = node_a;
|
392
|
+
node_b->m_key = nul;
|
393
|
+
node_b->m_depth = node_a->m_depth + count;
|
394
|
+
node_b->m_is_leaf = true;
|
395
|
+
node_b->m_parent->m_children[nul] = node_b;
|
396
|
+
|
397
|
+
return node_b;
|
398
|
+
} else {
|
399
|
+
radix_tree_node<K, T> *node_b, *node_c;
|
400
|
+
|
401
|
+
node_b = new radix_tree_node<K, T>;
|
402
|
+
|
403
|
+
node_b->m_parent = node_a;
|
404
|
+
node_b->m_depth = node->m_depth;
|
405
|
+
node_b->m_key = radix_substr(val.first, node_b->m_depth, len2 - count);
|
406
|
+
node_b->m_parent->m_children[node_b->m_key] = node_b;
|
407
|
+
|
408
|
+
node_c = new radix_tree_node<K, T>(val);
|
409
|
+
|
410
|
+
node_c->m_parent = node_b;
|
411
|
+
node_c->m_depth = radix_length(val.first);
|
412
|
+
node_c->m_key = nul;
|
413
|
+
node_c->m_is_leaf = true;
|
414
|
+
node_c->m_parent->m_children[nul] = node_c;
|
415
|
+
|
416
|
+
return node_c;
|
417
|
+
}
|
418
|
+
}
|
419
|
+
|
420
|
+
template <typename K, typename T>
|
421
|
+
std::pair<typename radix_tree<K, T>::iterator, bool> radix_tree<K, T>::insert(const value_type &val)
|
422
|
+
{
|
423
|
+
if (m_root == NULL) {
|
424
|
+
K nul = radix_substr(val.first, 0, 0);
|
425
|
+
|
426
|
+
m_root = new radix_tree_node<K, T>;
|
427
|
+
m_root->m_key = nul;
|
428
|
+
}
|
429
|
+
|
430
|
+
|
431
|
+
radix_tree_node<K, T> *node = find_node(val.first, m_root, 0);
|
432
|
+
|
433
|
+
if (node->m_is_leaf) {
|
434
|
+
return std::pair<iterator, bool>(node, false);
|
435
|
+
} else if (node == m_root) {
|
436
|
+
m_size++;
|
437
|
+
return std::pair<iterator, bool>(append(m_root, val), true);
|
438
|
+
} else {
|
439
|
+
m_size++;
|
440
|
+
int len = radix_length(node->m_key);
|
441
|
+
K key_sub = radix_substr(val.first, node->m_depth, len);
|
442
|
+
|
443
|
+
if (key_sub == node->m_key) {
|
444
|
+
return std::pair<iterator, bool>(append(node, val), true);
|
445
|
+
} else {
|
446
|
+
return std::pair<iterator, bool>(prepend(node, val), true);
|
447
|
+
}
|
448
|
+
}
|
449
|
+
}
|
450
|
+
|
451
|
+
template <typename K, typename T>
|
452
|
+
typename radix_tree<K, T>::iterator radix_tree<K, T>::find(const K &key)
|
453
|
+
{
|
454
|
+
if (m_root == NULL)
|
455
|
+
return iterator(NULL);
|
456
|
+
|
457
|
+
radix_tree_node<K, T> *node = find_node(key, m_root, 0);
|
458
|
+
|
459
|
+
// if the node is a internal node, return NULL
|
460
|
+
if (! node->m_is_leaf)
|
461
|
+
return iterator(NULL);
|
462
|
+
|
463
|
+
return iterator(node);
|
464
|
+
}
|
465
|
+
|
466
|
+
template <typename K, typename T>
|
467
|
+
radix_tree_node<K, T>* radix_tree<K, T>::find_node(const K &key, radix_tree_node<K, T> *node, int depth)
|
468
|
+
{
|
469
|
+
if (node->m_children.empty())
|
470
|
+
return node;
|
471
|
+
|
472
|
+
typename radix_tree_node<K, T>::it_child it;
|
473
|
+
int len_key = radix_length(key) - depth;
|
474
|
+
|
475
|
+
for (it = node->m_children.begin(); it != node->m_children.end(); ++it) {
|
476
|
+
if (len_key == 0) {
|
477
|
+
if (it->second->m_is_leaf)
|
478
|
+
return it->second;
|
479
|
+
else
|
480
|
+
continue;
|
481
|
+
}
|
482
|
+
|
483
|
+
if (! it->second->m_is_leaf && key[depth] == it->first[0] ) {
|
484
|
+
int len_node = radix_length(it->first);
|
485
|
+
K key_sub = radix_substr(key, depth, len_node);
|
486
|
+
|
487
|
+
if (key_sub == it->first) {
|
488
|
+
return find_node(key, it->second, depth+len_node);
|
489
|
+
} else {
|
490
|
+
return it->second;
|
491
|
+
}
|
492
|
+
}
|
493
|
+
}
|
494
|
+
|
495
|
+
return node;
|
496
|
+
}
|
497
|
+
|
498
|
+
/*
|
499
|
+
|
500
|
+
(root)
|
501
|
+
|
|
502
|
+
|---------------
|
503
|
+
| | |
|
504
|
+
abcde bcdef c
|
505
|
+
| | | |------
|
506
|
+
| | $3 | | |
|
507
|
+
f ge d e $6
|
508
|
+
| | | |
|
509
|
+
$1 $2 $4 $5
|
510
|
+
|
511
|
+
find_node():
|
512
|
+
bcdef -> $3
|
513
|
+
bcdefa -> bcdef
|
514
|
+
c -> $6
|
515
|
+
cf -> c
|
516
|
+
abch -> abcde
|
517
|
+
abc -> abcde
|
518
|
+
abcde -> abcde
|
519
|
+
abcdef -> $1
|
520
|
+
abcdeh -> abcde
|
521
|
+
de -> (root)
|
522
|
+
|
523
|
+
|
524
|
+
(root)
|
525
|
+
|
|
526
|
+
abcd
|
527
|
+
|
|
528
|
+
$
|
529
|
+
|
530
|
+
(root)
|
531
|
+
|
|
532
|
+
$
|
533
|
+
|
534
|
+
*/
|
535
|
+
|
536
|
+
#endif // RADIX_TREE_HPP
|