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/