Ruby  2.1.10p492(2016-04-01revision54464)
struct.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  struct.c -
4 
5  $Author: nagachika $
6  created at: Tue Mar 22 18:44:30 JST 1995
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #include "ruby/ruby.h"
13 #include "internal.h"
14 
16 static ID id_members;
17 
18 static VALUE struct_alloc(VALUE);
19 
20 static inline VALUE
22 {
23  for (;;) {
24  if (rb_ivar_defined(c, id))
25  return rb_ivar_get(c, id);
26  c = RCLASS_SUPER(c);
27  if (c == 0 || c == rb_cStruct)
28  return Qnil;
29  }
30 }
31 
32 VALUE
34 {
35  return struct_ivar_get(c, rb_intern(name));
36 }
37 
38 VALUE
40 {
41  VALUE members = struct_ivar_get(klass, id_members);
42 
43  if (NIL_P(members)) {
44  rb_raise(rb_eTypeError, "uninitialized struct");
45  }
46  if (!RB_TYPE_P(members, T_ARRAY)) {
47  rb_raise(rb_eTypeError, "corrupted struct");
48  }
49  return members;
50 }
51 
52 VALUE
54 {
56 
57  if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
58  rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
59  RARRAY_LEN(members), RSTRUCT_LEN(s));
60  }
61  return members;
62 }
63 
64 static VALUE
66 {
67  VALUE members = rb_struct_s_members(klass);
68 
69  return rb_ary_dup(members);
70 }
71 
72 /*
73  * call-seq:
74  * struct.members -> array
75  *
76  * Returns the struct members as an array of symbols:
77  *
78  * Customer = Struct.new(:name, :address, :zip)
79  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
80  * joe.members #=> [:name, :address, :zip]
81  */
82 
83 static VALUE
85 {
87 }
88 
89 NORETURN(static void not_a_member(ID id));
90 static void
92 {
93  rb_name_error(id, "`%"PRIsVALUE"' is not a struct member", QUOTE_ID(id));
94 }
95 
96 VALUE
98 {
99  VALUE members, slot;
100  long i, len;
101 
102  members = rb_struct_members(obj);
103  slot = ID2SYM(id);
104  len = RARRAY_LEN(members);
105  for (i=0; i<len; i++) {
106  if (RARRAY_AREF(members, i) == slot) {
107  return RSTRUCT_GET(obj, i);
108  }
109  }
110  not_a_member(id);
111 
112  UNREACHABLE;
113 }
114 
115 static VALUE
117 {
119 }
120 
121 static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);}
122 static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);}
123 static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);}
124 static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_GET(obj, 3);}
125 static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_GET(obj, 4);}
126 static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_GET(obj, 5);}
127 static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_GET(obj, 6);}
128 static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_GET(obj, 7);}
129 static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_GET(obj, 8);}
130 static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_GET(obj, 9);}
131 
132 #define N_REF_FUNC numberof(ref_func)
133 
134 static VALUE (*const ref_func[])(VALUE) = {
145 };
146 
147 static void
149 {
150  rb_check_frozen(s);
151  rb_check_trusted(s);
152 }
153 
154 static VALUE
156 {
157  VALUE members, slot;
158  long i, len;
159  ID fid = rb_frame_this_func();
160 
161  members = rb_struct_members(obj);
162  len = RARRAY_LEN(members);
163  rb_struct_modify(obj);
164  for (i=0; i<len; i++) {
165  slot = RARRAY_AREF(members, i);
166  if (rb_id_attrset(SYM2ID(slot)) == fid) {
167  RSTRUCT_SET(obj, i, val);
168  return val;
169  }
170  }
171  not_a_member(fid);
172 
173  UNREACHABLE;
174 }
175 
176 static VALUE
178 {
179  VALUE nstr;
180 
181  nstr = rb_class_new(klass);
182  rb_make_metaclass(nstr, RBASIC(klass)->klass);
183  rb_class_inherited(klass, nstr);
184  return nstr;
185 }
186 
187 static VALUE
189 {
190  /* old style: should we warn? */
191  ID id;
192  name = rb_str_to_str(name);
193  if (!rb_is_const_name(name)) {
194  rb_name_error_str(name, "identifier %"PRIsVALUE" needs to be constant",
195  QUOTE(name));
196  }
197  id = rb_to_id(name);
198  if (rb_const_defined_at(super, id)) {
199  rb_warn("redefining constant %"PRIsVALUE"::%"PRIsVALUE, super, name);
200  rb_mod_remove_const(super, ID2SYM(id));
201  }
202  return rb_define_class_id_under(super, id, super);
203 }
204 
205 static VALUE
206 setup_struct(VALUE nstr, VALUE members)
207 {
208  const VALUE *ptr_members;
209  long i, len;
210 
211  OBJ_FREEZE(members);
212  rb_ivar_set(nstr, id_members, members);
213 
218  ptr_members = RARRAY_CONST_PTR(members);
219  len = RARRAY_LEN(members);
220  for (i=0; i< len; i++) {
221  ID id = SYM2ID(ptr_members[i]);
222  if (i < N_REF_FUNC) {
223  rb_define_method_id(nstr, id, ref_func[i], 0);
224  }
225  else {
226  rb_define_method_id(nstr, id, rb_struct_ref, 0);
227  }
229  }
230 
231  return nstr;
232 }
233 
234 VALUE
236 {
237  return struct_alloc(klass);
238 }
239 
240 static VALUE
241 struct_define_without_accessor(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, VALUE members)
242 {
243  VALUE klass;
244 
245  if (class_name) {
246  if (outer) {
247  klass = rb_define_class_under(outer, class_name, super);
248  }
249  else {
250  klass = rb_define_class(class_name, super);
251  }
252  }
253  else {
254  klass = anonymous_struct(super);
255  }
256 
257  rb_ivar_set(klass, id_members, members);
258 
259  if (alloc) {
260  rb_define_alloc_func(klass, alloc);
261  }
262  else {
264  }
265 
266  return klass;
267 }
268 
269 VALUE
270 rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
271 {
272  va_list ar;
273  VALUE members;
274  char *name;
275 
276  members = rb_ary_tmp_new(0);
277  va_start(ar, alloc);
278  while ((name = va_arg(ar, char*)) != NULL) {
279  rb_ary_push(members, ID2SYM(rb_intern(name)));
280  }
281  va_end(ar);
282  OBJ_FREEZE(members);
283 
284  return struct_define_without_accessor(outer, class_name, super, alloc, members);
285 }
286 
287 VALUE
288 rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
289 {
290  va_list ar;
291  VALUE members;
292  char *name;
293 
294  members = rb_ary_tmp_new(0);
295  va_start(ar, alloc);
296  while ((name = va_arg(ar, char*)) != NULL) {
297  rb_ary_push(members, ID2SYM(rb_intern(name)));
298  }
299  va_end(ar);
300  OBJ_FREEZE(members);
301 
302  return struct_define_without_accessor(0, class_name, super, alloc, members);
303 }
304 
305 VALUE
306 rb_struct_define(const char *name, ...)
307 {
308  va_list ar;
309  VALUE st, ary;
310  char *mem;
311 
312  ary = rb_ary_tmp_new(0);
313 
314  va_start(ar, name);
315  while ((mem = va_arg(ar, char*)) != 0) {
316  ID slot = rb_intern(mem);
317  rb_ary_push(ary, ID2SYM(slot));
318  }
319  va_end(ar);
320 
321  if (!name) st = anonymous_struct(rb_cStruct);
322  else st = new_struct(rb_str_new2(name), rb_cStruct);
323  return setup_struct(st, ary);
324 }
325 
326 VALUE
327 rb_struct_define_under(VALUE outer, const char *name, ...)
328 {
329  va_list ar;
330  VALUE ary;
331  char *mem;
332 
333  ary = rb_ary_tmp_new(0);
334 
335  va_start(ar, name);
336  while ((mem = va_arg(ar, char*)) != 0) {
337  ID slot = rb_intern(mem);
338  rb_ary_push(ary, ID2SYM(slot));
339  }
340  va_end(ar);
341 
342  return setup_struct(rb_define_class_under(outer, name, rb_cStruct), ary);
343 }
344 
345 /*
346  * call-seq:
347  * Struct.new([class_name] [, member_name]+>) -> StructClass
348  * Struct.new([class_name] [, member_name]+>) {|StructClass| block } -> StructClass
349  * StructClass.new(value, ...) -> obj
350  * StructClass[value, ...] -> obj
351  *
352  * The first two forms are used to create a new Struct subclass +class_name+
353  * that can contain a value for each +member_name+. This subclass can be
354  * used to create instances of the structure like any other Class.
355  *
356  * If the +class_name+ is omitted an anonymous structure class will be
357  * created. Otherwise, the name of this struct will appear as a constant in
358  * class Struct, so it must be unique for all Structs in the system and
359  * must start with a capital letter. Assigning a structure class to a
360  * constant also gives the class the name of the constant.
361  *
362  * # Create a structure with a name under Struct
363  * Struct.new("Customer", :name, :address)
364  * #=> Struct::Customer
365  * Struct::Customer.new("Dave", "123 Main")
366  * #=> #<struct Struct::Customer name="Dave", address="123 Main">
367  *
368  * If a block is given it will be evaluated in the context of
369  * +StructClass+, passing the created class as a parameter:
370  *
371  * Customer = Struct.new(:name, :address) do
372  * def greeting
373  * "Hello #{name}!"
374  * end
375  * end
376  * Customer.new("Dave", "123 Main").greeting # => "Hello Dave!"
377  *
378  * This is the recommended way to customize a struct. Subclassing an
379  * anonymous struct creates an extra anonymous class that will never be used.
380  *
381  * The last two forms create a new instance of a struct subclass. The number
382  * of +value+ parameters must be less than or equal to the number of
383  * attributes defined for the structure. Unset parameters default to +nil+.
384  * Passing more parameters than number of attributes will raise
385  * an ArgumentError.
386  *
387  * # Create a structure named by its constant
388  * Customer = Struct.new(:name, :address)
389  * #=> Customer
390  * Customer.new("Dave", "123 Main")
391  * #=> #<struct Customer name="Dave", address="123 Main">
392  */
393 
394 static VALUE
396 {
397  VALUE name, rest;
398  long i;
399  VALUE st;
400  ID id;
401 
403  name = argv[0];
404  if (SYMBOL_P(name)) {
405  name = Qnil;
406  }
407  else {
408  --argc;
409  ++argv;
410  }
411  rest = rb_ary_tmp_new(argc);
412  for (i=0; i<argc; i++) {
413  id = rb_to_id(argv[i]);
414  RARRAY_ASET(rest, i, ID2SYM(id));
415  rb_ary_set_len(rest, i+1);
416  }
417  if (NIL_P(name)) {
418  st = anonymous_struct(klass);
419  }
420  else {
421  st = new_struct(name, klass);
422  }
423  setup_struct(st, rest);
424  if (rb_block_given_p()) {
425  rb_mod_module_eval(0, 0, st);
426  }
427 
428  return st;
429 }
430 
431 static long
433 {
434  VALUE members;
435  members = struct_ivar_get(klass, id_members);
436  if (!RB_TYPE_P(members, T_ARRAY)) {
437  rb_raise(rb_eTypeError, "broken members");
438  }
439  return RARRAY_LEN(members);
440 }
441 
442 /*
443  */
444 
445 static VALUE
447 {
448  VALUE klass = rb_obj_class(self);
449  long i, n;
450 
451  rb_struct_modify(self);
452  n = num_members(klass);
453  if (n < argc) {
454  rb_raise(rb_eArgError, "struct size differs");
455  }
456  for (i=0; i<argc; i++) {
457  RSTRUCT_SET(self, i, argv[i]);
458  }
459  if (n > argc) {
460  rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self)+argc, n-argc);
461  }
462  return Qnil;
463 }
464 
465 VALUE
467 {
468  return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self);
469 }
470 
471 static VALUE
473 {
474  long n;
476 
477  n = num_members(klass);
478 
479  if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
480  RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
481  RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
482  rb_mem_clear((VALUE *)st->as.ary, n);
483  }
484  else {
485  st->as.heap.ptr = ALLOC_N(VALUE, n);
486  rb_mem_clear((VALUE *)st->as.heap.ptr, n);
487  st->as.heap.len = n;
488  }
489 
490  return (VALUE)st;
491 }
492 
493 VALUE
495 {
496  return rb_class_new_instance(RARRAY_LENINT(values), RARRAY_PTR(values), klass);
497 }
498 
499 VALUE
501 {
502  VALUE tmpargs[N_REF_FUNC], *mem = tmpargs;
503  int size, i;
504  va_list args;
505 
506  size = rb_long2int(num_members(klass));
507  if (size > numberof(tmpargs)) {
508  tmpargs[0] = rb_ary_tmp_new(size);
509  mem = RARRAY_PTR(tmpargs[0]);
510  }
511  va_start(args, klass);
512  for (i=0; i<size; i++) {
513  mem[i] = va_arg(args, VALUE);
514  }
515  va_end(args);
516 
517  return rb_class_new_instance(size, mem, klass);
518 }
519 
520 static VALUE
522 
523 static VALUE
525 {
526  return rb_struct_size(s);
527 }
528 
529 /*
530  * call-seq:
531  * struct.each {|obj| block } -> struct
532  * struct.each -> an_enumerator
533  *
534  * Yields the value of each struct member in order. If no block is given an
535  * enumerator is returned.
536  *
537  * Customer = Struct.new(:name, :address, :zip)
538  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
539  * joe.each {|x| puts(x) }
540  *
541  * Produces:
542  *
543  * Joe Smith
544  * 123 Maple, Anytown NC
545  * 12345
546  */
547 
548 static VALUE
550 {
551  long i;
552 
554  for (i=0; i<RSTRUCT_LEN(s); i++) {
555  rb_yield(RSTRUCT_GET(s, i));
556  }
557  return s;
558 }
559 
560 /*
561  * call-seq:
562  * struct.each_pair {|sym, obj| block } -> struct
563  * struct.each_pair -> an_enumerator
564  *
565  * Yields the name and value of each struct member in order. If no block is
566  * given an enumerator is returned.
567  *
568  * Customer = Struct.new(:name, :address, :zip)
569  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
570  * joe.each_pair {|name, value| puts("#{name} => #{value}") }
571  *
572  * Produces:
573  *
574  * name => Joe Smith
575  * address => 123 Maple, Anytown NC
576  * zip => 12345
577  */
578 
579 static VALUE
581 {
582  VALUE members;
583  long i;
584 
586  members = rb_struct_members(s);
587  if (rb_block_arity() > 1) {
588  for (i=0; i<RSTRUCT_LEN(s); i++) {
589  VALUE key = rb_ary_entry(members, i);
590  VALUE value = RSTRUCT_GET(s, i);
591  rb_yield_values(2, key, value);
592  }
593  }
594  else {
595  for (i=0; i<RSTRUCT_LEN(s); i++) {
596  VALUE key = rb_ary_entry(members, i);
597  VALUE value = RSTRUCT_GET(s, i);
598  rb_yield(rb_assoc_new(key, value));
599  }
600  }
601  return s;
602 }
603 
604 static VALUE
606 {
607  VALUE cname = rb_class_name(rb_obj_class(s));
608  VALUE members, str = rb_str_new2("#<struct ");
609  long i, len;
610  char first = RSTRING_PTR(cname)[0];
611 
612  if (recur || first != '#') {
613  rb_str_append(str, cname);
614  }
615  if (recur) {
616  return rb_str_cat2(str, ":...>");
617  }
618 
619  members = rb_struct_members(s);
620  len = RSTRUCT_LEN(s);
621 
622  for (i=0; i<len; i++) {
623  VALUE slot;
624  ID id;
625 
626  if (i > 0) {
627  rb_str_cat2(str, ", ");
628  }
629  else if (first != '#') {
630  rb_str_cat2(str, " ");
631  }
632  slot = RARRAY_AREF(members, i);
633  id = SYM2ID(slot);
634  if (rb_is_local_id(id) || rb_is_const_id(id)) {
635  rb_str_append(str, rb_id2str(id));
636  }
637  else {
638  rb_str_append(str, rb_inspect(slot));
639  }
640  rb_str_cat2(str, "=");
641  rb_str_append(str, rb_inspect(RSTRUCT_GET(s, i)));
642  }
643  rb_str_cat2(str, ">");
644  OBJ_INFECT(str, s);
645 
646  return str;
647 }
648 
649 /*
650  * call-seq:
651  * struct.to_s -> string
652  * struct.inspect -> string
653  *
654  * Describe the contents of this struct in a string.
655  */
656 
657 static VALUE
659 {
660  return rb_exec_recursive(inspect_struct, s, 0);
661 }
662 
663 /*
664  * call-seq:
665  * struct.to_a -> array
666  * struct.values -> array
667  *
668  * Returns the values for this struct as an Array.
669  *
670  * Customer = Struct.new(:name, :address, :zip)
671  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
672  * joe.to_a[1] #=> "123 Maple, Anytown NC"
673  */
674 
675 static VALUE
677 {
679 }
680 
681 /*
682  * call-seq:
683  * struct.to_h -> hash
684  *
685  * Returns a Hash containing the names and values for the struct's members.
686  *
687  * Customer = Struct.new(:name, :address, :zip)
688  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
689  * joe.to_h[:address] #=> "123 Maple, Anytown NC"
690  */
691 
692 static VALUE
694 {
695  VALUE h = rb_hash_new();
696  VALUE members = rb_struct_members(s);
697  long i;
698 
699  for (i=0; i<RSTRUCT_LEN(s); i++) {
700  rb_hash_aset(h, rb_ary_entry(members, i), RSTRUCT_GET(s, i));
701  }
702  return h;
703 }
704 
705 /* :nodoc: */
706 VALUE
708 {
709  long i, len;
710 
711  if (!OBJ_INIT_COPY(copy, s)) return copy;
712  if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
713  rb_raise(rb_eTypeError, "struct size mismatch");
714  }
715 
716  for (i=0, len=RSTRUCT_LEN(copy); i<len; i++) {
717  RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i));
718  }
719 
720  return copy;
721 }
722 
723 static VALUE
725 {
726  VALUE members = rb_struct_members(s);
727  long i, len = RARRAY_LEN(members);
728 
729  for (i=0; i<len; i++) {
730  if (SYM2ID(RARRAY_AREF(members, i)) == id) {
731  return RSTRUCT_GET(s, i);
732  }
733  }
734  rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
735 
736  UNREACHABLE;
737 }
738 
739 /*
740  * call-seq:
741  * struct[member] -> anObject
742  * struct[index] -> anObject
743  *
744  * Attribute Reference---Returns the value of the given struct +member+ or
745  * the member at the given +index+. Raises NameError if the +member+ does
746  * not exist and IndexError if the +index+ is out of range.
747  *
748  * Customer = Struct.new(:name, :address, :zip)
749  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
750  *
751  * joe["name"] #=> "Joe Smith"
752  * joe[:name] #=> "Joe Smith"
753  * joe[0] #=> "Joe Smith"
754  */
755 
756 VALUE
758 {
759  long i;
760 
761  if (RB_TYPE_P(idx, T_SYMBOL)) {
762  return rb_struct_aref_id(s, SYM2ID(idx));
763  }
764  else if (RB_TYPE_P(idx, T_STRING)) {
765  ID id = rb_check_id(&idx);
766  if (!id) {
767  rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct",
768  QUOTE(idx));
769  }
770  return rb_struct_aref_id(s, id);
771  }
772 
773  i = NUM2LONG(idx);
774  if (i < 0) i = RSTRUCT_LEN(s) + i;
775  if (i < 0)
776  rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
777  i, RSTRUCT_LEN(s));
778  if (RSTRUCT_LEN(s) <= i)
779  rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
780  i, RSTRUCT_LEN(s));
781  return RSTRUCT_GET(s, i);
782 }
783 
784 static VALUE
786 {
787  VALUE members = rb_struct_members(s);
788  long i, len = RARRAY_LEN(members);
789 
790  if (RSTRUCT_LEN(s) != len) {
791  rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
792  len, RSTRUCT_LEN(s));
793  }
794 
795  for (i=0; i<len; i++) {
796  if (SYM2ID(RARRAY_AREF(members, i)) == id) {
797  rb_struct_modify(s);
798  RSTRUCT_SET(s, i, val);
799  return val;
800  }
801  }
802  rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
803 
804  UNREACHABLE;
805 }
806 
807 /*
808  * call-seq:
809  * struct[name] = obj -> obj
810  * struct[index] = obj -> obj
811  *
812  * Attribute Assignment---Sets the value of the given struct +member+ or
813  * the member at the given +index+. Raises NameError if the +name+ does not
814  * exist and IndexError if the +index+ is out of range.
815  *
816  * Customer = Struct.new(:name, :address, :zip)
817  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
818  *
819  * joe["name"] = "Luke"
820  * joe[:zip] = "90210"
821  *
822  * joe.name #=> "Luke"
823  * joe.zip #=> "90210"
824  */
825 
826 VALUE
828 {
829  long i;
830 
831  if (RB_TYPE_P(idx, T_SYMBOL)) {
832  return rb_struct_aset_id(s, SYM2ID(idx), val);
833  }
834  if (RB_TYPE_P(idx, T_STRING)) {
835  ID id = rb_check_id(&idx);
836  if (!id) {
837  rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct",
838  QUOTE(idx));
839  }
840  return rb_struct_aset_id(s, id, val);
841  }
842 
843  i = NUM2LONG(idx);
844  if (i < 0) i = RSTRUCT_LEN(s) + i;
845  if (i < 0) {
846  rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
847  i, RSTRUCT_LEN(s));
848  }
849  if (RSTRUCT_LEN(s) <= i) {
850  rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
851  i, RSTRUCT_LEN(s));
852  }
853  rb_struct_modify(s);
854  RSTRUCT_SET(s, i, val);
855  return val;
856 }
857 
858 static VALUE
860 {
861  return rb_struct_aref(s, LONG2NUM(n));
862 }
863 
864 /*
865  * call-seq:
866  * struct.values_at(selector, ...) -> an_array
867  *
868  * Returns the struct member values for each +selector+ as an Array. A
869  * +selector+ may be either an Integer offset or a Range of offsets (as in
870  * Array#values_at).
871  *
872  * Customer = Struct.new(:name, :address, :zip)
873  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
874  * joe.values_at 0, 2 #=> ["Joe Smith", 12345]
875  *
876  */
877 
878 static VALUE
880 {
881  return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
882 }
883 
884 /*
885  * call-seq:
886  * struct.select {|i| block } -> array
887  * struct.select -> an_enumerator
888  *
889  * Yields each member value from the struct to the block and returns an Array
890  * containing the member values from the +struct+ for which the given block
891  * returns a true value (equivalent to Enumerable#select).
892  *
893  * Lots = Struct.new(:a, :b, :c, :d, :e, :f)
894  * l = Lots.new(11, 22, 33, 44, 55, 66)
895  * l.select {|v| (v % 2).zero? } #=> [22, 44, 66]
896  */
897 
898 static VALUE
900 {
901  VALUE result;
902  long i;
903 
904  rb_check_arity(argc, 0, 0);
906  result = rb_ary_new();
907  for (i = 0; i < RSTRUCT_LEN(s); i++) {
908  if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
909  rb_ary_push(result, RSTRUCT_GET(s, i));
910  }
911  }
912 
913  return result;
914 }
915 
916 static VALUE
918 {
919  const VALUE *ptr, *ptr2;
920  long i, len;
921 
922  if (recur) return Qtrue; /* Subtle! */
923  ptr = RSTRUCT_CONST_PTR(s);
924  ptr2 = RSTRUCT_CONST_PTR(s2);
925  len = RSTRUCT_LEN(s);
926  for (i=0; i<len; i++) {
927  if (!rb_equal(ptr[i], ptr2[i])) return Qfalse;
928  }
929  return Qtrue;
930 }
931 
932 /*
933  * call-seq:
934  * struct == other -> true or false
935  *
936  * Equality---Returns +true+ if +other+ has the same struct subclass and has
937  * equal member values (according to Object#==).
938  *
939  * Customer = Struct.new(:name, :address, :zip)
940  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
941  * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
942  * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
943  * joe == joejr #=> true
944  * joe == jane #=> false
945  */
946 
947 static VALUE
949 {
950  if (s == s2) return Qtrue;
951  if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
952  if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
953  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
954  rb_bug("inconsistent struct"); /* should never happen */
955  }
956 
957  return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
958 }
959 
960 /*
961  * call-seq:
962  * struct.hash -> fixnum
963  *
964  * Returns a hash value based on this struct's contents (see Object#hash).
965  */
966 
967 static VALUE
969 {
970  long i, len;
971  st_index_t h;
972  VALUE n;
973  const VALUE *ptr;
974 
976  ptr = RSTRUCT_CONST_PTR(s);
977  len = RSTRUCT_LEN(s);
978  for (i = 0; i < len; i++) {
979  n = rb_hash(ptr[i]);
980  h = rb_hash_uint(h, NUM2LONG(n));
981  }
982  h = rb_hash_end(h);
983  return INT2FIX(h);
984 }
985 
986 static VALUE
988 {
989  const VALUE *ptr, *ptr2;
990  long i, len;
991 
992  if (recur) return Qtrue; /* Subtle! */
993  ptr = RSTRUCT_CONST_PTR(s);
994  ptr2 = RSTRUCT_CONST_PTR(s2);
995  len = RSTRUCT_LEN(s);
996  for (i=0; i<len; i++) {
997  if (!rb_eql(ptr[i], ptr2[i])) return Qfalse;
998  }
999  return Qtrue;
1000 }
1001 
1002 /*
1003  * call-seq:
1004  * struct.eql?(other) -> true or false
1005  *
1006  * Hash equality---+other+ and +struct+ refer to the same hash key if they
1007  * have the same struct subclass and have equal member values (according to
1008  * Object#eql?).
1009  */
1010 
1011 static VALUE
1013 {
1014  if (s == s2) return Qtrue;
1015  if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
1016  if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
1017  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
1018  rb_bug("inconsistent struct"); /* should never happen */
1019  }
1020 
1021  return rb_exec_recursive_paired(recursive_eql, s, s2, s2);
1022 }
1023 
1024 /*
1025  * call-seq:
1026  * struct.length -> fixnum
1027  * struct.size -> fixnum
1028  *
1029  * Returns the number of struct members.
1030  *
1031  * Customer = Struct.new(:name, :address, :zip)
1032  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1033  * joe.length #=> 3
1034  */
1035 
1036 static VALUE
1038 {
1039  return LONG2FIX(RSTRUCT_LEN(s));
1040 }
1041 
1042 /*
1043  * A Struct is a convenient way to bundle a number of attributes together,
1044  * using accessor methods, without having to write an explicit class.
1045  *
1046  * The Struct class generates new subclasses that hold a set of members and
1047  * their values. For each member a reader and writer method is created
1048  * similar to Module#attr_accessor.
1049  *
1050  * Customer = Struct.new(:name, :address) do
1051  * def greeting
1052  * "Hello #{name}!"
1053  * end
1054  * end
1055  *
1056  * dave = Customer.new("Dave", "123 Main")
1057  * dave.name #=> "Dave"
1058  * dave.greeting #=> "Hello Dave!"
1059  *
1060  * See Struct::new for further examples of creating struct subclasses and
1061  * instances.
1062  *
1063  * In the method descriptions that follow a "member" parameter refers to a
1064  * struct member which is either a quoted string (<code>"name"</code>) or a
1065  * Symbol (<code>:name</code>).
1066  */
1067 void
1069 {
1070  rb_cStruct = rb_define_class("Struct", rb_cObject);
1072 
1075 
1077  rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
1078 
1082 
1084  rb_define_alias(rb_cStruct, "to_s", "inspect");
1090 
1096  rb_define_method(rb_cStruct, "values_at", rb_struct_values_at, -1);
1097 
1099  id_members = rb_intern("__members__");
1100 }
static VALUE struct_entry(VALUE s, long n)
Definition: struct.c:859
static VALUE rb_struct_each_pair(VALUE s)
Definition: struct.c:580
VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc,...)
Definition: struct.c:270
#define RB_TYPE_P(obj, type)
static VALUE struct_ivar_get(VALUE c, ID id)
Definition: struct.c:21
RARRAY_PTR(q->result)[0]
#define rb_check_arity
static VALUE rb_struct_to_h(VALUE s)
Definition: struct.c:693
VALUE rb_struct_iv_get(VALUE c, const char *name)
Definition: struct.c:33
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1179
#define RSTRUCT_LEN(st)
int rb_eql(VALUE, VALUE)
Definition: object.c:100
void rb_bug(const char *fmt,...)
Definition: error.c:327
#define T_STRUCT
VALUE(* rb_alloc_func_t)(VALUE)
Definition: ripper.y:374
memo u1 value
Definition: enum.c:587
VALUE rb_struct_members(VALUE)
Definition: struct.c:53
#define OBJ_INFECT(x, s)
static VALUE rb_struct_each(VALUE s)
Definition: struct.c:549
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1857
VALUE rb_id2str(ID id)
Definition: ripper.c:17201
VALUE rb_mod_module_eval(int, VALUE *, VALUE)
Definition: vm_eval.c:1684
#define UNLIMITED_ARGUMENTS
static VALUE rb_struct_select(int argc, VALUE *argv, VALUE s)
Definition: struct.c:899
#define rb_check_trusted(obj)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1646
static VALUE anonymous_struct(VALUE klass)
Definition: struct.c:177
static VALUE rb_struct_ref3(VALUE obj)
Definition: struct.c:124
static void not_a_member(ID id)
Definition: struct.c:91
VALUE rb_struct_define(const char *,...)
Definition: struct.c:306
static VALUE rb_struct_to_a(VALUE s)
Definition: struct.c:676
VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:680
int rb_block_arity(void)
Definition: proc.c:871
#define rb_check_frozen(obj)
static VALUE rb_struct_eql(VALUE s, VALUE s2)
Definition: struct.c:1012
#define RSTRUCT_EMBED_LEN_MASK
ID rb_frame_this_func(void)
Definition: eval.c:943
rb_yield(i)
VALUE rb_eTypeError
Definition: error.c:548
void rb_mem_clear(register VALUE *mem, register long size)
Definition: array.c:35
#define OBJ_FREEZE(x)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define UNREACHABLE
Definition: ruby.h:42
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:900
#define QUOTE_ID(id)
static VALUE rb_struct_equal(VALUE s, VALUE s2)
Definition: struct.c:948
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:538
void Init_Struct(void)
Definition: struct.c:1068
#define RSTRUCT_EMBED_LEN_MAX
rb_str_append(str, i)
#define RSTRING_PTR(str)
NIL_P(eventloop_thread)
Definition: tcltklib.c:4056
#define T_ARRAY
static VALUE rb_struct_ref0(VALUE obj)
Definition: struct.c:121
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:657
VALUE rb_struct_new(VALUE,...)
Definition: struct.c:500
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
return Qtrue
Definition: tcltklib.c:9618
VALUE rb_obj_class(VALUE)
Definition: object.c:226
VALUE rb_class_name(VALUE)
Definition: variable.c:391
VALUE rb_struct_alloc(VALUE, VALUE)
Definition: struct.c:494
#define rb_ary_new4
static VALUE rb_struct_aref_id(VALUE s, ID id)
Definition: struct.c:724
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:808
static ID id_members
Definition: struct.c:16
static VALUE inspect_struct(VALUE s, VALUE dummy, int recur)
Definition: struct.c:605
#define rb_str_new2
static VALUE setup_struct(VALUE nstr, VALUE members)
Definition: struct.c:206
int size
Definition: encoding.c:49
static VALUE struct_define_without_accessor(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, VALUE members)
Definition: struct.c:241
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: ripper.c:17365
#define ID2SYM(x)
#define LONG2NUM(x)
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1115
VALUE rb_equal(VALUE, VALUE)
Definition: object.c:89
VALUE rb_str_to_str(VALUE)
Definition: string.c:964
i
Definition: enum.c:446
VALUE ary
Definition: enum.c:674
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:982
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:967
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1296
#define NORETURN(x)
Definition: ruby.h:33
#define RSTRUCT_EMBED_LEN_SHIFT
int rb_is_const_id(ID id)
Definition: ripper.c:17312
#define FL_WB_PROTECTED
static VALUE rb_struct_ref(VALUE obj)
Definition: struct.c:116
VALUE rb_class_inherited(VALUE super, VALUE klass)
Calls Class::inherited.
Definition: class.c:585
static VALUE rb_struct_ref2(VALUE obj)
Definition: struct.c:123
static long num_members(VALUE klass)
Definition: struct.c:432
#define RGENGC_WB_PROTECTED_STRUCT
Definition: ruby.h:717
static VALUE recursive_eql(VALUE s, VALUE s2, int recur)
Definition: struct.c:987
return Qfalse
Definition: tcltklib.c:6790
int rb_block_given_p(void)
Definition: eval.c:712
static VALUE rb_struct_aset_id(VALUE s, ID id, VALUE val)
Definition: struct.c:785
#define RARRAY_LEN(a)
#define Qnil
Definition: enum.c:67
static VALUE rb_struct_hash(VALUE s)
Definition: struct.c:968
static VALUE rb_struct_ref6(VALUE obj)
Definition: struct.c:127
#define val
Definition: tcltklib.c:1935
static VALUE char * str
Definition: tcltklib.c:3539
#define RARRAY_CONST_PTR(a)
#define RARRAY_AREF(a, i)
VALUE rb_ary_new(void)
Definition: array.c:499
unsigned long ID
Definition: ripper.y:89
va_end(args)
#define RCLASS_SUPER(c)
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2158
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:611
static VALUE VALUE obj
Definition: tcltklib.c:3150
#define INT2FIX(i)
#define T_STRING
#define OBJ_INIT_COPY(obj, orig)
VALUE rb_struct_define_under(VALUE, const char *,...)
Definition: struct.c:327
#define rb_hash_end(h)
VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t,...)
Definition: struct.c:288
static VALUE recursive_equal(VALUE s, VALUE s2, int recur)
Definition: struct.c:917
static VALUE rb_struct_ref8(VALUE obj)
Definition: struct.c:129
VALUE rb_eIndexError
Definition: error.c:550
static int VALUE key
Definition: tkutil.c:265
int len
Definition: enumerator.c:1332
#define RSTRUCT_SET(st, idx, v)
static VALUE rb_struct_ref9(VALUE obj)
Definition: struct.c:130
#define numberof(array)
Definition: etc.c:602
static VALUE rb_struct_set(VALUE obj, VALUE val)
Definition: struct.c:155
VALUE rb_struct_s_members(VALUE)
Definition: struct.c:39
#define rb_long2int(n)
VALUE * argv
Definition: tcltklib.c:1969
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1688
static VALUE rb_struct_s_members_m(VALUE klass)
Definition: struct.c:65
#define RTEST(v)
const int id
Definition: nkf.c:209
static VALUE struct_enum_size(VALUE s, VALUE args, VALUE eobj)
Definition: struct.c:524
VALUE rb_mEnumerable
Definition: enum.c:20
static VALUE rb_struct_ref4(VALUE obj)
Definition: struct.c:125
register char * s
Definition: os2.c:56
#define RSTRUCT_CONST_PTR(st)
static VALUE struct_alloc(VALUE)
Definition: struct.c:472
#define QUOTE(str)
int rb_is_local_id(ID id)
Definition: ripper.c:17342
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:620
VALUE rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, VALUE(*func)(VALUE, long))
Definition: array.c:2729
int argc
Definition: tcltklib.c:1968
int rb_const_defined_at(VALUE, ID)
Definition: variable.c:2133
ID rb_id_attrset(ID id)
Definition: ripper.c:15463
rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1))
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:519
VALUE rb_make_metaclass(VALUE obj, VALUE unused)
Definition: class.c:542
VALUE values
Definition: enum.c:719
static VALUE(*const ref_func[])(VALUE)
Definition: struct.c:134
VALUE idx
Definition: enumerator.c:499
#define N_REF_FUNC
Definition: struct.c:132
return ptr
Definition: tcltklib.c:789
VpDivd * c
Definition: bigdecimal.c:1223
VALUE rb_ivar_defined(VALUE, ID)
Definition: variable.c:1207
ID rb_to_id(VALUE)
Definition: string.c:8734
static VALUE rb_struct_size(VALUE s)
Definition: struct.c:1037
static VALUE rb_struct_values_at(int argc, VALUE *argv, VALUE s)
Definition: struct.c:879
#define recur(fmt)
int rb_is_const_name(VALUE name)
Definition: ripper.c:17430
#define NEWOBJ_OF(obj, type, klass, flags)
#define T_SYMBOL
void rb_define_method_id(VALUE klass, ID mid, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1473
VALUE rb_struct_aref(VALUE, VALUE)
Definition: struct.c:757
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
#define NUM2LONG(x)
#define SYMBOL_P(x)
static VALUE rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
Definition: struct.c:395
static void rb_struct_modify(VALUE s)
Definition: struct.c:148
VALUE name
Definition: enum.c:572
VALUE rb_hash(VALUE)
Definition: hash.c:106
VALUE rb_mod_remove_const(VALUE, VALUE)
Definition: variable.c:1920
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:5003
VALUE rb_struct_initialize(VALUE, VALUE)
Definition: struct.c:466
static VALUE rb_struct_ref7(VALUE obj)
Definition: struct.c:128
args[0]
Definition: enum.c:585
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1561
st_data_t st_index_t
Definition: ripper.y:48
#define ALLOC_N(type, n)
#define LONG2FIX(i)
#define RBASIC(obj)
#define RARRAY_LENINT(ary)
VALUE rb_struct_aset(VALUE, VALUE, VALUE)
Definition: struct.c:827
klass
Definition: tcltklib.c:3496
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1899
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4992
rb_ivar_set(yielder, id_memo, LONG2NUM(++count))
static VALUE rb_struct_ref1(VALUE obj)
Definition: struct.c:122
data n
Definition: enum.c:860
VALUE rb_struct_getmember(VALUE, ID)
Definition: struct.c:97
VALUE rb_hash_new(void)
Definition: hash.c:307
const char * rb_id2name(ID id)
Definition: ripper.c:17271
#define PRIsVALUE
static VALUE rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self)
Definition: struct.c:446
unsigned long VALUE
Definition: ripper.y:88
static VALUE rb_struct_inspect(VALUE s)
Definition: struct.c:658
static VALUE rb_struct_ref5(VALUE obj)
Definition: struct.c:126
#define RARRAY_ASET(a, i, v)
#define rb_intern(str)
return rb_yield_values(2, rb_enum_values_pack(argc, argv), INT2NUM(n))
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:707
#define NULL
Definition: _sdbm.c:102
static VALUE rb_struct_members_m(VALUE obj)
Definition: struct.c:84
volatile VALUE result
Definition: enum.c:1989
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:228
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1479
void rb_warn(const char *fmt,...)
Definition: error.c:223
#define SYM2ID(x)
static VALUE new_struct(VALUE name, VALUE super)
Definition: struct.c:188
VALUE rb_eArgError
Definition: error.c:549
Tcl_Interp *int * st
Definition: stubs.c:510
int dummy
Definition: tcltklib.c:4473
VALUE rb_struct_alloc_noinit(VALUE)
Definition: struct.c:235
#define rb_hash_uint(h, i)
VALUE rb_inspect(VALUE)
Definition: object.c:470
void rb_ary_set_len(VALUE ary, long len)
Definition: array.c:1603
#define RSTRUCT_GET(st, idx)
RUBY_EXTERN VALUE rb_cStruct
Definition: ripper.y:1592