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