aboutsummaryrefslogtreecommitdiffstats
path: root/object.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-09 12:27:26 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-11-09 12:27:26 +0000
commitd78da74d9f5a62111434b8d04f5d6e17e2329581 (patch)
tree64813c6d3e206f9ad51009a640750f26ce9e7231 /object.c
parentc90c20adad3c5d9cbf50533640bb03b284c202e6 (diff)
downloadruby-d78da74d9f5a62111434b8d04f5d6e17e2329581.tar.gz
dig
* array.c (rb_ary_dig): new method Array#dig. * hash.c (rb_hash_dig): new method Hash#dig. * object.c (rb_obj_dig): dig in nested arrays/hashes. [Feature #11643] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52504 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'object.c')
-rw-r--r--object.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/object.c b/object.c
index 9796ea937d..50c2fe04f5 100644
--- a/object.c
+++ b/object.c
@@ -3144,6 +3144,52 @@ rb_f_hash(VALUE obj, VALUE arg)
return rb_Hash(arg);
}
+struct dig_method {
+ VALUE klass;
+ int basic;
+};
+
+static ID id_dig;
+
+static int
+dig_basic_p(VALUE obj, struct dig_method *cache)
+{
+ VALUE klass = RBASIC_CLASS(obj);
+ if (klass != cache->klass) {
+ cache->klass = klass;
+ cache->basic = rb_method_basic_definition_p(klass, id_dig);
+ }
+ return cache->basic;
+}
+
+VALUE
+rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound)
+{
+ struct dig_method hash = {Qnil}, ary = {Qnil};
+
+ for (; argc > 0; ++argv, --argc) {
+ if (!SPECIAL_CONST_P(obj)) {
+ switch (BUILTIN_TYPE(obj)) {
+ case T_HASH:
+ if (dig_basic_p(obj, &hash)) {
+ obj = rb_hash_aref(obj, *argv);
+ continue;
+ }
+ break;
+ case T_ARRAY:
+ if (dig_basic_p(obj, &ary)) {
+ obj = rb_ary_at(obj, *argv);
+ continue;
+ }
+ }
+ }
+ obj = rb_check_funcall(obj, id_dig, argc, argv);
+ if (obj == Qundef) return notfound;
+ break;
+ }
+ return obj;
+}
+
/*
* Document-class: Class
*
@@ -3521,5 +3567,6 @@ void
Init_Object(void)
{
id_to_f = rb_intern_const("to_f");
+ id_dig = rb_intern_const("dig");
InitVM(Object);
}