mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
struct.c: dig
* object.c (rb_obj_dig): dig in nested structs too. * struct.c (rb_struct_dig): new method Struct#dig. [Feature #11688] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1ff30ea2b1
commit
20690026a7
6 changed files with 54 additions and 1 deletions
|
@ -1,3 +1,10 @@
|
|||
Mon Nov 16 18:21:52 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* 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@ruby-lang.org>
|
||||
|
||||
* compile.c (iseq_peephole_optimize): optimize tail calls on aref
|
||||
|
|
3
NEWS
3
NEWS
|
@ -95,6 +95,9 @@ with all sufficient information, see the ChangeLog file.
|
|||
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]
|
||||
|
||||
|
|
|
@ -1141,6 +1141,7 @@ VALUE rb_cstr_intern(const char *ptr, long len, rb_encoding *enc);
|
|||
|
||||
/* 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);
|
||||
|
|
9
object.c
9
object.c
|
@ -3165,7 +3165,7 @@ dig_basic_p(VALUE obj, struct dig_method *cache)
|
|||
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 obj, VALUE notfound)
|
|||
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);
|
||||
|
|
28
struct.c
28
struct.c
|
@ -923,6 +923,23 @@ rb_struct_aset(VALUE s, VALUE idx, VALUE val)
|
|||
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)
|
|||
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)
|
|||
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
|
||||
|
|
|
@ -353,6 +353,13 @@ module TestStruct
|
|||
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
|
||||
|
||||
|
|
Loading…
Reference in a new issue