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 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; }
static VALUE rb_struct_set(VALUE obj, SEL sel, VALUE val) { VALUE members, slot; long i; // foo=: -> foo char buf[100]; const size_t s = strlcpy(buf, sel_getName(sel), sizeof buf); buf[s - 2] = '\0'; ID field = rb_intern(buf); members = rb_struct_members(obj); rb_struct_modify(obj); for (i=0; i<RARRAY_LEN(members); i++) { slot = RARRAY_AT(members, i); if (SYM2ID(slot) == field) { GC_WB(&RSTRUCT_PTR(obj)[i], val); return val; } } rb_name_error(rb_frame_this_func(), "`%s' is not a struct member", rb_id2name(field)); return Qnil; /* not reached */ }
static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr; ID id; long i, len; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); #if !WITH_OBJC rb_make_metaclass(nstr, RBASIC(klass)->klass); #endif rb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = rb_str_to_str(name); id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", StringValuePtr(name)); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_under(klass, rb_id2name(id), klass); } rb_ivar_set(nstr, id_members, members); rb_objc_define_method(*(VALUE *)nstr, "alloc", struct_alloc, 0); rb_objc_define_method(*(VALUE *)nstr, "new", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "[]", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "members", rb_struct_s_members_m, 0); len = RARRAY_LEN(members); for (i=0; i< len; i++) { ID id = SYM2ID(RARRAY_AT(members, i)); if (rb_is_local_id(id) || rb_is_const_id(id)) { long j = i; /* Needed for block data reference. */ /* Struct attribute reader */ rb_objc_define_method(nstr, rb_id2name(id), pl_imp_implementationWithBlock(^(VALUE obj) { return RSTRUCT_PTR(obj)[j]; }), 0); /* Struct attribute writer */ rb_objc_define_method(nstr, rb_id2name(rb_id_attrset(id)), pl_imp_implementationWithBlock(^(VALUE obj, VALUE val) { VALUE *ptr = RSTRUCT_PTR(obj); rb_struct_modify(obj); GC_WB(&ptr[i], val); return val; }), 1);
static VALUE rb_struct_initialize_m(int argc, VALUE *argv, VALUE self) { VALUE klass = rb_obj_class(self); long n; rb_struct_modify(self); n = num_members(klass); if (n < argc) { rb_raise(rb_eArgError, "struct size differs"); } MEMCPY(RSTRUCT_PTR(self), argv, VALUE, argc); if (n > argc) { rb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc); } return Qnil; }
static VALUE rb_struct_set(VALUE obj, VALUE val) { VALUE members, slot; long i; members = rb_struct_members(obj); rb_struct_modify(obj); for (i=0; i<RARRAY_LEN(members); i++) { slot = RARRAY_PTR(members)[i]; if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) { return RSTRUCT_PTR(obj)[i] = val; } } rb_name_error(rb_frame_this_func(), "`%s' is not a struct member", rb_id2name(rb_frame_this_func())); return Qnil; /* not reached */ }
static VALUE rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self) { VALUE klass = rb_obj_class(self); long i, n; rb_struct_modify(self); n = num_members(klass); if (n < argc) { rb_raise(rb_eArgError, "struct size differs"); } for (i=0; i<argc; i++) { RSTRUCT_SET(self, i, argv[i]); } if (n > argc) { rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self)+argc, n-argc); } return Qnil; }
static VALUE rb_struct_initialize(VALUE self, VALUE values) { VALUE klass = rb_obj_class(self); VALUE size; long n; rb_struct_modify(self); size = rb_struct_iv_get(klass, "__size__"); n = FIX2LONG(size); if (n < RARRAY(values)->len) { rb_raise(rb_eArgError, "struct size differs"); } MEMCPY(RSTRUCT(self)->ptr, RARRAY(values)->ptr, VALUE, RARRAY(values)->len); if (n > RARRAY(values)->len) { rb_mem_clear(RSTRUCT(self)->ptr+RARRAY(values)->len, n-RARRAY(values)->len); } return Qnil; }
static VALUE rb_struct_set(VALUE obj, VALUE val) { VALUE members, slot; ID id; long i; members = rb_struct_members(obj); rb_struct_modify(obj); id = ruby_frame->orig_func; for (i=0; i<RARRAY(members)->len; i++) { slot = RARRAY(members)->ptr[i]; if (rb_id_attrset(SYM2ID(slot)) == id) { return RSTRUCT(obj)->ptr[i] = val; } } rb_name_error(ruby_frame->last_func, "`%s' is not a struct member", rb_id2name(id)); return Qnil; /* not reached */ }
static VALUE rb_struct_aset_id(VALUE s, ID id, VALUE val) { VALUE members; long i, len; members = rb_struct_members(s); rb_struct_modify(s); len = RARRAY_LEN(members); if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)", RARRAY_LEN(members), RSTRUCT_LEN(s)); } for (i=0; i<len; i++) { if (SYM2ID(RARRAY_AT(members, i)) == id) { GC_WB(&RSTRUCT_PTR(s)[i], val); return val; } } rb_name_error(id, "no member '%s' in struct", rb_id2name(id)); }
static VALUE rb_struct_aset_id(VALUE s, ID id, VALUE val) { VALUE members; long i, len; members = rb_struct_members(s); rb_struct_modify(s); len = RARRAY(members)->len; if (RSTRUCT(s)->len != RARRAY(members)->len) { rb_raise(rb_eTypeError, "struct size differs (%d required %d given)", RARRAY(members)->len, RSTRUCT(s)->len); } for (i=0; i<len; i++) { if (SYM2ID(RARRAY(members)->ptr[i]) == id) { RSTRUCT(s)->ptr[i] = val; return val; } } rb_name_error(id, "no member '%s' in struct", rb_id2name(id)); }
static VALUE rb_struct_set(VALUE obj, VALUE val) { VALUE members, slot; long i, len; members = rb_struct_members(obj); len = RARRAY_LEN(members); rb_struct_modify(obj); for (i=0; i<len; i++) { slot = RARRAY_AREF(members, i); if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) { RSTRUCT_SET(obj, i, val); return val; } } rb_name_error(rb_frame_this_func(), "`%s' is not a struct member", rb_id2name(rb_frame_this_func())); UNREACHABLE; }
VALUE rb_struct_aset(VALUE s, VALUE idx, VALUE val) { long i; if (RB_TYPE_P(idx, T_STRING) || RB_TYPE_P(idx, T_SYMBOL)) { return rb_struct_aset_id(s, rb_to_id(idx), 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); return RSTRUCT_PTR(s)[i] = val; }
static VALUE rb_struct_set(VALUE obj, VALUE val) { VALUE members, slot, *ptr, *ptr_members; long i, len; members = rb_struct_members(obj); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); rb_struct_modify(obj); ptr = RSTRUCT_PTR(obj); for (i=0; i<len; i++) { slot = ptr_members[i]; if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) { return ptr[i] = val; } } rb_name_error(rb_frame_this_func(), "`%s' is not a struct member", rb_id2name(rb_frame_this_func())); UNREACHABLE; }
VALUE rb_struct_aset(VALUE s, VALUE idx, VALUE val) { long i; if (TYPE(idx) == T_STRING || TYPE(idx) == T_SYMBOL) { return rb_struct_aset_id(s, rb_to_id(idx), val); } i = NUM2LONG(idx); if (i < 0) i = RSTRUCT(s)->len + i; if (i < 0) { rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)", i, RSTRUCT(s)->len); } if (RSTRUCT(s)->len <= i) { rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)", i, RSTRUCT(s)->len); } rb_struct_modify(s); return RSTRUCT(s)->ptr[i] = val; }
static VALUE rb_struct_aset_id(VALUE s, ID id, VALUE val) { VALUE members = rb_struct_members(s); long i, len = RARRAY_LEN(members); if (RSTRUCT_LEN(s) != len) { rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)", len, RSTRUCT_LEN(s)); } for (i=0; i<len; i++) { if (SYM2ID(RARRAY_AREF(members, i)) == id) { rb_struct_modify(s); RSTRUCT_SET(s, i, val); return val; } } rb_name_error(id, "no member '%s' in struct", rb_id2name(id)); UNREACHABLE; }
VALUE rb_struct_initialize(VALUE self, SEL sel, VALUE values) { VALUE klass = rb_obj_class(self); VALUE size; long n; rb_struct_modify(self); size = rb_struct_iv_get(klass, "__size__"); n = FIX2LONG(size); if (n < RARRAY_LEN(values)) { rb_raise(rb_eArgError, "struct size differs"); } for (int i = 0; i < RARRAY_LEN(values); i++) { GC_WB(&RSTRUCT_PTR(self)[i], RARRAY_AT(values, i)); } if (n > RARRAY_LEN(values)) { for (int i = RARRAY_LEN(values); i < n; i++) { RSTRUCT_PTR(self)[i] = Qnil; } } return Qnil; }
static VALUE rb_struct_aset_imp(VALUE s, SEL sel, VALUE idx, VALUE val) { long i; if (TYPE(idx) == T_STRING || TYPE(idx) == T_SYMBOL) { return rb_struct_aset_id(s, rb_to_id(idx), 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); GC_WB(&RSTRUCT_PTR(s)[i], val); return val; }