mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-struct: add recursive inspect check instead of _inspect hack
This commit is contained in:
@@ -45,35 +45,6 @@ class Struct
|
||||
ary
|
||||
end
|
||||
|
||||
def _inspect(recur_list)
|
||||
return "#<struct #{self.class}:...>" if recur_list[self.object_id]
|
||||
recur_list[self.object_id] = true
|
||||
name = self.class.to_s
|
||||
if name[0] == "#"
|
||||
str = "#<struct "
|
||||
else
|
||||
str = "#<struct #{name} "
|
||||
end
|
||||
buf = []
|
||||
self.each_pair do |k,v|
|
||||
buf.push k.to_s + "=" + v._inspect(recur_list)
|
||||
end
|
||||
str + buf.join(", ") + ">"
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# struct.to_s -> string
|
||||
# struct.inspect -> string
|
||||
#
|
||||
# Describe the contents of this struct in a string.
|
||||
#
|
||||
# 15.2.18.4.10(x)
|
||||
#
|
||||
def inspect
|
||||
self._inspect({})
|
||||
end
|
||||
|
||||
##
|
||||
# 15.2.18.4.11(x)
|
||||
#
|
||||
|
||||
@@ -634,6 +634,49 @@ mrb_struct_values_at(mrb_state *mrb, mrb_value self)
|
||||
return mrb_get_values_at(mrb, self, RSTRUCT_LEN(self), argc, argv, struct_aref_int);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* struct.to_s -> string
|
||||
* struct.inspect -> string
|
||||
*
|
||||
* Returns a string representation of Data
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_struct_to_s(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value members, ret, cname;
|
||||
mrb_value *mems;
|
||||
mrb_int mlen;
|
||||
|
||||
mrb->c->ci->mid = MRB_SYM(inspect);
|
||||
ret = mrb_str_new_lit(mrb, "#<struct ");
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
cname = mrb_class_path(mrb, mrb_class_real(mrb_class(mrb, self)));
|
||||
if (!mrb_nil_p(cname)) {
|
||||
mrb_str_cat_str(mrb, ret, cname);
|
||||
mrb_str_cat_lit(mrb, ret, " ");
|
||||
}
|
||||
if (mrb_inspect_recursive_p(mrb, self)) {
|
||||
mrb_str_cat_lit(mrb, ret, "...>");
|
||||
return ret;
|
||||
}
|
||||
members = struct_members(mrb, self);
|
||||
mlen = RARRAY_LEN(members);
|
||||
mems = RARRAY_PTR(members);
|
||||
for (mrb_int i=0; i<mlen; i++) {
|
||||
mrb_int len;
|
||||
const char *name = mrb_sym_name_len(mrb, mrb_symbol(mems[i]), &len);
|
||||
if (i>0) mrb_str_cat_lit(mrb, ret, ", ");
|
||||
mrb_str_cat(mrb, ret, name, len);
|
||||
mrb_str_cat_lit(mrb, ret, "=");
|
||||
mrb_str_cat_str(mrb, ret, mrb_inspect(mrb, mrb_ary_ref(mrb, self, i)));
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
}
|
||||
mrb_str_cat_lit(mrb, ret, ">");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* A <code>Struct</code> is a convenient way to bundle a number of
|
||||
* attributes together, using accessor methods, without having to write
|
||||
@@ -665,6 +708,8 @@ mrb_mruby_struct_gem_init(mrb_state* mrb)
|
||||
mrb_define_method(mrb, st, "initialize", mrb_struct_initialize, MRB_ARGS_ANY()); /* 15.2.18.4.8 */
|
||||
mrb_define_method(mrb, st, "initialize_copy", mrb_struct_init_copy, MRB_ARGS_REQ(1)); /* 15.2.18.4.9 */
|
||||
mrb_define_method(mrb, st, "eql?", mrb_struct_eql, MRB_ARGS_REQ(1)); /* 15.2.18.4.12(x) */
|
||||
mrb_define_method(mrb, st, "to_s", mrb_struct_to_s, MRB_ARGS_NONE()); /* 15.2.18.4.11(x) */
|
||||
mrb_define_method(mrb, st, "inspect", mrb_struct_to_s, MRB_ARGS_NONE()); /* 15.2.18.4.10(x) */
|
||||
|
||||
mrb_define_method(mrb, st, "size", mrb_struct_len, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, st, "length", mrb_struct_len, MRB_ARGS_NONE());
|
||||
|
||||
@@ -119,7 +119,7 @@ assert('struct inspect') do
|
||||
c = Struct.new(:m1, :m2, :m3, :m4, :m5, :recur)
|
||||
cc = c.new(1,2,3,4,5,nil)
|
||||
cc.recur = cc
|
||||
assert_equal "#<struct m1=1, m2=2, m3=3, m4=4, m5=5, recur=#<struct #{cc.class}:...>>", cc.inspect
|
||||
assert_equal "#<struct m1=1, m2=2, m3=3, m4=4, m5=5, recur=#<struct ...>>", cc.inspect
|
||||
end
|
||||
|
||||
assert('Struct#length, Struct#size') do
|
||||
|
||||
Reference in New Issue
Block a user