VALUE rb_struct_aref(VALUE s, VALUE idx) { long i; if (RB_TYPE_P(idx, T_SYMBOL)) { return rb_struct_aref_id(s, SYM2ID(idx)); } else if (RB_TYPE_P(idx, T_STRING)) { ID id = rb_check_id(&idx); if (!id) { rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct", QUOTE(idx)); } return rb_struct_aref_id(s, id); } i = NUM2LONG(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)", i, RSTRUCT_LEN(s)); if (RSTRUCT_LEN(s) <= i) rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)", i, RSTRUCT_LEN(s)); return RSTRUCT_PTR(s)[i]; }
static mrb_value mrb_struct_aset(mrb_state *mrb, mrb_value s) { mrb_int i; mrb_value idx; mrb_value val; mrb_get_args(mrb, "oo", &idx, &val); if (mrb_string_p(idx)) { mrb_value sym = mrb_check_intern_str(mrb, idx); if (mrb_nil_p(sym)) { mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx); } idx = sym; } if (mrb_symbol_p(idx)) { return mrb_struct_aset_sym(mrb, s, mrb_symbol(idx), val); } i = mrb_int(mrb, idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too small for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); } if (RSTRUCT_LEN(s) <= i) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too large for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); } return RSTRUCT_PTR(s)[i] = val; }
mrb_value mrb_struct_aset(mrb_state *mrb, mrb_value s) { mrb_int i; mrb_value idx; mrb_value val; mrb_get_args(mrb, "oo", &idx, &val); if (mrb_string_p(idx) || mrb_symbol_p(idx)) { return mrb_struct_aset_id(mrb, s, mrb_obj_to_sym(mrb, idx), val); } i = mrb_fixnum(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too small for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); } if (RSTRUCT_LEN(s) <= i) { mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too large for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); } return RSTRUCT_PTR(s)[i] = val; }
/* * code-seq: * struct.eql?(other) -> true or false * * Two structures are equal if they are the same object, or if all their * fields are equal (using <code>eql?</code>). */ static mrb_value mrb_struct_eql(mrb_state *mrb, mrb_value s) { mrb_value s2; mrb_value *ptr, *ptr2; mrb_int i, len; mrb_get_args(mrb, "o", &s2); if (mrb_obj_equal(mrb, s, s2)) { return mrb_true_value(); } if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) { return mrb_false_value(); } if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { mrb_bug(mrb, "inconsistent struct"); /* should never happen */ } ptr = RSTRUCT_PTR(s); ptr2 = RSTRUCT_PTR(s2); len = RSTRUCT_LEN(s); for (i=0; i<len; i++) { if (!mrb_eql(mrb, ptr[i], ptr2[i])) { return mrb_false_value(); } } return mrb_true_value(); }
/* * code-seq: * struct.eql?(other) -> true or false * * Two structures are equal if they are the same object, or if all their * fields are equal (using <code>eql?</code>). */ static mrb_value mrb_struct_eql(mrb_state *mrb, mrb_value s) { mrb_value s2; mrb_value *ptr, *ptr2; mrb_int i, len; mrb_bool eql_p; mrb_get_args(mrb, "o", &s2); if (mrb_obj_equal(mrb, s, s2)) { eql_p = 1; } else if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct") || mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) { eql_p = 0; } else if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { mrb_bug(mrb, "inconsistent struct"); /* should never happen */ eql_p = 0; /* This substuture is just to suppress warnings. never called. */ } else { ptr = RSTRUCT_PTR(s); ptr2 = RSTRUCT_PTR(s2); len = RSTRUCT_LEN(s); eql_p = 1; for (i=0; i<len; i++) { if (!mrb_eql(mrb, ptr[i], ptr2[i])) { eql_p = 0; break; } } } return mrb_bool_value(eql_p); }
static VALUE rb_struct_aset_id(VALUE s, ID id, VALUE val) { VALUE members, *ptr, *ptr_members; long i, len; members = rb_struct_members(s); len = RARRAY_LEN(members); rb_struct_modify(s); if (RSTRUCT_LEN(s) != len) { rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)", len, RSTRUCT_LEN(s)); } ptr = RSTRUCT_PTR(s); ptr_members = RARRAY_PTR(members); for (i=0; i<len; i++) { if (SYM2ID(ptr_members[i]) == id) { ptr[i] = val; return val; } } rb_name_error(id, "no member '%s' in struct", rb_id2name(id)); UNREACHABLE; }
/* * call-seq: * struct[symbol] -> anObject * struct[fixnum] -> anObject * * Attribute Reference---Returns the value of the instance variable * named by <i>symbol</i>, or indexed (0..length-1) by * <i>fixnum</i>. Will raise <code>NameError</code> if the named * variable does not exist, or <code>IndexError</code> if the index is * out of range. * * Customer = Struct.new(:name, :address, :zip) * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) * * joe["name"] #=> "Joe Smith" * joe[:name] #=> "Joe Smith" * joe[0] #=> "Joe Smith" */ mrb_value mrb_struct_aref_n(mrb_state *mrb, mrb_value s, mrb_value idx) { mrb_int i; if (mrb_string_p(idx)) { mrb_value sym = mrb_check_intern_str(mrb, idx); if (mrb_nil_p(sym)) { mrb_raisef(mrb, E_INDEX_ERROR, "no member '%S' in struct", idx); } idx = sym; } if (mrb_symbol_p(idx)) { return mrb_struct_aref_id(mrb, s, mrb_symbol(idx)); } i = mrb_fixnum(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too small for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); if (RSTRUCT_LEN(s) <= i) mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too large for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); return RSTRUCT_PTR(s)[i]; }
mrb_value mrb_struct_aset(mrb_state *mrb, mrb_value s) { long i; mrb_value idx; mrb_value val; mrb_get_args(mrb, "oo", &idx, &val); if (mrb_type(idx) == MRB_TT_STRING || mrb_type(idx) == MRB_TT_SYMBOL) { return mrb_struct_aset_id(mrb, s, mrb_to_id(mrb, idx), val); } i = mrb_fixnum(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) { mrb_raise(mrb, E_INDEX_ERROR, "offset %ld too small for struct(size:%ld)", i, RSTRUCT_LEN(s)); } if (RSTRUCT_LEN(s) <= i) { mrb_raise(mrb, E_INDEX_ERROR, "offset %ld too large for struct(size:%ld)", i, RSTRUCT_LEN(s)); } mrb_struct_modify(s); return RSTRUCT_PTR(s)[i] = val; }
VALUE rb_struct_aset(VALUE s, VALUE idx, VALUE val) { long i; if (RB_TYPE_P(idx, T_SYMBOL)) { return rb_struct_aset_id(s, SYM2ID(idx), val); } if (RB_TYPE_P(idx, T_STRING)) { ID id = rb_check_id(&idx); if (!id) { rb_name_error_str(idx, "no member '%"PRIsVALUE"' in struct", QUOTE(idx)); } return rb_struct_aset_id(s, id, val); } i = NUM2LONG(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) { rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)", i, RSTRUCT_LEN(s)); } if (RSTRUCT_LEN(s) <= i) { rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)", i, RSTRUCT_LEN(s)); } rb_struct_modify(s); RSTRUCT_SET(s, i, val); return val; }
static mrb_value mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) { mrb_value members, *ptr; const mrb_value *ptr_members; mrb_int i, len; members = struct_members(mrb, s); len = RARRAY_LEN(members); if (RSTRUCT_LEN(s) != len) { mrb_raisef(mrb, E_TYPE_ERROR, "struct size differs (%S required %S given)", mrb_fixnum_value(len), mrb_fixnum_value(RSTRUCT_LEN(s))); } ptr = RSTRUCT_PTR(s); ptr_members = RARRAY_PTR(members); for (i=0; i<len; i++) { if (mrb_symbol(ptr_members[i]) == id) { ptr[i] = val; return val; } } mrb_name_error(mrb, id, "no member '%S' in struct", mrb_sym2str(mrb, id)); return val; /* not reach */ }
/* :nodoc: */ VALUE rb_struct_init_copy(VALUE copy, VALUE s) { if (!OBJ_INIT_COPY(copy, s)) return copy; if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) { rb_raise(rb_eTypeError, "struct size mismatch"); } MEMCPY(RSTRUCT_PTR(copy), RSTRUCT_PTR(s), VALUE, RSTRUCT_LEN(copy)); return copy; }
VALUE rb_struct_members(VALUE s) { VALUE members = rb_struct_s_members(rb_obj_class(s)); if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)", RARRAY_LEN(members), RSTRUCT_LEN(s)); } return members; }
static VALUE rb_struct_eql(VALUE s, VALUE s2) { if (s == s2) return Qtrue; if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse; if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse; if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { rb_bug("inconsistent struct"); /* should never happen */ } return rb_exec_recursive_paired(recursive_eql, s, s2, s2); }
mrb_value mrb_struct_members(mrb_state *mrb, mrb_value s) { mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s))); if (mrb_type(s) == MRB_TT_STRUCT) { if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { mrb_raise(mrb, E_TYPE_ERROR, "struct size differs (%ld required %ld given)", RARRAY_LEN(members), RSTRUCT_LEN(s)); } } return members; }
mrb_value mrb_struct_members(mrb_state *mrb, mrb_value s) { mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s))); if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) { if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { mrb_raisef(mrb, E_TYPE_ERROR, "struct size differs (%S required %S given)", mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s))); } } return members; }
static mrb_value struct_aref_int(mrb_state *mrb, mrb_value s, mrb_int i) { if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too small for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); if (RSTRUCT_LEN(s) <= i) mrb_raisef(mrb, E_INDEX_ERROR, "offset %S too large for struct(size:%S)", mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); return RSTRUCT_PTR(s)[i]; }
static mrb_value struct_members(mrb_state *mrb, mrb_value s) { mrb_value members = struct_s_members(mrb, mrb_obj_class(mrb, s)); if (!mrb_array_p(s)) { mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct"); } if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { mrb_raisef(mrb, E_TYPE_ERROR, "struct size differs (%S required %S given)", mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s))); } return members; }
/* * code-seq: * struct.eql?(other) -> true or false * * Two structures are equal if they are the same object, or if all their * fields are equal (using <code>eql?</code>). */ static mrb_value mrb_struct_eql(mrb_state *mrb, mrb_value s) { mrb_value s2; mrb_get_args(mrb, "o", &s2); if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value(); if (mrb_type(s2) != MRB_TT_STRUCT) return mrb_false_value(); if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) return mrb_false_value(); if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { mrb_bug("inconsistent struct"); /* should never happen */ } return mrb_exec_recursive_paired(mrb, recursive_eql, s, s2, (void*)0); }
/* :nodoc: */ VALUE rb_struct_init_copy(VALUE copy, VALUE s) { if (copy == s) return copy; rb_check_frozen(copy); if (!rb_obj_is_instance_of(s, rb_obj_class(copy))) { rb_raise(rb_eTypeError, "wrong argument class"); } if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) { rb_raise(rb_eTypeError, "struct size mismatch"); } MEMCPY(RSTRUCT_PTR(copy), RSTRUCT_PTR(s), VALUE, RSTRUCT_LEN(copy)); return copy; }
/* :nodoc: */ static void get_min_max(VALUE segment, VALUE *min, VALUE *max) { VALUE *tmp; switch(TYPE(segment)) { case T_ARRAY: if(RARRAY_LEN(segment) < 2) rb_raise(eMiyakoError, "pairs have illegal array! (above 2 elements)"); tmp = RARRAY_PTR(segment); *min = *tmp++; *max = *tmp; break; case T_STRUCT: if(RSTRUCT_LEN(segment) < 2) rb_raise(eMiyakoError, "pairs have illegal struct! (above 2 attributes)"); tmp = RSTRUCT_PTR(segment); *min = *tmp++; *max = *tmp; break; default: *min = rb_funcall(segment, rb_intern("min"), 0); *max = rb_funcall(segment, rb_intern("max"), 0); break; } }
/* :nodoc: */ VALUE rb_struct_init_copy(VALUE copy, VALUE s) { long i, len; if (!OBJ_INIT_COPY(copy, s)) return copy; if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) { rb_raise(rb_eTypeError, "struct size mismatch"); } for (i=0, len=RSTRUCT_LEN(copy); i<len; i++) { RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i)); } return copy; }
/* :nodoc: */ static void get_position(VALUE pos, Sint16 *x, Sint16 *y) { VALUE *tmp; switch(TYPE(pos)) { case T_ARRAY: if(RARRAY_LEN(pos) < 2) rb_raise(eMiyakoError, "pairs have illegal array!"); tmp = RARRAY_PTR(pos); *x = (Sint16)(NUM2INT(*tmp++)); *y = (Sint16)(NUM2INT(*tmp)); break; case T_STRUCT: if(RSTRUCT_LEN(pos) < 2) rb_raise(eMiyakoError, "pairs have illegal struct!"); tmp = RSTRUCT_PTR(pos); *x = (Sint16)(NUM2INT(*tmp++)); *y = (Sint16)(NUM2INT(*tmp)); break; default: *x = (Sint16)(NUM2INT(rb_funcall(pos, rb_intern("x"), 0))); *y = (Sint16)(NUM2INT(rb_funcall(pos, rb_intern("y"), 0))); break; } }
/* :nodoc: */ static VALUE collision_get_position(VALUE pos, VALUE *x, VALUE *y) { VALUE *tmp; switch(TYPE(pos)) { case T_ARRAY: if(RARRAY_LEN(pos) < 2) rb_raise(eMiyakoError, "pairs have illegal array!"); tmp = RARRAY_PTR(pos); *x = *tmp++; *y = *tmp; break; case T_STRUCT: if(RSTRUCT_LEN(pos) < 2) rb_raise(eMiyakoError, "pairs have illegal struct!"); tmp = RSTRUCT_PTR(pos); *x = *tmp++; *y = *tmp; break; default: *x = rb_funcall(pos, rb_intern("x"), 0); *y = rb_funcall(pos, rb_intern("y"), 0); break; } return Qnil; }
static VALUE rb_struct_eql(VALUE s, SEL sel, VALUE s2) { if (s == s2) { return Qtrue; } if (TYPE(s2) != T_STRUCT) { return Qfalse; } if (rb_obj_class(s) != rb_obj_class(s2)) { return Qfalse; } if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { rb_bug("inconsistent struct"); /* should never happen */ } return rb_exec_recursive(rb_struct_eql_r, s, s2); }
/* :nodoc: */ VALUE rb_struct_init_copy(VALUE copy, SEL sel, VALUE s) { if (copy == s) return copy; rb_check_frozen(copy); if (!rb_obj_is_instance_of(s, rb_obj_class(copy))) { rb_raise(rb_eTypeError, "wrong argument class"); } if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) { rb_raise(rb_eTypeError, "struct size mismatch"); } for (int i = 0; i < RSTRUCT_LEN(copy); i++) { GC_WB(&RSTRUCT_PTR(copy)[i], RSTRUCT_PTR(s)[i]); } return copy; }
/* :nodoc: */ mrb_value mrb_struct_init_copy(mrb_state *mrb, mrb_value copy) { mrb_value s; mrb_get_args(mrb, "o", &s); if (mrb_obj_equal(mrb, copy, s)) return copy; if (!mrb_obj_is_instance_of(mrb, s, mrb_obj_class(mrb, copy))) { mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); } if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) { mrb_raise(mrb, E_TYPE_ERROR, "struct size mismatch"); } memcpy(RSTRUCT_PTR(copy), RSTRUCT_PTR(s), sizeof(mrb_value)*RSTRUCT_LEN(copy)); return copy; }
VALUE rb_struct_aref(VALUE s, VALUE idx) { long i; if (RB_TYPE_P(idx, T_STRING) || RB_TYPE_P(idx, T_SYMBOL)) { return rb_struct_aref_id(s, rb_to_id(idx)); } i = NUM2LONG(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)", i, RSTRUCT_LEN(s)); if (RSTRUCT_LEN(s) <= i) rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)", i, RSTRUCT_LEN(s)); return RSTRUCT_PTR(s)[i]; }
static VALUE rb_struct_aref_imp(VALUE s, SEL sel, VALUE idx) { long i; if (TYPE(idx) == T_STRING || TYPE(idx) == T_SYMBOL) { return rb_struct_aref_id(s, rb_to_id(idx)); } i = NUM2LONG(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)", i, RSTRUCT_LEN(s)); if (RSTRUCT_LEN(s) <= i) rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)", i, RSTRUCT_LEN(s)); return RSTRUCT_PTR(s)[i]; }
/* * call-seq: * struct[symbol] -> anObject * struct[fixnum] -> anObject * * Attribute Reference---Returns the value of the instance variable * named by <i>symbol</i>, or indexed (0..length-1) by * <i>fixnum</i>. Will raise <code>NameError</code> if the named * variable does not exist, or <code>IndexError</code> if the index is * out of range. * * Customer = Struct.new(:name, :address, :zip) * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) * * joe["name"] #=> "Joe Smith" * joe[:name] #=> "Joe Smith" * joe[0] #=> "Joe Smith" */ mrb_value mrb_struct_aref_n(mrb_state *mrb, mrb_value s, mrb_value idx) { long i; if (mrb_type(idx) == MRB_TT_STRING || mrb_type(idx) == MRB_TT_SYMBOL) { return mrb_struct_aref_id(mrb, s, mrb_to_id(mrb, idx)); } i = mrb_fixnum(idx); if (i < 0) i = RSTRUCT_LEN(s) + i; if (i < 0) mrb_raise(mrb, E_INDEX_ERROR, "offset %ld too small for struct(size:%ld)", i, RSTRUCT_LEN(s)); if (RSTRUCT_LEN(s) <= i) mrb_raise(mrb, E_INDEX_ERROR, "offset %ld too large for struct(size:%ld)", i, RSTRUCT_LEN(s)); return RSTRUCT_PTR(s)[i]; }
static mrb_value mrb_struct_values_at(mrb_state *mrb, mrb_value self) { mrb_int argc; mrb_value *argv; mrb_get_args(mrb, "*", &argv, &argc); return mrb_get_values_at(mrb, self, RSTRUCT_LEN(self), argc, argv, struct_aref_int); }