ext/trie/trie.c in tyler-trie-0.1.2 vs ext/trie/trie.c in tyler-trie-0.1.3

- old
+ new

@@ -81,17 +81,25 @@ return INT2FIX(trie_data); } else return Qnil; } -static VALUE trie_add(VALUE self, VALUE key) { +static VALUE trie_add(VALUE self, VALUE args) { SBTrie *sb_trie; Data_Get_Struct(self, SBTrie, sb_trie); + long size = RARRAY(args)->len; + if(size < 1 || size > 2) + return Qnil; + + VALUE key; + key = RARRAY(args)->ptr[0]; + short value = size == 2 ? NUM2INT(RARRAY(args)->ptr[1]) : TRIE_DATA_ERROR; + const TrieChar *sb_key = stringToTrieChar(key); - if(sb_trie_store(sb_trie, sb_key, TRIE_DATA_ERROR)) + if(sb_trie_store(sb_trie, sb_key, value)) return Qtrue; else return Qnil; } @@ -112,11 +120,11 @@ for(c = 1; c < TRIE_CHAR_MAX; c++) { if(sb_trie_state_is_walkable(state,c)) { SBTrieState *next_state = sb_trie_state_clone(state); sb_trie_state_walk(next_state, (TrieChar)c); - char *word = (char*) malloc(strlen(prefix) + 2); + char *word = (char*)malloc(strlen(prefix) + 2); strcat(strcpy(word, prefix), (char*)&c); if(sb_trie_state_is_terminal(next_state)) rb_ary_push(children, rb_str_new2(word)); @@ -152,10 +160,57 @@ sb_trie_state_free(state); return children; } +static VALUE trie_walk_to_terminal(VALUE self, VALUE args) { + SBTrie *sb_trie; + Data_Get_Struct(self, SBTrie, sb_trie); + + long size = RARRAY(args)->len; + if(size < 1 || size > 2) + return Qnil; + + VALUE rb_path; + rb_path = RARRAY(args)->ptr[0]; + short include_value = size == 2 ? RTEST(RARRAY(args)->ptr[1]) : 0; + + SBTrieState *state = sb_trie_root(sb_trie); + + char *path = RSTRING(rb_path)->ptr; + + TrieChar *iterator = (TrieChar*)path; + while(*iterator != '\0') { + if(sb_trie_state_is_terminal(state)) { + int word_length = (int)iterator - (int)path; + char *word = (char*)malloc(word_length + 1); + strncpy(word, path, word_length); + word[word_length] = '\0'; + VALUE rb_word = rb_str_new2((const char*)word); + + if(include_value) { + sb_trie_state_walk(state, (TrieChar)'\0'); + + VALUE return_ary = rb_ary_new(); + rb_ary_push(return_ary, rb_word); + TrieData trie_data = sb_trie_state_get_data(state); + rb_ary_push(return_ary, INT2FIX(trie_data)); + return return_ary; + } else + return rb_word; + } + + if(!sb_trie_state_is_walkable(state, *iterator)) + return Qnil; + + sb_trie_state_walk(state, *iterator); + iterator++; + } + + return Qnil; +} + static VALUE trie_get_path(VALUE self) { return rb_iv_get(self, "@path"); } VALUE cTrie; @@ -165,10 +220,11 @@ rb_define_alloc_func(cTrie, trie_alloc); rb_define_method(cTrie, "initialize", trie_initialize, 1); rb_define_method(cTrie, "path", trie_get_path, 0); rb_define_method(cTrie, "has_key?", trie_has_key, 1); rb_define_method(cTrie, "get", trie_get, 1); - rb_define_method(cTrie, "add", trie_add, 1); + 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); }