[Feature] st_update()

$B$J$+$@$G$9!#(B

st_table$B$K$"$kCM$rJQ99$7$?$j:o=|$7$?$j$H$$$&$3$H$,$7$?$$$3$H$,$^(B
$B$^$"$k$N$G$9$,!"(Bst_lookup()$B$H(Bst_delete()/st_insert()$B$NAH$_9g$o$;(B
$B$@$H%O%C%7%eCM$N7W;;$dC5:w$rFs2s7+$jJV$5$J$/$F$O$J$j$^$;$s!#(B

$B$=$3$G!"0J2<$N$h$&$J4X?t$O$I$&$G$7$g$&$+!#(B

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);

table$B$+$i(Bkey$B$KBP1~$9$k%Z%"$rC5$7$F!"(Bfunc$B$r8F$S=P$7$^$9!#(Bfunc$B$,(B
ST_DELETE$B$rJV$7$?>l9g$OAjEv$9$k%-!<$r:o=|!"(BST_CONTINUE$B$rJV$7$?>l(B
$B9g$O(B*value$B$GCM$r99?7$7$^$9!#(B

diff --git i/include/ruby/st.h w/include/ruby/st.h
index 50f2a75…ff3da2a 100644
— i/include/ruby/st.h
+++ w/include/ruby/st.h
@@ -113,6 +113,7 @@ 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_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);
int st_foreach(st_table , int ()(ANYARGS), st_data_t);
int st_reverse_foreach(st_table , int ()(ANYARGS), st_data_t);
void st_add_direct(st_table *, st_data_t, st_data_t);
diff --git i/st.c w/st.c
index 0186667…d95f551 100644
— i/st.c
+++ w/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;

$B$^$D$b$H(B $B$f$-$R$m$G$9(B

In message “Re: [ruby-dev:44998] [Feature] st_update()”
on Wed, 14 Dec 2011 16:53:25 +0900, Nobuyoshi N.
[email protected] writes:

|st_table$B$K$“$kCM$rJQ99$7$?$j:o=|$7$?$j$H$$$&$3$H$,$7$?$$$3$H$,$^(B
|$B$^$”$k$N$G$9$,!"(Bst_lookup()$B$H(Bst_delete()/st_insert()$B$NAH$_9g$o$;(B
|$B$@$H%O%C%7%eCM$N7W;;$dC5:w$rFs2s7+$jJV$5$J$/$F$O$J$j$^$;$s!#(B
|
|$B$=$3$G!"0J2<$N$h$&$J4X?t$O$I$&$G$7$g$&$+!#(B
|
| 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);
|
|table$B$+$i(Bkey$B$KBP1~$9$k%Z%“$rC5$7$F!”(Bfunc$B$r8F$S=P$7$^$9!#(Bfunc$B$,(B
|ST_DELETE$B$rJV$7$?>l9g$OAjEv$9$k%-!<$r:o=|!"(BST_CONTINUE$B$rJV$7$?>l(B
|$B9g$O(B
value$B$GCM$r99?7$7$^$9!#(B

$B$$$$$s$8$c$J$$$G$7$g$&$+!#(B