tyler-trie 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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