diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | hash.c | 5 | ||||
-rw-r--r-- | include/ruby/st.h | 1 | ||||
-rw-r--r-- | st.c | 40 |
4 files changed, 51 insertions, 3 deletions
@@ -2,6 +2,14 @@ Wed May 27 23:00:38 2009 Nobuyoshi Nakada <nobu@ruby-lang.org> * parse.y (struct parser_params): lex_gets_ptr should be long. +Wed May 27 14:08:39 2009 Yukihiro Matsumoto <matz@ruby-lang.org> + + * st.c (st_insert2): new function with processing new key, + e.g. copy. + + * hash.c (rb_hash_aset): use st_insert2() to reduce redundant + st_lookup calls. + Wed May 27 02:31:38 2009 NARUSE, Yui <naruse@ruby-lang.org> * ext/readline/readline.c (readline_getc): the function for @@ -1015,12 +1015,11 @@ VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val) { rb_hash_modify(hash); - if (RHASH(hash)->ntbl->type == &identhash || - rb_obj_class(key) != rb_cString || st_lookup(RHASH(hash)->ntbl, key, 0)) { + if (RHASH(hash)->ntbl->type == &identhash || rb_obj_class(key) != rb_cString) { st_insert(RHASH(hash)->ntbl, key, val); } else { - st_add_direct(RHASH(hash)->ntbl, rb_str_new4(key), val); + st_insert2(RHASH(hash)->ntbl, key, val, rb_str_new4); } return val; } diff --git a/include/ruby/st.h b/include/ruby/st.h index 73216ba45c..0c80d3a225 100644 --- a/include/ruby/st.h +++ b/include/ruby/st.h @@ -93,6 +93,7 @@ st_table *st_init_strcasetable_with_size(int); int st_delete(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */ int st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t); int st_insert(st_table *, st_data_t, st_data_t); +int st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); int st_lookup(st_table *, st_data_t, st_data_t *); int st_get_key(st_table *, st_data_t, st_data_t *); int st_foreach(st_table *, int (*)(ANYARGS), st_data_t); @@ -416,6 +416,46 @@ st_insert(register st_table *table, register st_data_t key, st_data_t value) } } +int +st_insert2(register st_table *table, register st_data_t key, st_data_t value, + st_data_t (*func)(st_data_t)) +{ + unsigned int hash_val, bin_pos; + register st_table_entry *ptr; + + if (table->entries_packed) { + st_index_t i; + for (i = 0; i < table->num_entries; i++) { + if ((st_data_t)table->bins[i*2] == key) { + table->bins[i*2+1] = (struct st_table_entry*)value; + return 1; + } + } + if ((table->num_entries+1) * 2 <= table->num_bins && table->num_entries+1 <= MAX_PACKED_NUMHASH) { + i = table->num_entries++; + table->bins[i*2] = (struct st_table_entry*)key; + table->bins[i*2+1] = (struct st_table_entry*)value; + return 0; + } + else { + unpack_entries(table); + } + } + + hash_val = do_hash(key, table); + FIND_ENTRY(table, ptr, hash_val, bin_pos); + + if (ptr == 0) { + key = (*func)(key); + ADD_DIRECT(table, key, value, hash_val, bin_pos); + return 0; + } + else { + ptr->record = value; + return 1; + } +} + void st_add_direct(st_table *table, st_data_t key, st_data_t value) { |