[#44925] [Backport93 - Backport #5702][Open] backport r33935 — Yusuke Endoh <mame@...>

19 messages 2011/12/03

[#44940] Re: [ruby-cvs:41134] naruse:r33956 (trunk): Comment out tests which fails with GDBM-DBM compat mode. — Tanaka Akira <akr@...>

2011/12/6 <naruse@ruby-lang.org>:

9 messages 2011/12/05
[#44941] Re: [ruby-cvs:41134] naruse:r33956 (trunk): Comment out tests which fails with GDBM-DBM compat mode. — KOSAKI Motohiro <kosaki.motohiro@...> 2011/12/05

2011年12月5日16:56 Tanaka Akira <akr@fsij.org>:

[#44942] Re: [ruby-cvs:41134] naruse:r33956 (trunk): Comment out tests which fails with GDBM-DBM compat mode. — KOSAKI Motohiro <kosaki.motohiro@...> 2011/12/05

> おかしいな。gdbmは勝手にcreateフラグを立ててしまうので当該2つの

[#44985] [ruby-trunk - Bug #5757][Open] main threadがreadやselectで待っていると、^C でなかなか死なない — Yui NARUSE <naruse@...>

12 messages 2011/12/13

[#45021] [ruby-trunk - Bug #5786][Open] LoadError: cannot load such file -- openssl — Kazuhiro NISHIYAMA <redmine@...>

11 messages 2011/12/21

[#45057] [ruby-trunk - Feature #5820][Assigned] Merge Onigmo to Ruby 2.0 — Yui NARUSE <naruse@...>

21 messages 2011/12/28

[ruby-dev:44998] [Feature] st_update()

From: Nobuyoshi Nakada <nobu@...>
Date: 2011-12-14 07:53:25 UTC
List: ruby-dev #44998
なかだです。

st_tableにある値を変更したり削除したりということがしたいことがま
まあるのですが、st_lookup()とst_delete()/st_insert()の組み合わせ
だとハッシュ値の計算や探索を二回繰り返さなくてはなりません。

そこで、以下のような関数はどうでしょうか。

  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からkeyに対応するペアを探して、funcを呼び出します。funcが
ST_DELETEを返した場合は相当するキーを削除、ST_CONTINUEを返した場
合は*valueで値を更新します。



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;


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread

Prev Next