ffi-radix_tree 0.2.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c2547ed89d9cbedb9bd340a86785aa16f0becd3c
4
- data.tar.gz: 737b4483c593146c8c9fef84330f9ed5eac149ee
2
+ SHA256:
3
+ metadata.gz: 63946ad680524b97f53dd06a3bb4514ce3ab4b12a2f2d5a23fef32e36941bfba
4
+ data.tar.gz: 4235440c2f4f348c3d9f9e496ba5dbf1b0c5c4645b674cd04086ce60f57da650
5
5
  SHA512:
6
- metadata.gz: 79474879d50035f089b2a04b60db2dee547e9aabf4aeffa43c33b430156bac7004e55da050e35bb71cda97eede7bcda077c9ca4a53dbc66809d040a06c04d277
7
- data.tar.gz: becb72bae362661101c75aed79d53c42f9d698c19116593b0180971026ba8e59eebcb712d8c65ea7e4e5ffbd71a9de6ef6dcf46b2a22141cc2e64288fdafddb9
6
+ metadata.gz: 7ac02fdf65f154c8c3746a565b2b6d3afe738643b9227f82313ddc7bc12cfce6f2f617ac535a876fa2b6da60588fe8564b9d24d86212f71f568fcf2d08ce9ff3
7
+ data.tar.gz: ee16b0514b5a1efef08d3a95c7646e78e9ab44d2f110a3b928aa5335964f63a86b1fb064847c9ba9ac417c4c951bc72259e8039a07556b8c0739806affe9bd37
data/README.md CHANGED
@@ -22,7 +22,41 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ ```ruby
26
+ # create a new tree
27
+ rtree = ::FFI::RadixTree::Tree.new
28
+
29
+ # add key/value pairs to the tree
30
+ rtree.push("key1", "value1")
31
+ rtree.push("key2", ["value2", "value3"])
32
+ rtree.push("key3", { :attr1 => "value4", :attr2 => "value5" })
33
+
34
+ # work with the collection
35
+ if rtree.has_key?("key1")
36
+ val = rtree.get("key2")
37
+ rtree.set("key3", "value6")
38
+ end
39
+
40
+ # search the tree using the keys
41
+
42
+ # keys based off the root word: "manage"
43
+ rtree.push("manage", "base verb")
44
+ rtree.push("managed", "past tense")
45
+ rtree.push("manager", "noun")
46
+ rtree.push("managers", "plural noun")
47
+ rtree.push("managing", "present tense")
48
+
49
+ # Find the key that matches the _most_ of the beggining of the search term
50
+ rtree.longest_prefix("managerial") # returns "manager"
51
+ rtree.longest_prefix_and_value("managerial") # returns ["manager", "noun"]
52
+ rtree.longest_prefix_value("managerial") # returns "noun"
53
+
54
+ # Find all values whose keys match the _most_ of the beginning of the search term
55
+ rtree.greedy_match("managerial") # returns ["noun", "plural noun"]
56
+
57
+ # Find all values whose keys are included _anywhere_ in the search term
58
+ rtree.greedy_substring_match("I managed to jump") # returns ["base verb", "past tense"]
59
+ ```
26
60
 
27
61
  ## Development
28
62
 
data/Rakefile CHANGED
@@ -7,6 +7,67 @@ namespace :radixtree do
7
7
  task :compile do
8
8
  Rake::Task[:compile_radixtree].invoke
9
9
  end
10
+
11
+ desc "run benchmarks for radixtree lib"
12
+ task :benchmark do
13
+ require "benchmark/ips"
14
+ require "./lib/ffi/radix_tree"
15
+
16
+ radix_tree = ::FFI::RadixTree::Tree.new
17
+
18
+ (1..1000).each do |number|
19
+ radix_tree.push(number.to_s, "DERP#{number}" * (number % 10))
20
+ radix_tree.push(number.to_s * 100, "DERP#{number}" * (number % 10))
21
+ radix_tree.push(number.to_s * 1000, "DERP#{number}" * (number % 10))
22
+ end
23
+
24
+ ::Benchmark.ips do |x|
25
+ x.config(:warmup => 10)
26
+
27
+ x.report("get") do
28
+ radix_tree.get(rand(1000).to_s * [1, 100, 100].sample)
29
+ end
30
+
31
+ x.report("longest prefix") do
32
+ radix_tree.longest_prefix(rand(1000).to_s * [1, 100, 100].sample)
33
+ end
34
+
35
+ x.report("get then value") do
36
+ val = rand(1000).to_s * [1, 100, 100].sample
37
+
38
+ radix_tree.longest_prefix(val)
39
+ radix_tree.longest_prefix_value(val)
40
+ end
41
+
42
+ x.report("prefix and value (combined)") do
43
+ radix_tree.longest_prefix_and_value(rand(1000).to_s * [1, 100, 100].sample)
44
+ end
45
+
46
+ x.report("longest prefix (miss)") do
47
+ radix_tree.longest_prefix("DERP DERPIE")
48
+ end
49
+
50
+ x.report("prefix and value (combined/miss)") do
51
+ radix_tree.longest_prefix_and_value("DERP DERPIE")
52
+ end
53
+
54
+ x.report("greedy match") do
55
+ radix_tree.greedy_match(rand(1000).to_s * [1, 100, 100].sample)
56
+ end
57
+
58
+ x.report("greedy match (miss)") do
59
+ radix_tree.greedy_match("DERP DERPIE")
60
+ end
61
+
62
+ x.report("greedy substring match") do
63
+ radix_tree.greedy_substring_match(rand(1000).to_s * [1, 100, 100].sample)
64
+ end
65
+
66
+ x.report("greedy substring match (miss)") do
67
+ radix_tree.greedy_substring_match("DERP DERPIE")
68
+ end
69
+ end
70
+ end
10
71
  end
11
72
 
12
73
  Rake::TestTask.new(:spec) do |t|
@@ -34,7 +34,8 @@ Gem::Specification.new do |spec|
34
34
  spec.add_dependency "msgpack"
35
35
  spec.add_dependency "ffi"
36
36
 
37
- spec.add_development_dependency "bundler", "~> 1.15"
37
+ spec.add_development_dependency "benchmark-ips"
38
+ spec.add_development_dependency "bundler"
38
39
  spec.add_development_dependency "rake", "~> 10.0"
39
40
  spec.add_development_dependency "mocha"
40
41
  spec.add_development_dependency "pry"
@@ -1,5 +1,5 @@
1
1
  module FFI
2
2
  module RadixTree
3
- VERSION = "0.2.0"
3
+ VERSION = "0.6.0"
4
4
  end
5
5
  end
@@ -77,30 +77,29 @@ module FFI
77
77
  attach_function :erase, [:pointer, :string], :void
78
78
  attach_function :fetch, [:pointer, :string, :pointer], :pointer
79
79
  attach_function :insert, [:pointer, :string, :pointer, :size_t], :void
80
+ attach_function :update, [:pointer, :string, :pointer, :size_t], :bool
80
81
  attach_function :longest_prefix, [:pointer, :string], :string
82
+ attach_function :longest_prefix_and_value, [:pointer, :string, :pointer, :pointer], :pointer
81
83
  attach_function :longest_prefix_value, [:pointer, :string, :pointer], :pointer
84
+ attach_function :greedy_match, [:pointer, :string, :pointer, :pointer], :int
85
+ attach_function :greedy_substring_match, [:pointer, :string, :pointer, :pointer], :int
82
86
  attach_function :match_free, [:pointer], :void
87
+ attach_function :match_sizes_free, [:pointer], :void
88
+ attach_function :multi_match_free, [:pointer, :int], :void
83
89
  attach_function :has_key, [:pointer, :string], :bool
84
90
 
85
91
  class Tree
86
- def self.destroy!(tree)
87
- tree.destroy! unless tree.nil?
88
- end
89
-
90
92
  def initialize
91
- @ptr = ::FFI::RadixTree.create
93
+ @ptr = ::FFI::AutoPointer.new(::FFI::RadixTree.create, ::FFI::RadixTree.method(:destroy))
92
94
  @first_character_present = {}
93
95
  end
94
96
 
95
- def destroy!
96
- ::FFI::RadixTree.destroy(@ptr) unless @ptr.nil?
97
- @ptr = nil
98
- end
99
-
100
97
  def has_key?(key)
101
98
  ::FFI::RadixTree.has_key(@ptr, key)
102
99
  end
103
100
 
101
+ alias_method :key?, :has_key?
102
+
104
103
  def push(key, value)
105
104
  push_response = nil
106
105
  @first_character_present[key[0]] = true
@@ -115,6 +114,25 @@ module FFI
115
114
  push_response
116
115
  end
117
116
 
117
+ def push_or_update(key, value)
118
+ response = nil
119
+ @first_character_present[key[0]] = true
120
+ storage_data = ::MessagePack.pack(value)
121
+ bytesize = storage_data.bytesize
122
+
123
+ ::FFI::MemoryPointer.new(:char, bytesize, true) do |memory_buffer|
124
+ memory_buffer.put_bytes(0, storage_data)
125
+ response = ::FFI::RadixTree.update(@ptr, key, memory_buffer, bytesize)
126
+ response ||= ::FFI::RadixTree.insert(@ptr, key, memory_buffer, bytesize)
127
+ end
128
+
129
+ response
130
+ end
131
+
132
+ def erase(key)
133
+ ::FFI::RadixTree.erase(@ptr, key)
134
+ end
135
+
118
136
  def get(key)
119
137
  return nil unless @first_character_present[key[0]]
120
138
  byte_pointer = get_response = nil
@@ -122,7 +140,11 @@ module FFI
122
140
  ::FFI::MemoryPointer.new(:int) do |byte_length|
123
141
  byte_pointer = ::FFI::RadixTree.fetch(@ptr, key, byte_length)
124
142
  bytesize = byte_length.read_int
125
- get_response = ::MessagePack.unpack(byte_pointer.get_bytes(0, bytesize)) if bytesize && bytesize > 0
143
+
144
+ if bytesize && bytesize > 0
145
+ bytes = byte_pointer.get_bytes(0, bytesize)
146
+ get_response = ::MessagePack.unpack(bytes)
147
+ end
126
148
  end
127
149
 
128
150
  get_response
@@ -139,6 +161,29 @@ module FFI
139
161
  ::FFI::RadixTree.match_free(p_out) if p_out
140
162
  end
141
163
 
164
+ def longest_prefix_and_value(string)
165
+ return [nil, nil] unless @first_character_present[string[0]]
166
+ byte_pointer = prefix_response = get_response = nil
167
+
168
+ ::FFI::MemoryPointer.new(:int) do |byte_length|
169
+ ::FFI::MemoryPointer.new(:int) do |prefix_length|
170
+ byte_pointer = ::FFI::RadixTree.longest_prefix_and_value(@ptr, string, byte_length, prefix_length)
171
+ bytesize = byte_length.read_int
172
+
173
+ if bytesize && bytesize > 0
174
+ prefix_size = prefix_length.read_int
175
+ get_response = byte_pointer.get_bytes(0, bytesize)
176
+ prefix_response = get_response[0..(prefix_size - 1)]
177
+ get_response = ::MessagePack.unpack(get_response[prefix_size..-1])
178
+ end
179
+ end
180
+ end
181
+
182
+ [prefix_response, get_response]
183
+ ensure
184
+ ::FFI::RadixTree.match_free(byte_pointer) if byte_pointer
185
+ end
186
+
142
187
  def longest_prefix_value(string)
143
188
  return nil unless @first_character_present[string[0]]
144
189
  byte_pointer = get_response = nil
@@ -153,6 +198,61 @@ module FFI
153
198
  ensure
154
199
  ::FFI::RadixTree.match_free(byte_pointer) if byte_pointer
155
200
  end
201
+
202
+ def greedy_match(string)
203
+ return [] unless @first_character_present[string[0]]
204
+ array_pointer = nil
205
+ match_sizes_pointer = nil
206
+ array_size = 0
207
+ get_response = []
208
+
209
+ ::FFI::MemoryPointer.new(:pointer) do |match_array|
210
+ ::FFI::MemoryPointer.new(:pointer) do |match_sizes_array|
211
+ array_size = ::FFI::RadixTree.greedy_match(@ptr, string, match_array, match_sizes_array)
212
+ if array_size > 0
213
+ match_sizes_pointer = match_sizes_array.read_pointer
214
+ match_sizes = match_sizes_pointer.get_array_of_int(0, array_size)
215
+ array_pointer = match_array.read_pointer
216
+ char_arrays = array_pointer.get_array_of_pointer(0, array_size)
217
+ char_arrays.each_with_index do |ptr, index|
218
+ get_response << ::MessagePack.unpack(ptr.get_bytes(0, match_sizes[index]))
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ get_response
225
+ ensure
226
+ ::FFI::RadixTree.multi_match_free(array_pointer, array_size) if array_pointer
227
+ ::FFI::RadixTree.match_sizes_free(match_sizes_pointer) if match_sizes_pointer
228
+ end
229
+
230
+ def greedy_substring_match(string)
231
+ array_pointer = nil
232
+ match_sizes_pointer = nil
233
+ array_size = 0
234
+ get_response = []
235
+
236
+ ::FFI::MemoryPointer.new(:pointer) do |match_array|
237
+ ::FFI::MemoryPointer.new(:pointer) do |match_sizes_array|
238
+ array_size = ::FFI::RadixTree.greedy_substring_match(@ptr, string, match_array, match_sizes_array)
239
+ if array_size > 0
240
+ match_sizes_pointer = match_sizes_array.read_pointer
241
+ match_sizes = match_sizes_pointer.get_array_of_int(0, array_size)
242
+ array_pointer = match_array.read_pointer
243
+ char_arrays = array_pointer.get_array_of_pointer(0, array_size)
244
+ char_arrays.each_with_index do |ptr, index|
245
+ get_response << ::MessagePack.unpack(ptr.get_bytes(0, match_sizes[index]))
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ get_response
252
+ ensure
253
+ ::FFI::RadixTree.multi_match_free(array_pointer, array_size) if array_pointer
254
+ ::FFI::RadixTree.match_sizes_free(match_sizes_pointer) if match_sizes_pointer
255
+ end
156
256
  end
157
257
  end
158
258
  end
@@ -32,9 +32,19 @@ bool has_key(radix_tree<std::string, std::vector<char>>* map_pointer, const char
32
32
  }
33
33
 
34
34
  void match_free(const char* match) {
35
+ delete[] match;
36
+ }
37
+
38
+ void match_sizes_free(const int* match_sizes) {
39
+ delete[] match_sizes;
40
+ }
41
+
42
+ void multi_match_free(const char** match, int length) {
35
43
  if (match != NULL) {
44
+ for (int i=0; i<length; ++i) {
45
+ delete[] match[i];
46
+ }
36
47
  delete[] match;
37
- match = NULL;
38
48
  }
39
49
  }
40
50
 
@@ -44,7 +54,6 @@ const char* longest_prefix(radix_tree<std::string, std::vector<char>>* map_point
44
54
 
45
55
  if (iter != map_pointer->end()) {
46
56
  char *val = new char[iter->first.size() + 1]{0};
47
- val[iter->first.size()] = '\0';
48
57
  memcpy(val, iter->first.c_str(), iter->first.size());
49
58
 
50
59
  return val;
@@ -53,6 +62,33 @@ const char* longest_prefix(radix_tree<std::string, std::vector<char>>* map_point
53
62
  return NULL;
54
63
  }
55
64
 
65
+ const char* longest_prefix_and_value(radix_tree<std::string, std::vector<char>>* map_pointer, const char* key, int* read_size, int* prefix_size) {
66
+ std::string string_key(key);
67
+ auto iter = map_pointer->longest_match(string_key);
68
+
69
+ if (iter != map_pointer->end()) {
70
+ long counter = 0;
71
+ int size_of_response = iter->second.size() + iter->first.size();
72
+ char *return_val = new char[size_of_response]{0};
73
+
74
+ strncpy(return_val, iter->first.c_str(), iter->first.size());
75
+ counter = iter->first.size();
76
+
77
+ for( auto& val3 : iter->second) {
78
+ return_val[counter] = val3;
79
+ counter++;
80
+ }
81
+
82
+ *prefix_size = iter->first.size();
83
+ *read_size = size_of_response;
84
+ return return_val;
85
+ }
86
+
87
+ *prefix_size = 0;
88
+ *read_size = 0;
89
+ return NULL;
90
+ }
91
+
56
92
  const char* longest_prefix_value(radix_tree<std::string, std::vector<char>>* map_pointer, const char* key, int* read_size) {
57
93
  std::string string_key(key);
58
94
  auto iter = map_pointer->longest_match(string_key);
@@ -73,7 +109,7 @@ const char* longest_prefix_value(radix_tree<std::string, std::vector<char>>* map
73
109
  return NULL;
74
110
  }
75
111
 
76
- const char* fetch(radix_tree<std::string, std::vector<char>>* map_pointer, const char* key, int* read_size) {
112
+ char* fetch(radix_tree<std::string, std::vector<char>>* map_pointer, const char* key, int* read_size) {
77
113
  auto iter = map_pointer->find(std::string(key));
78
114
  long counter = 0;
79
115
 
@@ -92,10 +128,64 @@ const char* fetch(radix_tree<std::string, std::vector<char>>* map_pointer, const
92
128
  return NULL;
93
129
  }
94
130
 
131
+ int greedy_match(radix_tree<std::string, std::vector<char>>* map_pointer, const char* key, const char*** matches, int** match_sizes) {
132
+ std::string string_key(key);
133
+ typedef radix_tree<std::string, std::vector<char>>::iterator iterator;
134
+ std::vector<iterator> vec;
135
+ map_pointer->greedy_match(string_key, vec);
136
+ long counter = 0;
137
+
138
+ if (vec.size() > 0) {
139
+ *matches = new const char* [vec.size()]{nullptr};
140
+ *match_sizes = new int [vec.size()]{0};
141
+ for (auto& iter : vec) {
142
+ auto ret_str = new char[iter->second.size()];
143
+ long char_index = 0;
144
+ for (auto& val : iter->second) {
145
+ ret_str[char_index] = val;
146
+ ++char_index;
147
+ }
148
+ (*matches)[counter] = ret_str;
149
+ (*match_sizes)[counter] = iter->second.size();
150
+ ++counter;
151
+ }
152
+ }
153
+ return counter;
154
+ }
155
+
156
+ int greedy_substring_match(radix_tree<std::string, std::vector<char>>* map_pointer, const char* key, const char*** matches, int** match_sizes) {
157
+ std::string string_key(key);
158
+ typedef radix_tree<std::string, std::vector<char>>::iterator iterator;
159
+ std::vector<iterator> vec;
160
+ map_pointer->greedy_substring_match(string_key, vec);
161
+ long counter = 0;
162
+
163
+ if (vec.size() > 0) {
164
+ *matches = new const char* [vec.size()]{nullptr};
165
+ *match_sizes = new int [vec.size()]{0};
166
+ for (auto& iter : vec) {
167
+ auto ret_str = new char[iter->second.size()];
168
+ long char_index = 0;
169
+ for (auto& val : iter->second) {
170
+ ret_str[char_index] = val;
171
+ ++char_index;
172
+ }
173
+ (*matches)[counter] = ret_str;
174
+ (*match_sizes)[counter] = iter->second.size();
175
+ ++counter;
176
+ }
177
+ }
178
+ return counter;
179
+ }
180
+
95
181
  void insert(radix_tree<std::string, std::vector<char>>* map_pointer, const char* key, char* value, size_t size) {
96
182
  map_pointer->insert({std::string(key), std::vector<char>(value, value + size)});
97
183
  }
98
184
 
185
+ bool update(radix_tree<std::string, std::vector<char>>* map_pointer, const char* key, char* value, size_t size) {
186
+ return map_pointer->update({std::string(key), std::vector<char>(value, value + size)});
187
+ }
188
+
99
189
  void destroy(radix_tree<std::string, std::vector<char>>* map_pointer) {
100
190
  delete map_pointer;
101
191
  map_pointer = NULL;
@@ -67,10 +67,12 @@ public:
67
67
  iterator end();
68
68
 
69
69
  std::pair<iterator, bool> insert(const value_type &val);
70
+ bool update(const value_type &val);
70
71
  bool erase(const K &key);
71
72
  void erase(iterator it);
72
73
  void prefix_match(const K &key, std::vector<iterator> &vec);
73
74
  void greedy_match(const K &key, std::vector<iterator> &vec);
75
+ void greedy_substring_match(const K &key, std::vector<iterator> &vec);
74
76
  iterator longest_match(const K &key);
75
77
 
76
78
  T& operator[] (const K &lhs);
@@ -81,9 +83,11 @@ private:
81
83
 
82
84
  radix_tree_node<K, T>* begin(radix_tree_node<K, T> *node);
83
85
  radix_tree_node<K, T>* find_node(const K &key, radix_tree_node<K, T> *node, int depth);
86
+ std::vector<radix_tree_node<K, T>*> find_leaf_nodes_with_substr(const K &key, radix_tree_node<K, T> *node, const K &ancestor_key);
84
87
  radix_tree_node<K, T>* append(radix_tree_node<K, T> *parent, const value_type &val);
85
88
  radix_tree_node<K, T>* prepend(radix_tree_node<K, T> *node, const value_type &val);
86
89
  void greedy_match(radix_tree_node<K, T> *node, std::vector<iterator> &vec);
90
+ void greedy_substring_match(radix_tree_node<K, T> *node, std::vector<iterator> &vec);
87
91
 
88
92
  radix_tree(const radix_tree& other); // delete
89
93
  radix_tree& operator =(const radix_tree other); // delete
@@ -232,6 +236,23 @@ void radix_tree<K, T>::greedy_match(radix_tree_node<K, T> *node, std::vector<ite
232
236
  }
233
237
  }
234
238
 
239
+ template <typename K, typename T>
240
+ void radix_tree<K, T>::greedy_substring_match(const K &key, std::vector<iterator> &vec)
241
+ {
242
+ std::vector<radix_tree_node<K, T>*> nodes;
243
+
244
+ vec.clear();
245
+
246
+ if (m_root == NULL)
247
+ return;
248
+
249
+ nodes = find_leaf_nodes_with_substr(key, m_root, "");
250
+
251
+ for (auto& node : nodes) {
252
+ vec.push_back(node);
253
+ }
254
+ }
255
+
235
256
  template <typename K, typename T>
236
257
  void radix_tree<K, T>::erase(iterator it)
237
258
  {
@@ -448,6 +469,22 @@ std::pair<typename radix_tree<K, T>::iterator, bool> radix_tree<K, T>::insert(co
448
469
  }
449
470
  }
450
471
 
472
+ template <typename K, typename T>
473
+ bool radix_tree<K, T>::update(const value_type &val)
474
+ {
475
+ if (m_root == NULL)
476
+ return false;
477
+
478
+ radix_tree_node<K, T> *node = find_node(val.first, m_root, 0);
479
+
480
+ // if the node is a internal node, return false
481
+ if (! node->m_is_leaf)
482
+ return false;
483
+
484
+ node->m_value = new value_type(val);
485
+ return true;
486
+ }
487
+
451
488
  template <typename K, typename T>
452
489
  typename radix_tree<K, T>::iterator radix_tree<K, T>::find(const K &key)
453
490
  {
@@ -495,6 +532,30 @@ radix_tree_node<K, T>* radix_tree<K, T>::find_node(const K &key, radix_tree_node
495
532
  return node;
496
533
  }
497
534
 
535
+ template <typename K, typename T>
536
+ std::vector<radix_tree_node<K, T>*> radix_tree<K, T>::find_leaf_nodes_with_substr(const K &key, radix_tree_node<K, T> *node, const K &ancestor_key)
537
+ {
538
+ std::vector<radix_tree_node<K, T>*> nodes;
539
+
540
+ if (node->m_children.empty())
541
+ return nodes;
542
+
543
+ typename radix_tree_node<K, T>::it_child it;
544
+ for (it = node->m_children.begin(); it != node->m_children.end(); ++it) {
545
+ if (it->second->m_is_leaf) {
546
+ nodes.push_back(it->second);
547
+ } else {
548
+ auto child_key = ancestor_key + it->first;
549
+ if (key.find(child_key) != std::string::npos ) {
550
+ auto found_nodes = find_leaf_nodes_with_substr(key, it->second, child_key);
551
+ nodes.insert(nodes.end(), found_nodes.begin(), found_nodes.end());
552
+ }
553
+ }
554
+ }
555
+
556
+ return nodes;
557
+ }
558
+
498
559
  /*
499
560
 
500
561
  (root)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-radix_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Dewitt
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-23 00:00:00.000000000 Z
11
+ date: 2021-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -38,20 +38,34 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: benchmark-ips
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - "~>"
59
+ - - ">="
46
60
  - !ruby/object:Gem::Version
47
- version: '1.15'
61
+ version: '0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - "~>"
66
+ - - ">="
53
67
  - !ruby/object:Gem::Version
54
- version: '1.15'
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -138,7 +152,7 @@ licenses:
138
152
  - MIT
139
153
  metadata:
140
154
  allowed_push_host: https://rubygems.org
141
- post_install_message:
155
+ post_install_message:
142
156
  rdoc_options: []
143
157
  require_paths:
144
158
  - lib
@@ -153,9 +167,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
167
  - !ruby/object:Gem::Version
154
168
  version: '0'
155
169
  requirements: []
156
- rubyforge_project:
157
- rubygems_version: 2.6.13
158
- signing_key:
170
+ rubygems_version: 3.0.3
171
+ signing_key:
159
172
  specification_version: 4
160
173
  summary: radix tree implementation in c++ with FFI bindings
161
174
  test_files: []