Ruby  1.9.3p392(2013-02-22revision39386)
struct.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  struct.c -
4 
5  $Author: nobu $
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
33 rb_struct_iv_get(VALUE c, const char *name)
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 (TYPE(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, ary;
68  VALUE *p, *pend;
69 
70  members = rb_struct_s_members(klass);
71  ary = rb_ary_new2(RARRAY_LEN(members));
72  p = RARRAY_PTR(members); pend = p + RARRAY_LEN(members);
73  while (p < pend) {
74  rb_ary_push(ary, *p);
75  p++;
76  }
77 
78  return ary;
79 }
80 
81 /*
82  * call-seq:
83  * struct.members -> array
84  *
85  * Returns an array of strings representing the names of the instance
86  * variables.
87  *
88  * Customer = Struct.new(:name, :address, :zip)
89  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
90  * joe.members #=> [:name, :address, :zip]
91  */
92 
93 static VALUE
95 {
97 }
98 
99 VALUE
101 {
102  VALUE members, slot, *ptr, *ptr_members;
103  long i, len;
104 
105  ptr = RSTRUCT_PTR(obj);
106  members = rb_struct_members(obj);
107  ptr_members = RARRAY_PTR(members);
108  slot = ID2SYM(id);
109  len = RARRAY_LEN(members);
110  for (i=0; i<len; i++) {
111  if (ptr_members[i] == slot) {
112  return ptr[i];
113  }
114  }
115  rb_name_error(id, "%s is not struct member", rb_id2name(id));
116  return Qnil; /* not reached */
117 }
118 
119 static VALUE
121 {
123 }
124 
125 static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_PTR(obj)[0];}
126 static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_PTR(obj)[1];}
127 static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_PTR(obj)[2];}
128 static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_PTR(obj)[3];}
129 static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_PTR(obj)[4];}
130 static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_PTR(obj)[5];}
131 static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_PTR(obj)[6];}
132 static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_PTR(obj)[7];}
133 static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_PTR(obj)[8];}
134 static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_PTR(obj)[9];}
135 
136 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
137 #define N_REF_FUNC numberof(ref_func)
138 
139 static VALUE (*const ref_func[])(VALUE) = {
150 };
151 
152 static void
154 {
155  rb_check_frozen(s);
156  if (!OBJ_UNTRUSTED(s) && rb_safe_level() >= 4)
157  rb_raise(rb_eSecurityError, "Insecure: can't modify Struct");
158 }
159 
160 static VALUE
162 {
163  VALUE members, slot, *ptr, *ptr_members;
164  long i, len;
165 
166  members = rb_struct_members(obj);
167  ptr_members = RARRAY_PTR(members);
168  len = RARRAY_LEN(members);
169  rb_struct_modify(obj);
170  ptr = RSTRUCT_PTR(obj);
171  for (i=0; i<len; i++) {
172  slot = ptr_members[i];
173  if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) {
174  return ptr[i] = val;
175  }
176  }
177  rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
179  return Qnil; /* not reached */
180 }
181 
182 static VALUE
183 make_struct(VALUE name, VALUE members, VALUE klass)
184 {
185  VALUE nstr, *ptr_members;
186  ID id;
187  long i, len;
188 
189  OBJ_FREEZE(members);
190  if (NIL_P(name)) {
191  nstr = rb_class_new(klass);
192  rb_make_metaclass(nstr, RBASIC(klass)->klass);
193  rb_class_inherited(klass, nstr);
194  }
195  else {
196  /* old style: should we warn? */
197  name = rb_str_to_str(name);
198  id = rb_to_id(name);
199  if (!rb_is_const_id(id)) {
200  rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name));
201  }
202  if (rb_const_defined_at(klass, id)) {
203  rb_warn("redefining constant Struct::%s", StringValuePtr(name));
204  rb_mod_remove_const(klass, ID2SYM(id));
205  }
206  nstr = rb_define_class_id_under(klass, id, klass);
207  }
208  rb_ivar_set(nstr, id_members, members);
209 
214  ptr_members = RARRAY_PTR(members);
215  len = RARRAY_LEN(members);
216  for (i=0; i< len; i++) {
217  ID id = SYM2ID(ptr_members[i]);
218  if (rb_is_local_id(id) || rb_is_const_id(id)) {
219  if (i < N_REF_FUNC) {
220  rb_define_method_id(nstr, id, ref_func[i], 0);
221  }
222  else {
223  rb_define_method_id(nstr, id, rb_struct_ref, 0);
224  }
226  }
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_new2(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 = rb_class_new(super);
259  rb_make_metaclass(klass, RBASIC(super)->klass);
260  rb_class_inherited(super, klass);
261  }
262 
263  rb_ivar_set(klass, id_members, members);
264 
265  if (alloc)
266  rb_define_alloc_func(klass, alloc);
267  else
269 
270  return klass;
271 }
272 
273 VALUE
274 rb_struct_define(const char *name, ...)
275 {
276  va_list ar;
277  VALUE nm, ary;
278  char *mem;
279 
280  if (!name) nm = Qnil;
281  else nm = rb_str_new2(name);
282  ary = rb_ary_new();
283 
284  va_start(ar, name);
285  while ((mem = va_arg(ar, char*)) != 0) {
286  ID slot = rb_intern(mem);
287  rb_ary_push(ary, ID2SYM(slot));
288  }
289  va_end(ar);
290 
291  return make_struct(nm, ary, rb_cStruct);
292 }
293 
294 /*
295  * call-seq:
296  * Struct.new( [aString] [, aSym]+> ) -> StructClass
297  * StructClass.new(arg, ...) -> obj
298  * StructClass[arg, ...] -> obj
299  *
300  * Creates a new class, named by <i>aString</i>, containing accessor
301  * methods for the given symbols. If the name <i>aString</i> is
302  * omitted, an anonymous structure class will be created. Otherwise,
303  * the name of this struct will appear as a constant in class
304  * <code>Struct</code>, so it must be unique for all
305  * <code>Struct</code>s in the system and should start with a capital
306  * letter. Assigning a structure class to a constant effectively gives
307  * the class the name of the constant.
308  *
309  * <code>Struct::new</code> returns a new <code>Class</code> object,
310  * which can then be used to create specific instances of the new
311  * structure. The number of actual parameters must be
312  * less than or equal to the number of attributes defined for this
313  * class; unset parameters default to <code>nil</code>. Passing too many
314  * parameters will raise an <code>ArgumentError</code>.
315  *
316  * The remaining methods listed in this section (class and instance)
317  * are defined for this generated class.
318  *
319  * # Create a structure with a name in Struct
320  * Struct.new("Customer", :name, :address) #=> Struct::Customer
321  * Struct::Customer.new("Dave", "123 Main") #=> #<struct Struct::Customer name="Dave", address="123 Main">
322  *
323  * # Create a structure named by its constant
324  * Customer = Struct.new(:name, :address) #=> Customer
325  * Customer.new("Dave", "123 Main") #=> #<struct Customer name="Dave", address="123 Main">
326  */
327 
328 static VALUE
330 {
331  VALUE name, rest;
332  long i;
333  VALUE st;
334  ID id;
335 
336  rb_scan_args(argc, argv, "1*", &name, &rest);
337  if (!NIL_P(name) && SYMBOL_P(name)) {
338  rb_ary_unshift(rest, name);
339  name = Qnil;
340  }
341  for (i=0; i<RARRAY_LEN(rest); i++) {
342  id = rb_to_id(RARRAY_PTR(rest)[i]);
343  RARRAY_PTR(rest)[i] = ID2SYM(id);
344  }
345  st = make_struct(name, rest, klass);
346  if (rb_block_given_p()) {
347  rb_mod_module_eval(0, 0, st);
348  }
349 
350  return st;
351 }
352 
353 static long
355 {
356  VALUE members;
357  members = struct_ivar_get(klass, id_members);
358  if (TYPE(members) != T_ARRAY) {
359  rb_raise(rb_eTypeError, "broken members");
360  }
361  return RARRAY_LEN(members);
362 }
363 
364 /*
365  */
366 
367 static VALUE
369 {
370  VALUE klass = rb_obj_class(self);
371  long n;
372 
373  rb_struct_modify(self);
374  n = num_members(klass);
375  if (n < argc) {
376  rb_raise(rb_eArgError, "struct size differs");
377  }
378  MEMCPY(RSTRUCT_PTR(self), argv, VALUE, argc);
379  if (n > argc) {
380  rb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc);
381  }
382  return Qnil;
383 }
384 
385 VALUE
387 {
388  return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_PTR(values), self);
389 }
390 
391 static VALUE
393 {
394  long n;
395  NEWOBJ(st, struct RStruct);
396  OBJSETUP(st, 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
421 rb_struct_new(VALUE klass, ...)
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 /*
442  * call-seq:
443  * struct.each {|obj| block } -> struct
444  * struct.each -> an_enumerator
445  *
446  * Calls <i>block</i> once for each instance variable, passing the
447  * value as a parameter.
448  *
449  * If no block is given, an enumerator is returned instead.
450  *
451  * Customer = Struct.new(:name, :address, :zip)
452  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
453  * joe.each {|x| puts(x) }
454  *
455  * <em>produces:</em>
456  *
457  * Joe Smith
458  * 123 Maple, Anytown NC
459  * 12345
460  */
461 
462 static VALUE
464 {
465  long i;
466 
467  RETURN_ENUMERATOR(s, 0, 0);
468  for (i=0; i<RSTRUCT_LEN(s); i++) {
469  rb_yield(RSTRUCT_PTR(s)[i]);
470  }
471  return s;
472 }
473 
474 /*
475  * call-seq:
476  * struct.each_pair {|sym, obj| block } -> struct
477  * struct.each_pair -> an_enumerator
478  *
479  * Calls <i>block</i> once for each instance variable, passing the name
480  * (as a symbol) and the value as parameters.
481  *
482  * If no block is given, an enumerator is returned instead.
483  *
484  * Customer = Struct.new(:name, :address, :zip)
485  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
486  * joe.each_pair {|name, value| puts("#{name} => #{value}") }
487  *
488  * <em>produces:</em>
489  *
490  * name => Joe Smith
491  * address => 123 Maple, Anytown NC
492  * zip => 12345
493  */
494 
495 static VALUE
497 {
498  VALUE members;
499  long i;
500 
501  RETURN_ENUMERATOR(s, 0, 0);
502  members = rb_struct_members(s);
503  for (i=0; i<RSTRUCT_LEN(s); i++) {
504  rb_yield_values(2, rb_ary_entry(members, i), RSTRUCT_PTR(s)[i]);
505  }
506  return s;
507 }
508 
509 static VALUE
511 {
512  VALUE cname = rb_class_name(rb_obj_class(s));
513  VALUE members, str = rb_str_new2("#<struct ");
514  VALUE *ptr, *ptr_members;
515  long i, len;
516  char first = RSTRING_PTR(cname)[0];
517 
518  if (recur || first != '#') {
519  rb_str_append(str, cname);
520  }
521  if (recur) {
522  return rb_str_cat2(str, ":...>");
523  }
524 
525  members = rb_struct_members(s);
526  ptr_members = RARRAY_PTR(members);
527  ptr = RSTRUCT_PTR(s);
528  len = RSTRUCT_LEN(s);
529  for (i=0; i<len; i++) {
530  VALUE slot;
531  ID id;
532 
533  if (i > 0) {
534  rb_str_cat2(str, ", ");
535  }
536  else if (first != '#') {
537  rb_str_cat2(str, " ");
538  }
539  slot = ptr_members[i];
540  id = SYM2ID(slot);
541  if (rb_is_local_id(id) || rb_is_const_id(id)) {
542  rb_str_append(str, rb_id2str(id));
543  }
544  else {
545  rb_str_append(str, rb_inspect(slot));
546  }
547  rb_str_cat2(str, "=");
548  rb_str_append(str, rb_inspect(ptr[i]));
549  }
550  rb_str_cat2(str, ">");
551  OBJ_INFECT(str, s);
552 
553  return str;
554 }
555 
556 /*
557  * call-seq:
558  * struct.to_s -> string
559  * struct.inspect -> string
560  *
561  * Describe the contents of this struct in a string.
562  */
563 
564 static VALUE
566 {
567  return rb_exec_recursive(inspect_struct, s, 0);
568 }
569 
570 /*
571  * call-seq:
572  * struct.to_a -> array
573  * struct.values -> array
574  *
575  * Returns the values for this instance as an array.
576  *
577  * Customer = Struct.new(:name, :address, :zip)
578  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
579  * joe.to_a[1] #=> "123 Maple, Anytown NC"
580  */
581 
582 static VALUE
584 {
585  return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s));
586 }
587 
588 /* :nodoc: */
589 VALUE
591 {
592  if (copy == s) return copy;
593  rb_check_frozen(copy);
594  if (!rb_obj_is_instance_of(s, rb_obj_class(copy))) {
595  rb_raise(rb_eTypeError, "wrong argument class");
596  }
597  if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
598  rb_raise(rb_eTypeError, "struct size mismatch");
599  }
600  MEMCPY(RSTRUCT_PTR(copy), RSTRUCT_PTR(s), VALUE, RSTRUCT_LEN(copy));
601 
602  return copy;
603 }
604 
605 static VALUE
607 {
608  VALUE *ptr, members, *ptr_members;
609  long i, len;
610 
611  ptr = RSTRUCT_PTR(s);
612  members = rb_struct_members(s);
613  ptr_members = RARRAY_PTR(members);
614  len = RARRAY_LEN(members);
615  for (i=0; i<len; i++) {
616  if (SYM2ID(ptr_members[i]) == id) {
617  return ptr[i];
618  }
619  }
620  rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
621  return Qnil; /* not reached */
622 }
623 
624 /*
625  * call-seq:
626  * struct[symbol] -> anObject
627  * struct[fixnum] -> anObject
628  *
629  * Attribute Reference---Returns the value of the instance variable
630  * named by <i>symbol</i>, or indexed (0..length-1) by
631  * <i>fixnum</i>. Will raise <code>NameError</code> if the named
632  * variable does not exist, or <code>IndexError</code> if the index is
633  * out of range.
634  *
635  * Customer = Struct.new(:name, :address, :zip)
636  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
637  *
638  * joe["name"] #=> "Joe Smith"
639  * joe[:name] #=> "Joe Smith"
640  * joe[0] #=> "Joe Smith"
641  */
642 
643 VALUE
645 {
646  long i;
647 
648  if (TYPE(idx) == T_STRING || TYPE(idx) == T_SYMBOL) {
649  return rb_struct_aref_id(s, rb_to_id(idx));
650  }
651 
652  i = NUM2LONG(idx);
653  if (i < 0) i = RSTRUCT_LEN(s) + i;
654  if (i < 0)
655  rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
656  i, RSTRUCT_LEN(s));
657  if (RSTRUCT_LEN(s) <= i)
658  rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
659  i, RSTRUCT_LEN(s));
660  return RSTRUCT_PTR(s)[i];
661 }
662 
663 static VALUE
665 {
666  VALUE members, *ptr, *ptr_members;
667  long i, len;
668 
669  members = rb_struct_members(s);
670  len = RARRAY_LEN(members);
671  rb_struct_modify(s);
672  if (RSTRUCT_LEN(s) != len) {
673  rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
674  len, RSTRUCT_LEN(s));
675  }
676  ptr = RSTRUCT_PTR(s);
677  ptr_members = RARRAY_PTR(members);
678  for (i=0; i<len; i++) {
679  if (SYM2ID(ptr_members[i]) == id) {
680  ptr[i] = val;
681  return val;
682  }
683  }
684  rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
685 }
686 
687 /*
688  * call-seq:
689  * struct[symbol] = obj -> obj
690  * struct[fixnum] = obj -> obj
691  *
692  * Attribute Assignment---Assigns to the instance variable named by
693  * <i>symbol</i> or <i>fixnum</i> the value <i>obj</i> and
694  * returns it. Will raise a <code>NameError</code> if the named
695  * variable does not exist, or an <code>IndexError</code> if the index
696  * is out of range.
697  *
698  * Customer = Struct.new(:name, :address, :zip)
699  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
700  *
701  * joe["name"] = "Luke"
702  * joe[:zip] = "90210"
703  *
704  * joe.name #=> "Luke"
705  * joe.zip #=> "90210"
706  */
707 
708 VALUE
710 {
711  long i;
712 
713  if (TYPE(idx) == T_STRING || TYPE(idx) == T_SYMBOL) {
714  return rb_struct_aset_id(s, rb_to_id(idx), val);
715  }
716 
717  i = NUM2LONG(idx);
718  if (i < 0) i = RSTRUCT_LEN(s) + i;
719  if (i < 0) {
720  rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
721  i, RSTRUCT_LEN(s));
722  }
723  if (RSTRUCT_LEN(s) <= i) {
724  rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
725  i, RSTRUCT_LEN(s));
726  }
727  rb_struct_modify(s);
728  return RSTRUCT_PTR(s)[i] = val;
729 }
730 
731 static VALUE
732 struct_entry(VALUE s, long n)
733 {
734  return rb_struct_aref(s, LONG2NUM(n));
735 }
736 
737 /*
738  * call-seq:
739  * struct.values_at(selector,... ) -> an_array
740  *
741  * Returns an array containing the elements in
742  * +self+ corresponding to the given selector(s). The selectors
743  * may be either integer indices or ranges.
744  * See also </code>.select<code>.
745  *
746  * a = %w{ a b c d e f }
747  * a.values_at(1, 3, 5)
748  * a.values_at(1, 3, 5, 7)
749  * a.values_at(-1, -3, -5, -7)
750  * a.values_at(1..3, 2...5)
751  */
752 
753 static VALUE
755 {
756  return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
757 }
758 
759 /*
760  * call-seq:
761  * struct.select {|i| block } -> array
762  * struct.select -> an_enumerator
763  *
764  * Invokes the block passing in successive elements from
765  * <i>struct</i>, returning an array containing those elements
766  * for which the block returns a true value (equivalent to
767  * <code>Enumerable#select</code>).
768  *
769  * Lots = Struct.new(:a, :b, :c, :d, :e, :f)
770  * l = Lots.new(11, 22, 33, 44, 55, 66)
771  * l.select {|v| (v % 2).zero? } #=> [22, 44, 66]
772  */
773 
774 static VALUE
776 {
777  VALUE result;
778  long i;
779 
780  if (argc > 0) {
781  rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
782  }
783  RETURN_ENUMERATOR(s, 0, 0);
784  result = rb_ary_new();
785  for (i = 0; i < RSTRUCT_LEN(s); i++) {
786  if (RTEST(rb_yield(RSTRUCT_PTR(s)[i]))) {
787  rb_ary_push(result, RSTRUCT_PTR(s)[i]);
788  }
789  }
790 
791  return result;
792 }
793 
794 static VALUE
796 {
797  VALUE *ptr, *ptr2;
798  long i, len;
799 
800  if (recur) return Qtrue; /* Subtle! */
801  ptr = RSTRUCT_PTR(s);
802  ptr2 = RSTRUCT_PTR(s2);
803  len = RSTRUCT_LEN(s);
804  for (i=0; i<len; i++) {
805  if (!rb_equal(ptr[i], ptr2[i])) return Qfalse;
806  }
807  return Qtrue;
808 }
809 
810 /*
811  * call-seq:
812  * struct == other_struct -> true or false
813  *
814  * Equality---Returns <code>true</code> if <i>other_struct</i> is
815  * equal to this one: they must be of the same class as generated by
816  * <code>Struct::new</code>, and the values of all instance variables
817  * must be equal (according to <code>Object#==</code>).
818  *
819  * Customer = Struct.new(:name, :address, :zip)
820  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
821  * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
822  * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
823  * joe == joejr #=> true
824  * joe == jane #=> false
825  */
826 
827 static VALUE
829 {
830  if (s == s2) return Qtrue;
831  if (TYPE(s2) != T_STRUCT) return Qfalse;
832  if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
833  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
834  rb_bug("inconsistent struct"); /* should never happen */
835  }
836 
837  return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
838 }
839 
840 static VALUE
842 {
843  long i, len;
844  st_index_t h;
845  VALUE n, *ptr;
846 
848  if (!recur) {
849  ptr = RSTRUCT_PTR(s);
850  len = RSTRUCT_LEN(s);
851  for (i = 0; i < len; i++) {
852  n = rb_hash(ptr[i]);
853  h = rb_hash_uint(h, NUM2LONG(n));
854  }
855  }
856  h = rb_hash_end(h);
857  return INT2FIX(h);
858 }
859 
860 /*
861  * call-seq:
862  * struct.hash -> fixnum
863  *
864  * Return a hash value based on this struct's contents.
865  */
866 
867 static VALUE
869 {
871 }
872 
873 static VALUE
875 {
876  VALUE *ptr, *ptr2;
877  long i, len;
878 
879  if (recur) return Qtrue; /* Subtle! */
880  ptr = RSTRUCT_PTR(s);
881  ptr2 = RSTRUCT_PTR(s2);
882  len = RSTRUCT_LEN(s);
883  for (i=0; i<len; i++) {
884  if (!rb_eql(ptr[i], ptr2[i])) return Qfalse;
885  }
886  return Qtrue;
887 }
888 
889 /*
890  * code-seq:
891  * struct.eql?(other) -> true or false
892  *
893  * Two structures are equal if they are the same object, or if all their
894  * fields are equal (using <code>eql?</code>).
895  */
896 
897 static VALUE
899 {
900  if (s == s2) return Qtrue;
901  if (TYPE(s2) != T_STRUCT) return Qfalse;
902  if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
903  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
904  rb_bug("inconsistent struct"); /* should never happen */
905  }
906 
907  return rb_exec_recursive_paired(recursive_eql, s, s2, s2);
908 }
909 
910 /*
911  * call-seq:
912  * struct.length -> fixnum
913  * struct.size -> fixnum
914  *
915  * Returns the number of instance variables.
916  *
917  * Customer = Struct.new(:name, :address, :zip)
918  * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
919  * joe.length #=> 3
920  */
921 
922 static VALUE
924 {
925  return LONG2FIX(RSTRUCT_LEN(s));
926 }
927 
928 /*
929  * A <code>Struct</code> is a convenient way to bundle a number of
930  * attributes together, using accessor methods, without having to write
931  * an explicit class.
932  *
933  * The <code>Struct</code> class is a generator of specific classes,
934  * each one of which is defined to hold a set of variables and their
935  * accessors. In these examples, we'll call the generated class
936  * ``<i>Customer</i>Class,'' and we'll show an example instance of that
937  * class as ``<i>Customer</i>Inst.''
938  *
939  * In the descriptions that follow, the parameter <i>symbol</i> refers
940  * to a symbol, which is either a quoted string or a
941  * <code>Symbol</code> (such as <code>:name</code>).
942  */
943 void
945 {
948 
951 
953  rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
954 
958 
960  rb_define_alias(rb_cStruct, "to_s", "inspect");
965 
972 
974  id_members = rb_intern("__members__");
975 }
976