2 ** struct.c - Struct class
4 ** See Copyright Notice in mruby.h
10 #include "mruby/array.h"
11 #include "mruby/string.h"
12 #include "mruby/class.h"
13 #include "mruby/variable.h"
14 #include "mruby/hash.h"
15 #include "mruby/range.h"
17 #define RSTRUCT_LEN(st) mrb_ary_ptr(st)->len
18 #define RSTRUCT_PTR(st) mrb_ary_ptr(st)->ptr
20 static struct RClass
*
21 struct_class(mrb_state
*mrb
)
23 return mrb_class_get(mrb
, "Struct");
26 static inline mrb_value
27 struct_ivar_get(mrb_state
*mrb
, mrb_value c
, mrb_sym id
)
29 struct RClass
* kclass
;
30 struct RClass
* sclass
= struct_class(mrb
);
34 ans
= mrb_iv_get(mrb
, c
, id
);
35 if (!mrb_nil_p(ans
)) return ans
;
36 kclass
= RCLASS_SUPER(c
);
37 if (kclass
== 0 || kclass
== sclass
)
38 return mrb_nil_value();
39 c
= mrb_obj_value(kclass
);
44 mrb_struct_s_members(mrb_state
*mrb
, mrb_value klass
)
46 mrb_value members
= struct_ivar_get(mrb
, klass
, mrb_intern_lit(mrb
, "__members__"));
48 if (mrb_nil_p(members
)) {
49 mrb_raise(mrb
, E_TYPE_ERROR
, "uninitialized struct");
51 if (!mrb_array_p(members
)) {
52 mrb_raise(mrb
, E_TYPE_ERROR
, "corrupted struct");
58 mrb_struct_members(mrb_state
*mrb
, mrb_value s
)
60 mrb_value members
= mrb_struct_s_members(mrb
, mrb_obj_value(mrb_obj_class(mrb
, s
)));
61 if (!strcmp(mrb_class_name(mrb
, mrb_obj_class(mrb
, s
)), "Struct")) {
62 if (RSTRUCT_LEN(s
) != RARRAY_LEN(members
)) {
63 mrb_raisef(mrb
, E_TYPE_ERROR
,
64 "struct size differs (%S required %S given)",
65 mrb_fixnum_value(RARRAY_LEN(members
)), mrb_fixnum_value(RSTRUCT_LEN(s
)));
72 mrb_struct_s_members_m(mrb_state
*mrb
, mrb_value klass
)
74 mrb_value members
, ary
;
76 members
= mrb_struct_s_members(mrb
, klass
);
77 ary
= mrb_ary_new_capa(mrb
, RARRAY_LEN(members
));
78 mrb_ary_replace(mrb
, ary
, members
);
85 * struct.members -> array
87 * Returns an array of strings representing the names of the instance
90 * Customer = Struct.new(:name, :address, :zip)
91 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
92 * joe.members #=> [:name, :address, :zip]
96 mrb_struct_members_m(mrb_state
*mrb
, mrb_value obj
)
98 return mrb_struct_s_members_m(mrb
, mrb_obj_value(mrb_obj_class(mrb
, obj
)));
102 mrb_struct_getmember(mrb_state
*mrb
, mrb_value obj
, mrb_sym id
)
104 mrb_value members
, slot
, *ptr
;
105 const mrb_value
*ptr_members
;
108 ptr
= RSTRUCT_PTR(obj
);
109 members
= mrb_struct_members(mrb
, obj
);
110 ptr_members
= RARRAY_PTR(members
);
111 slot
= mrb_symbol_value(id
);
112 len
= RARRAY_LEN(members
);
113 for (i
=0; i
<len
; i
++) {
114 if (mrb_obj_equal(mrb
, ptr_members
[i
], slot
)) {
118 mrb_raisef(mrb
, E_INDEX_ERROR
, "`%S' is not a struct member", mrb_sym2str(mrb
, id
));
119 return mrb_nil_value(); /* not reached */
123 mrb_struct_ref(mrb_state
*mrb
, mrb_value obj
)
125 return mrb_struct_getmember(mrb
, obj
, mrb
->c
->ci
->mid
);
128 static mrb_value
mrb_struct_ref0(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[0];}
129 static mrb_value
mrb_struct_ref1(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[1];}
130 static mrb_value
mrb_struct_ref2(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[2];}
131 static mrb_value
mrb_struct_ref3(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[3];}
132 static mrb_value
mrb_struct_ref4(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[4];}
133 static mrb_value
mrb_struct_ref5(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[5];}
134 static mrb_value
mrb_struct_ref6(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[6];}
135 static mrb_value
mrb_struct_ref7(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[7];}
136 static mrb_value
mrb_struct_ref8(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[8];}
137 static mrb_value
mrb_struct_ref9(mrb_state
* mrb
, mrb_value obj
) {return RSTRUCT_PTR(obj
)[9];}
139 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
140 #define N_REF_FUNC numberof(ref_func)
142 static const mrb_func_t ref_func
[] = {
156 mrb_id_attrset(mrb_state
*mrb
, mrb_sym id
)
163 name
= mrb_sym2name_len(mrb
, id
, &len
);
164 buf
= (char *)mrb_malloc(mrb
, (size_t)len
+2);
165 memcpy(buf
, name
, (size_t)len
);
169 mid
= mrb_intern(mrb
, buf
, len
+1);
175 mrb_struct_set(mrb_state
*mrb
, mrb_value obj
, mrb_value val
)
178 mrb_int i
, len
, slen
;
180 mrb_value members
, slot
, *ptr
;
181 const mrb_value
*ptr_members
;
184 name
= mrb_sym2name_len(mrb
, mrb
->c
->ci
->mid
, &slen
);
185 mid
= mrb_intern(mrb
, name
, slen
-1); /* omit last "=" */
187 members
= mrb_struct_members(mrb
, obj
);
188 ptr_members
= RARRAY_PTR(members
);
189 len
= RARRAY_LEN(members
);
190 ptr
= RSTRUCT_PTR(obj
);
191 for (i
=0; i
<len
; i
++) {
192 slot
= ptr_members
[i
];
193 if (mrb_symbol(slot
) == mid
) {
197 mrb_raisef(mrb
, E_INDEX_ERROR
, "`%S' is not a struct member", mrb_sym2str(mrb
, mid
));
198 return mrb_nil_value(); /* not reached */
202 mrb_struct_set_m(mrb_state
*mrb
, mrb_value obj
)
206 mrb_get_args(mrb
, "o", &val
);
207 return mrb_struct_set(mrb
, obj
, val
);
211 is_local_id(mrb_state
*mrb
, const char *name
)
213 if (!name
) return FALSE
;
214 return !ISUPPER(name
[0]);
218 is_const_id(mrb_state
*mrb
, const char *name
)
220 if (!name
) return FALSE
;
221 return ISUPPER(name
[0]);
225 make_struct_define_accessors(mrb_state
*mrb
, mrb_value members
, struct RClass
*c
)
227 const mrb_value
*ptr_members
= RARRAY_PTR(members
);
229 mrb_int len
= RARRAY_LEN(members
);
230 int ai
= mrb_gc_arena_save(mrb
);
232 for (i
=0; i
<len
; i
++) {
233 mrb_sym id
= mrb_symbol(ptr_members
[i
]);
234 const char *name
= mrb_sym2name_len(mrb
, id
, NULL
);
236 if (is_local_id(mrb
, name
) || is_const_id(mrb
, name
)) {
237 if (i
< N_REF_FUNC
) {
238 mrb_define_method_id(mrb
, c
, id
, ref_func
[i
], MRB_ARGS_NONE());
241 mrb_define_method_id(mrb
, c
, id
, mrb_struct_ref
, MRB_ARGS_NONE());
243 mrb_define_method_id(mrb
, c
, mrb_id_attrset(mrb
, id
), mrb_struct_set_m
, MRB_ARGS_REQ(1));
244 mrb_gc_arena_restore(mrb
, ai
);
250 make_struct(mrb_state
*mrb
, mrb_value name
, mrb_value members
, struct RClass
* klass
)
256 if (mrb_nil_p(name
)) {
257 c
= mrb_class_new(mrb
, klass
);
260 /* old style: should we warn? */
261 name
= mrb_str_to_str(mrb
, name
);
262 id
= mrb_obj_to_sym(mrb
, name
);
263 if (!is_const_id(mrb
, mrb_sym2name_len(mrb
, id
, NULL
))) {
264 mrb_name_error(mrb
, id
, "identifier %S needs to be constant", name
);
266 if (mrb_const_defined_at(mrb
, klass
, id
)) {
267 mrb_warn(mrb
, "redefining constant Struct::%S", name
);
268 /* ?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); */
270 c
= mrb_define_class_under(mrb
, klass
, RSTRING_PTR(name
), klass
);
272 MRB_SET_INSTANCE_TT(c
, MRB_TT_ARRAY
);
273 nstr
= mrb_obj_value(c
);
274 mrb_iv_set(mrb
, nstr
, mrb_intern_lit(mrb
, "__members__"), members
);
276 mrb_define_class_method(mrb
, c
, "new", mrb_instance_new
, MRB_ARGS_ANY());
277 mrb_define_class_method(mrb
, c
, "[]", mrb_instance_new
, MRB_ARGS_ANY());
278 mrb_define_class_method(mrb
, c
, "members", mrb_struct_s_members_m
, MRB_ARGS_NONE());
279 /* RSTRUCT(nstr)->basic.c->super = c->c; */
280 make_struct_define_accessors(mrb
, members
, c
);
287 * Struct.new( [aString] [, aSym]+> ) -> StructClass
288 * StructClass.new(arg, ...) -> obj
289 * StructClass[arg, ...] -> obj
291 * Creates a new class, named by <i>aString</i>, containing accessor
292 * methods for the given symbols. If the name <i>aString</i> is
293 * omitted, an anonymous structure class will be created. Otherwise,
294 * the name of this struct will appear as a constant in class
295 * <code>Struct</code>, so it must be unique for all
296 * <code>Struct</code>s in the system and should start with a capital
297 * letter. Assigning a structure class to a constant effectively gives
298 * the class the name of the constant.
300 * <code>Struct::new</code> returns a new <code>Class</code> object,
301 * which can then be used to create specific instances of the new
302 * structure. The number of actual parameters must be
303 * less than or equal to the number of attributes defined for this
304 * class; unset parameters default to <code>nil</code>. Passing too many
305 * parameters will raise an <code>ArgumentError</code>.
307 * The remaining methods listed in this section (class and instance)
308 * are defined for this generated class.
310 * # Create a structure with a name in Struct
311 * Struct.new("Customer", :name, :address) #=> Struct::Customer
312 * Struct::Customer.new("Dave", "123 Main") #=> #<struct Struct::Customer name="Dave", address="123 Main">
314 * # Create a structure named by its constant
315 * Customer = Struct.new(:name, :address) #=> Customer
316 * Customer.new("Dave", "123 Main") #=> #<struct Customer name="Dave", address="123 Main">
319 mrb_struct_s_def(mrb_state
*mrb
, mrb_value klass
)
321 mrb_value name
, rest
;
330 name
= mrb_nil_value();
331 rest
= mrb_nil_value();
332 mrb_get_args(mrb
, "*&", &argv
, &argc
, &b
);
333 if (argc
== 0) { /* special case to avoid crash */
334 rest
= mrb_ary_new(mrb
);
337 if (argc
> 0) name
= argv
[0];
338 if (argc
> 1) rest
= argv
[1];
339 if (mrb_array_p(rest
)) {
340 if (!mrb_nil_p(name
) && mrb_symbol_p(name
)) {
341 /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
342 mrb_ary_unshift(mrb
, rest
, name
);
343 name
= mrb_nil_value();
349 if (!mrb_nil_p(name
) && mrb_symbol_p(name
)) {
350 /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
351 name
= mrb_nil_value();
355 rest
= mrb_ary_new_from_values(mrb
, argcnt
, pargv
);
357 for (i
=0; i
<RARRAY_LEN(rest
); i
++) {
358 id
= mrb_obj_to_sym(mrb
, RARRAY_PTR(rest
)[i
]);
359 mrb_ary_set(mrb
, rest
, i
, mrb_symbol_value(id
));
362 st
= make_struct(mrb
, name
, rest
, struct_class(mrb
));
364 mrb_yield_with_class(mrb
, b
, 1, &st
, st
, mrb_class_ptr(klass
));
371 num_members(mrb_state
*mrb
, struct RClass
*klass
)
375 members
= struct_ivar_get(mrb
, mrb_obj_value(klass
), mrb_intern_lit(mrb
, "__members__"));
376 if (!mrb_array_p(members
)) {
377 mrb_raise(mrb
, E_TYPE_ERROR
, "broken members");
379 return RARRAY_LEN(members
);
386 mrb_struct_initialize_withArg(mrb_state
*mrb
, mrb_int argc
, mrb_value
*argv
, mrb_value self
)
388 struct RClass
*klass
= mrb_obj_class(mrb
, self
);
391 n
= num_members(mrb
, klass
);
393 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "struct size differs");
396 for (i
= 0; i
< argc
; i
++) {
397 mrb_ary_set(mrb
, self
, i
, argv
[i
]);
399 for (i
= argc
; i
< n
; i
++) {
400 mrb_ary_set(mrb
, self
, i
, mrb_nil_value());
406 mrb_struct_initialize_m(mrb_state
*mrb
, /*int argc, mrb_value *argv,*/ mrb_value self
)
411 mrb_get_args(mrb
, "*", &argv
, &argc
);
412 return mrb_struct_initialize_withArg(mrb
, argc
, argv
, self
);
416 inspect_struct(mrb_state
*mrb
, mrb_value s
, mrb_bool recur
)
418 const char *cn
= mrb_class_name(mrb
, mrb_obj_class(mrb
, s
));
419 mrb_value members
, str
= mrb_str_new_lit(mrb
, "#<struct ");
421 const mrb_value
*ptr_members
;
425 mrb_str_append(mrb
, str
, mrb_str_new_cstr(mrb
, cn
));
428 return mrb_str_cat_lit(mrb
, str
, ":...>");
431 members
= mrb_struct_members(mrb
, s
);
432 ptr_members
= RARRAY_PTR(members
);
433 ptr
= RSTRUCT_PTR(s
);
434 len
= RSTRUCT_LEN(s
);
435 for (i
=0; i
<len
; i
++) {
442 mrb_str_cat_lit(mrb
, str
, ", ");
445 mrb_str_cat_lit(mrb
, str
, " ");
447 slot
= ptr_members
[i
];
448 id
= mrb_symbol(slot
);
449 name
= mrb_sym2name_len(mrb
, id
, &namelen
);
450 if (is_local_id(mrb
, name
) || is_const_id(mrb
, name
)) {
451 mrb_str_append(mrb
, str
, mrb_str_new(mrb
, name
, namelen
));
454 mrb_str_append(mrb
, str
, mrb_inspect(mrb
, slot
));
456 mrb_str_cat_lit(mrb
, str
, "=");
457 mrb_str_append(mrb
, str
, mrb_inspect(mrb
, ptr
[i
]));
459 mrb_str_cat_lit(mrb
, str
, ">");
466 * struct.to_s -> string
467 * struct.inspect -> string
469 * Describe the contents of this struct in a string.
472 mrb_struct_inspect(mrb_state
*mrb
, mrb_value s
)
474 return inspect_struct(mrb
, s
, FALSE
);
480 mrb_struct_init_copy(mrb_state
*mrb
, mrb_value copy
)
485 mrb_get_args(mrb
, "o", &s
);
487 if (mrb_obj_equal(mrb
, copy
, s
)) return copy
;
488 if (!mrb_obj_is_instance_of(mrb
, s
, mrb_obj_class(mrb
, copy
))) {
489 mrb_raise(mrb
, E_TYPE_ERROR
, "wrong argument class");
491 if (!mrb_array_p(s
)) {
492 mrb_raise(mrb
, E_TYPE_ERROR
, "corrupted struct");
494 if (RSTRUCT_LEN(copy
) != RSTRUCT_LEN(s
)) {
495 mrb_raise(mrb
, E_TYPE_ERROR
, "struct size mismatch");
497 len
= RSTRUCT_LEN(copy
);
498 for (i
= 0; i
< len
; i
++) {
499 mrb_ary_set(mrb
, copy
, i
, RSTRUCT_PTR(s
)[i
]);
505 struct_aref_sym(mrb_state
*mrb
, mrb_value s
, mrb_sym id
)
507 mrb_value
*ptr
, members
;
508 const mrb_value
*ptr_members
;
511 ptr
= RSTRUCT_PTR(s
);
512 members
= mrb_struct_members(mrb
, s
);
513 ptr_members
= RARRAY_PTR(members
);
514 len
= RARRAY_LEN(members
);
515 for (i
=0; i
<len
; i
++) {
516 if (mrb_symbol(ptr_members
[i
]) == id
) {
520 mrb_raisef(mrb
, E_INDEX_ERROR
, "no member '%S' in struct", mrb_sym2str(mrb
, id
));
521 return mrb_nil_value(); /* not reached */
525 struct_aref_int(mrb_state
*mrb
, mrb_value s
, mrb_int i
)
527 if (i
< 0) i
= RSTRUCT_LEN(s
) + i
;
529 mrb_raisef(mrb
, E_INDEX_ERROR
,
530 "offset %S too small for struct(size:%S)",
531 mrb_fixnum_value(i
), mrb_fixnum_value(RSTRUCT_LEN(s
)));
532 if (RSTRUCT_LEN(s
) <= i
)
533 mrb_raisef(mrb
, E_INDEX_ERROR
,
534 "offset %S too large for struct(size:%S)",
535 mrb_fixnum_value(i
), mrb_fixnum_value(RSTRUCT_LEN(s
)));
536 return RSTRUCT_PTR(s
)[i
];
542 * struct[symbol] -> anObject
543 * struct[fixnum] -> anObject
545 * Attribute Reference---Returns the value of the instance variable
546 * named by <i>symbol</i>, or indexed (0..length-1) by
547 * <i>fixnum</i>. Will raise <code>NameError</code> if the named
548 * variable does not exist, or <code>IndexError</code> if the index is
551 * Customer = Struct.new(:name, :address, :zip)
552 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
554 * joe["name"] #=> "Joe Smith"
555 * joe[:name] #=> "Joe Smith"
556 * joe[0] #=> "Joe Smith"
559 mrb_struct_aref(mrb_state
*mrb
, mrb_value s
)
563 mrb_get_args(mrb
, "o", &idx
);
564 if (mrb_string_p(idx
)) {
565 mrb_value sym
= mrb_check_intern_str(mrb
, idx
);
567 if (mrb_nil_p(sym
)) {
568 mrb_raisef(mrb
, E_INDEX_ERROR
, "no member '%S' in struct", idx
);
572 if (mrb_symbol_p(idx
)) {
573 return struct_aref_sym(mrb
, s
, mrb_symbol(idx
));
575 return struct_aref_int(mrb
, s
, mrb_int(mrb
, idx
));
579 mrb_struct_aset_sym(mrb_state
*mrb
, mrb_value s
, mrb_sym id
, mrb_value val
)
581 mrb_value members
, *ptr
;
582 const mrb_value
*ptr_members
;
585 members
= mrb_struct_members(mrb
, s
);
586 len
= RARRAY_LEN(members
);
587 if (RSTRUCT_LEN(s
) != len
) {
588 mrb_raisef(mrb
, E_TYPE_ERROR
,
589 "struct size differs (%S required %S given)",
590 mrb_fixnum_value(len
), mrb_fixnum_value(RSTRUCT_LEN(s
)));
592 ptr
= RSTRUCT_PTR(s
);
593 ptr_members
= RARRAY_PTR(members
);
594 for (i
=0; i
<len
; i
++) {
595 if (mrb_symbol(ptr_members
[i
]) == id
) {
600 mrb_raisef(mrb
, E_INDEX_ERROR
, "no member '%S' in struct", mrb_sym2str(mrb
, id
));
601 return val
; /* not reach */
607 * struct[symbol] = obj -> obj
608 * struct[fixnum] = obj -> obj
610 * Attribute Assignment---Assigns to the instance variable named by
611 * <i>symbol</i> or <i>fixnum</i> the value <i>obj</i> and
612 * returns it. Will raise a <code>NameError</code> if the named
613 * variable does not exist, or an <code>IndexError</code> if the index
616 * Customer = Struct.new(:name, :address, :zip)
617 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
619 * joe["name"] = "Luke"
620 * joe[:zip] = "90210"
622 * joe.name #=> "Luke"
623 * joe.zip #=> "90210"
627 mrb_struct_aset(mrb_state
*mrb
, mrb_value s
)
633 mrb_get_args(mrb
, "oo", &idx
, &val
);
635 if (mrb_string_p(idx
)) {
636 mrb_value sym
= mrb_check_intern_str(mrb
, idx
);
638 if (mrb_nil_p(sym
)) {
639 mrb_raisef(mrb
, E_INDEX_ERROR
, "no member '%S' in struct", idx
);
643 if (mrb_symbol_p(idx
)) {
644 return mrb_struct_aset_sym(mrb
, s
, mrb_symbol(idx
), val
);
647 i
= mrb_int(mrb
, idx
);
648 if (i
< 0) i
= RSTRUCT_LEN(s
) + i
;
650 mrb_raisef(mrb
, E_INDEX_ERROR
,
651 "offset %S too small for struct(size:%S)",
652 mrb_fixnum_value(i
), mrb_fixnum_value(RSTRUCT_LEN(s
)));
654 if (RSTRUCT_LEN(s
) <= i
) {
655 mrb_raisef(mrb
, E_INDEX_ERROR
,
656 "offset %S too large for struct(size:%S)",
657 mrb_fixnum_value(i
), mrb_fixnum_value(RSTRUCT_LEN(s
)));
659 return RSTRUCT_PTR(s
)[i
] = val
;
665 * struct == other_struct -> true or false
667 * Equality---Returns <code>true</code> if <i>other_struct</i> is
668 * equal to this one: they must be of the same class as generated by
669 * <code>Struct::new</code>, and the values of all instance variables
670 * must be equal (according to <code>Object#==</code>).
672 * Customer = Struct.new(:name, :address, :zip)
673 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
674 * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
675 * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
676 * joe == joejr #=> true
677 * joe == jane #=> false
681 mrb_struct_equal(mrb_state
*mrb
, mrb_value s
)
684 mrb_value
*ptr
, *ptr2
;
688 mrb_get_args(mrb
, "o", &s2
);
689 if (mrb_obj_equal(mrb
, s
, s2
)) {
692 else if (!strcmp(mrb_class_name(mrb
, mrb_obj_class(mrb
, s
)), "Struct") ||
693 mrb_obj_class(mrb
, s
) != mrb_obj_class(mrb
, s2
)) {
696 else if (RSTRUCT_LEN(s
) != RSTRUCT_LEN(s2
)) {
697 mrb_bug(mrb
, "inconsistent struct"); /* should never happen */
698 equal_p
= 0; /* This substuture is just to suppress warnings. never called. */
701 ptr
= RSTRUCT_PTR(s
);
702 ptr2
= RSTRUCT_PTR(s2
);
703 len
= RSTRUCT_LEN(s
);
705 for (i
=0; i
<len
; i
++) {
706 if (!mrb_equal(mrb
, ptr
[i
], ptr2
[i
])) {
713 return mrb_bool_value(equal_p
);
716 /* 15.2.18.4.12(x) */
719 * struct.eql?(other) -> true or false
721 * Two structures are equal if they are the same object, or if all their
722 * fields are equal (using <code>eql?</code>).
725 mrb_struct_eql(mrb_state
*mrb
, mrb_value s
)
728 mrb_value
*ptr
, *ptr2
;
732 mrb_get_args(mrb
, "o", &s2
);
733 if (mrb_obj_equal(mrb
, s
, s2
)) {
736 else if (strcmp(mrb_class_name(mrb
, mrb_obj_class(mrb
, s2
)), "Struct") ||
737 mrb_obj_class(mrb
, s
) != mrb_obj_class(mrb
, s2
)) {
740 else if (RSTRUCT_LEN(s
) != RSTRUCT_LEN(s2
)) {
741 mrb_bug(mrb
, "inconsistent struct"); /* should never happen */
742 eql_p
= 0; /* This substuture is just to suppress warnings. never called. */
745 ptr
= RSTRUCT_PTR(s
);
746 ptr2
= RSTRUCT_PTR(s2
);
747 len
= RSTRUCT_LEN(s
);
749 for (i
=0; i
<len
; i
++) {
750 if (!mrb_eql(mrb
, ptr
[i
], ptr2
[i
])) {
757 return mrb_bool_value(eql_p
);
762 * struct.length -> Fixnum
763 * struct.size -> Fixnum
765 * Returns number of struct members.
768 mrb_struct_len(mrb_state
*mrb
, mrb_value self
)
770 return mrb_fixnum_value(RSTRUCT_LEN(self
));
775 * struct.to_a -> array
776 * struct.values -> array
778 * Create an array from struct values.
781 mrb_struct_to_a(mrb_state
*mrb
, mrb_value self
)
783 return mrb_ary_new_from_values(mrb
, RSTRUCT_LEN(self
), RSTRUCT_PTR(self
));
788 * struct.to_h -> hash
790 * Create a hash from member names and struct values.
793 mrb_struct_to_h(mrb_state
*mrb
, mrb_value self
)
795 mrb_value members
, ret
;
798 members
= mrb_struct_s_members(mrb
, mrb_obj_value(mrb_class(mrb
, self
)));
799 ret
= mrb_hash_new_capa(mrb
, RARRAY_LEN(members
));
801 for (i
= 0; i
< RARRAY_LEN(members
); ++i
) {
802 mrb_hash_set(mrb
, ret
, RARRAY_PTR(members
)[i
], RSTRUCT_PTR(self
)[i
]);
809 mrb_struct_values_at(mrb_state
*mrb
, mrb_value self
)
814 mrb_get_args(mrb
, "*", &argv
, &argc
);
816 return mrb_get_values_at(mrb
, self
, RSTRUCT_LEN(self
), argc
, argv
, struct_aref_int
);
820 * A <code>Struct</code> is a convenient way to bundle a number of
821 * attributes together, using accessor methods, without having to write
824 * The <code>Struct</code> class is a generator of specific classes,
825 * each one of which is defined to hold a set of variables and their
826 * accessors. In these examples, we'll call the generated class
827 * ``<i>Customer</i>Class,'' and we'll show an example instance of that
828 * class as ``<i>Customer</i>Inst.''
830 * In the descriptions that follow, the parameter <i>symbol</i> refers
831 * to a symbol, which is either a quoted string or a
832 * <code>Symbol</code> (such as <code>:name</code>).
835 mrb_mruby_struct_gem_init(mrb_state
* mrb
)
838 st
= mrb_define_class(mrb
, "Struct", mrb
->object_class
);
840 mrb_define_class_method(mrb
, st
, "new", mrb_struct_s_def
, MRB_ARGS_ANY()); /* 15.2.18.3.1 */
842 mrb_define_method(mrb
, st
, "==", mrb_struct_equal
, MRB_ARGS_REQ(1)); /* 15.2.18.4.1 */
843 mrb_define_method(mrb
, st
, "[]", mrb_struct_aref
, MRB_ARGS_REQ(1)); /* 15.2.18.4.2 */
844 mrb_define_method(mrb
, st
, "[]=", mrb_struct_aset
, MRB_ARGS_REQ(2)); /* 15.2.18.4.3 */
845 mrb_define_method(mrb
, st
, "members", mrb_struct_members_m
, MRB_ARGS_NONE()); /* 15.2.18.4.6 */
846 mrb_define_method(mrb
, st
, "initialize", mrb_struct_initialize_m
,MRB_ARGS_ANY()); /* 15.2.18.4.8 */
847 mrb_define_method(mrb
, st
, "initialize_copy", mrb_struct_init_copy
, MRB_ARGS_REQ(1)); /* 15.2.18.4.9 */
848 mrb_define_method(mrb
, st
, "inspect", mrb_struct_inspect
, MRB_ARGS_NONE()); /* 15.2.18.4.10(x) */
849 mrb_define_alias(mrb
, st
, "to_s", "inspect"); /* 15.2.18.4.11(x) */
850 mrb_define_method(mrb
, st
, "eql?", mrb_struct_eql
, MRB_ARGS_REQ(1)); /* 15.2.18.4.12(x) */
852 mrb_define_method(mrb
, st
, "size", mrb_struct_len
, MRB_ARGS_NONE());
853 mrb_define_method(mrb
, st
, "length", mrb_struct_len
, MRB_ARGS_NONE());
854 mrb_define_method(mrb
, st
, "to_a", mrb_struct_to_a
, MRB_ARGS_NONE());
855 mrb_define_method(mrb
, st
, "values", mrb_struct_to_a
, MRB_ARGS_NONE());
856 mrb_define_method(mrb
, st
, "to_h", mrb_struct_to_h
, MRB_ARGS_NONE());
857 mrb_define_method(mrb
, st
, "values_at", mrb_struct_values_at
, MRB_ARGS_NONE());
861 mrb_mruby_struct_gem_final(mrb_state
* mrb
)