ext/trie/trie.c in tyler-trie-0.1.3 vs ext/trie/trie.c in tyler-trie-0.2.0
- old
+ new
@@ -2,10 +2,12 @@
#include <datrie/sb-trie.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+VALUE cTrie, cTrieNode;
+
static TrieChar* stringToTrieChar(VALUE string) {
return (TrieChar*) RSTRING(string)->ptr;
}
static void trie_free(SBTrie *sb_trie) {
@@ -204,19 +206,115 @@
sb_trie_state_walk(state, *iterator);
iterator++;
}
+ sb_trie_state_free(state);
+
return Qnil;
}
static VALUE trie_get_path(VALUE self) {
return rb_iv_get(self, "@path");
}
-
-VALUE cTrie;
+static void trie_node_free(SBTrieState *state) {
+ if(state)
+ sb_trie_state_free(state);
+}
+
+static VALUE trie_node_alloc(VALUE klass) {
+ SBTrieState *state;
+ VALUE obj;
+
+ obj = Data_Wrap_Struct(klass, 0, trie_node_free, state);
+
+ return obj;
+}
+
+static VALUE trie_root(VALUE self) {
+ SBTrie *sb_trie;
+ Data_Get_Struct(self, SBTrie, sb_trie);
+
+ VALUE trie_node = trie_node_alloc(cTrieNode);
+
+ // replace the pretend SBTrieState created in TrieNode's alloc with a real one
+ RDATA(trie_node)->data = sb_trie_root(sb_trie);
+
+ rb_iv_set(trie_node, "@state", Qnil);
+ rb_iv_set(trie_node, "@full_state", rb_str_new2(""));
+ return trie_node;
+}
+
+static VALUE trie_node_get_state(VALUE self) {
+ return rb_iv_get(self, "@state");
+}
+static VALUE trie_node_get_full_state(VALUE self) {
+ return rb_iv_get(self, "@full_state");
+}
+
+static VALUE trie_node_walk_bang(VALUE self, VALUE rchar) {
+ SBTrieState *state;
+ Data_Get_Struct(self, SBTrieState, state);
+
+ if(RSTRING(rchar)->len != 1)
+ return Qnil;
+
+ char ch = RSTRING(rchar)->ptr[0];
+ int result = sb_trie_state_walk(state, (TrieChar)ch);
+
+ if(result) {
+ rb_iv_set(self, "@state", rchar);
+ VALUE full_state = rb_iv_get(self, "@full_state");
+ rb_str_append(full_state, rchar);
+ rb_iv_set(self, "@full_state", full_state);
+ return self;
+ } else
+ return Qnil;
+}
+
+static VALUE trie_node_value(VALUE self) {
+ SBTrieState *state, *dup;
+ Data_Get_Struct(self, SBTrieState, state);
+
+ dup = sb_trie_state_clone(state);
+
+ sb_trie_state_walk(dup, (TrieChar)'\0');
+ TrieData trie_data = sb_trie_state_get_data(dup);
+ sb_trie_state_free(dup);
+
+ return TRIE_DATA_ERROR == trie_data ? Qnil : INT2FIX(trie_data);
+}
+
+static VALUE trie_node_terminal(VALUE self) {
+ SBTrieState *state;
+ Data_Get_Struct(self, SBTrieState, state);
+
+ return sb_trie_state_is_terminal(state) ? Qtrue : Qnil;
+}
+
+static VALUE trie_node_leaf(VALUE self) {
+ SBTrieState *state;
+ Data_Get_Struct(self, SBTrieState, state);
+
+ return sb_trie_state_is_leaf(state) ? Qtrue : Qnil;
+}
+
+static VALUE trie_node_clone(VALUE self) {
+ SBTrieState *state;
+ Data_Get_Struct(self, SBTrieState, state);
+
+ VALUE new_node = trie_node_alloc(cTrieNode);
+ RDATA(new_node)->data = sb_trie_state_clone(state);
+
+ rb_iv_set(new_node, "@state", rb_iv_get(self, "@state"));
+ rb_iv_set(new_node, "@full_state", rb_iv_get(self, "@full_state"));
+
+ return new_node;
+}
+
+
void Init_trie() {
cTrie = rb_define_class("Trie", rb_cObject);
rb_define_alloc_func(cTrie, trie_alloc);
rb_define_method(cTrie, "initialize", trie_initialize, 1);
rb_define_method(cTrie, "path", trie_get_path, 0);
@@ -225,6 +323,17 @@
rb_define_method(cTrie, "add", trie_add, -2);
rb_define_method(cTrie, "delete", trie_delete, 1);
rb_define_method(cTrie, "close", trie_close, 0);
rb_define_method(cTrie, "children", trie_children, 1);
rb_define_method(cTrie, "walk_to_terminal", trie_walk_to_terminal, -2);
+ rb_define_method(cTrie, "root", trie_root, 0);
+
+ cTrieNode = rb_define_class("TrieNode", rb_cObject);
+ rb_define_alloc_func(cTrieNode, trie_node_alloc);
+ rb_define_method(cTrieNode, "state", trie_node_get_state, 0);
+ rb_define_method(cTrieNode, "full_state", trie_node_get_full_state, 0);
+ rb_define_method(cTrieNode, "walk!", trie_node_walk_bang, 1);
+ rb_define_method(cTrieNode, "value", trie_node_value, 0);
+ rb_define_method(cTrieNode, "terminal?", trie_node_terminal, 0);
+ rb_define_method(cTrieNode, "leaf?", trie_node_leaf, 0);
+ rb_define_method(cTrieNode, "clone", trie_node_clone, 0);
}