Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
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 {
19  AREF_HASH_UNIT = 5,
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, int keyword_init)
320 {
321  long i, len;
322  VALUE (*new_func)(int, const VALUE *, VALUE) = rb_class_new_instance;
323 
324  if (keyword_init) new_func = struct_new_kw;
325 
326  members = struct_set_members(nstr, members);
327 
328  rb_define_alloc_func(nstr, struct_alloc);
329  rb_define_singleton_method(nstr, "new", new_func, -1);
330  rb_define_singleton_method(nstr, "[]", new_func, -1);
331  rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0);
332  rb_define_singleton_method(nstr, "inspect", rb_struct_s_inspect, 0);
333  len = RARRAY_LEN(members);
334  for (i=0; i< len; i++) {
335  VALUE sym = RARRAY_AREF(members, i);
336  ID id = SYM2ID(sym);
337  VALUE off = LONG2NUM(i);
338 
339  if (i < N_REF_FUNC) {
340  rb_define_method_id(nstr, id, ref_func[i], 0);
341  }
342  else {
343  define_aref_method(nstr, sym, off);
344  }
345  define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off);
346  }
347 
348  return nstr;
349 }
350 
351 VALUE
353 {
354  return struct_alloc(klass);
355 }
356 
357 static VALUE
358 struct_make_members_list(va_list ar)
359 {
360  char *mem;
362  st_table *tbl = RHASH_TBL(list);
363 
365  while ((mem = va_arg(ar, char*)) != 0) {
367  if (st_insert(tbl, sym, Qtrue)) {
368  rb_raise(rb_eArgError, "duplicate member: %s", mem);
369  }
370  }
371  ary = rb_hash_keys(list);
372  st_clear(tbl);
375  return ary;
376 }
377 
378 static VALUE
379 struct_define_without_accessor(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, VALUE members)
380 {
381  VALUE klass;
382 
383  if (class_name) {
384  if (outer) {
385  klass = rb_define_class_under(outer, class_name, super);
386  }
387  else {
388  klass = rb_define_class(class_name, super);
389  }
390  }
391  else {
392  klass = anonymous_struct(super);
393  }
394 
395  struct_set_members(klass, members);
396 
397  if (alloc) {
398  rb_define_alloc_func(klass, alloc);
399  }
400  else {
401  rb_define_alloc_func(klass, struct_alloc);
402  }
403 
404  return klass;
405 }
406 
407 VALUE
408 rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
409 {
410  va_list ar;
411  VALUE members;
412 
413  va_start(ar, alloc);
414  members = struct_make_members_list(ar);
415  va_end(ar);
416 
417  return struct_define_without_accessor(outer, class_name, super, alloc, members);
418 }
419 
420 VALUE
421 rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
422 {
423  va_list ar;
424  VALUE members;
425 
426  va_start(ar, alloc);
427  members = struct_make_members_list(ar);
428  va_end(ar);
429 
430  return struct_define_without_accessor(0, class_name, super, alloc, members);
431 }
432 
433 VALUE
434 rb_struct_define(const char *name, ...)
435 {
436  va_list ar;
437  VALUE st, ary;
438 
439  va_start(ar, name);
440  ary = struct_make_members_list(ar);
441  va_end(ar);
442 
443  if (!name) st = anonymous_struct(rb_cStruct);
444  else st = new_struct(rb_str_new2(name), rb_cStruct);
445  return setup_struct(st, ary, 0);
446 }
447 
448 VALUE
449 rb_struct_define_under(VALUE outer, const char *name, ...)
450 {
451  va_list ar;
452  VALUE ary;
453 
454  va_start(ar, name);
455  ary = struct_make_members_list(ar);
456  va_end(ar);
457 
458  return setup_struct(rb_define_class_under(outer, name, rb_cStruct), ary, 0);
459 }
460 
461 /*
462  * call-seq:
463  * Struct.new([class_name] [, member_name]+) -> StructClass
464  * Struct.new([class_name] [, member_name]+, keyword_init: true) -> StructClass
465  * Struct.new([class_name] [, member_name]+) {|StructClass| block } -> StructClass
466  * StructClass.new(value, ...) -> object
467  * StructClass[value, ...] -> object
468  *
469  * The first two forms are used to create a new Struct subclass +class_name+
470  * that can contain a value for each +member_name+. This subclass can be
471  * used to create instances of the structure like any other Class.
472  *
473  * If the +class_name+ is omitted an anonymous structure class will be
474  * created. Otherwise, the name of this struct will appear as a constant in
475  * class Struct, so it must be unique for all Structs in the system and
476  * must start with a capital letter. Assigning a structure class to a
477  * constant also gives the class the name of the constant.
478  *
479  * # Create a structure with a name under Struct
480  * Struct.new("Customer", :name, :address)
481  * #=> Struct::Customer
482  * Struct::Customer.new("Dave", "123 Main")
483  * #=> #<struct Struct::Customer name="Dave", address="123 Main">
484  *
485  * # Create a structure named by its constant
486  * Customer = Struct.new(:name, :address)
487  * #=> Customer
488  * Customer.new("Dave", "123 Main")
489  * #=> #<struct Customer name="Dave", address="123 Main">
490  *
491  * If the optional +keyword_init+ keyword argument is set to +true+,
492  * .new takes keyword arguments instead of normal arguments.
493  *
494  * Customer = Struct.new(:name, :address, keyword_init: true)
495  * Customer.new(name: "Dave", address: "123 Main")
496  * #=> #<struct Customer name="Dave", address="123 Main">
497  *
498  * If a block is given it will be evaluated in the context of
499  * +StructClass+, passing the created class as a parameter:
500  *
501  * Customer = Struct.new(:name, :address) do
502  * def greeting
503  * "Hello #{name}!"
504  * end
505  * end
506  * Customer.new("Dave", "123 Main").greeting #=> "Hello Dave!"
507  *
508  * This is the recommended way to customize a struct. Subclassing an
509  * anonymous struct creates an extra anonymous class that will never be used.
510  *
511  * The last two forms create a new instance of a struct subclass. The number
512  * of +value+ parameters must be less than or equal to the number of
513  * attributes defined for the structure. Unset parameters default to +nil+.
514  * Passing more parameters than number of attributes will raise
515  * an ArgumentError.
516  *
517  * Customer = Struct.new(:name, :address)
518  * Customer.new("Dave", "123 Main")
519  * #=> #<struct Customer name="Dave", address="123 Main">
520  * Customer["Dave"]
521  * #=> #<struct Customer name="Dave", address=nil>
522  */
523 
524 static VALUE
525 rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
526 {
527  VALUE name, rest, keyword_init = Qfalse;
528  long i;
529  VALUE st;
530  st_table *tbl;
531 
533  name = argv[0];
534  if (SYMBOL_P(name)) {
535  name = Qnil;
536  }
537  else {
538  --argc;
539  ++argv;
540  }
541 
542  if (RB_TYPE_P(argv[argc-1], T_HASH)) {
543  static ID keyword_ids[1];
544 
545  if (!keyword_ids[0]) {
546  keyword_ids[0] = rb_intern("keyword_init");
547  }
548  rb_get_kwargs(argv[argc-1], keyword_ids, 0, 1, &keyword_init);
549  if (keyword_init == Qundef) {
550  keyword_init = Qfalse;
551  }
552  --argc;
553  }
554 
555  rest = rb_ident_hash_new();
556  RBASIC_CLEAR_CLASS(rest);
557  tbl = RHASH_TBL(rest);
558  for (i=0; i<argc; i++) {
559  VALUE mem = rb_to_symbol(argv[i]);
560  if (rb_is_attrset_sym(mem)) {
561  rb_raise(rb_eArgError, "invalid struct member: %"PRIsVALUE, mem);
562  }
563  if (st_insert(tbl, mem, Qtrue)) {
564  rb_raise(rb_eArgError, "duplicate member: %"PRIsVALUE, mem);
565  }
566  }
567  rest = rb_hash_keys(rest);
568  st_clear(tbl);
569  RBASIC_CLEAR_CLASS(rest);
570  OBJ_FREEZE_RAW(rest);
571  if (NIL_P(name)) {
572  st = anonymous_struct(klass);
573  }
574  else {
575  st = new_struct(name, klass);
576  }
577  setup_struct(st, rest, (int)keyword_init);
578  rb_ivar_set(st, id_keyword_init, keyword_init);
579  if (rb_block_given_p()) {
580  rb_mod_module_eval(0, 0, st);
581  }
582 
583  return st;
584 }
585 
586 static long
587 num_members(VALUE klass)
588 {
589  VALUE members;
590  members = struct_ivar_get(klass, id_members);
591  if (!RB_TYPE_P(members, T_ARRAY)) {
592  rb_raise(rb_eTypeError, "broken members");
593  }
594  return RARRAY_LEN(members);
595 }
596 
597 /*
598  */
599 
601  VALUE self;
603 };
604 
605 static int rb_struct_pos(VALUE s, VALUE *name);
606 
607 static int
608 struct_hash_set_i(VALUE key, VALUE val, VALUE arg)
609 {
610  struct struct_hash_set_arg *args = (struct struct_hash_set_arg *)arg;
611  int i = rb_struct_pos(args->self, &key);
612  if (i < 0) {
613  if (args->unknown_keywords == Qnil) {
614  args->unknown_keywords = rb_ary_new();
615  }
617  }
618  else {
619  rb_struct_modify(args->self);
620  RSTRUCT_SET(args->self, i, val);
621  }
622  return ST_CONTINUE;
623 }
624 
625 static VALUE
626 rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self)
627 {
628  VALUE klass = rb_obj_class(self);
629  long i, n;
630 
631  rb_struct_modify(self);
632  n = num_members(klass);
633  if (argc > 0 && RTEST(rb_struct_s_keyword_init(klass))) {
634  struct struct_hash_set_arg arg;
635  if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
636  rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0)", argc);
637  }
639  arg.self = self;
640  arg.unknown_keywords = Qnil;
641  rb_hash_foreach(argv[0], struct_hash_set_i, (VALUE)&arg);
642  if (arg.unknown_keywords != Qnil) {
643  rb_raise(rb_eArgError, "unknown keywords: %s",
644  RSTRING_PTR(rb_ary_join(arg.unknown_keywords, rb_str_new2(", "))));
645  }
646  }
647  else {
648  if (n < argc) {
649  rb_raise(rb_eArgError, "struct size differs");
650  }
651  for (i=0; i<argc; i++) {
652  RSTRUCT_SET(self, i, argv[i]);
653  }
654  if (n > argc) {
656  }
657  }
658  return Qnil;
659 }
660 
661 VALUE
663 {
664  return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self);
665 }
666 
667 static VALUE *
668 struct_heap_alloc(VALUE st, size_t len)
669 {
671 
672  if (ptr) {
674  return ptr;
675  }
676  else {
678  return ALLOC_N(VALUE, len);
679  }
680 }
681 
682 #if USE_TRANSIENT_HEAP
683 void
685 {
686  if (RSTRUCT_TRANSIENT_P(obj)) {
687  const VALUE *old_ptr = rb_struct_const_heap_ptr(obj);
688  VALUE *new_ptr;
689  long len = RSTRUCT_LEN(obj);
690 
691  if (promote) {
692  new_ptr = ALLOC_N(VALUE, len);
694  }
695  else {
696  new_ptr = struct_heap_alloc(obj, len);
697  }
698  MEMCPY(new_ptr, old_ptr, VALUE, len);
699  RSTRUCT(obj)->as.heap.ptr = new_ptr;
700  }
701 }
702 #endif
703 
704 static VALUE
705 struct_alloc(VALUE klass)
706 {
707  long n;
709 
710  n = num_members(klass);
711 
712  if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
713  RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
714  RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
715  rb_mem_clear((VALUE *)st->as.ary, n);
716  }
717  else {
718  st->as.heap.ptr = struct_heap_alloc((VALUE)st, n);
719  rb_mem_clear((VALUE *)st->as.heap.ptr, n);
720  st->as.heap.len = n;
721  }
722 
723  return (VALUE)st;
724 }
725 
726 VALUE
728 {
729  return rb_class_new_instance(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), klass);
730 }
731 
732 VALUE
734 {
735  VALUE tmpargs[N_REF_FUNC], *mem = tmpargs;
736  int size, i;
737  va_list args;
738 
739  size = rb_long2int(num_members(klass));
740  if (size > numberof(tmpargs)) {
741  tmpargs[0] = rb_ary_tmp_new(size);
742  mem = RARRAY_PTR(tmpargs[0]);
743  }
744  va_start(args, klass);
745  for (i=0; i<size; i++) {
746  mem[i] = va_arg(args, VALUE);
747  }
748  va_end(args);
749 
750  return rb_class_new_instance(size, mem, klass);
751 }
752 
753 static VALUE
754 struct_enum_size(VALUE s, VALUE args, VALUE eobj)
755 {
756  return rb_struct_size(s);
757 }
758 
759 /*
760  * call-seq:
761  * struct.each {|obj| block } -> struct
762  * struct.each -> enumerator
763  *
764  * Yields the value of each struct member in order. If no block is given an
765  * enumerator is returned.
766  *
767  * Customer = Struct.new(:name, :address, :zip)
768  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
769  * joe.each {|x| puts(x) }
770  *
771  * Produces:
772  *
773  * Joe Smith
774  * 123 Maple, Anytown NC
775  * 12345
776  */
777 
778 static VALUE
779 rb_struct_each(VALUE s)
780 {
781  long i;
782 
783  RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
784  for (i=0; i<RSTRUCT_LEN(s); i++) {
785  rb_yield(RSTRUCT_GET(s, i));
786  }
787  return s;
788 }
789 
790 /*
791  * call-seq:
792  * struct.each_pair {|sym, obj| block } -> struct
793  * struct.each_pair -> enumerator
794  *
795  * Yields the name and value of each struct member in order. If no block is
796  * given an enumerator is returned.
797  *
798  * Customer = Struct.new(:name, :address, :zip)
799  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
800  * joe.each_pair {|name, value| puts("#{name} => #{value}") }
801  *
802  * Produces:
803  *
804  * name => Joe Smith
805  * address => 123 Maple, Anytown NC
806  * zip => 12345
807  */
808 
809 static VALUE
810 rb_struct_each_pair(VALUE s)
811 {
812  VALUE members;
813  long i;
814 
815  RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
816  members = rb_struct_members(s);
817  if (rb_block_arity() > 1) {
818  for (i=0; i<RSTRUCT_LEN(s); i++) {
819  VALUE key = rb_ary_entry(members, i);
820  VALUE value = RSTRUCT_GET(s, i);
821  rb_yield_values(2, key, value);
822  }
823  }
824  else {
825  for (i=0; i<RSTRUCT_LEN(s); i++) {
826  VALUE key = rb_ary_entry(members, i);
827  VALUE value = RSTRUCT_GET(s, i);
828  rb_yield(rb_assoc_new(key, value));
829  }
830  }
831  return s;
832 }
833 
834 static VALUE
835 inspect_struct(VALUE s, VALUE dummy, int recur)
836 {
837  VALUE cname = rb_class_path(rb_obj_class(s));
838  VALUE members, str = rb_str_new2("#<struct ");
839  long i, len;
840  char first = RSTRING_PTR(cname)[0];
841 
842  if (recur || first != '#') {
843  rb_str_append(str, cname);
844  }
845  if (recur) {
846  return rb_str_cat2(str, ":...>");
847  }
848 
849  members = rb_struct_members(s);
850  len = RSTRUCT_LEN(s);
851 
852  for (i=0; i<len; i++) {
853  VALUE slot;
854  ID id;
855 
856  if (i > 0) {
857  rb_str_cat2(str, ", ");
858  }
859  else if (first != '#') {
860  rb_str_cat2(str, " ");
861  }
862  slot = RARRAY_AREF(members, i);
863  id = SYM2ID(slot);
864  if (rb_is_local_id(id) || rb_is_const_id(id)) {
866  }
867  else {
868  rb_str_append(str, rb_inspect(slot));
869  }
870  rb_str_cat2(str, "=");
872  }
873  rb_str_cat2(str, ">");
874 
875  return str;
876 }
877 
878 /*
879  * call-seq:
880  * struct.to_s -> string
881  * struct.inspect -> string
882  *
883  * Returns a description of this struct as a string.
884  */
885 
886 static VALUE
887 rb_struct_inspect(VALUE s)
888 {
889  return rb_exec_recursive(inspect_struct, s, 0);
890 }
891 
892 /*
893  * call-seq:
894  * struct.to_a -> array
895  * struct.values -> array
896  *
897  * Returns the values for this struct as an Array.
898  *
899  * Customer = Struct.new(:name, :address, :zip)
900  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
901  * joe.to_a[1] #=> "123 Maple, Anytown NC"
902  */
903 
904 static VALUE
905 rb_struct_to_a(VALUE s)
906 {
908 }
909 
910 /*
911  * call-seq:
912  * struct.to_h -> hash
913  * struct.to_h {|name, value| block } -> hash
914  *
915  * Returns a Hash containing the names and values for the struct's members.
916  *
917  * If a block is given, the results of the block on each pair of the receiver
918  * will be used as pairs.
919  *
920  * Customer = Struct.new(:name, :address, :zip)
921  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
922  * joe.to_h[:address] #=> "123 Maple, Anytown NC"
923  * joe.to_h{|name, value| [name.upcase, value.to_s.upcase]}[:ADDRESS]
924  * #=> "123 MAPLE, ANYTOWN NC"
925  */
926 
927 static VALUE
928 rb_struct_to_h(VALUE s)
929 {
931  VALUE members = rb_struct_members(s);
932  long i;
933  int block_given = rb_block_given_p();
934 
935  for (i=0; i<RSTRUCT_LEN(s); i++) {
936  VALUE k = rb_ary_entry(members, i), v = RSTRUCT_GET(s, i);
937  if (block_given)
939  else
940  rb_hash_aset(h, k, v);
941  }
942  return h;
943 }
944 
945 static VALUE
946 rb_struct_deconstruct_keys(VALUE s, VALUE keys)
947 {
948  VALUE h;
949  long i;
950 
951  if (NIL_P(keys)) {
952  return rb_struct_to_h(s);
953  }
954  if (UNLIKELY(!RB_TYPE_P(keys, T_ARRAY))) {
956  "wrong argument type %"PRIsVALUE" (expected Array or nil)",
957  rb_obj_class(keys));
958 
959  }
960  if (RSTRUCT_LEN(s) < RARRAY_LEN(keys)) {
961  return rb_hash_new_with_size(0);
962  }
964  for (i=0; i<RARRAY_LEN(keys); i++) {
965  VALUE key = RARRAY_AREF(keys, i);
966  int i = rb_struct_pos(s, &key);
967  if (i < 0) {
968  return h;
969  }
970  rb_hash_aset(h, key, RSTRUCT_GET(s, i));
971  }
972  return h;
973 }
974 
975 /* :nodoc: */
976 VALUE
978 {
979  long i, len;
980 
981  if (!OBJ_INIT_COPY(copy, s)) return copy;
982  if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
983  rb_raise(rb_eTypeError, "struct size mismatch");
984  }
985 
986  for (i=0, len=RSTRUCT_LEN(copy); i<len; i++) {
987  RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i));
988  }
989 
990  return copy;
991 }
992 
993 static int
994 rb_struct_pos(VALUE s, VALUE *name)
995 {
996  long i;
997  VALUE idx = *name;
998 
999  if (RB_TYPE_P(idx, T_SYMBOL)) {
1000  return struct_member_pos(s, idx);
1001  }
1002  else if (RB_TYPE_P(idx, T_STRING)) {
1003  idx = rb_check_symbol(name);
1004  if (NIL_P(idx)) return -1;
1005  return struct_member_pos(s, idx);
1006  }
1007  else {
1008  long len;
1009  i = NUM2LONG(idx);
1010  len = RSTRUCT_LEN(s);
1011  if (i < 0) {
1012  if (i + len < 0) {
1013  *name = LONG2FIX(i);
1014  return -1;
1015  }
1016  i += len;
1017  }
1018  else if (len <= i) {
1019  *name = LONG2FIX(i);
1020  return -1;
1021  }
1022  return (int)i;
1023  }
1024 }
1025 
1026 NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx));
1027 static void
1028 invalid_struct_pos(VALUE s, VALUE idx)
1029 {
1030  if (FIXNUM_P(idx)) {
1031  long i = FIX2INT(idx), len = RSTRUCT_LEN(s);
1032  if (i < 0) {
1033  rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
1034  i, len);
1035  }
1036  else {
1037  rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
1038  i, len);
1039  }
1040  }
1041  else {
1042  rb_name_err_raise("no member '%1$s' in struct", s, idx);
1043  }
1044 }
1045 
1046 /*
1047  * call-seq:
1048  * struct[member] -> object
1049  * struct[index] -> object
1050  *
1051  * Attribute Reference---Returns the value of the given struct +member+ or
1052  * the member at the given +index+. Raises NameError if the +member+ does
1053  * not exist and IndexError if the +index+ is out of range.
1054  *
1055  * Customer = Struct.new(:name, :address, :zip)
1056  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1057  *
1058  * joe["name"] #=> "Joe Smith"
1059  * joe[:name] #=> "Joe Smith"
1060  * joe[0] #=> "Joe Smith"
1061  */
1062 
1063 VALUE
1065 {
1066  int i = rb_struct_pos(s, &idx);
1067  if (i < 0) invalid_struct_pos(s, idx);
1068  return RSTRUCT_GET(s, i);
1069 }
1070 
1071 /*
1072  * call-seq:
1073  * struct[member] = obj -> obj
1074  * struct[index] = obj -> obj
1075  *
1076  * Attribute Assignment---Sets the value of the given struct +member+ or
1077  * the member at the given +index+. Raises NameError if the +member+ does not
1078  * exist and IndexError if the +index+ is out of range.
1079  *
1080  * Customer = Struct.new(:name, :address, :zip)
1081  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1082  *
1083  * joe["name"] = "Luke"
1084  * joe[:zip] = "90210"
1085  *
1086  * joe.name #=> "Luke"
1087  * joe.zip #=> "90210"
1088  */
1089 
1090 VALUE
1092 {
1093  int i = rb_struct_pos(s, &idx);
1094  if (i < 0) invalid_struct_pos(s, idx);
1095  rb_struct_modify(s);
1096  RSTRUCT_SET(s, i, val);
1097  return val;
1098 }
1099 
1101 NOINLINE(static VALUE rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound));
1102 
1103 VALUE
1105 {
1106  return rb_struct_lookup_default(s, idx, Qnil);
1107 }
1108 
1109 static VALUE
1110 rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound)
1111 {
1112  int i = rb_struct_pos(s, &idx);
1113  if (i < 0) return notfound;
1114  return RSTRUCT_GET(s, i);
1115 }
1116 
1117 static VALUE
1118 struct_entry(VALUE s, long n)
1119 {
1120  return rb_struct_aref(s, LONG2NUM(n));
1121 }
1122 
1123 /*
1124  * call-seq:
1125  * struct.values_at(selector, ...) -> array
1126  *
1127  * Returns the struct member values for each +selector+ as an Array. A
1128  * +selector+ may be either an Integer offset or a Range of offsets (as in
1129  * Array#values_at).
1130  *
1131  * Customer = Struct.new(:name, :address, :zip)
1132  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1133  * joe.values_at(0, 2) #=> ["Joe Smith", 12345]
1134  *
1135  */
1136 
1137 static VALUE
1138 rb_struct_values_at(int argc, VALUE *argv, VALUE s)
1139 {
1140  return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
1141 }
1142 
1143 /*
1144  * call-seq:
1145  * struct.select {|obj| block } -> array
1146  * struct.select -> enumerator
1147  * struct.filter {|obj| block } -> array
1148  * struct.filter -> enumerator
1149  *
1150  * Yields each member value from the struct to the block and returns an Array
1151  * containing the member values from the +struct+ for which the given block
1152  * returns a true value (equivalent to Enumerable#select).
1153  *
1154  * Lots = Struct.new(:a, :b, :c, :d, :e, :f)
1155  * l = Lots.new(11, 22, 33, 44, 55, 66)
1156  * l.select {|v| v.even? } #=> [22, 44, 66]
1157  *
1158  * Struct#filter is an alias for Struct#select.
1159  */
1160 
1161 static VALUE
1162 rb_struct_select(int argc, VALUE *argv, VALUE s)
1163 {
1164  VALUE result;
1165  long i;
1166 
1167  rb_check_arity(argc, 0, 0);
1168  RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
1169  result = rb_ary_new();
1170  for (i = 0; i < RSTRUCT_LEN(s); i++) {
1171  if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
1172  rb_ary_push(result, RSTRUCT_GET(s, i));
1173  }
1174  }
1175 
1176  return result;
1177 }
1178 
1179 static VALUE
1180 recursive_equal(VALUE s, VALUE s2, int recur)
1181 {
1182  long i, len;
1183 
1184  if (recur) return Qtrue; /* Subtle! */
1185  len = RSTRUCT_LEN(s);
1186  for (i=0; i<len; i++) {
1187  if (!rb_equal(RSTRUCT_GET(s, i), RSTRUCT_GET(s2, i))) return Qfalse;
1188  }
1189  return Qtrue;
1190 }
1191 
1192 /*
1193  * call-seq:
1194  * struct == other -> true or false
1195  *
1196  * Equality---Returns +true+ if +other+ has the same struct subclass and has
1197  * equal member values (according to Object#==).
1198  *
1199  * Customer = Struct.new(:name, :address, :zip)
1200  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1201  * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1202  * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
1203  * joe == joejr #=> true
1204  * joe == jane #=> false
1205  */
1206 
1207 static VALUE
1208 rb_struct_equal(VALUE s, VALUE s2)
1209 {
1210  if (s == s2) return Qtrue;
1211  if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
1212  if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
1213  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
1214  rb_bug("inconsistent struct"); /* should never happen */
1215  }
1216 
1217  return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
1218 }
1219 
1220 /*
1221  * call-seq:
1222  * struct.hash -> integer
1223  *
1224  * Returns a hash value based on this struct's contents.
1225  *
1226  * See also Object#hash.
1227  */
1228 
1229 static VALUE
1230 rb_struct_hash(VALUE s)
1231 {
1232  long i, len;
1233  st_index_t h;
1234  VALUE n;
1235 
1237  len = RSTRUCT_LEN(s);
1238  for (i = 0; i < len; i++) {
1239  n = rb_hash(RSTRUCT_GET(s, i));
1240  h = rb_hash_uint(h, NUM2LONG(n));
1241  }
1242  h = rb_hash_end(h);
1243  return ST2FIX(h);
1244 }
1245 
1246 static VALUE
1247 recursive_eql(VALUE s, VALUE s2, int recur)
1248 {
1249  long i, len;
1250 
1251  if (recur) return Qtrue; /* Subtle! */
1252  len = RSTRUCT_LEN(s);
1253  for (i=0; i<len; i++) {
1254  if (!rb_eql(RSTRUCT_GET(s, i), RSTRUCT_GET(s2, i))) return Qfalse;
1255  }
1256  return Qtrue;
1257 }
1258 
1259 /*
1260  * call-seq:
1261  * struct.eql?(other) -> true or false
1262  *
1263  * Hash equality---+other+ and +struct+ refer to the same hash key if they
1264  * have the same struct subclass and have equal member values (according to
1265  * Object#eql?).
1266  */
1267 
1268 static VALUE
1269 rb_struct_eql(VALUE s, VALUE s2)
1270 {
1271  if (s == s2) return Qtrue;
1272  if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
1273  if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
1274  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
1275  rb_bug("inconsistent struct"); /* should never happen */
1276  }
1277 
1278  return rb_exec_recursive_paired(recursive_eql, s, s2, s2);
1279 }
1280 
1281 /*
1282  * call-seq:
1283  * struct.length -> integer
1284  * struct.size -> integer
1285  *
1286  * Returns the number of struct members.
1287  *
1288  * Customer = Struct.new(:name, :address, :zip)
1289  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1290  * joe.length #=> 3
1291  */
1292 
1293 VALUE
1295 {
1296  return LONG2FIX(RSTRUCT_LEN(s));
1297 }
1298 
1299 /*
1300  * call-seq:
1301  * struct.dig(key, ...) -> object
1302  *
1303  * Extracts the nested value specified by the sequence of +key+
1304  * objects by calling +dig+ at each step, returning +nil+ if any
1305  * intermediate step is +nil+.
1306  *
1307  * Foo = Struct.new(:a)
1308  * f = Foo.new(Foo.new({b: [1, 2, 3]}))
1309  *
1310  * f.dig(:a, :a, :b, 0) # => 1
1311  * f.dig(:b, 0) # => nil
1312  * f.dig(:a, :a, :b, :c) # TypeError: no implicit conversion of Symbol into Integer
1313  */
1314 
1315 static VALUE
1316 rb_struct_dig(int argc, VALUE *argv, VALUE self)
1317 {
1319  self = rb_struct_lookup(self, *argv);
1320  if (!--argc) return self;
1321  ++argv;
1322  return rb_obj_dig(argc, argv, self, Qnil);
1323 }
1324 
1325 /*
1326  * Document-class: Struct
1327  *
1328  * A Struct is a convenient way to bundle a number of attributes together,
1329  * using accessor methods, without having to write an explicit class.
1330  *
1331  * The Struct class generates new subclasses that hold a set of members and
1332  * their values. For each member a reader and writer method is created
1333  * similar to Module#attr_accessor.
1334  *
1335  * Customer = Struct.new(:name, :address) do
1336  * def greeting
1337  * "Hello #{name}!"
1338  * end
1339  * end
1340  *
1341  * dave = Customer.new("Dave", "123 Main")
1342  * dave.name #=> "Dave"
1343  * dave.greeting #=> "Hello Dave!"
1344  *
1345  * See Struct::new for further examples of creating struct subclasses and
1346  * instances.
1347  *
1348  * In the method descriptions that follow, a "member" parameter refers to a
1349  * struct member which is either a quoted string (<code>"name"</code>) or a
1350  * Symbol (<code>:name</code>).
1351  */
1352 void
1354 {
1355  rb_cStruct = rb_define_class("Struct", rb_cObject);
1357 
1359  rb_define_singleton_method(rb_cStruct, "new", rb_struct_s_def, -1);
1360 
1361  rb_define_method(rb_cStruct, "initialize", rb_struct_initialize_m, -1);
1362  rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
1363 
1364  rb_define_method(rb_cStruct, "==", rb_struct_equal, 1);
1365  rb_define_method(rb_cStruct, "eql?", rb_struct_eql, 1);
1366  rb_define_method(rb_cStruct, "hash", rb_struct_hash, 0);
1367 
1368  rb_define_method(rb_cStruct, "inspect", rb_struct_inspect, 0);
1369  rb_define_alias(rb_cStruct, "to_s", "inspect");
1370  rb_define_method(rb_cStruct, "to_a", rb_struct_to_a, 0);
1371  rb_define_method(rb_cStruct, "to_h", rb_struct_to_h, 0);
1372  rb_define_method(rb_cStruct, "values", rb_struct_to_a, 0);
1375 
1376  rb_define_method(rb_cStruct, "each", rb_struct_each, 0);
1377  rb_define_method(rb_cStruct, "each_pair", rb_struct_each_pair, 0);
1380  rb_define_method(rb_cStruct, "select", rb_struct_select, -1);
1381  rb_define_method(rb_cStruct, "filter", rb_struct_select, -1);
1382  rb_define_method(rb_cStruct, "values_at", rb_struct_values_at, -1);
1383 
1384  rb_define_method(rb_cStruct, "members", rb_struct_members_m, 0);
1385  rb_define_method(rb_cStruct, "dig", rb_struct_dig, -1);
1386 
1387  rb_define_method(rb_cStruct, "deconstruct", rb_struct_to_a, 0);
1388  rb_define_method(rb_cStruct, "deconstruct_keys", rb_struct_deconstruct_keys, 1);
1389 }
1390 
1391 #undef rb_intern
1392 void
1394 {
1395  id_members = rb_intern("__members__");
1396  id_back_members = rb_intern("__members_back__");
1397  id_keyword_init = rb_intern("__keyword_init__");
1398 
1399  InitVM(Struct);
1400 }
rb_is_const_name
int rb_is_const_name(VALUE name)
Definition: symbol.c:1050
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
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5464
UNLIKELY
#define UNLIKELY(x)
Definition: ffi_common.h:126
ID
unsigned long ID
Definition: ruby.h:103
rb_str_cat_cstr
#define rb_str_cat_cstr(str, ptr)
Definition: rb_mjit_min_header-2.7.1.h:6126
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:1393
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.1.h:5742
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:9476
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:977
rb_mod_remove_const
VALUE rb_mod_remove_const(VALUE, VALUE)
Definition: variable.c:2479
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
AREF_HASH_UNIT
@ AREF_HASH_UNIT
Definition: struct.c:28
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.1.h:13259
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:4272
rb_struct_alloc
VALUE rb_struct_alloc(VALUE klass, VALUE values)
Definition: struct.c:727
rb_struct_members
VALUE rb_struct_members(VALUE s)
Definition: struct.c:72
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
rb_struct_aset
VALUE rb_struct_aset(VALUE s, VALUE idx, VALUE val)
Definition: struct.c:1091
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:1986
rb_sym_intern_ascii_cstr
#define rb_sym_intern_ascii_cstr(ptr)
Definition: rb_mjit_min_header-2.7.1.h:7763
rb_struct_lookup
VALUE rb_struct_lookup(VALUE s, VALUE idx)
Definition: struct.c:1104
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
rb_to_symbol
VALUE rb_to_symbol(VALUE name)
Definition: string.c:11156
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5456
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
st
enum ruby_tag_type st
Definition: rb_mjit_min_header-2.7.1.h:11116
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
rb_struct_new
VALUE rb_struct_new(VALUE klass,...)
Definition: struct.c:733
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:923
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
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5601
rb_eIndexError
VALUE rb_eIndexError
Definition: error.c:924
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
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.1.h:13509
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:600
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:3403
ptr
struct RIMemo * ptr
Definition: debug.c:74
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
keys
const rb_iseq_t const char const VALUE keys
Definition: rb_mjit_min_header-2.7.1.h:13511
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:434
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:602
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:408
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:601
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:2669
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
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
va_start
#define va_start(v, l)
Definition: rb_mjit_min_header-2.7.1.h:3978
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
s2
const char * s2
Definition: rb_mjit_min_header-2.7.1.h:5454
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
h
size_t st_index_t h
Definition: rb_mjit_min_header-2.7.1.h:5462
sym
#define sym(x)
Definition: date_core.c:3716
mask
enum @11::@13::@14 mask
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:684
rb_struct_aref
VALUE rb_struct_aref(VALUE s, VALUE idx)
Definition: struct.c:1064
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:352
rb_hash_start
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1434
transient_heap.h
va_list
__gnuc_va_list va_list
Definition: rb_mjit_min_header-2.7.1.h:836
vm_core.h
va_arg
#define va_arg(v, l)
Definition: rb_mjit_min_header-2.7.1.h:3980
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
RSTRUCT_EMBED_LEN_SHIFT
#define RSTRUCT_EMBED_LEN_SHIFT
Definition: internal.h:921
RSTRUCT_TRANSIENT_FLAG
@ RSTRUCT_TRANSIENT_FLAG
Definition: internal.h:927
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
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:1294
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
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:9485
RSTRUCT_SET
#define RSTRUCT_SET(st, idx, v)
Definition: ruby.h:1257
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1072
rb_hash_set_pair
VALUE rb_hash_set_pair(VALUE hash, VALUE arg)
Definition: hash.c:3326
rb_struct_define_under
VALUE rb_struct_define_under(VALUE outer, const char *name,...)
Definition: struct.c:449
rb_str_to_str
VALUE rb_str_to_str(VALUE)
Definition: string.c:1382
rb_yield_values
#define rb_yield_values(argc,...)
Definition: rb_mjit_min_header-2.7.1.h:6584
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
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
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:421
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
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:2847
int
__inline__ int
Definition: rb_mjit_min_header-2.7.1.h:2839
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
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
v
int VALUE v
Definition: rb_mjit_min_header-2.7.1.h:12337
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
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
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:662
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:2688
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:1576
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
va_end
#define va_end(v)
Definition: rb_mjit_min_header-2.7.1.h:3979
RSTRUCT
#define RSTRUCT(obj)
Definition: internal.h:966
InitVM_Struct
void InitVM_Struct(void)
Definition: struct.c:1353
AREF_HASH_THRESHOLD
@ AREF_HASH_THRESHOLD
Definition: struct.c:29
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