[前][次][番号順一覧][スレッド一覧]

ruby-changes:22092

From: nobu <ko1@a...>
Date: Tue, 27 Dec 2011 22:04:42 +0900 (JST)
Subject: [ruby-changes:22092] nobu:r34141 (trunk): * st.c (st_update): new function to lookup the given key and

nobu	2011-12-27 22:04:30 +0900 (Tue, 27 Dec 2011)

  New Revision: 34141

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=34141

  Log:
    * st.c (st_update): new function to lookup the given key and
      update the value.  [ruby-dev:44998]

  Added directories:
    trunk/ext/-test-/st/
    trunk/ext/-test-/st/update/
    trunk/test/-ext-/st/
  Added files:
    trunk/ext/-test-/st/update/extconf.rb
    trunk/ext/-test-/st/update/update.c
    trunk/test/-ext-/st/test_update.rb
  Modified files:
    trunk/ChangeLog
    trunk/include/ruby/st.h
    trunk/st.c

Index: include/ruby/st.h
===================================================================
--- include/ruby/st.h	(revision 34140)
+++ include/ruby/st.h	(revision 34141)
@@ -113,6 +113,7 @@
 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);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 34140)
+++ ChangeLog	(revision 34141)
@@ -1,3 +1,8 @@
+Tue Dec 27 22:04:27 2011  Nobuyoshi Nakada  <nobu@r...>
+
+	* st.c (st_update): new function to lookup the given key and
+	  update the value.  [ruby-dev:44998]
+
 Tue Dec 27 21:17:33 2011  Nobuyoshi Nakada  <nobu@r...>
 
 	* node.h (rb_args_info): change pre_args_num and post_args_num as
Index: st.c
===================================================================
--- st.c	(revision 34140)
+++ st.c	(revision 34141)
@@ -733,6 +733,62 @@
 }
 
 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;
Index: ext/-test-/st/update/update.c
===================================================================
--- ext/-test-/st/update/update.c	(revision 0)
+++ ext/-test-/st/update/update.c	(revision 34141)
@@ -0,0 +1,34 @@
+#include <ruby.h>
+#include <ruby/st.h>
+
+static int
+update_func(st_data_t key, st_data_t *value, st_data_t arg)
+{
+    VALUE ret = rb_yield_values(2, (VALUE)key, (VALUE)*value);
+    switch (ret) {
+      case Qfalse:
+	return ST_STOP;
+      case Qnil:
+	return ST_DELETE;
+      default:
+	*value = ret;
+	return ST_CONTINUE;
+    }
+}
+
+static VALUE
+test_st_update(VALUE self, VALUE key)
+{
+    if (st_update(RHASH_TBL(self), (st_data_t)key, update_func, 0))
+	return Qtrue;
+    else
+	return Qfalse;
+}
+
+void
+Init_update(void)
+{
+    VALUE st = rb_define_class_under(rb_define_module("Bug"), "StTable", rb_cHash);
+    rb_define_method(st, "st_update", test_st_update, 1);
+}
+

Property changes on: ext/-test-/st/update/update.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ext/-test-/st/update/extconf.rb
===================================================================
--- ext/-test-/st/update/extconf.rb	(revision 0)
+++ ext/-test-/st/update/extconf.rb	(revision 34141)
@@ -0,0 +1 @@
+create_makefile("-test-/st/update")

Property changes on: ext/-test-/st/update/extconf.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: test/-ext-/st/test_update.rb
===================================================================
--- test/-ext-/st/test_update.rb	(revision 0)
+++ test/-ext-/st/test_update.rb	(revision 34141)
@@ -0,0 +1,39 @@
+require 'test/unit'
+require "-test-/st/update"
+
+class Bug::StTable
+  class Test_Update < Test::Unit::TestCase
+    def setup
+      @tbl = Bug::StTable.new
+      @tbl[:a] = 1
+      @tbl[:b] = 2
+    end
+
+    def test_notfound
+      called = false
+      assert_equal(false, @tbl.st_update(:c) {called = true})
+      assert_equal(false, called)
+    end
+
+    def test_continue
+      args = nil
+      assert_equal(true, @tbl.st_update(:a) {|*x| args = x; false})
+      assert_equal({a: 1, b: 2}, @tbl, :a)
+      assert_equal([:a, 1], args)
+    end
+
+    def test_delete
+      args = nil
+      assert_equal(true, @tbl.st_update(:a) {|*x| args = x; nil})
+      assert_equal({b: 2}, @tbl, :a)
+      assert_equal([:a, 1], args)
+    end
+
+    def test_update
+      args = nil
+      assert_equal(true, @tbl.st_update(:a) {|*x| args = x; 3})
+      assert_equal({a: 3, b: 2}, @tbl, :a)
+      assert_equal([:a, 1], args)
+    end
+  end
+end

Property changes on: test/-ext-/st/test_update.rb
___________________________________________________________________
Added: svn:eol-style
   + LF


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]