Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
struct.c
Go to the documentation of this file.
1/**********************************************************************
2
3 struct.c -
4
5 $Author$
6 created at: Tue Mar 22 18:44:30 JST 1995
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9
10**********************************************************************/
11
12#include "internal.h"
13#include "vm_core.h"
14#include "id.h"
15#include "transient_heap.h"
16
17/* only for struct[:field] access */
18enum {
21};
22
25
27static ID id_members, id_back_members, id_keyword_init;
28
29static VALUE struct_alloc(VALUE);
30
31static inline VALUE
32struct_ivar_get(VALUE c, ID id)
33{
34 VALUE orig = c;
35 VALUE ivar = rb_attr_get(c, id);
36
37 if (!NIL_P(ivar))
38 return ivar;
39
40 for (;;) {
41 c = RCLASS_SUPER(c);
42 if (c == 0 || c == rb_cStruct)
43 return Qnil;
44 ivar = rb_attr_get(c, id);
45 if (!NIL_P(ivar)) {
46 return rb_ivar_set(orig, id, ivar);
47 }
48 }
49}
50
53{
54 return struct_ivar_get(klass, id_keyword_init);
55}
56
59{
60 VALUE members = struct_ivar_get(klass, id_members);
61
62 if (NIL_P(members)) {
63 rb_raise(rb_eTypeError, "uninitialized struct");
64 }
65 if (!RB_TYPE_P(members, T_ARRAY)) {
66 rb_raise(rb_eTypeError, "corrupted struct");
67 }
68 return members;
69}
70
73{
75
76 if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
77 rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
78 RARRAY_LEN(members), RSTRUCT_LEN(s));
79 }
80 return members;
81}
82
83static long
84struct_member_pos_ideal(VALUE name, long mask)
85{
86 /* (id & (mask/2)) * 2 */
87 return (SYM2ID(name) >> (ID_SCOPE_SHIFT - 1)) & mask;
88}
89
90static long
91struct_member_pos_probe(long prev, long mask)
92{
93 /* (((prev/2) * AREF_HASH_UNIT + 1) & (mask/2)) * 2 */
94 return (prev * AREF_HASH_UNIT + 2) & mask;
95}
96
97static VALUE
98struct_set_members(VALUE klass, VALUE /* frozen hidden array */ members)
99{
100 VALUE back;
101 const long members_length = RARRAY_LEN(members);
102
103 if (members_length <= AREF_HASH_THRESHOLD) {
104 back = members;
105 }
106 else {
107 long i, j, mask = 64;
108 VALUE name;
109
110 while (mask < members_length * AREF_HASH_UNIT) mask *= 2;
111
112 back = rb_ary_tmp_new(mask + 1);
113 rb_ary_store(back, mask, INT2FIX(members_length));
114 mask -= 2; /* mask = (2**k-1)*2 */
115
116 for (i=0; i < members_length; i++) {
117 name = RARRAY_AREF(members, i);
118
119 j = struct_member_pos_ideal(name, mask);
120
121 for (;;) {
122 if (!RTEST(RARRAY_AREF(back, j))) {
123 rb_ary_store(back, j, name);
124 rb_ary_store(back, j + 1, INT2FIX(i));
125 break;
126 }
127 j = struct_member_pos_probe(j, mask);
128 }
129 }
130 OBJ_FREEZE_RAW(back);
131 }
132 rb_ivar_set(klass, id_members, members);
133 rb_ivar_set(klass, id_back_members, back);
134
135 return members;
136}
137
138static inline int
139struct_member_pos(VALUE s, VALUE name)
140{
141 VALUE back = struct_ivar_get(rb_obj_class(s), id_back_members);
142 long j, mask;
143
144 if (UNLIKELY(NIL_P(back))) {
145 rb_raise(rb_eTypeError, "uninitialized struct");
146 }
147 if (UNLIKELY(!RB_TYPE_P(back, T_ARRAY))) {
148 rb_raise(rb_eTypeError, "corrupted struct");
149 }
150
151 mask = RARRAY_LEN(back);
152
153 if (mask <= AREF_HASH_THRESHOLD) {
154 if (UNLIKELY(RSTRUCT_LEN(s) != mask)) {
156 "struct size differs (%ld required %ld given)",
157 mask, RSTRUCT_LEN(s));
158 }
159 for (j = 0; j < mask; j++) {
160 if (RARRAY_AREF(back, j) == name)
161 return (int)j;
162 }
163 return -1;
164 }
165
166 if (UNLIKELY(RSTRUCT_LEN(s) != FIX2INT(RARRAY_AREF(back, mask-1)))) {
167 rb_raise(rb_eTypeError, "struct size differs (%d required %ld given)",
168 FIX2INT(RARRAY_AREF(back, mask-1)), RSTRUCT_LEN(s));
169 }
170
171 mask -= 3;
172 j = struct_member_pos_ideal(name, mask);
173
174 for (;;) {
175 VALUE e = RARRAY_AREF(back, j);
176 if (e == name)
177 return FIX2INT(RARRAY_AREF(back, j + 1));
178 if (!RTEST(e)) {
179 return -1;
180 }
181 j = struct_member_pos_probe(j, mask);
182 }
183}
184
185static VALUE
186rb_struct_s_members_m(VALUE klass)
187{
189
190 return rb_ary_dup(members);
191}
192
193/*
194 * call-seq:
195 * struct.members -> array
196 *
197 * Returns the struct members as an array of symbols:
198 *
199 * Customer = Struct.new(:name, :address, :zip)
200 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
201 * joe.members #=> [:name, :address, :zip]
202 */
203
204static VALUE
205rb_struct_members_m(VALUE obj)
206{
207 return rb_struct_s_members_m(rb_obj_class(obj));
208}
209
210VALUE
212{
213 VALUE slot = ID2SYM(id);
214 int i = struct_member_pos(obj, slot);
215 if (i != -1) {
216 return RSTRUCT_GET(obj, i);
217 }
218 rb_name_err_raise("`%1$s' is not a struct member", obj, ID2SYM(id));
219
221}
222
223static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);}
224static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);}
225static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);}
226static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_GET(obj, 3);}
227static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_GET(obj, 4);}
228static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_GET(obj, 5);}
229static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_GET(obj, 6);}
230static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_GET(obj, 7);}
231static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_GET(obj, 8);}
232static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_GET(obj, 9);}
233
234#define N_REF_FUNC numberof(ref_func)
235
236static VALUE (*const ref_func[])(VALUE) = {
237 rb_struct_ref0,
238 rb_struct_ref1,
239 rb_struct_ref2,
240 rb_struct_ref3,
241 rb_struct_ref4,
242 rb_struct_ref5,
243 rb_struct_ref6,
244 rb_struct_ref7,
245 rb_struct_ref8,
246 rb_struct_ref9,
247};
248
249static void
250rb_struct_modify(VALUE s)
251{
253}
254
255static VALUE
256anonymous_struct(VALUE klass)
257{
258 VALUE nstr;
259
260 nstr = rb_class_new(klass);
263 return nstr;
264}
265
266static VALUE
267new_struct(VALUE name, VALUE super)
268{
269 /* old style: should we warn? */
270 ID id;
272 if (!rb_is_const_name(name)) {
273 rb_name_err_raise("identifier %1$s needs to be constant",
274 super, name);
275 }
276 id = rb_to_id(name);
277 if (rb_const_defined_at(super, id)) {
278 rb_warn("redefining constant %"PRIsVALUE"::%"PRIsVALUE, super, name);
279 rb_mod_remove_const(super, ID2SYM(id));
280 }
281 return rb_define_class_id_under(super, id, super);
282}
283
284static void
285define_aref_method(VALUE nstr, VALUE name, VALUE off)
286{
289
291}
292
293static void
294define_aset_method(VALUE nstr, VALUE name, VALUE off)
295{
298
300}
301
302static VALUE
303rb_struct_s_inspect(VALUE klass)
304{
305 VALUE inspect = rb_class_name(klass);
307 rb_str_cat_cstr(inspect, "(keyword_init: true)");
308 }
309 return inspect;
310}
311
312static VALUE
313struct_new_kw(int argc, const VALUE *argv, VALUE klass)
314{
316}
317
318static VALUE
319setup_struct(VALUE nstr, VALUE members)
320{
321 long i, len;
322
323 members = struct_set_members(nstr, members);
324
325 rb_define_alloc_func(nstr, struct_alloc);
326 rb_define_singleton_method(nstr, "new", struct_new_kw, -1);
327 rb_define_singleton_method(nstr, "[]", struct_new_kw, -1);
328 rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0);
329 rb_define_singleton_method(nstr, "inspect", rb_struct_s_inspect, 0);
330 len = RARRAY_LEN(members);
331 for (i=0; i< len; i++) {
332 VALUE sym = RARRAY_AREF(members, i);
333 ID id = SYM2ID(sym);
334 VALUE off = LONG2NUM(i);
335
336 if (i < N_REF_FUNC) {
337 rb_define_method_id(nstr, id, ref_func[i], 0);
338 }
339 else {
340 define_aref_method(nstr, sym, off);
341 }
342 define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off);
343 }
344
345 return nstr;
346}
347
348VALUE
350{
351 return struct_alloc(klass);
352}
353
354static VALUE
355struct_make_members_list(va_list ar)
356{
357 char *mem;
359 st_table *tbl = RHASH_TBL(list);
360
362 while ((mem = va_arg(ar, char*)) != 0) {
364 if (st_insert(tbl, sym, Qtrue)) {
365 rb_raise(rb_eArgError, "duplicate member: %s", mem);
366 }
367 }
368 ary = rb_hash_keys(list);
369 st_clear(tbl);
371 OBJ_FREEZE_RAW(ary);
372 return ary;
373}
374
375static VALUE
376struct_define_without_accessor(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, VALUE members)
377{
378 VALUE klass;
379
380 if (class_name) {
381 if (outer) {
382 klass = rb_define_class_under(outer, class_name, super);
383 }
384 else {
385 klass = rb_define_class(class_name, super);
386 }
387 }
388 else {
389 klass = anonymous_struct(super);
390 }
391
392 struct_set_members(klass, members);
393
394 if (alloc) {
396 }
397 else {
398 rb_define_alloc_func(klass, struct_alloc);
399 }
400
401 return klass;
402}
403
404VALUE
405rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
406{
407 va_list ar;
408 VALUE members;
409
410 va_start(ar, alloc);
411 members = struct_make_members_list(ar);
412 va_end(ar);
413
414 return struct_define_without_accessor(outer, class_name, super, alloc, members);
415}
416
417VALUE
418rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
419{
420 va_list ar;
421 VALUE members;
422
423 va_start(ar, alloc);
424 members = struct_make_members_list(ar);
425 va_end(ar);
426
427 return struct_define_without_accessor(0, class_name, super, alloc, members);
428}
429
430VALUE
431rb_struct_define(const char *name, ...)
432{
433 va_list ar;
434 VALUE st, ary;
435
436 va_start(ar, name);
437 ary = struct_make_members_list(ar);
438 va_end(ar);
439
440 if (!name) st = anonymous_struct(rb_cStruct);
441 else st = new_struct(rb_str_new2(name), rb_cStruct);
442 return setup_struct(st, ary);
443}
444
445VALUE
446rb_struct_define_under(VALUE outer, const char *name, ...)
447{
448 va_list ar;
449 VALUE ary;
450
451 va_start(ar, name);
452 ary = struct_make_members_list(ar);
453 va_end(ar);
454
455 return setup_struct(rb_define_class_under(outer, name, rb_cStruct), ary);
456}
457
458/*
459 * call-seq:
460 * Struct.new([class_name] [, member_name]+) -> StructClass
461 * Struct.new([class_name] [, member_name]+, keyword_init: true) -> StructClass
462 * Struct.new([class_name] [, member_name]+) {|StructClass| block } -> StructClass
463 * StructClass.new(value, ...) -> object
464 * StructClass[value, ...] -> object
465 *
466 * The first two forms are used to create a new Struct subclass +class_name+
467 * that can contain a value for each +member_name+. This subclass can be
468 * used to create instances of the structure like any other Class.
469 *
470 * If the +class_name+ is omitted an anonymous structure class will be
471 * created. Otherwise, the name of this struct will appear as a constant in
472 * class Struct, so it must be unique for all Structs in the system and
473 * must start with a capital letter. Assigning a structure class to a
474 * constant also gives the class the name of the constant.
475 *
476 * # Create a structure with a name under Struct
477 * Struct.new("Customer", :name, :address)
478 * #=> Struct::Customer
479 * Struct::Customer.new("Dave", "123 Main")
480 * #=> #<struct Struct::Customer name="Dave", address="123 Main">
481 *
482 * # Create a structure named by its constant
483 * Customer = Struct.new(:name, :address)
484 * #=> Customer
485 * Customer.new("Dave", "123 Main")
486 * #=> #<struct Customer name="Dave", address="123 Main">
487 *
488 * If the optional +keyword_init+ keyword argument is set to +true+,
489 * .new takes keyword arguments instead of normal arguments.
490 *
491 * Customer = Struct.new(:name, :address, keyword_init: true)
492 * Customer.new(name: "Dave", address: "123 Main")
493 * #=> #<struct Customer name="Dave", address="123 Main">
494 *
495 * If a block is given it will be evaluated in the context of
496 * +StructClass+, passing the created class as a parameter:
497 *
498 * Customer = Struct.new(:name, :address) do
499 * def greeting
500 * "Hello #{name}!"
501 * end
502 * end
503 * Customer.new("Dave", "123 Main").greeting #=> "Hello Dave!"
504 *
505 * This is the recommended way to customize a struct. Subclassing an
506 * anonymous struct creates an extra anonymous class that will never be used.
507 *
508 * The last two forms create a new instance of a struct subclass. The number
509 * of +value+ parameters must be less than or equal to the number of
510 * attributes defined for the structure. Unset parameters default to +nil+.
511 * Passing more parameters than number of attributes will raise
512 * an ArgumentError.
513 *
514 * Customer = Struct.new(:name, :address)
515 * Customer.new("Dave", "123 Main")
516 * #=> #<struct Customer name="Dave", address="123 Main">
517 * Customer["Dave"]
518 * #=> #<struct Customer name="Dave", address=nil>
519 */
520
521static VALUE
522rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
523{
524 VALUE name, rest, keyword_init = Qfalse;
525 long i;
526 VALUE st;
527 st_table *tbl;
528
530 name = argv[0];
531 if (SYMBOL_P(name)) {
532 name = Qnil;
533 }
534 else {
535 --argc;
536 ++argv;
537 }
538
539 if (RB_TYPE_P(argv[argc-1], T_HASH)) {
540 static ID keyword_ids[1];
541
542 if (!keyword_ids[0]) {
543 keyword_ids[0] = rb_intern("keyword_init");
544 }
545 rb_get_kwargs(argv[argc-1], keyword_ids, 0, 1, &keyword_init);
546 if (keyword_init == Qundef) {
547 keyword_init = Qfalse;
548 }
549 --argc;
550 }
551
552 rest = rb_ident_hash_new();
553 RBASIC_CLEAR_CLASS(rest);
554 tbl = RHASH_TBL(rest);
555 for (i=0; i<argc; i++) {
556 VALUE mem = rb_to_symbol(argv[i]);
557 if (rb_is_attrset_sym(mem)) {
558 rb_raise(rb_eArgError, "invalid struct member: %"PRIsVALUE, mem);
559 }
560 if (st_insert(tbl, mem, Qtrue)) {
561 rb_raise(rb_eArgError, "duplicate member: %"PRIsVALUE, mem);
562 }
563 }
564 rest = rb_hash_keys(rest);
565 st_clear(tbl);
566 RBASIC_CLEAR_CLASS(rest);
567 OBJ_FREEZE_RAW(rest);
568 if (NIL_P(name)) {
569 st = anonymous_struct(klass);
570 }
571 else {
572 st = new_struct(name, klass);
573 }
574 setup_struct(st, rest);
575 rb_ivar_set(st, id_keyword_init, keyword_init);
576 if (rb_block_given_p()) {
577 rb_mod_module_eval(0, 0, st);
578 }
579
580 return st;
581}
582
583static long
584num_members(VALUE klass)
585{
586 VALUE members;
587 members = struct_ivar_get(klass, id_members);
588 if (!RB_TYPE_P(members, T_ARRAY)) {
589 rb_raise(rb_eTypeError, "broken members");
590 }
591 return RARRAY_LEN(members);
592}
593
594/*
595 */
596
598 VALUE self;
600};
601
602static int rb_struct_pos(VALUE s, VALUE *name);
603
604static int
605struct_hash_set_i(VALUE key, VALUE val, VALUE arg)
606{
607 struct struct_hash_set_arg *args = (struct struct_hash_set_arg *)arg;
608 int i = rb_struct_pos(args->self, &key);
609 if (i < 0) {
610 if (args->unknown_keywords == Qnil) {
612 }
614 }
615 else {
616 rb_struct_modify(args->self);
617 RSTRUCT_SET(args->self, i, val);
618 }
619 return ST_CONTINUE;
620}
621
622static VALUE
623rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self)
624{
625 VALUE klass = rb_obj_class(self);
626 long i, n;
627
628 rb_struct_modify(self);
629 n = num_members(klass);
632 if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
633 rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0)", argc);
634 }
636 arg.self = self;
637 arg.unknown_keywords = Qnil;
638 rb_hash_foreach(argv[0], struct_hash_set_i, (VALUE)&arg);
639 if (arg.unknown_keywords != Qnil) {
640 rb_raise(rb_eArgError, "unknown keywords: %s",
641 RSTRING_PTR(rb_ary_join(arg.unknown_keywords, rb_str_new2(", "))));
642 }
643 }
644 else {
645 if (n < argc) {
646 rb_raise(rb_eArgError, "struct size differs");
647 }
648 for (i=0; i<argc; i++) {
649 RSTRUCT_SET(self, i, argv[i]);
650 }
651 if (n > argc) {
653 }
654 }
655 return Qnil;
656}
657
658VALUE
660{
661 return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self);
662}
663
664static VALUE *
665struct_heap_alloc(VALUE st, size_t len)
666{
668
669 if (ptr) {
671 return ptr;
672 }
673 else {
675 return ALLOC_N(VALUE, len);
676 }
677}
678
679#if USE_TRANSIENT_HEAP
680void
682{
684 const VALUE *old_ptr = rb_struct_const_heap_ptr(obj);
685 VALUE *new_ptr;
686 long len = RSTRUCT_LEN(obj);
687
688 if (promote) {
689 new_ptr = ALLOC_N(VALUE, len);
691 }
692 else {
693 new_ptr = struct_heap_alloc(obj, len);
694 }
695 MEMCPY(new_ptr, old_ptr, VALUE, len);
696 RSTRUCT(obj)->as.heap.ptr = new_ptr;
697 }
698}
699#endif
700
701static VALUE
702struct_alloc(VALUE klass)
703{
704 long n;
706
707 n = num_members(klass);
708
709 if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
710 RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
711 RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
712 rb_mem_clear((VALUE *)st->as.ary, n);
713 }
714 else {
715 st->as.heap.ptr = struct_heap_alloc((VALUE)st, n);
716 rb_mem_clear((VALUE *)st->as.heap.ptr, n);
717 st->as.heap.len = n;
718 }
719
720 return (VALUE)st;
721}
722
723VALUE
725{
727}
728
729VALUE
731{
732 VALUE tmpargs[N_REF_FUNC], *mem = tmpargs;
733 int size, i;
734 va_list args;
735
736 size = rb_long2int(num_members(klass));
737 if (size > numberof(tmpargs)) {
738 tmpargs[0] = rb_ary_tmp_new(size);
739 mem = RARRAY_PTR(tmpargs[0]);
740 }
741 va_start(args, klass);
742 for (i=0; i<size; i++) {
743 mem[i] = va_arg(args, VALUE);
744 }
745 va_end(args);
746
747 return rb_class_new_instance(size, mem, klass);
748}
749
750static VALUE
751struct_enum_size(VALUE s, VALUE args, VALUE eobj)
752{
753 return rb_struct_size(s);
754}
755
756/*
757 * call-seq:
758 * struct.each {|obj| block } -> struct
759 * struct.each -> enumerator
760 *
761 * Yields the value of each struct member in order. If no block is given an
762 * enumerator is returned.
763 *
764 * Customer = Struct.new(:name, :address, :zip)
765 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
766 * joe.each {|x| puts(x) }
767 *
768 * Produces:
769 *
770 * Joe Smith
771 * 123 Maple, Anytown NC
772 * 12345
773 */
774
775static VALUE
776rb_struct_each(VALUE s)
777{
778 long i;
779
780 RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
781 for (i=0; i<RSTRUCT_LEN(s); i++) {
783 }
784 return s;
785}
786
787/*
788 * call-seq:
789 * struct.each_pair {|sym, obj| block } -> struct
790 * struct.each_pair -> enumerator
791 *
792 * Yields the name and value of each struct member in order. If no block is
793 * given an enumerator is returned.
794 *
795 * Customer = Struct.new(:name, :address, :zip)
796 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
797 * joe.each_pair {|name, value| puts("#{name} => #{value}") }
798 *
799 * Produces:
800 *
801 * name => Joe Smith
802 * address => 123 Maple, Anytown NC
803 * zip => 12345
804 */
805
806static VALUE
807rb_struct_each_pair(VALUE s)
808{
809 VALUE members;
810 long i;
811
812 RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
813 members = rb_struct_members(s);
814 if (rb_block_arity() > 1) {
815 for (i=0; i<RSTRUCT_LEN(s); i++) {
816 VALUE key = rb_ary_entry(members, i);
817 VALUE value = RSTRUCT_GET(s, i);
818 rb_yield_values(2, key, value);
819 }
820 }
821 else {
822 for (i=0; i<RSTRUCT_LEN(s); i++) {
823 VALUE key = rb_ary_entry(members, i);
824 VALUE value = RSTRUCT_GET(s, i);
825 rb_yield(rb_assoc_new(key, value));
826 }
827 }
828 return s;
829}
830
831static VALUE
832inspect_struct(VALUE s, VALUE dummy, int recur)
833{
834 VALUE cname = rb_class_path(rb_obj_class(s));
835 VALUE members, str = rb_str_new2("#<struct ");
836 long i, len;
837 char first = RSTRING_PTR(cname)[0];
838
839 if (recur || first != '#') {
840 rb_str_append(str, cname);
841 }
842 if (recur) {
843 return rb_str_cat2(str, ":...>");
844 }
845
846 members = rb_struct_members(s);
847 len = RSTRUCT_LEN(s);
848
849 for (i=0; i<len; i++) {
850 VALUE slot;
851 ID id;
852
853 if (i > 0) {
854 rb_str_cat2(str, ", ");
855 }
856 else if (first != '#') {
857 rb_str_cat2(str, " ");
858 }
859 slot = RARRAY_AREF(members, i);
860 id = SYM2ID(slot);
861 if (rb_is_local_id(id) || rb_is_const_id(id)) {
863 }
864 else {
866 }
867 rb_str_cat2(str, "=");
869 }
870 rb_str_cat2(str, ">");
871
872 return str;
873}
874
875/*
876 * call-seq:
877 * struct.to_s -> string
878 * struct.inspect -> string
879 *
880 * Returns a description of this struct as a string.
881 */
882
883static VALUE
884rb_struct_inspect(VALUE s)
885{
886 return rb_exec_recursive(inspect_struct, s, 0);
887}
888
889/*
890 * call-seq:
891 * struct.to_a -> array
892 * struct.values -> array
893 *
894 * Returns the values for this struct as an Array.
895 *
896 * Customer = Struct.new(:name, :address, :zip)
897 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
898 * joe.to_a[1] #=> "123 Maple, Anytown NC"
899 */
900
901static VALUE
902rb_struct_to_a(VALUE s)
903{
905}
906
907/*
908 * call-seq:
909 * struct.to_h -> hash
910 * struct.to_h {|name, value| block } -> hash
911 *
912 * Returns a Hash containing the names and values for the struct's members.
913 *
914 * If a block is given, the results of the block on each pair of the receiver
915 * will be used as pairs.
916 *
917 * Customer = Struct.new(:name, :address, :zip)
918 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
919 * joe.to_h[:address] #=> "123 Maple, Anytown NC"
920 * joe.to_h{|name, value| [name.upcase, value.to_s.upcase]}[:ADDRESS]
921 * #=> "123 MAPLE, ANYTOWN NC"
922 */
923
924static VALUE
925rb_struct_to_h(VALUE s)
926{
928 VALUE members = rb_struct_members(s);
929 long i;
930 int block_given = rb_block_given_p();
931
932 for (i=0; i<RSTRUCT_LEN(s); i++) {
933 VALUE k = rb_ary_entry(members, i), v = RSTRUCT_GET(s, i);
934 if (block_given)
936 else
937 rb_hash_aset(h, k, v);
938 }
939 return h;
940}
941
942static VALUE
943rb_struct_deconstruct_keys(VALUE s, VALUE keys)
944{
945 VALUE h;
946 long i;
947
948 if (NIL_P(keys)) {
949 return rb_struct_to_h(s);
950 }
951 if (UNLIKELY(!RB_TYPE_P(keys, T_ARRAY))) {
953 "wrong argument type %"PRIsVALUE" (expected Array or nil)",
955
956 }
957 if (RSTRUCT_LEN(s) < RARRAY_LEN(keys)) {
958 return rb_hash_new_with_size(0);
959 }
961 for (i=0; i<RARRAY_LEN(keys); i++) {
963 int i = rb_struct_pos(s, &key);
964 if (i < 0) {
965 return h;
966 }
968 }
969 return h;
970}
971
972/* :nodoc: */
973VALUE
975{
976 long i, len;
977
978 if (!OBJ_INIT_COPY(copy, s)) return copy;
979 if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
980 rb_raise(rb_eTypeError, "struct size mismatch");
981 }
982
983 for (i=0, len=RSTRUCT_LEN(copy); i<len; i++) {
984 RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i));
985 }
986
987 return copy;
988}
989
990static int
991rb_struct_pos(VALUE s, VALUE *name)
992{
993 long i;
994 VALUE idx = *name;
995
996 if (RB_TYPE_P(idx, T_SYMBOL)) {
997 return struct_member_pos(s, idx);
998 }
999 else if (RB_TYPE_P(idx, T_STRING)) {
1000 idx = rb_check_symbol(name);
1001 if (NIL_P(idx)) return -1;
1002 return struct_member_pos(s, idx);
1003 }
1004 else {
1005 long len;
1006 i = NUM2LONG(idx);
1007 len = RSTRUCT_LEN(s);
1008 if (i < 0) {
1009 if (i + len < 0) {
1010 *name = LONG2FIX(i);
1011 return -1;
1012 }
1013 i += len;
1014 }
1015 else if (len <= i) {
1016 *name = LONG2FIX(i);
1017 return -1;
1018 }
1019 return (int)i;
1020 }
1021}
1022
1023NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx));
1024static void
1025invalid_struct_pos(VALUE s, VALUE idx)
1026{
1027 if (FIXNUM_P(idx)) {
1028 long i = FIX2INT(idx), len = RSTRUCT_LEN(s);
1029 if (i < 0) {
1030 rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
1031 i, len);
1032 }
1033 else {
1034 rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
1035 i, len);
1036 }
1037 }
1038 else {
1039 rb_name_err_raise("no member '%1$s' in struct", s, idx);
1040 }
1041}
1042
1043/*
1044 * call-seq:
1045 * struct[member] -> object
1046 * struct[index] -> object
1047 *
1048 * Attribute Reference---Returns the value of the given struct +member+ or
1049 * the member at the given +index+. Raises NameError if the +member+ does
1050 * not exist and IndexError if the +index+ is out of range.
1051 *
1052 * Customer = Struct.new(:name, :address, :zip)
1053 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1054 *
1055 * joe["name"] #=> "Joe Smith"
1056 * joe[:name] #=> "Joe Smith"
1057 * joe[0] #=> "Joe Smith"
1058 */
1059
1060VALUE
1062{
1063 int i = rb_struct_pos(s, &idx);
1064 if (i < 0) invalid_struct_pos(s, idx);
1065 return RSTRUCT_GET(s, i);
1066}
1067
1068/*
1069 * call-seq:
1070 * struct[member] = obj -> obj
1071 * struct[index] = obj -> obj
1072 *
1073 * Attribute Assignment---Sets the value of the given struct +member+ or
1074 * the member at the given +index+. Raises NameError if the +member+ does not
1075 * exist and IndexError if the +index+ is out of range.
1076 *
1077 * Customer = Struct.new(:name, :address, :zip)
1078 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1079 *
1080 * joe["name"] = "Luke"
1081 * joe[:zip] = "90210"
1082 *
1083 * joe.name #=> "Luke"
1084 * joe.zip #=> "90210"
1085 */
1086
1087VALUE
1089{
1090 int i = rb_struct_pos(s, &idx);
1091 if (i < 0) invalid_struct_pos(s, idx);
1092 rb_struct_modify(s);
1093 RSTRUCT_SET(s, i, val);
1094 return val;
1095}
1096
1098NOINLINE(static VALUE rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound));
1099
1100VALUE
1102{
1103 return rb_struct_lookup_default(s, idx, Qnil);
1104}
1105
1106static VALUE
1107rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound)
1108{
1109 int i = rb_struct_pos(s, &idx);
1110 if (i < 0) return notfound;
1111 return RSTRUCT_GET(s, i);
1112}
1113
1114static VALUE
1115struct_entry(VALUE s, long n)
1116{
1117 return rb_struct_aref(s, LONG2NUM(n));
1118}
1119
1120/*
1121 * call-seq:
1122 * struct.values_at(selector, ...) -> array
1123 *
1124 * Returns the struct member values for each +selector+ as an Array. A
1125 * +selector+ may be either an Integer offset or a Range of offsets (as in
1126 * Array#values_at).
1127 *
1128 * Customer = Struct.new(:name, :address, :zip)
1129 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1130 * joe.values_at(0, 2) #=> ["Joe Smith", 12345]
1131 *
1132 */
1133
1134static VALUE
1135rb_struct_values_at(int argc, VALUE *argv, VALUE s)
1136{
1137 return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
1138}
1139
1140/*
1141 * call-seq:
1142 * struct.select {|obj| block } -> array
1143 * struct.select -> enumerator
1144 * struct.filter {|obj| block } -> array
1145 * struct.filter -> enumerator
1146 *
1147 * Yields each member value from the struct to the block and returns an Array
1148 * containing the member values from the +struct+ for which the given block
1149 * returns a true value (equivalent to Enumerable#select).
1150 *
1151 * Lots = Struct.new(:a, :b, :c, :d, :e, :f)
1152 * l = Lots.new(11, 22, 33, 44, 55, 66)
1153 * l.select {|v| v.even? } #=> [22, 44, 66]
1154 *
1155 * Struct#filter is an alias for Struct#select.
1156 */
1157
1158static VALUE
1159rb_struct_select(int argc, VALUE *argv, VALUE s)
1160{
1161 VALUE result;
1162 long i;
1163
1164 rb_check_arity(argc, 0, 0);
1165 RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
1166 result = rb_ary_new();
1167 for (i = 0; i < RSTRUCT_LEN(s); i++) {
1168 if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
1169 rb_ary_push(result, RSTRUCT_GET(s, i));
1170 }
1171 }
1172
1173 return result;
1174}
1175
1176static VALUE
1177recursive_equal(VALUE s, VALUE s2, int recur)
1178{
1179 long i, len;
1180
1181 if (recur) return Qtrue; /* Subtle! */
1182 len = RSTRUCT_LEN(s);
1183 for (i=0; i<len; i++) {
1184 if (!rb_equal(RSTRUCT_GET(s, i), RSTRUCT_GET(s2, i))) return Qfalse;
1185 }
1186 return Qtrue;
1187}
1188
1189/*
1190 * call-seq:
1191 * struct == other -> true or false
1192 *
1193 * Equality---Returns +true+ if +other+ has the same struct subclass and has
1194 * equal member values (according to Object#==).
1195 *
1196 * Customer = Struct.new(:name, :address, :zip)
1197 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1198 * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1199 * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
1200 * joe == joejr #=> true
1201 * joe == jane #=> false
1202 */
1203
1204static VALUE
1205rb_struct_equal(VALUE s, VALUE s2)
1206{
1207 if (s == s2) return Qtrue;
1208 if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
1209 if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
1210 if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
1211 rb_bug("inconsistent struct"); /* should never happen */
1212 }
1213
1214 return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
1215}
1216
1217/*
1218 * call-seq:
1219 * struct.hash -> integer
1220 *
1221 * Returns a hash value based on this struct's contents.
1222 *
1223 * See also Object#hash.
1224 */
1225
1226static VALUE
1227rb_struct_hash(VALUE s)
1228{
1229 long i, len;
1230 st_index_t h;
1231 VALUE n;
1232
1234 len = RSTRUCT_LEN(s);
1235 for (i = 0; i < len; i++) {
1236 n = rb_hash(RSTRUCT_GET(s, i));
1237 h = rb_hash_uint(h, NUM2LONG(n));
1238 }
1239 h = rb_hash_end(h);
1240 return ST2FIX(h);
1241}
1242
1243static VALUE
1244recursive_eql(VALUE s, VALUE s2, int recur)
1245{
1246 long i, len;
1247
1248 if (recur) return Qtrue; /* Subtle! */
1249 len = RSTRUCT_LEN(s);
1250 for (i=0; i<len; i++) {
1251 if (!rb_eql(RSTRUCT_GET(s, i), RSTRUCT_GET(s2, i))) return Qfalse;
1252 }
1253 return Qtrue;
1254}
1255
1256/*
1257 * call-seq:
1258 * struct.eql?(other) -> true or false
1259 *
1260 * Hash equality---+other+ and +struct+ refer to the same hash key if they
1261 * have the same struct subclass and have equal member values (according to
1262 * Object#eql?).
1263 */
1264
1265static VALUE
1266rb_struct_eql(VALUE s, VALUE s2)
1267{
1268 if (s == s2) return Qtrue;
1269 if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
1270 if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
1271 if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
1272 rb_bug("inconsistent struct"); /* should never happen */
1273 }
1274
1275 return rb_exec_recursive_paired(recursive_eql, s, s2, s2);
1276}
1277
1278/*
1279 * call-seq:
1280 * struct.length -> integer
1281 * struct.size -> integer
1282 *
1283 * Returns the number of struct members.
1284 *
1285 * Customer = Struct.new(:name, :address, :zip)
1286 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1287 * joe.length #=> 3
1288 */
1289
1290VALUE
1292{
1293 return LONG2FIX(RSTRUCT_LEN(s));
1294}
1295
1296/*
1297 * call-seq:
1298 * struct.dig(key, ...) -> object
1299 *
1300 * Extracts the nested value specified by the sequence of +key+
1301 * objects by calling +dig+ at each step, returning +nil+ if any
1302 * intermediate step is +nil+.
1303 *
1304 * Foo = Struct.new(:a)
1305 * f = Foo.new(Foo.new({b: [1, 2, 3]}))
1306 *
1307 * f.dig(:a, :a, :b, 0) # => 1
1308 * f.dig(:b, 0) # => nil
1309 * f.dig(:a, :a, :b, :c) # TypeError: no implicit conversion of Symbol into Integer
1310 */
1311
1312static VALUE
1313rb_struct_dig(int argc, VALUE *argv, VALUE self)
1314{
1316 self = rb_struct_lookup(self, *argv);
1317 if (!--argc) return self;
1318 ++argv;
1319 return rb_obj_dig(argc, argv, self, Qnil);
1320}
1321
1322/*
1323 * Document-class: Struct
1324 *
1325 * A Struct is a convenient way to bundle a number of attributes together,
1326 * using accessor methods, without having to write an explicit class.
1327 *
1328 * The Struct class generates new subclasses that hold a set of members and
1329 * their values. For each member a reader and writer method is created
1330 * similar to Module#attr_accessor.
1331 *
1332 * Customer = Struct.new(:name, :address) do
1333 * def greeting
1334 * "Hello #{name}!"
1335 * end
1336 * end
1337 *
1338 * dave = Customer.new("Dave", "123 Main")
1339 * dave.name #=> "Dave"
1340 * dave.greeting #=> "Hello Dave!"
1341 *
1342 * See Struct::new for further examples of creating struct subclasses and
1343 * instances.
1344 *
1345 * In the method descriptions that follow, a "member" parameter refers to a
1346 * struct member which is either a quoted string (<code>"name"</code>) or a
1347 * Symbol (<code>:name</code>).
1348 */
1349void
1351{
1354
1356 rb_define_singleton_method(rb_cStruct, "new", rb_struct_s_def, -1);
1357
1358 rb_define_method(rb_cStruct, "initialize", rb_struct_initialize_m, -1);
1359 rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
1360
1361 rb_define_method(rb_cStruct, "==", rb_struct_equal, 1);
1362 rb_define_method(rb_cStruct, "eql?", rb_struct_eql, 1);
1363 rb_define_method(rb_cStruct, "hash", rb_struct_hash, 0);
1364
1365 rb_define_method(rb_cStruct, "inspect", rb_struct_inspect, 0);
1366 rb_define_alias(rb_cStruct, "to_s", "inspect");
1367 rb_define_method(rb_cStruct, "to_a", rb_struct_to_a, 0);
1368 rb_define_method(rb_cStruct, "to_h", rb_struct_to_h, 0);
1369 rb_define_method(rb_cStruct, "values", rb_struct_to_a, 0);
1372
1373 rb_define_method(rb_cStruct, "each", rb_struct_each, 0);
1374 rb_define_method(rb_cStruct, "each_pair", rb_struct_each_pair, 0);
1377 rb_define_method(rb_cStruct, "select", rb_struct_select, -1);
1378 rb_define_method(rb_cStruct, "filter", rb_struct_select, -1);
1379 rb_define_method(rb_cStruct, "values_at", rb_struct_values_at, -1);
1380
1381 rb_define_method(rb_cStruct, "members", rb_struct_members_m, 0);
1382 rb_define_method(rb_cStruct, "dig", rb_struct_dig, -1);
1383
1384 rb_define_method(rb_cStruct, "deconstruct", rb_struct_to_a, 0);
1385 rb_define_method(rb_cStruct, "deconstruct_keys", rb_struct_deconstruct_keys, 1);
1386}
1387
1388#undef rb_intern
1389void
1391{
1392 id_members = rb_intern("__members__");
1393 id_back_members = rb_intern("__members_back__");
1394 id_keyword_init = rb_intern("__keyword_init__");
1395
1396 InitVM(Struct);
1397}
#define sym(x)
Definition: date_core.c:3717
#define recur(fmt)
enum @73::@75::@76 mask
struct RIMemo * ptr
Definition: debug.c:65
struct rb_encoding_entry * list
Definition: encoding.c:56
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
void rb_include_module(VALUE, VALUE)
Definition: class.c:882
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
Definition: class.c:662
VALUE rb_class_new(VALUE)
Creates a new class.
Definition: class.c:244
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
Definition: class.c:711
VALUE rb_class_inherited(VALUE, VALUE)
Calls Class::inherited.
Definition: class.c:636
VALUE rb_define_class_id_under(VALUE, ID, VALUE)
Defines a class under the namespace of outer.
Definition: class.c:734
VALUE rb_make_metaclass(VALUE, VALUE)
Definition: class.c:593
void rb_define_alias(VALUE, const char *, const char *)
Defines an alias of a method.
Definition: class.c:1818
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *)
Definition: class.c:1904
VALUE rb_cStruct
Definition: struct.c:26
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
VALUE rb_mEnumerable
Definition: enum.c:20
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
void rb_bug(const char *fmt,...)
Definition: error.c:636
VALUE rb_eTypeError
Definition: error.c:924
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_eIndexError
Definition: error.c:926
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound)
Definition: object.c:3791
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:1955
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1931
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
Definition: object.c:147
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
const char * name
Definition: nkf.c:208
VALUE rb_class_name(VALUE)
Definition: variable.c:274
#define RARRAY_LEN(a)
#define rb_str_new2
#define MEMCPY(p1, p2, type, n)
void rb_hash_foreach(VALUE, int(*)(VALUE, VALUE, VALUE), VALUE)
VALUE rb_str_to_str(VALUE)
Definition: string.c:1382
#define NULL
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:5085
#define RBASIC_CLEAR_CLASS(obj)
#define RSTRUCT_EMBED_LEN_SHIFT
VALUE rb_hash(VALUE)
Definition: hash.c:129
#define UNLIMITED_ARGUMENTS
#define RGENGC_WB_PROTECTED_STRUCT
#define NEWOBJ_OF(obj, type, klass, flags)
#define RTEST(v)
#define rb_hash_uint(h, i)
#define OBJ_INIT_COPY(obj, orig)
#define RCLASS_SUPER(c)
enum ruby_tag_type st
#define RBASIC(obj)
#define RSTRUCT_SET(st, idx, v)
#define T_STRING
#define rb_hash_end(h)
VALUE rb_assoc_new(VALUE, VALUE)
Definition: array.c:896
#define rb_yield_values(argc,...)
void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi)
Definition: vm_method.c:685
#define RARRAY_LENINT(ary)
#define RSTRUCT_CONST_PTR(st)
#define LONG2FIX(i)
#define Qundef
#define rb_str_cat2
const VALUE VALUE obj
#define rb_check_frozen(obj)
#define RSTRING_PTR(str)
#define RSTRUCT_EMBED_LEN_MAX
VALUE rb_ident_hash_new(void)
Definition: hash.c:4278
int rb_block_arity(void)
Definition: proc.c:1144
VALUE rb_hash_set_pair(VALUE hash, VALUE pair)
Definition: hash.c:3332
#define NIL_P(v)
#define T_STRUCT
#define RSTRUCT(obj)
#define numberof(array)
#define rb_name_err_raise(mesg, recv, name)
VALUE rb_check_symbol(volatile VALUE *namep)
Definition: symbol.c:952
#define RARRAY_PTR(a)
#define ID2SYM(x)
const char size_t n
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1438
#define SYM2ID(x)
VALUE rb_mod_module_eval(int, const VALUE *, VALUE)
Definition: vm_eval.c:2069
const char const char *typedef unsigned long VALUE
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
VALUE rb_ary_join(VALUE, VALUE)
Definition: array.c:2347
#define rb_ary_new4
const rb_iseq_t const char const VALUE keys
#define rb_sym_intern_ascii_cstr(ptr)
int rb_const_defined_at(VALUE, ID)
Definition: variable.c:2692
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
uint32_t i
__inline__ const void *__restrict__ size_t len
VALUE rb_class_path(VALUE)
Definition: variable.c:153
#define ALLOC_N(type, n)
#define va_end(v)
VALUE rb_hash_new_with_size(st_index_t size)
Definition: hash.c:1529
#define T_HASH
#define LONG2NUM(x)
__gnuc_va_list va_list
void rb_define_singleton_method(VALUE, const char *, VALUE(*)(), int)
#define rb_long2int(n)
#define FUNC_FASTCALL(x)
#define PRIsVALUE
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
const char * s2
VALUE rb_ary_tmp_new(long)
Definition: array.c:768
#define FIX2INT(x)
int VALUE v
VALUE rb_ary_new(void)
Definition: array.c:723
#define ID_SCOPE_SHIFT
#define RSTRUCT_TRANSIENT_P(st)
#define RB_PASS_CALLED_KEYWORDS
@ RSTRUCT_TRANSIENT_FLAG
#define rb_str_cat_cstr(str, ptr)
#define rb_intern(str)
#define va_arg(v, l)
#define UNREACHABLE_RETURN(val)
#define va_start(v, l)
const rb_iseq_t * iseq
VALUE rb_hash_keys(VALUE hash)
Definition: hash.c:3409
#define RSTRUCT_GET(st, idx)
unsigned int size
#define Qtrue
VALUE rb_mod_remove_const(VALUE, VALUE)
Definition: variable.c:2483
#define RSTRUCT_LEN(st)
#define FL_UNSET_RAW(x, f)
#define UNLIKELY(x)
#define RSTRUCT_TRANSIENT_SET(st)
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
VALUE rb_ary_dup(VALUE)
Definition: array.c:2238
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
#define Qnil
#define Qfalse
#define T_ARRAY
#define OBJ_FREEZE_RAW(x)
st_data_t st_index_t
#define RB_TYPE_P(obj, type)
#define FL_WB_PROTECTED
#define INT2FIX(i)
VALUE rb_to_symbol(VALUE name)
Definition: string.c:11156
#define T_SYMBOL
const VALUE * argv
#define SYMBOL_P(x)
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
#define FIXNUM_P(f)
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:729
void rb_mem_clear(VALUE *, long)
Definition: array.c:243
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
Definition: hash.c:2852
int rb_is_const_name(VALUE name)
Definition: symbol.c:1050
#define RHASH_TBL(h)
#define rb_check_arity
VALUE rb_get_values_at(VALUE, long, int, const VALUE *, VALUE(*)(VALUE, long))
Definition: array.c:3106
#define RSTRUCT_TRANSIENT_UNSET(st)
ID rb_id_attrset(ID)
Definition: symbol.c:98
void rb_define_method_id(VALUE, ID, VALUE(*)(), int)
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5074
unsigned long ID
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
#define InitVM(ext)
size_t st_index_t h
VALUE ID id
#define NUM2LONG(x)
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define RARRAY_AREF(a, i)
VALUE(* rb_alloc_func_t)(VALUE)
#define ST2FIX(h)
#define RARRAY_CONST_PTR(a)
void rb_ary_store(VALUE, long, VALUE)
Definition: array.c:1079
VALUE rb_ary_entry(VALUE, long)
Definition: array.c:1512
ID rb_to_id(VALUE)
Definition: string.c:11146
unsigned long VALUE
Definition: ruby.h:102
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
void st_clear(st_table *tab)
Definition: st.c:698
VALUE rb_struct_define_under(VALUE outer, const char *name,...)
Definition: struct.c:446
void InitVM_Struct(void)
Definition: struct.c:1350
@ AREF_HASH_THRESHOLD
Definition: struct.c:20
@ AREF_HASH_UNIT
Definition: struct.c:19
VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc,...)
Definition: struct.c:405
VALUE rb_struct_new(VALUE klass,...)
Definition: struct.c:730
VALUE rb_struct_getmember(VALUE obj, ID id)
Definition: struct.c:211
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:974
void Init_Struct(void)
Definition: struct.c:1390
VALUE rb_struct_size(VALUE s)
Definition: struct.c:1291
VALUE rb_struct_initialize(VALUE self, VALUE values)
Definition: struct.c:659
FUNC_MINIMIZED(VALUE rb_struct_lookup(VALUE s, VALUE idx))
VALUE rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc,...)
Definition: struct.c:418
VALUE rb_struct_define(const char *name,...)
Definition: struct.c:431
VALUE rb_struct_alloc(VALUE klass, VALUE values)
Definition: struct.c:724
VALUE rb_struct_aset(VALUE s, VALUE idx, VALUE val)
Definition: struct.c:1088
void rb_struct_transient_heap_evacuate(VALUE obj, int promote)
Definition: struct.c:681
const rb_iseq_t * rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func)
Definition: compile.c:9475
NOINLINE(static VALUE rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound))
VALUE rb_struct_members(VALUE s)
Definition: struct.c:72
NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx))
VALUE rb_struct_alloc_noinit(VALUE klass)
Definition: struct.c:349
VALUE rb_struct_s_members(VALUE klass)
Definition: struct.c:58
VALUE rb_struct_lookup(VALUE s, VALUE idx)
Definition: struct.c:1101
VALUE rb_struct_aref(VALUE s, VALUE idx)
Definition: struct.c:1061
const rb_iseq_t * rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func)
Definition: compile.c:9484
#define N_REF_FUNC
Definition: struct.c:234
VALUE rb_struct_s_keyword_init(VALUE klass)
Definition: struct.c:52
VALUE unknown_keywords
Definition: struct.c:599
int rb_is_const_id(ID id)
Definition: symbol.c:854
int rb_is_attrset_sym(VALUE sym)
Definition: symbol.c:902
int rb_is_local_id(ID id)
Definition: symbol.c:884
void * rb_transient_heap_alloc(VALUE obj, size_t req_size)
#define rb_id2str(id)
Definition: vm_backtrace.c:30
rb_control_frame_t *FUNC_FASTCALL rb_insn_func_t(rb_execution_context_t *, rb_control_frame_t *)
Definition: vm_core.h:1143
rb_control_frame_t *FUNC_FASTCALL() rb_vm_opt_struct_aset(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)
rb_control_frame_t *FUNC_FASTCALL() rb_vm_opt_struct_aref(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)