Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
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 */
18 enum {
21 };
22 
25 
27 static ID id_members, id_back_members, id_keyword_init;
28 
29 static VALUE struct_alloc(VALUE);
30 
31 static inline VALUE
32 struct_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 
51 VALUE
53 {
54  return struct_ivar_get(klass, id_keyword_init);
55 }
56 
57 VALUE
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 
71 VALUE
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 
83 static long
84 struct_member_pos_ideal(VALUE name, long mask)
85 {
86  /* (id & (mask/2)) * 2 */
87  return (SYM2ID(name) >> (ID_SCOPE_SHIFT - 1)) & mask;
88 }
89 
90 static long
91 struct_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 
97 static VALUE
98 struct_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 
138 static inline int
139 struct_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 
185 static VALUE
186 rb_struct_s_members_m(VALUE klass)
187 {
188  VALUE members = rb_struct_s_members(klass);
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 
204 static VALUE
205 rb_struct_members_m(VALUE obj)
206 {
207  return rb_struct_s_members_m(rb_obj_class(obj));
208 }
209 
210 VALUE
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 
223 static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);}
224 static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);}
225 static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);}
226 static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_GET(obj, 3);}
227 static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_GET(obj, 4);}
228 static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_GET(obj, 5);}
229 static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_GET(obj, 6);}
230 static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_GET(obj, 7);}
231 static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_GET(obj, 8);}
232 static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_GET(obj, 9);}
233 
234 #define N_REF_FUNC numberof(ref_func)
235 
236 static 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 
249 static void
250 rb_struct_modify(VALUE s)
251 {
252  rb_check_frozen(s);
253 }
254 
255 static VALUE
256 anonymous_struct(VALUE klass)
257 {
258  VALUE nstr;
259 
260  nstr = rb_class_new(klass);
262  rb_class_inherited(klass, nstr);
263  return nstr;
264 }
265 
266 static VALUE
267 new_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 
284 static void
285 define_aref_method(VALUE nstr, VALUE name, VALUE off)
286 {
289 
291 }
292 
293 static void
294 define_aset_method(VALUE nstr, VALUE name, VALUE off)
295 {
298 
300 }
301 
302 static VALUE
303 rb_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 
312 static VALUE
313 struct_new_kw(int argc, const VALUE *argv, VALUE klass)
314 {
316 }
317 
318 static VALUE
319 setup_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 
348 VALUE
350 {
351  return struct_alloc(klass);
352 }
353 
354 static VALUE
355 struct_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);
372  return ary;
373 }
374 
375 static VALUE
376 struct_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) {
395  rb_define_alloc_func(klass, alloc);
396  }
397  else {
398  rb_define_alloc_func(klass, struct_alloc);
399  }
400 
401  return klass;
402 }
403 
404 VALUE
405 rb_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 
417 VALUE
418 rb_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 
430 VALUE
431 rb_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 
445 VALUE
446 rb_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 
521 static VALUE
522 rb_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 
583 static long
584 num_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 
602 static int rb_struct_pos(VALUE s, VALUE *name);
603 
604 static int
605 struct_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) {
611  args->unknown_keywords = rb_ary_new();
612  }
614  }
615  else {
616  rb_struct_modify(args->self);
617  RSTRUCT_SET(args->self, i, val);
618  }
619  return ST_CONTINUE;
620 }
621 
622 static VALUE
623 rb_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);
630  if (argc > 0 && RTEST(rb_struct_s_keyword_init(klass))) {
631  struct struct_hash_set_arg arg;
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 
658 VALUE
660 {
661  return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self);
662 }
663 
664 static VALUE *
665 struct_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
680 void
682 {
683  if (RSTRUCT_TRANSIENT_P(obj)) {
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 
701 static VALUE
702 struct_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 
723 VALUE
725 {
726  return rb_class_new_instance(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), klass);
727 }
728 
729 VALUE
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 
750 static VALUE
751 struct_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 
775 static VALUE
776 rb_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++) {
782  rb_yield(RSTRUCT_GET(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 
806 static VALUE
807 rb_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 
831 static VALUE
832 inspect_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 {
865  rb_str_append(str, rb_inspect(slot));
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 
883 static VALUE
884 rb_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 
901 static VALUE
902 rb_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 
924 static VALUE
925 rb_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 
942 static VALUE
943 rb_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)",
954  rb_obj_class(keys));
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++) {
962  VALUE key = RARRAY_AREF(keys, i);
963  int i = rb_struct_pos(s, &key);
964  if (i < 0) {
965  return h;
966  }
967  rb_hash_aset(h, key, RSTRUCT_GET(s, i));
968  }
969  return h;
970 }
971 
972 /* :nodoc: */
973 VALUE
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 
990 static int
991 rb_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 
1023 NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx));
1024 static void
1025 invalid_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 
1060 VALUE
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 
1087 VALUE
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 
1098 NOINLINE(static VALUE rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound));
1099 
1100 VALUE
1102 {
1103  return rb_struct_lookup_default(s, idx, Qnil);
1104 }
1105 
1106 static VALUE
1107 rb_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 
1114 static VALUE
1115 struct_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 
1134 static VALUE
1135 rb_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 
1158 static VALUE
1159 rb_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 
1176 static VALUE
1177 recursive_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 
1204 static VALUE
1205 rb_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 
1226 static VALUE
1227 rb_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 
1243 static VALUE
1244 recursive_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 
1265 static VALUE
1266 rb_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 
1290 VALUE
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 
1312 static VALUE
1313 rb_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  */
1349 void
1351 {
1352  rb_cStruct = rb_define_class("Struct", rb_cObject);
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
1389 void
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 }
rb_is_const_name
int rb_is_const_name(VALUE name)
Definition: symbol.c:1050
va_end
#define va_end(v)
Definition: rb_mjit_min_header-2.7.2.h:4014
rb_check_symbol
VALUE rb_check_symbol(volatile VALUE *namep)
Definition: symbol.c:952
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1886
UNLIKELY
#define UNLIKELY(x)
Definition: ffi_common.h:126
ID
unsigned long ID
Definition: ruby.h:103
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
Init_Struct
void Init_Struct(void)
Definition: struct.c:1390
rb_define_method_id
void rb_define_method_id(VALUE klass, ID mid, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1542
rb_is_const_id
int rb_is_const_id(ID id)
Definition: symbol.c:854
rb_method_for_self_aref
const rb_iseq_t * rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func)
Definition: compile.c:9477
rb_block_arity
int rb_block_arity(void)
Definition: proc.c:1144
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
rb_struct_init_copy
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:974
rb_mod_remove_const
VALUE rb_mod_remove_const(VALUE, VALUE)
Definition: variable.c:2483
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_class_inherited
MJIT_FUNC_EXPORTED VALUE rb_class_inherited(VALUE super, VALUE klass)
Calls Class::inherited.
Definition: class.c:623
FUNC_MINIMIZED
FUNC_MINIMIZED(VALUE rb_struct_lookup(VALUE s, VALUE idx))
id
const int id
Definition: nkf.c:209
RB_PASS_CALLED_KEYWORDS
#define RB_PASS_CALLED_KEYWORDS
Definition: ruby.h:1980
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
rb_iseq_struct
Definition: vm_core.h:456
rb_ident_hash_new
VALUE rb_ident_hash_new(void)
Definition: hash.c:4278
rb_struct_alloc
VALUE rb_struct_alloc(VALUE klass, VALUE values)
Definition: struct.c:724
s2
const char * s2
Definition: rb_mjit_min_header-2.7.2.h:5489
rb_struct_members
VALUE rb_struct_members(VALUE s)
Definition: struct.c:72
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:315
rb_struct_aset
VALUE rb_struct_aset(VALUE s, VALUE idx, VALUE val)
Definition: struct.c:1088
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
rb_add_method_iseq
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:684
RBASIC_CLEAR_CLASS
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:1987
rb_struct_lookup
VALUE rb_struct_lookup(VALUE s, VALUE idx)
Definition: struct.c:1101
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
rb_to_symbol
VALUE rb_to_symbol(VALUE name)
Definition: string.c:11156
rb_vm_opt_struct_aset
rb_control_frame_t *FUNC_FASTCALL() rb_vm_opt_struct_aset(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)
Definition: vm_insnhelper.c:3474
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
i
uint32_t i
Definition: rb_mjit_min_header-2.7.2.h:5499
rb_str_cat_cstr
#define rb_str_cat_cstr(str, ptr)
Definition: rb_mjit_min_header-2.7.2.h:6161
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
rb_struct_new
VALUE rb_struct_new(VALUE klass,...)
Definition: struct.c:730
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
rb_class_new_instance_kw
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1931
rb_equal
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_id_attrset
ID rb_id_attrset(ID)
Definition: symbol.c:98
rb_eArgError
VALUE rb_eArgError
Definition: error.c:925
va_list
__gnuc_va_list va_list
Definition: rb_mjit_min_header-2.7.2.h:839
rb_intern
#define rb_intern(str)
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1079
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
RARRAY_PTR
#define RARRAY_PTR(a)
Definition: ruby.h:1110
id.h
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
rb_eIndexError
VALUE rb_eIndexError
Definition: error.c:926
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
rb_get_values_at
VALUE rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE(*func)(VALUE, long))
Definition: array.c:3106
rb_is_attrset_sym
int rb_is_attrset_sym(VALUE sym)
Definition: symbol.c:902
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
struct_hash_set_arg
Definition: struct.c:597
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
rb_long2int
#define rb_long2int(n)
Definition: ruby.h:350
rb_hash_keys
MJIT_FUNC_EXPORTED VALUE rb_hash_keys(VALUE hash)
Definition: hash.c:3409
ptr
struct RIMemo * ptr
Definition: debug.c:65
RSTRUCT_TRANSIENT_SET
#define RSTRUCT_TRANSIENT_SET(st)
Definition: internal.h:934
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_struct_s_keyword_init
VALUE rb_struct_s_keyword_init(VALUE klass)
Definition: struct.c:52
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:271
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
rb_yield_values
#define rb_yield_values(argc,...)
Definition: rb_mjit_min_header-2.7.2.h:6619
NULL
#define NULL
Definition: _sdbm.c:101
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Definition: ruby.h:1279
rb_struct_define
VALUE rb_struct_define(const char *name,...)
Definition: struct.c:431
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
RSTRUCT_EMBED_LEN_MAX
#define RSTRUCT_EMBED_LEN_MAX
Definition: internal.h:919
st_insert
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
T_SYMBOL
#define T_SYMBOL
Definition: ruby.h:540
struct_hash_set_arg::unknown_keywords
VALUE unknown_keywords
Definition: struct.c:599
RString::ary
char ary[RSTRING_EMBED_LEN_MAX+1]
Definition: ruby.h:999
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
rb_eql
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
Definition: object.c:147
rb_struct_define_without_accessor_under
VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc,...)
Definition: struct.c:405
InitVM
#define InitVM(ext)
Definition: ruby.h:2329
rb_hash_new_with_size
MJIT_FUNC_EXPORTED VALUE rb_hash_new_with_size(st_index_t size)
Definition: hash.c:1529
struct_hash_set_arg::self
VALUE self
Definition: struct.c:598
RARRAY_LENINT
#define RARRAY_LENINT(ary)
Definition: ruby.h:1071
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
Definition: intern.h:57
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
rb_sym_intern_ascii_cstr
#define rb_sym_intern_ascii_cstr(ptr)
Definition: rb_mjit_min_header-2.7.2.h:7799
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
NORETURN
NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx))
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
keys
const rb_iseq_t const char const VALUE keys
Definition: rb_mjit_min_header-2.7.2.h:13554
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.2.h:13302
st_clear
void st_clear(st_table *tab)
Definition: st.c:698
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
RSTRUCT_TRANSIENT_P
#define RSTRUCT_TRANSIENT_P(st)
Definition: internal.h:933
h
size_t st_index_t h
Definition: rb_mjit_min_header-2.7.2.h:5497
rb_obj_dig
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound)
Definition: object.c:3791
rb_insn_func_t
rb_control_frame_t *FUNC_FASTCALL rb_insn_func_t(rb_execution_context_t *, rb_control_frame_t *)
Definition: vm_core.h:1143
RGENGC_WB_PROTECTED_STRUCT
#define RGENGC_WB_PROTECTED_STRUCT
Definition: ruby.h:808
RSTRUCT_EMBED_LEN_MASK
#define RSTRUCT_EMBED_LEN_MASK
Definition: internal.h:920
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:768
AREF_HASH_THRESHOLD
@ AREF_HASH_THRESHOLD
Definition: struct.c:20
sym
#define sym(x)
Definition: date_core.c:3716
rb_to_id
ID rb_to_id(VALUE)
Definition: string.c:11146
rb_struct_transient_heap_evacuate
void rb_struct_transient_heap_evacuate(VALUE obj, int promote)
Definition: struct.c:681
st
enum ruby_tag_type st
Definition: rb_mjit_min_header-2.7.2.h:11159
rb_struct_aref
VALUE rb_struct_aref(VALUE s, VALUE idx)
Definition: struct.c:1061
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
st_index_t
st_data_t st_index_t
Definition: st.h:50
rb_struct_alloc_noinit
VALUE rb_struct_alloc_noinit(VALUE klass)
Definition: struct.c:349
rb_hash_start
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1434
transient_heap.h
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: psych_emitter.c:7
vm_core.h
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:924
RSTRUCT_EMBED_LEN_SHIFT
#define RSTRUCT_EMBED_LEN_SHIFT
Definition: internal.h:921
va_arg
#define va_arg(v, l)
Definition: rb_mjit_min_header-2.7.2.h:4015
rb_control_frame_struct
Definition: vm_core.h:760
rb_transient_heap_alloc
void * rb_transient_heap_alloc(VALUE obj, size_t req_size)
Definition: transient_heap.c:359
rb_struct_getmember
VALUE rb_struct_getmember(VALUE obj, ID id)
Definition: struct.c:211
rb_mem_clear
void rb_mem_clear(VALUE *mem, long size)
Definition: array.c:243
size
int size
Definition: encoding.c:58
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
RCLASS_SUPER
#define RCLASS_SUPER(c)
Definition: classext.h:16
rb_struct_size
VALUE rb_struct_size(VALUE s)
Definition: struct.c:1291
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.2.h:5636
METHOD_VISI_PUBLIC
@ METHOD_VISI_PUBLIC
Definition: method.h:28
rb_hash_foreach
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
Definition: hash.c:1483
list
struct rb_encoding_entry * list
Definition: encoding.c:56
AREF_HASH_UNIT
@ AREF_HASH_UNIT
Definition: struct.c:19
mask
enum @0::@2::@3 mask
ID_SCOPE_SHIFT
#define ID_SCOPE_SHIFT
Definition: id.h:31
key
key
Definition: openssl_missing.h:181
T_HASH
#define T_HASH
Definition: ruby.h:531
rb_method_for_self_aset
const rb_iseq_t * rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func)
Definition: compile.c:9486
RSTRUCT_SET
#define RSTRUCT_SET(st, idx, v)
Definition: ruby.h:1257
rb_hash_set_pair
VALUE rb_hash_set_pair(VALUE hash, VALUE arg)
Definition: hash.c:3332
rb_struct_define_under
VALUE rb_struct_define_under(VALUE outer, const char *name,...)
Definition: struct.c:446
rb_str_to_str
VALUE rb_str_to_str(VALUE)
Definition: string.c:1382
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:241
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
RSTRUCT_LEN
#define RSTRUCT_LEN(st)
Definition: ruby.h:1255
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:105
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
FL_UNSET_RAW
#define FL_UNSET_RAW(x, f)
Definition: ruby.h:1360
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.2.h:5777
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:636
internal.h
OBJ_INIT_COPY
#define OBJ_INIT_COPY(obj, orig)
Definition: intern.h:331
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
argv
char ** argv
Definition: ruby.c:223
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
RSTRUCT_TRANSIENT_UNSET
#define RSTRUCT_TRANSIENT_UNSET(st)
Definition: internal.h:935
rb_hash_uint
#define rb_hash_uint(h, i)
Definition: intern.h:815
rb_ary_join
VALUE rb_ary_join(VALUE ary, VALUE sep)
Definition: array.c:2347
rb_struct_define_without_accessor
VALUE rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc,...)
Definition: struct.c:418
rb_hash
VALUE rb_hash(VALUE obj)
Definition: hash.c:129
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
rb_hash_end
#define rb_hash_end(h)
Definition: intern.h:816
FUNC_FASTCALL
#define FUNC_FASTCALL(x)
Definition: vm_core.h:1139
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(s)
Definition: psych_emitter.c:4
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1753
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2852
rb_alloc_func_t
VALUE(* rb_alloc_func_t)(VALUE)
Definition: intern.h:427
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
OBJ_FREEZE_RAW
#define OBJ_FREEZE_RAW(x)
Definition: ruby.h:1376
va_start
#define va_start(v, l)
Definition: rb_mjit_min_header-2.7.2.h:4013
argc
int argc
Definition: ruby.c:222
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5075
recur
#define recur(fmt)
Definition: date_strptime.c:152
rb_is_local_id
int rb_is_local_id(ID id)
Definition: symbol.c:884
rb_make_metaclass
VALUE rb_make_metaclass(VALUE obj, VALUE unused)
Definition: class.c:580
RSTRUCT_GET
#define RSTRUCT_GET(st, idx)
Definition: ruby.h:1258
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:274
v
int VALUE v
Definition: rb_mjit_min_header-2.7.2.h:12380
len
uint8_t len
Definition: escape.c:17
rb_class_path
VALUE rb_class_path(VALUE)
Definition: variable.c:153
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
RSTRUCT_TRANSIENT_FLAG
@ RSTRUCT_TRANSIENT_FLAG
Definition: internal.h:927
RStruct
Definition: internal.h:942
rb_class_new_instance
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:1955
rb_ary_dup
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:2238
rb_struct_initialize
VALUE rb_struct_initialize(VALUE self, VALUE values)
Definition: struct.c:659
rb_exec_recursive_paired
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:5086
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
T_STRING
#define T_STRING
Definition: ruby.h:528
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
rb_const_defined_at
int rb_const_defined_at(VALUE, ID)
Definition: variable.c:2692
rb_cStruct
VALUE rb_cStruct
Definition: struct.c:26
RHASH_TBL
#define RHASH_TBL(h)
Definition: ruby.h:1127
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
ST2FIX
#define ST2FIX(h)
Definition: ruby_missing.h:21
rb_struct_s_members
VALUE rb_struct_s_members(VALUE klass)
Definition: struct.c:58
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
N_REF_FUNC
#define N_REF_FUNC
Definition: struct.c:234
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:785
T_STRUCT
#define T_STRUCT
Definition: ruby.h:532
Qnil
#define Qnil
Definition: ruby.h:469
rb_define_class_id_under
VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:721
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
rb_name_err_raise
#define rb_name_err_raise(mesg, recv, name)
Definition: internal.h:1577
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:722
numberof
#define numberof(array)
Definition: etc.c:618
UNREACHABLE_RETURN
#define UNREACHABLE_RETURN(val)
Definition: ruby.h:59
st_table
Definition: st.h:79
rb_mod_module_eval
VALUE rb_mod_module_eval(int, const VALUE *, VALUE)
Definition: vm_eval.c:2069
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
RTEST
#define RTEST(v)
Definition: ruby.h:481
SYM2ID
#define SYM2ID(x)
Definition: ruby.h:415
rb_vm_opt_struct_aref
rb_control_frame_t *FUNC_FASTCALL() rb_vm_opt_struct_aref(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)
Definition: vm_insnhelper.c:3467
RSTRUCT_CONST_PTR
#define RSTRUCT_CONST_PTR(st)
Definition: internal.h:962
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.2.h:13552
RSTRUCT
#define RSTRUCT(obj)
Definition: internal.h:966
InitVM_Struct
void InitVM_Struct(void)
Definition: struct.c:1350
NOINLINE
NOINLINE(static VALUE rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound))
name
const char * name
Definition: nkf.c:208
rb_execution_context_struct
Definition: vm_core.h:843
n
const char size_t n
Definition: rb_mjit_min_header-2.7.2.h:5491