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

ruby-changes:40515

From: nobu <ko1@a...>
Date: Mon, 16 Nov 2015 18:22:21 +0900 (JST)
Subject: [ruby-changes:40515] nobu:r52596 (trunk): struct.c: dig

nobu	2015-11-16 18:21:56 +0900 (Mon, 16 Nov 2015)

  New Revision: 52596

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

  Log:
    struct.c: dig
    
    * object.c (rb_obj_dig): dig in nested structs too.
    * struct.c (rb_struct_dig): new method Struct#dig.
      [Feature #11688]

  Modified files:
    trunk/ChangeLog
    trunk/NEWS
    trunk/internal.h
    trunk/object.c
    trunk/struct.c
    trunk/test/ruby/test_struct.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 52595)
+++ ChangeLog	(revision 52596)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Nov 16 18:21:52 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* object.c (rb_obj_dig): dig in nested structs too.
+
+	* struct.c (rb_struct_dig): new method Struct#dig.
+	  [Feature #11688]
+
 Mon Nov 16 17:41:33 2015  Nobuyoshi Nakada  <nobu@r...>
 
 	* compile.c (iseq_peephole_optimize): optimize tail calls on aref
Index: object.c
===================================================================
--- object.c	(revision 52595)
+++ object.c	(revision 52596)
@@ -3165,7 +3165,7 @@ dig_basic_p(VALUE obj, struct dig_method https://github.com/ruby/ruby/blob/trunk/object.c#L3165
 VALUE
 rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound)
 {
-    struct dig_method hash = {Qnil}, ary = {Qnil};
+    struct dig_method hash = {Qnil}, ary = {Qnil}, strt = {Qnil};
 
     for (; argc > 0; ++argv, --argc) {
 	if (!SPECIAL_CONST_P(obj)) {
@@ -3181,6 +3181,13 @@ rb_obj_dig(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/object.c#L3181
 		    obj = rb_ary_at(obj, *argv);
 		    continue;
 		}
+		break;
+	      case T_STRUCT:
+		if (dig_basic_p(obj, &strt)) {
+		    obj = rb_struct_lookup(obj, *argv);
+		    continue;
+		}
+		break;
 	    }
 	}
 	return rb_check_funcall_default(obj, id_dig, argc, argv, notfound);
Index: struct.c
===================================================================
--- struct.c	(revision 52595)
+++ struct.c	(revision 52596)
@@ -923,6 +923,23 @@ rb_struct_aset(VALUE s, VALUE idx, VALUE https://github.com/ruby/ruby/blob/trunk/struct.c#L923
     return val;
 }
 
+FUNC_MINIMIZED(VALUE rb_struct_lookup(VALUE s, VALUE idx));
+NOINLINE(static VALUE rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound));
+
+VALUE
+rb_struct_lookup(VALUE s, VALUE idx)
+{
+    return rb_struct_lookup_default(s, idx, Qnil);
+}
+
+static VALUE
+rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound)
+{
+    int i = rb_struct_pos(s, &idx);
+    if (i < 0) return notfound;
+    return RSTRUCT_GET(s, i);
+}
+
 static VALUE
 struct_entry(VALUE s, long n)
 {
@@ -1109,6 +1126,16 @@ rb_struct_size(VALUE s) https://github.com/ruby/ruby/blob/trunk/struct.c#L1126
     return LONG2FIX(RSTRUCT_LEN(s));
 }
 
+static VALUE
+rb_struct_dig(int argc, VALUE *argv, VALUE self)
+{
+    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
+    self = rb_struct_lookup(self, *argv);
+    if (!--argc) return self;
+    ++argv;
+    return rb_obj_dig(argc, argv, self, Qnil);
+}
+
 /*
  *  A Struct is a convenient way to bundle a number of attributes together,
  *  using accessor methods, without having to write an explicit class.
@@ -1166,6 +1193,7 @@ InitVM_Struct(void) https://github.com/ruby/ruby/blob/trunk/struct.c#L1193
     rb_define_method(rb_cStruct, "values_at", rb_struct_values_at, -1);
 
     rb_define_method(rb_cStruct, "members", rb_struct_members_m, 0);
+    rb_define_method(rb_cStruct, "dig", rb_struct_dig, -1);
 }
 
 #undef rb_intern
Index: NEWS
===================================================================
--- NEWS	(revision 52595)
+++ NEWS	(revision 52596)
@@ -95,6 +95,9 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L95
     Backtrace doesn't show each methods (show block lines directly).
     TracePoint also ignore these calls. [Feature #11569]
 
+* Struct
+  * Struct#dig [Feature #11686]
+
 * Thread
   * Thread#name, Thread#name= are added to handle thread names [Feature #11251]
 
Index: internal.h
===================================================================
--- internal.h	(revision 52595)
+++ internal.h	(revision 52596)
@@ -1141,6 +1141,7 @@ VALUE rb_cstr_intern(const char *ptr, lo https://github.com/ruby/ruby/blob/trunk/internal.h#L1141
 
 /* struct.c */
 VALUE rb_struct_init_copy(VALUE copy, VALUE s);
+VALUE rb_struct_lookup(VALUE s, VALUE idx);
 
 /* time.c */
 struct timeval rb_time_timeval(VALUE);
Index: test/ruby/test_struct.rb
===================================================================
--- test/ruby/test_struct.rb	(revision 52595)
+++ test/ruby/test_struct.rb	(revision 52596)
@@ -353,6 +353,13 @@ module TestStruct https://github.com/ruby/ruby/blob/trunk/test/ruby/test_struct.rb#L353
     assert_equal "[Bug #9353]", x.send(:a=, "[Bug #9353]")
   end
 
+  def test_dig
+    klass = @Struct.new(:a)
+    o = klass.new(klass.new({b: [1, 2, 3]}))
+    assert_equal(1, o.dig(:a, :a, :b, 0))
+    assert_nil(o.dig(:b, 0))
+  end
+
   class TopStruct < Test::Unit::TestCase
     include TestStruct
 

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

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