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