tyler-trie 0.1.3 → 0.2.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.
Files changed (4) hide show
  1. data/VERSION.yml +2 -2
  2. data/ext/trie/trie.c +111 -2
  3. data/spec/trie_spec.rb +115 -0
  4. metadata +2 -2
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- patch: 3
2
+ patch: 0
3
3
  major: 0
4
- minor: 1
4
+ minor: 2
data/ext/trie/trie.c CHANGED
@@ -4,6 +4,8 @@
4
4
  #include <stdio.h>
5
5
  #include <string.h>
6
6
 
7
+ VALUE cTrie, cTrieNode;
8
+
7
9
  static TrieChar* stringToTrieChar(VALUE string) {
8
10
  return (TrieChar*) RSTRING(string)->ptr;
9
11
  }
@@ -206,15 +208,111 @@ static VALUE trie_walk_to_terminal(VALUE self, VALUE args) {
206
208
  iterator++;
207
209
  }
208
210
 
211
+ sb_trie_state_free(state);
212
+
209
213
  return Qnil;
210
214
  }
211
215
 
212
216
  static VALUE trie_get_path(VALUE self) {
213
217
  return rb_iv_get(self, "@path");
214
218
  }
215
-
216
- VALUE cTrie;
217
219
 
220
+ static void trie_node_free(SBTrieState *state) {
221
+ if(state)
222
+ sb_trie_state_free(state);
223
+ }
224
+
225
+ static VALUE trie_node_alloc(VALUE klass) {
226
+ SBTrieState *state;
227
+ VALUE obj;
228
+
229
+ obj = Data_Wrap_Struct(klass, 0, trie_node_free, state);
230
+
231
+ return obj;
232
+ }
233
+
234
+ static VALUE trie_root(VALUE self) {
235
+ SBTrie *sb_trie;
236
+ Data_Get_Struct(self, SBTrie, sb_trie);
237
+
238
+ VALUE trie_node = trie_node_alloc(cTrieNode);
239
+
240
+ // replace the pretend SBTrieState created in TrieNode's alloc with a real one
241
+ RDATA(trie_node)->data = sb_trie_root(sb_trie);
242
+
243
+ rb_iv_set(trie_node, "@state", Qnil);
244
+ rb_iv_set(trie_node, "@full_state", rb_str_new2(""));
245
+ return trie_node;
246
+ }
247
+
248
+ static VALUE trie_node_get_state(VALUE self) {
249
+ return rb_iv_get(self, "@state");
250
+ }
251
+ static VALUE trie_node_get_full_state(VALUE self) {
252
+ return rb_iv_get(self, "@full_state");
253
+ }
254
+
255
+ static VALUE trie_node_walk_bang(VALUE self, VALUE rchar) {
256
+ SBTrieState *state;
257
+ Data_Get_Struct(self, SBTrieState, state);
258
+
259
+ if(RSTRING(rchar)->len != 1)
260
+ return Qnil;
261
+
262
+ char ch = RSTRING(rchar)->ptr[0];
263
+ int result = sb_trie_state_walk(state, (TrieChar)ch);
264
+
265
+ if(result) {
266
+ rb_iv_set(self, "@state", rchar);
267
+ VALUE full_state = rb_iv_get(self, "@full_state");
268
+ rb_str_append(full_state, rchar);
269
+ rb_iv_set(self, "@full_state", full_state);
270
+ return self;
271
+ } else
272
+ return Qnil;
273
+ }
274
+
275
+ static VALUE trie_node_value(VALUE self) {
276
+ SBTrieState *state, *dup;
277
+ Data_Get_Struct(self, SBTrieState, state);
278
+
279
+ dup = sb_trie_state_clone(state);
280
+
281
+ sb_trie_state_walk(dup, (TrieChar)'\0');
282
+ TrieData trie_data = sb_trie_state_get_data(dup);
283
+ sb_trie_state_free(dup);
284
+
285
+ return TRIE_DATA_ERROR == trie_data ? Qnil : INT2FIX(trie_data);
286
+ }
287
+
288
+ static VALUE trie_node_terminal(VALUE self) {
289
+ SBTrieState *state;
290
+ Data_Get_Struct(self, SBTrieState, state);
291
+
292
+ return sb_trie_state_is_terminal(state) ? Qtrue : Qnil;
293
+ }
294
+
295
+ static VALUE trie_node_leaf(VALUE self) {
296
+ SBTrieState *state;
297
+ Data_Get_Struct(self, SBTrieState, state);
298
+
299
+ return sb_trie_state_is_leaf(state) ? Qtrue : Qnil;
300
+ }
301
+
302
+ static VALUE trie_node_clone(VALUE self) {
303
+ SBTrieState *state;
304
+ Data_Get_Struct(self, SBTrieState, state);
305
+
306
+ VALUE new_node = trie_node_alloc(cTrieNode);
307
+ RDATA(new_node)->data = sb_trie_state_clone(state);
308
+
309
+ rb_iv_set(new_node, "@state", rb_iv_get(self, "@state"));
310
+ rb_iv_set(new_node, "@full_state", rb_iv_get(self, "@full_state"));
311
+
312
+ return new_node;
313
+ }
314
+
315
+
218
316
  void Init_trie() {
219
317
  cTrie = rb_define_class("Trie", rb_cObject);
220
318
  rb_define_alloc_func(cTrie, trie_alloc);
@@ -227,4 +325,15 @@ void Init_trie() {
227
325
  rb_define_method(cTrie, "close", trie_close, 0);
228
326
  rb_define_method(cTrie, "children", trie_children, 1);
229
327
  rb_define_method(cTrie, "walk_to_terminal", trie_walk_to_terminal, -2);
328
+ rb_define_method(cTrie, "root", trie_root, 0);
329
+
330
+ cTrieNode = rb_define_class("TrieNode", rb_cObject);
331
+ rb_define_alloc_func(cTrieNode, trie_node_alloc);
332
+ rb_define_method(cTrieNode, "state", trie_node_get_state, 0);
333
+ rb_define_method(cTrieNode, "full_state", trie_node_get_full_state, 0);
334
+ rb_define_method(cTrieNode, "walk!", trie_node_walk_bang, 1);
335
+ rb_define_method(cTrieNode, "value", trie_node_value, 0);
336
+ rb_define_method(cTrieNode, "terminal?", trie_node_terminal, 0);
337
+ rb_define_method(cTrieNode, "leaf?", trie_node_leaf, 0);
338
+ rb_define_method(cTrieNode, "clone", trie_node_clone, 0);
230
339
  }
data/spec/trie_spec.rb CHANGED
@@ -99,4 +99,119 @@ describe Trie do
99
99
  @trie.walk_to_terminal('anderson',true).should == ['and', 15]
100
100
  end
101
101
  end
102
+
103
+ describe :root do
104
+ it 'returns a TrieNode' do
105
+ @trie.root.should be_an_instance_of(TrieNode)
106
+ end
107
+
108
+ it 'returns a different TrieNode each time' do
109
+ @trie.root.should_not == @trie.root
110
+ end
111
+ end
112
+ end
113
+
114
+ describe TrieNode do
115
+ before :each do
116
+ @trie = Trie.new(TRIE_PATH);
117
+ @trie.add('rocket',1)
118
+ @trie.add('rock',2)
119
+ @trie.add('frederico',3)
120
+ @node = @trie.root
121
+ end
122
+
123
+ after :each do
124
+ @trie.close
125
+ File.delete('spec/test-trie/trie.br')
126
+ File.delete('spec/test-trie/trie.tl')
127
+ File.delete('spec/test-trie/trie.sbm')
128
+ end
129
+
130
+ describe :state do
131
+ it 'returns the most recent state character' do
132
+ @node.walk!('r')
133
+ @node.state.should == 'r'
134
+ @node.walk!('o')
135
+ @node.state.should == 'o'
136
+ end
137
+
138
+ it 'is nil when no walk has occurred' do
139
+ @node.state.should == nil
140
+ end
141
+ end
142
+
143
+ describe :full_state do
144
+ it 'returns the current string' do
145
+ @node.walk!('r').walk!('o').walk!('c')
146
+ @node.full_state.should == 'roc'
147
+ end
148
+
149
+ it 'is a blank string when no walk has occurred' do
150
+ @node.full_state.should == ''
151
+ end
152
+ end
153
+
154
+ describe :walk! do
155
+ it 'returns the updated object when the walk succeeds' do
156
+ other = @node.walk!('r')
157
+ other.should == @node
158
+ end
159
+
160
+ it 'returns nil when the walk fails' do
161
+ @node.walk!('q').should be_nil
162
+ end
163
+ end
164
+
165
+ describe :value do
166
+ it 'returns nil when the node is not terminal' do
167
+ @node.walk!('r')
168
+ @node.value.should be_nil
169
+ end
170
+
171
+ it 'returns a value when the node is terminal' do
172
+ @node.walk!('r').walk!('o').walk!('c').walk!('k')
173
+ @node.value.should == 2
174
+ end
175
+ end
176
+
177
+ describe :terminal? do
178
+ it 'returns true when the node is a word end' do
179
+ @node.walk!('r').walk!('o').walk!('c').walk!('k')
180
+ @node.should be_terminal
181
+ end
182
+
183
+ it 'returns nil when the node is not a word end' do
184
+ @node.walk!('r').walk!('o').walk!('c')
185
+ @node.should_not be_terminal
186
+ end
187
+ end
188
+
189
+ describe :leaf? do
190
+ it 'returns true when this is the end of a branch of the trie' do
191
+ @node.walk!('r').walk!('o').walk!('c').walk!('k').walk!('e').walk!('t')
192
+ @node.should be_leaf
193
+ end
194
+
195
+ it 'returns nil when there are more splits on this branch' do
196
+ @node.walk!('r').walk!('o').walk!('c').walk!('k')
197
+ @node.should_not be_leaf
198
+ end
199
+ end
200
+
201
+ describe :clone do
202
+ it 'creates a new instance of this node which is not this node' do
203
+ new_node = @node.clone
204
+ new_node.should_not == @node
205
+ end
206
+
207
+ it 'matches the state of the current node' do
208
+ new_node = @node.clone
209
+ new_node.state.should == @node.state
210
+ end
211
+
212
+ it 'matches the full_state of the current node' do
213
+ new_node = @node.clone
214
+ new_node.full_state.should == @node.full_state
215
+ end
216
+ end
102
217
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tyler-trie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler McMullen
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-09 00:00:00 -07:00
12
+ date: 2009-03-10 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15