Ruby  2.0.0p451(2014-02-24revision45167)
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 an array of symbols representing the names of the instance
77  * variables.
78  *
79  * Customer = Struct.new(:name, :address, :zip)
80  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
81  * joe.members #=> [:name, :address, :zip]
82  */
83 
84 static VALUE
86 {
88 }
89 
90 VALUE
92 {
93  VALUE members, slot, *ptr, *ptr_members;
94  long i, len;
95 
96  ptr = RSTRUCT_PTR(obj);
97  members = rb_struct_members(obj);
98  ptr_members = RARRAY_PTR(members);
99  slot = ID2SYM(id);
100  len = RARRAY_LEN(members);
101  for (i=0; i<len; i++) {
102  if (ptr_members[i] == slot) {
103  return ptr[i];
104  }
105  }
106  rb_name_error(id, "%s is not struct member", rb_id2name(id));
107 
108  UNREACHABLE;
109 }
110 
111 static VALUE
113 {
115 }
116 
117 static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_PTR(obj)[0];}
118 static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_PTR(obj)[1];}
119 static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_PTR(obj)[2];}
120 static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_PTR(obj)[3];}
121 static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_PTR(obj)[4];}
122 static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_PTR(obj)[5];}
123 static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_PTR(obj)[6];}
124 static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_PTR(obj)[7];}
125 static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_PTR(obj)[8];}
126 static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_PTR(obj)[9];}
127 
128 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
129 #define N_REF_FUNC numberof(ref_func)
130 
131 static VALUE (*const ref_func[])(VALUE) = {
142 };
143 
144 static void
146 {
147  rb_check_frozen(s);
148  rb_check_trusted(s);
149 }
150 
151 static VALUE
153 {
154  VALUE members, slot, *ptr, *ptr_members;
155  long i, len;
156 
157  members = rb_struct_members(obj);
158  ptr_members = RARRAY_PTR(members);
159  len = RARRAY_LEN(members);
160  rb_struct_modify(obj);
161  ptr = RSTRUCT_PTR(obj);
162  for (i=0; i<len; i++) {
163  slot = ptr_members[i];
164  if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) {
165  return ptr[i] = val;
166  }
167  }
168  rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
170 
171  UNREACHABLE;
172 }
173 
174 static VALUE
176 {
177  VALUE nstr;
178 
179  nstr = rb_class_new(klass);
180  rb_make_metaclass(nstr, RBASIC(klass)->klass);
181  rb_class_inherited(klass, nstr);
182  return nstr;
183 }
184 
185 static VALUE
187 {
188  /* old style: should we warn? */
189  ID id;
190  name = rb_str_to_str(name);
191  if (!rb_is_const_name(name)) {
192  rb_name_error_str(name, "identifier %"PRIsVALUE" needs to be constant",
193  QUOTE(name));
194  }
195  id = rb_to_id(name);
196  if (rb_const_defined_at(super, id)) {
197  rb_warn("redefining constant %"PRIsVALUE"::%"PRIsVALUE, super, name);
198  rb_mod_remove_const(super, ID2SYM(id));
199  }
200  return rb_define_class_id_under(super, id, super);
201 }
202 
203 static VALUE
204 setup_struct(VALUE nstr, VALUE members)
205 {
206  VALUE *ptr_members;
207  long i, len;
208 
209  OBJ_FREEZE(members);
210  rb_ivar_set(nstr, id_members, members);
211 
216  ptr_members = RARRAY_PTR(members);
217  len = RARRAY_LEN(members);
218  for (i=0; i< len; i++) {
219  ID id = SYM2ID(ptr_members[i]);
220  if (i < N_REF_FUNC) {
221  rb_define_method_id(nstr, id, ref_func[i], 0);
222  }
223  else {
224  rb_define_method_id(nstr, id, rb_struct_ref, 0);
225  }
227  }
228 
229  return nstr;
230 }
231 
232 VALUE
234 {
235  return struct_alloc(klass);
236 }
237 
238 VALUE
239 rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
240 {
241  VALUE klass;
242  va_list ar;
243  VALUE members;
244  char *name;
245 
246  members = rb_ary_tmp_new(0);
247  va_start(ar, alloc);
248  while ((name = va_arg(ar, char*)) != NULL) {
249  rb_ary_push(members, ID2SYM(rb_intern(name)));
250  }
251  va_end(ar);
252  OBJ_FREEZE(members);
253 
254  if (class_name) {
255  klass = rb_define_class(class_name, super);
256  }
257  else {
258  klass = anonymous_struct(super);
259  }
260 
261  rb_ivar_set(klass, id_members, members);
262 
263  if (alloc)
264  rb_define_alloc_func(klass, alloc);
265  else
267 
268  return klass;
269 }
270 
271 VALUE
272 rb_struct_define(const char *name, ...)
273 {
274  va_list ar;
275  VALUE st, ary;
276  char *mem;
277 
278  ary = rb_ary_tmp_new(0);
279 
280  va_start(ar, name);
281  while ((mem = va_arg(ar, char*)) != 0) {
282  ID slot = rb_intern(mem);
283  rb_ary_push(ary, ID2SYM(slot));
284  }
285  va_end(ar);
286 
287  if (!name) st = anonymous_struct(rb_cStruct);
288  else st = new_struct(rb_str_new2(name), rb_cStruct);
289  return setup_struct(st, ary);
290 }
291 
292 /*
293  * call-seq:
294  * Struct.new( [aString] [, aSym]+> ) -> StructClass
295  * Struct.new( [aString] [, aSym]+> ) {|StructClass| block } -> StructClass
296  * StructClass.new(arg, ...) -> obj
297  * StructClass[arg, ...] -> obj
298  *
299  * Creates a new class, named by <i>aString</i>, containing accessor
300  * methods for the given symbols. If the name <i>aString</i> is
301  * omitted, an anonymous structure class will be created. Otherwise,
302  * the name of this struct will appear as a constant in class
303  * <code>Struct</code>, so it must be unique for all
304  * <code>Struct</code>s in the system and should start with a capital
305  * letter. Assigning a structure class to a constant effectively gives
306  * the class the name of the constant.
307  *
308  * If a block is given, it will be evaluated in the context of
309  * <i>StructClass</i>, passing <i>StructClass</i> as a parameter.
310  *
311  * Customer = Struct.new(:name, :address) do
312  * def greeting
313  * "Hello #{name}!"
314  * end
315  * end
316  * Customer.new("Dave", "123 Main").greeting # => "Hello Dave!"
317  *
318  * <code>Struct::new</code> returns a new <code>Class</code> object,
319  * which can then be used to create specific instances of the new
320  * structure. The number of actual parameters must be
321  * less than or equal to the number of attributes defined for this
322  * class; unset parameters default to <code>nil</code>. Passing too many
323  * parameters will raise an <code>ArgumentError</code>.
324  *
325  * The remaining methods listed in this section (class and instance)
326  * are defined for this generated class.
327  *
328  * # Create a structure with a name in Struct
329  * Struct.new("Customer", :name, :address) #=> Struct::Customer
330  * Struct::Customer.new("Dave", "123 Main") #=> #<struct Struct::Customer name="Dave", address="123 Main">
331  *
332  * # Create a structure named by its constant
333  * Customer = Struct.new(:name, :address) #=> Customer
334  * Customer.new("Dave", "123 Main") #=> #<struct Customer name="Dave", address="123 Main">
335  */
336 
337 static VALUE
339 {
340  VALUE name, rest;
341  long i;
342  VALUE st;
343  ID id;
344 
346  name = argv[0];
347  if (SYMBOL_P(name)) {
348  name = Qnil;
349  }
350  else {
351  --argc;
352  ++argv;
353  }
354  rest = rb_ary_tmp_new(argc);
355  for (i=0; i<argc; i++) {
356  id = rb_to_id(argv[i]);
357  RARRAY_PTR(rest)[i] = ID2SYM(id);
358  rb_ary_set_len(rest, i+1);
359  }
360  if (NIL_P(name)) {
361  st = anonymous_struct(klass);
362  }
363  else {
364  st = new_struct(name, klass);
365  }
366  setup_struct(st, rest);
367  if (rb_block_given_p()) {
368  rb_mod_module_eval(0, 0, st);
369  }
370 
371  return st;
372 }
373 
374 static long
376 {
377  VALUE members;
378  members = struct_ivar_get(klass, id_members);
379  if (!RB_TYPE_P(members, T_ARRAY)) {
380  rb_raise(rb_eTypeError, "broken members");
381  }
382  return RARRAY_LEN(members);
383 }
384 
385 /*
386  */
387 
388 static VALUE
390 {
391  VALUE klass = rb_obj_class(self);
392  long n;
393 
394  rb_struct_modify(self);
395  n = num_members(klass);
396  if (n < argc) {
397  rb_raise(rb_eArgError, "struct size differs");
398  }
399  MEMCPY(RSTRUCT_PTR(self), argv, VALUE, argc);
400  if (n > argc) {
401  rb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc);
402  }
403  return Qnil;
404 }
405 
406 VALUE
408 {
409  return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_PTR(values), self);
410 }
411 
412 static VALUE
414 {
415  long n;
416  NEWOBJ_OF(st, struct RStruct, klass, T_STRUCT);
417 
418  n = num_members(klass);
419 
420  if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
421  RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
422  RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
423  rb_mem_clear(st->as.ary, n);
424  }
425  else {
426  st->as.heap.ptr = ALLOC_N(VALUE, n);
427  rb_mem_clear(st->as.heap.ptr, n);
428  st->as.heap.len = n;
429  }
430 
431  return (VALUE)st;
432 }
433 
434 VALUE
436 {
437  return rb_class_new_instance(RARRAY_LENINT(values), RARRAY_PTR(values), klass);
438 }
439 
440 VALUE
441 rb_struct_new(VALUE klass, ...)
442 {
443  VALUE tmpargs[N_REF_FUNC], *mem = tmpargs;
444  int size, i;
445  va_list args;
446 
447  size = rb_long2int(num_members(klass));
448  if (size > numberof(tmpargs)) {
449  tmpargs[0] = rb_ary_tmp_new(size);
450  mem = RARRAY_PTR(tmpargs[0]);
451  }
452  va_start(args, klass);
453  for (i=0; i<size; i++) {
454  mem[i] = va_arg(args, VALUE);
455  }
456  va_end(args);
457 
458  return rb_class_new_instance(size, mem, klass);
459 }
460 
461 static VALUE
463 
464 /*
465  * call-seq:
466  * struct.each {|obj| block } -> struct
467  * struct.each -> an_enumerator
468  *
469  * Calls <i>block</i> once for each instance variable, passing the
470  * value as a parameter.
471  *
472  * If no block is given, an enumerator is returned instead.
473  *
474  * Customer = Struct.new(:name, :address, :zip)
475  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
476  * joe.each {|x| puts(x) }
477  *
478  * <em>produces:</em>
479  *
480  * Joe Smith
481  * 123 Maple, Anytown NC
482  * 12345
483  */
484 
485 static VALUE
487 {
488  long i;
489 
491  for (i=0; i<RSTRUCT_LEN(s); i++) {
492  rb_yield(RSTRUCT_PTR(s)[i]);
493  }
494  return s;
495 }
496 
497 /*
498  * call-seq:
499  * struct.each_pair {|sym, obj| block } -> struct
500  * struct.each_pair -> an_enumerator
501  *
502  * Calls <i>block</i> once for each instance variable, passing the name
503  * (as a symbol) and the value as parameters.
504  *
505  * If no block is given, an enumerator is returned instead.
506  *
507  * Customer = Struct.new(:name, :address, :zip)
508  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
509  * joe.each_pair {|name, value| puts("#{name} => #{value}") }
510  *
511  * <em>produces:</em>
512  *
513  * name => Joe Smith
514  * address => 123 Maple, Anytown NC
515  * zip => 12345
516  */
517 
518 static VALUE
520 {
521  VALUE members;
522  long i;
523 
525  members = rb_struct_members(s);
526  for (i=0; i<RSTRUCT_LEN(s); i++) {
527  VALUE key = rb_ary_entry(members, i);
528  VALUE value = RSTRUCT_PTR(s)[i];
529  rb_yield(rb_assoc_new(key, value));
530  }
531  return s;
532 }
533 
534 static VALUE
536 {
537  VALUE cname = rb_class_name(rb_obj_class(s));
538  VALUE members, str = rb_str_new2("#<struct ");
539  VALUE *ptr, *ptr_members;
540  long i, len;
541  char first = RSTRING_PTR(cname)[0];
542 
543  if (recur || first != '#') {
544  rb_str_append(str, cname);
545  }
546  if (recur) {
547  return rb_str_cat2(str, ":...>");
548  }
549 
550  members = rb_struct_members(s);
551  ptr_members = RARRAY_PTR(members);
552  ptr = RSTRUCT_PTR(s);
553  len = RSTRUCT_LEN(s);
554  for (i=0; i<len; i++) {
555  VALUE slot;
556  ID id;
557 
558  if (i > 0) {
559  rb_str_cat2(str, ", ");
560  }
561  else if (first != '#') {
562  rb_str_cat2(str, " ");
563  }
564  slot = ptr_members[i];
565  id = SYM2ID(slot);
566  if (rb_is_local_id(id) || rb_is_const_id(id)) {
567  rb_str_append(str, rb_id2str(id));
568  }
569  else {
570  rb_str_append(str, rb_inspect(slot));
571  }
572  rb_str_cat2(str, "=");
573  rb_str_append(str, rb_inspect(ptr[i]));
574  }
575  rb_str_cat2(str, ">");
576  OBJ_INFECT(str, s);
577 
578  return str;
579 }
580 
581 /*
582  * call-seq:
583  * struct.to_s -> string
584  * struct.inspect -> string
585  *
586  * Describe the contents of this struct in a string.
587  */
588 
589 static VALUE
591 {
592  return rb_exec_recursive(inspect_struct, s, 0);
593 }
594 
595 /*
596  * call-seq:
597  * struct.to_a -> array
598  * struct.values -> array
599  *
600  * Returns the values for this instance as an array.
601  *
602  * Customer = Struct.new(:name, :address, :zip)
603  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
604  * joe.to_a[1] #=> "123 Maple, Anytown NC"
605  */
606 
607 static VALUE
609 {
610  return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s));
611 }
612 
613 /*
614  * call-seq:
615  * struct.to_h -> hash
616  *
617  * Returns the values for this instance as a hash with keys
618  * corresponding to the instance variable name.
619  *
620  * Customer = Struct.new(:name, :address, :zip)
621  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
622  * joe.to_h[:address] #=> "123 Maple, Anytown NC"
623  */
624 
625 static VALUE
627 {
628  VALUE h = rb_hash_new();
629  VALUE members = rb_struct_members(s);
630  long i;
631 
632  for (i=0; i<RSTRUCT_LEN(s); i++) {
633  rb_hash_aset(h, rb_ary_entry(members, i), RSTRUCT_PTR(s)[i]);
634  }
635  return h;
636 }
637 
638 /* :nodoc: */
639 VALUE
641 {
642  if (!OBJ_INIT_COPY(copy, s)) return copy;
643  if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
644  rb_raise(rb_eTypeError, "struct size mismatch");
645  }
646  MEMCPY(RSTRUCT_PTR(copy), RSTRUCT_PTR(s), VALUE, RSTRUCT_LEN(copy));
647 
648  return copy;
649 }
650 
651 static VALUE
653 {
654  VALUE *ptr, members, *ptr_members;
655  long i, len;
656 
657  ptr = RSTRUCT_PTR(s);
658  members = rb_struct_members(s);
659  ptr_members = RARRAY_PTR(members);
660  len = RARRAY_LEN(members);
661  for (i=0; i<len; i++) {
662  if (SYM2ID(ptr_members[i]) == id) {
663  return ptr[i];
664  }
665  }
666  rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
667 
668  UNREACHABLE;
669 }
670 
671 /*
672  * call-seq:
673  * struct[symbol] -> anObject
674  * struct[fixnum] -> anObject
675  *
676  * Attribute Reference---Returns the value of the instance variable
677  * named by <i>symbol</i>, or indexed (0..length-1) by
678  * <i>fixnum</i>. Will raise <code>NameError</code> if the named
679  * variable does not exist, or <code>IndexError</code> if the index is
680  * out of range.
681  *
682  * Customer = Struct.new(:name, :address, :zip)
683  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
684  *
685  * joe["name"] #=> "Joe Smith"
686  * joe[:name] #=> "Joe Smith"
687  * joe[0] #=> "Joe Smith"
688  */
689 
690 VALUE
692 {
693  long i;
694 
695  if (RB_TYPE_P(idx, T_SYMBOL)) {
696  return rb_struct_aref_id(s, SYM2ID(idx));
697  }
698  else if (RB_TYPE_P(idx, T_STRING)) {
699  ID id = rb_check_id(&idx);
700  if (!id) {
701  rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct",
702  QUOTE(idx));
703  }
704  return rb_struct_aref_id(s, id);
705  }
706 
707  i = NUM2LONG(idx);
708  if (i < 0) i = RSTRUCT_LEN(s) + i;
709  if (i < 0)
710  rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
711  i, RSTRUCT_LEN(s));
712  if (RSTRUCT_LEN(s) <= i)
713  rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
714  i, RSTRUCT_LEN(s));
715  return RSTRUCT_PTR(s)[i];
716 }
717 
718 static VALUE
720 {
721  VALUE members, *ptr, *ptr_members;
722  long i, len;
723 
724  members = rb_struct_members(s);
725  len = RARRAY_LEN(members);
726  rb_struct_modify(s);
727  if (RSTRUCT_LEN(s) != len) {
728  rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
729  len, RSTRUCT_LEN(s));
730  }
731  ptr = RSTRUCT_PTR(s);
732  ptr_members = RARRAY_PTR(members);
733  for (i=0; i<len; i++) {
734  if (SYM2ID(ptr_members[i]) == id) {
735  ptr[i] = val;
736  return val;
737  }
738  }
739  rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
740 
741  UNREACHABLE;
742 }
743 
744 /*
745  * call-seq:
746  * struct[symbol] = obj -> obj
747  * struct[fixnum] = obj -> obj
748  *
749  * Attribute Assignment---Assigns to the instance variable named by
750  * <i>symbol</i> or <i>fixnum</i> the value <i>obj</i> and
751  * returns it. Will raise a <code>NameError</code> if the named
752  * variable does not exist, or an <code>IndexError</code> if the index
753  * is out of range.
754  *
755  * Customer = Struct.new(:name, :address, :zip)
756  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
757  *
758  * joe["name"] = "Luke"
759  * joe[:zip] = "90210"
760  *
761  * joe.name #=> "Luke"
762  * joe.zip #=> "90210"
763  */
764 
765 VALUE
767 {
768  long i;
769 
770  if (RB_TYPE_P(idx, T_SYMBOL)) {
771  return rb_struct_aset_id(s, SYM2ID(idx), val);
772  }
773  if (RB_TYPE_P(idx, T_STRING)) {
774  ID id = rb_check_id(&idx);
775  if (!id) {
776  rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct",
777  QUOTE(idx));
778  }
779  return rb_struct_aset_id(s, id, val);
780  }
781 
782  i = NUM2LONG(idx);
783  if (i < 0) i = RSTRUCT_LEN(s) + i;
784  if (i < 0) {
785  rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
786  i, RSTRUCT_LEN(s));
787  }
788  if (RSTRUCT_LEN(s) <= i) {
789  rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
790  i, RSTRUCT_LEN(s));
791  }
792  rb_struct_modify(s);
793  return RSTRUCT_PTR(s)[i] = val;
794 }
795 
796 static VALUE
797 struct_entry(VALUE s, long n)
798 {
799  return rb_struct_aref(s, LONG2NUM(n));
800 }
801 
802 /*
803  * call-seq:
804  * struct.values_at(selector,... ) -> an_array
805  *
806  * Returns an array containing the elements in
807  * +self+ corresponding to the given selector(s). The selectors
808  * may be either integer indices or ranges.
809  * See also </code>.select<code>.
810  *
811  * a = %w{ a b c d e f }
812  * a.values_at(1, 3, 5)
813  * a.values_at(1, 3, 5, 7)
814  * a.values_at(-1, -3, -5, -7)
815  * a.values_at(1..3, 2...5)
816  */
817 
818 static VALUE
820 {
821  return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
822 }
823 
824 /*
825  * call-seq:
826  * struct.select {|i| block } -> array
827  * struct.select -> an_enumerator
828  *
829  * Invokes the block passing in successive elements from
830  * <i>struct</i>, returning an array containing those elements
831  * for which the block returns a true value (equivalent to
832  * <code>Enumerable#select</code>).
833  *
834  * Lots = Struct.new(:a, :b, :c, :d, :e, :f)
835  * l = Lots.new(11, 22, 33, 44, 55, 66)
836  * l.select {|v| (v % 2).zero? } #=> [22, 44, 66]
837  */
838 
839 static VALUE
841 {
842  VALUE result;
843  long i;
844 
845  rb_check_arity(argc, 0, 0);
847  result = rb_ary_new();
848  for (i = 0; i < RSTRUCT_LEN(s); i++) {
849  if (RTEST(rb_yield(RSTRUCT_PTR(s)[i]))) {
850  rb_ary_push(result, RSTRUCT_PTR(s)[i]);
851  }
852  }
853 
854  return result;
855 }
856 
857 static VALUE
859 {
860  VALUE *ptr, *ptr2;
861  long i, len;
862 
863  if (recur) return Qtrue; /* Subtle! */
864  ptr = RSTRUCT_PTR(s);
865  ptr2 = RSTRUCT_PTR(s2);
866  len = RSTRUCT_LEN(s);
867  for (i=0; i<len; i++) {
868  if (!rb_equal(ptr[i], ptr2[i])) return Qfalse;
869  }
870  return Qtrue;
871 }
872 
873 /*
874  * call-seq:
875  * struct == other_struct -> true or false
876  *
877  * Equality---Returns <code>true</code> if <i>other_struct</i> is
878  * equal to this one: they must be of the same class as generated by
879  * <code>Struct::new</code>, and the values of all instance variables
880  * must be equal (according to <code>Object#==</code>).
881  *
882  * Customer = Struct.new(:name, :address, :zip)
883  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
884  * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
885  * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
886  * joe == joejr #=> true
887  * joe == jane #=> false
888  */
889 
890 static VALUE
892 {
893  if (s == s2) return Qtrue;
894  if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
895  if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
896  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
897  rb_bug("inconsistent struct"); /* should never happen */
898  }
899 
900  return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
901 }
902 
903 static VALUE
905 {
906  long i, len;
907  st_index_t h;
908  VALUE n, *ptr;
909 
911  if (!recur) {
912  ptr = RSTRUCT_PTR(s);
913  len = RSTRUCT_LEN(s);
914  for (i = 0; i < len; i++) {
915  n = rb_hash(ptr[i]);
916  h = rb_hash_uint(h, NUM2LONG(n));
917  }
918  }
919  h = rb_hash_end(h);
920  return INT2FIX(h);
921 }
922 
923 /*
924  * call-seq:
925  * struct.hash -> fixnum
926  *
927  * Return a hash value based on this struct's contents.
928  */
929 
930 static VALUE
932 {
934 }
935 
936 static VALUE
938 {
939  VALUE *ptr, *ptr2;
940  long i, len;
941 
942  if (recur) return Qtrue; /* Subtle! */
943  ptr = RSTRUCT_PTR(s);
944  ptr2 = RSTRUCT_PTR(s2);
945  len = RSTRUCT_LEN(s);
946  for (i=0; i<len; i++) {
947  if (!rb_eql(ptr[i], ptr2[i])) return Qfalse;
948  }
949  return Qtrue;
950 }
951 
952 /*
953  * call-seq:
954  * struct.eql?(other) -> true or false
955  *
956  * Two structures are equal if they are the same object, or if all their
957  * fields are equal (using <code>eql?</code>).
958  */
959 
960 static VALUE
962 {
963  if (s == s2) return Qtrue;
964  if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
965  if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
966  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
967  rb_bug("inconsistent struct"); /* should never happen */
968  }
969 
970  return rb_exec_recursive_paired(recursive_eql, s, s2, s2);
971 }
972 
973 /*
974  * call-seq:
975  * struct.length -> fixnum
976  * struct.size -> fixnum
977  *
978  * Returns the number of instance variables.
979  *
980  * Customer = Struct.new(:name, :address, :zip)
981  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
982  * joe.length #=> 3
983  */
984 
985 static VALUE
987 {
988  return LONG2FIX(RSTRUCT_LEN(s));
989 }
990 
991 /*
992  * A <code>Struct</code> is a convenient way to bundle a number of
993  * attributes together, using accessor methods, without having to write
994  * an explicit class.
995  *
996  * The <code>Struct</code> class is a generator of specific classes,
997  * each one of which is defined to hold a set of variables and their
998  * accessors. In these examples, we'll call the generated class
999  * ``<i>Customer</i>Class,'' and we'll show an example instance of that
1000  * class as ``<i>Customer</i>Inst.''
1001  *
1002  * In the descriptions that follow, the parameter <i>symbol</i> refers
1003  * to a symbol, which is either a quoted string or a
1004  * <code>Symbol</code> (such as <code>:name</code>).
1005  */
1006 void
1008 {
1009  rb_cStruct = rb_define_class("Struct", rb_cObject);
1011 
1014 
1016  rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
1017 
1021 
1023  rb_define_alias(rb_cStruct, "to_s", "inspect");
1029 
1035  rb_define_method(rb_cStruct, "values_at", rb_struct_values_at, -1);
1036 
1038  id_members = rb_intern("__members__");
1039 }
static VALUE struct_entry(VALUE s, long n)
Definition: struct.c:797
static VALUE rb_struct_each_pair(VALUE s)
Definition: struct.c:519
#define RB_TYPE_P(obj, type)
static VALUE struct_ivar_get(VALUE c, ID id)
Definition: struct.c:21
static VALUE rb_struct_to_h(VALUE s)
Definition: struct.c:626
VALUE rb_struct_s_members(VALUE klass)
Definition: struct.c:39
VALUE rb_struct_iv_get(VALUE c, const char *name)
Definition: struct.c:33
VALUE rb_ary_new4(long n, const VALUE *elts)
Definition: array.c:451
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1101
#define RSTRUCT_LEN(st)
int rb_eql(VALUE, VALUE)
Definition: object.c:67
void rb_bug(const char *fmt,...)
Definition: error.c:290
#define T_STRUCT
VALUE(* rb_alloc_func_t)(VALUE)
Definition: ripper.y:352
#define OBJ_INFECT(x, s)
static VALUE rb_struct_each(VALUE s)
Definition: struct.c:486
int i
Definition: win32ole.c:784
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1775
unsigned long VALUE
Definition: ripper.y:104
VALUE rb_id2str(ID id)
Definition: ripper.c:16992
VALUE rb_mod_module_eval(int, VALUE *, VALUE)
Definition: vm_eval.c:1668
#define UNLIMITED_ARGUMENTS
static VALUE rb_struct_select(int argc, VALUE *argv, VALUE s)
Definition: struct.c:840
#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:1497
VALUE rb_struct_define(const char *name,...)
Definition: struct.c:272
static VALUE anonymous_struct(VALUE klass)
Definition: struct.c:175
static VALUE rb_struct_ref3(VALUE obj)
Definition: struct.c:120
VALUE rb_struct_initialize(VALUE self, VALUE values)
Definition: struct.c:407
static VALUE rb_struct_to_a(VALUE s)
Definition: struct.c:608
VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:568
#define rb_check_frozen(obj)
static VALUE rb_struct_eql(VALUE s, VALUE s2)
Definition: struct.c:961
const int id
Definition: nkf.c:209
#define RSTRUCT_EMBED_LEN_MASK
ID rb_frame_this_func(void)
Definition: eval.c:902
VALUE rb_eTypeError
Definition: error.c:511
void rb_mem_clear(register VALUE *mem, register long size)
Definition: array.c:37
#define OBJ_FREEZE(x)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define UNREACHABLE
Definition: ruby.h:40
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
static VALUE rb_struct_equal(VALUE s, VALUE s2)
Definition: struct.c:891
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:465
void Init_Struct(void)
Definition: struct.c:1007
#define RSTRUCT_EMBED_LEN_MAX
#define RSTRING_PTR(str)
#define T_ARRAY
VALUE rb_struct_getmember(VALUE obj, ID id)
Definition: struct.c:91
VALUE rb_struct_aset(VALUE s, VALUE idx, VALUE val)
Definition: struct.c:766
#define Qnil
static VALUE rb_struct_ref0(VALUE obj)
Definition: struct.c:117
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
VALUE rb_obj_class(VALUE)
Definition: object.c:194
VALUE rb_class_name(VALUE)
Definition: variable.c:383
VALUE rb_struct_alloc(VALUE klass, VALUE values)
Definition: struct.c:435
static VALUE rb_struct_aref_id(VALUE s, ID id)
Definition: struct.c:652
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:695
static ID id_members
Definition: struct.c:16
static VALUE inspect_struct(VALUE s, VALUE dummy, int recur)
Definition: struct.c:535
#define rb_str_new2
static VALUE setup_struct(VALUE nstr, VALUE members)
Definition: struct.c:204
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: ripper.c:17152
#define ID2SYM(x)
static VALUE rb_struct_initialize_m(int argc, VALUE *argv, VALUE self)
Definition: struct.c:389
#define LONG2NUM(x)
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2122
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1116
VALUE rb_equal(VALUE, VALUE)
Definition: object.c:56
VALUE rb_str_to_str(VALUE)
Definition: string.c:849
void rb_name_error_str(VALUE str, const char *fmt,...)
Definition: error.c:914
void rb_name_error(ID id, const char *fmt,...)
Definition: error.c:899
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1416
#define RSTRUCT_EMBED_LEN_SHIFT
VALUE rb_struct_aref(VALUE s, VALUE idx)
Definition: struct.c:691
int args
Definition: win32ole.c:785
int rb_is_const_id(ID id)
Definition: ripper.c:17099
#define RSTRUCT_PTR(st)
static VALUE rb_struct_ref(VALUE obj)
Definition: struct.c:112
VALUE rb_class_inherited(VALUE super, VALUE klass)
Calls Class::inherited.
Definition: class.c:473
static VALUE rb_struct_ref2(VALUE obj)
Definition: struct.c:119
static long num_members(VALUE klass)
Definition: struct.c:375
static VALUE recursive_eql(VALUE s, VALUE s2, int recur)
Definition: struct.c:937
int rb_block_given_p(void)
Definition: eval.c:672
static VALUE rb_struct_aset_id(VALUE s, ID id, VALUE val)
Definition: struct.c:719
#define RARRAY_LEN(a)
static VALUE rb_struct_hash(VALUE s)
Definition: struct.c:931
static VALUE rb_struct_ref6(VALUE obj)
Definition: struct.c:123
#define val
#define Qtrue
return c
Definition: ripper.y:7591
VALUE rb_ary_new(void)
Definition: array.c:424
unsigned long ID
Definition: ripper.y:105
#define RCLASS_SUPER(c)
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:1983
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
#define INT2FIX(i)
#define Qfalse
#define T_STRING
static VALUE recursive_hash(VALUE s, VALUE dummy, int recur)
Definition: struct.c:904
#define OBJ_INIT_COPY(obj, orig)
int argc
Definition: ruby.c:130
#define NIL_P(v)
#define rb_hash_end(h)
static VALUE recursive_equal(VALUE s, VALUE s2, int recur)
Definition: struct.c:858
VALUE rb_struct_new(VALUE klass,...)
Definition: struct.c:441
static VALUE rb_struct_ref8(VALUE obj)
Definition: struct.c:125
VALUE rb_eIndexError
Definition: error.c:513
static VALUE rb_struct_ref9(VALUE obj)
Definition: struct.c:126
static VALUE rb_struct_set(VALUE obj, VALUE val)
Definition: struct.c:152
#define rb_long2int(n)
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1539
VALUE rb_yield(VALUE)
Definition: vm_eval.c:933
static VALUE rb_struct_s_members_m(VALUE klass)
Definition: struct.c:65
#define RTEST(v)
VALUE rb_mEnumerable
Definition: enum.c:20
static VALUE rb_struct_ref4(VALUE obj)
Definition: struct.c:121
static VALUE struct_alloc(VALUE)
Definition: struct.c:413
#define numberof(array)
Definition: struct.c:128
#define QUOTE(str)
int rb_is_local_id(ID id)
Definition: ripper.c:17129
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:545
VALUE rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, VALUE(*func)(VALUE, long))
Definition: array.c:2580
#define RARRAY_PTR(a)
VALUE rb_cStruct
Definition: struct.c:15
static VALUE result
Definition: nkf.c:40
int rb_const_defined_at(VALUE, ID)
Definition: variable.c:2109
VALUE rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc,...)
Definition: struct.c:239
ID rb_id_attrset(ID id)
Definition: ripper.c:15277
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:492
VALUE rb_make_metaclass(VALUE obj, VALUE unused)
Definition: class.c:430
VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4895
static VALUE(*const ref_func[])(VALUE)
Definition: struct.c:131
#define N_REF_FUNC
Definition: struct.c:129
VALUE rb_ivar_defined(VALUE, ID)
Definition: variable.c:1204
#define MEMCPY(p1, p2, type, n)
ID rb_to_id(VALUE)
Definition: string.c:8155
static VALUE rb_struct_size(VALUE s)
Definition: struct.c:986
static VALUE rb_struct_values_at(int argc, VALUE *argv, VALUE s)
Definition: struct.c:819
#define recur(fmt)
int rb_is_const_name(VALUE name)
Definition: ripper.c:17227
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1128
#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:1338
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
int size
Definition: encoding.c:52
#define NUM2LONG(x)
#define SYMBOL_P(x)
static VALUE rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
Definition: struct.c:338
static void rb_struct_modify(VALUE s)
Definition: struct.c:145
VALUE rb_hash(VALUE)
Definition: hash.c:66
VALUE rb_mod_remove_const(VALUE, VALUE)
Definition: variable.c:1916
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:4883
static VALUE rb_struct_ref7(VALUE obj)
Definition: struct.c:124
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
st_data_t st_index_t
Definition: ripper.y:63
#define ALLOC_N(type, n)
#define LONG2FIX(i)
uint8_t key[16]
Definition: random.c:1370
#define RBASIC(obj)
#define RARRAY_LENINT(ary)
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1778
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4872
static VALUE rb_struct_ref1(VALUE obj)
Definition: struct.c:118
const char * name
Definition: nkf.c:208
VALUE rb_hash_new(void)
Definition: hash.c:234
const char * rb_id2name(ID id)
Definition: ripper.c:17058
VALUE rb_struct_alloc_noinit(VALUE klass)
Definition: struct.c:233
#define rb_check_arity(argc, min, max)
#define PRIsVALUE
VALUE rb_struct_members(VALUE s)
Definition: struct.c:53
static VALUE rb_struct_inspect(VALUE s)
Definition: struct.c:590
static VALUE rb_struct_ref5(VALUE obj)
Definition: struct.c:122
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:103
static VALUE rb_struct_members_m(VALUE obj)
Definition: struct.c:85
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:117
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
void rb_warn(const char *fmt,...)
Definition: error.c:216
#define SYM2ID(x)
static VALUE new_struct(VALUE name, VALUE super)
Definition: struct.c:186
VALUE rb_eArgError
Definition: error.c:512
char ** argv
Definition: ruby.c:131
#define rb_hash_uint(h, i)
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:640
VALUE rb_inspect(VALUE)
Definition: object.c:402
void rb_ary_set_len(VALUE ary, long len)
Definition: array.c:1490