aboutsummaryrefslogtreecommitdiffstats
path: root/st.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-12-27 13:04:30 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-12-27 13:04:30 +0000
commit2f6d8bdc94926a625f769f72b890ed78553c928f (patch)
tree1fa4e037a9a8ed2601142ef2150e5c613ada59ca /st.c
parent7f649d10ed8055214e0062800b2d117453b2304f (diff)
downloadruby-2f6d8bdc94926a625f769f72b890ed78553c928f.tar.gz
* st.c (st_update): new function to lookup the given key and
update the value. [ruby-dev:44998] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34141 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'st.c')
-rw-r--r--st.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/st.c b/st.c
index 0186667ef1..d95f551063 100644
--- a/st.c
+++ b/st.c
@@ -733,6 +733,62 @@ st_cleanup_safe(st_table *table, st_data_t never)
}
int
+st_update(st_table *table, st_data_t key, int (*func)(st_data_t key, st_data_t *value, st_data_t arg), st_data_t arg)
+{
+ st_index_t hash_val, bin_pos;
+ register st_table_entry *ptr, **last, *tmp;
+ st_data_t value;
+
+ 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) {
+ value = (st_data_t)table->bins[i*2+1];
+ switch ((*func)(key, &value, arg)) {
+ case ST_CONTINUE:
+ table->bins[i*2+1] = (struct st_table_entry*)value;
+ break;
+ case ST_DELETE:
+ table->num_entries--;
+ memmove(&table->bins[i*2], &table->bins[(i+1)*2],
+ sizeof(struct st_table_entry*) * 2 * (table->num_entries-i));
+ }
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ hash_val = do_hash(key, table);
+ FIND_ENTRY(table, ptr, hash_val, bin_pos);
+
+ if (ptr == 0) {
+ return 0;
+ }
+ else {
+ value = ptr->record;
+ switch ((*func)(ptr->key, &value, arg)) {
+ case ST_CONTINUE:
+ ptr->record = value;
+ break;
+ case ST_DELETE:
+ last = &table->bins[bin_pos];
+ for (; (tmp = *last) != 0; last = &tmp->next) {
+ if (ptr == tmp) {
+ tmp = ptr->fore;
+ *last = ptr->next;
+ REMOVE_ENTRY(table, ptr);
+ free(ptr);
+ break;
+ }
+ }
+ break;
+ }
+ return 1;
+ }
+}
+
+int
st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
{
st_table_entry *ptr, **last, *tmp;