VALUE rb_struct_members(VALUE s) { VALUE members = rb_struct_s_members(rb_obj_class(s)); if (RSTRUCT(s)->len != RARRAY(members)->len) { rb_raise(rb_eTypeError, "struct size differs (%d required %d given)", RARRAY(members)->len, RSTRUCT(s)->len); } return members; }
static VALUE rb_struct_each(VALUE s) { long i; RETURN_ENUMERATOR(s, 0, 0); for (i=0; i<RSTRUCT(s)->len; i++) { rb_yield(RSTRUCT(s)->ptr[i]); } return s; }
static VALUE range_loader(VALUE range, VALUE obj) { if (TYPE(obj) != T_OBJECT || RBASIC(obj)->klass != rb_cObject) { rb_raise(rb_eTypeError, "not a dumped range object"); } RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg); RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end); RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl); return range; }
static VALUE rb_struct_each_pair(VALUE s) { VALUE members; long i; RETURN_ENUMERATOR(s, 0, 0); members = rb_struct_members(s); for (i=0; i<RSTRUCT(s)->len; i++) { rb_yield_values(2, rb_ary_entry(members, i), RSTRUCT(s)->ptr[i]); } return s; }
static VALUE rb_struct_hash(VALUE s) { long i, h; VALUE n; h = rb_hash(rb_obj_class(s)); for (i = 0; i < RSTRUCT(s)->len; i++) { h = (h << 1) | (h<0 ? 1 : 0); n = rb_hash(RSTRUCT(s)->ptr[i]); h ^= NUM2LONG(n); } return LONG2FIX(h); }
/* :nodoc: */ static 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(copy)->len != RSTRUCT(s)->len) { rb_raise(rb_eTypeError, "struct size mismatch"); } MEMCPY(RSTRUCT(copy)->ptr, RSTRUCT(s)->ptr, VALUE, RSTRUCT(copy)->len); return copy; }
static VALUE rb_struct_eql(VALUE s, VALUE s2) { long i; 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(s)->len != RSTRUCT(s2)->len) { rb_bug("inconsistent struct"); /* should never happen */ } for (i=0; i<RSTRUCT(s)->len; i++) { if (!rb_eql(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return Qfalse; } return Qtrue; }
static VALUE rb_struct_select(int argc, VALUE *argv, VALUE s) { VALUE result; long i; if (argc > 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); } result = rb_ary_new(); for (i = 0; i < RSTRUCT(s)->len; i++) { if (RTEST(rb_yield(RSTRUCT(s)->ptr[i]))) { rb_ary_push(result, RSTRUCT(s)->ptr[i]); } } return result; }
VALUE rb_struct_aref(VALUE s, 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(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); return RSTRUCT(s)->ptr[i]; }
static void range_init(VALUE range, VALUE beg, VALUE end, int exclude_end) { VALUE args[2]; args[0] = beg; args[1] = end; if (!FIXNUM_P(beg) || !FIXNUM_P(end)) { VALUE v; v = rb_rescue(range_check, (VALUE)args, range_failed, 0); if (NIL_P(v)) range_failed(); } SET_EXCL(range, exclude_end); RSTRUCT(range)->as.ary[0] = beg; RSTRUCT(range)->as.ary[1] = end; }
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 int fragment_byteno(VALUE fragment) { VALUE val; Check_Type(fragment, T_STRUCT); if (RBASIC(fragment)->klass != Fragment) { rb_raise(rb_eTypeError, "not fragment"); } val = RSTRUCT(fragment)->ptr[3]; return NUM2INT(val); }
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 fragment_type(VALUE fragment) { VALUE val; Check_Type(fragment, T_STRUCT); if (RBASIC(fragment)->klass != Fragment) { rb_raise(rb_eTypeError, "not fragment"); } val = RSTRUCT(fragment)->ptr[0]; Check_Type(val, T_SYMBOL); return val; }
static VALUE fragment_text(VALUE fragment) { VALUE val; Check_Type(fragment, T_STRUCT); if (RBASIC(fragment)->klass != Fragment) { rb_raise(rb_eTypeError, "not fragment"); } val = RSTRUCT(fragment)->ptr[1]; StringValue(val); return val; }
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 inspect_struct(VALUE s) { const char *cname = rb_class2name(rb_obj_class(s)); VALUE str, members; long i; members = rb_struct_members(s); str = rb_str_buf_new2("#<struct "); rb_str_cat2(str, cname); rb_str_cat2(str, " "); for (i=0; i<RSTRUCT(s)->len; i++) { VALUE slot; ID id; const char *p; if (i > 0) { rb_str_cat2(str, ", "); } slot = RARRAY(members)->ptr[i]; id = SYM2ID(slot); if (rb_is_local_id(id) || rb_is_const_id(id)) { p = rb_id2name(id); rb_str_cat2(str, p); } else { rb_str_append(str, rb_inspect(slot)); } rb_str_cat2(str, "="); rb_str_append(str, rb_inspect(RSTRUCT(s)->ptr[i])); } rb_str_cat2(str, ">"); OBJ_INFECT(str, s); return str; }
static VALUE rb_struct_aref_id(VALUE s, ID id) { VALUE members; long i, len; members = rb_struct_members(s); len = RARRAY(members)->len; for (i=0; i<len; i++) { if (SYM2ID(RARRAY(members)->ptr[i]) == id) { return RSTRUCT(s)->ptr[i]; } } rb_name_error(id, "no member '%s' in struct", rb_id2name(id)); return Qnil; /* not reached */ }
VALUE rb_struct_getmember(VALUE obj, ID id) { VALUE members, slot; long i; members = rb_struct_members(obj); slot = ID2SYM(id); for (i=0; i<RARRAY(members)->len; i++) { if (RARRAY(members)->ptr[i] == slot) { return RSTRUCT(obj)->ptr[i]; } } rb_name_error(id, "%s is not struct member", rb_id2name(id)); return Qnil; /* not reached */ }
static mrb_value mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_value self) { struct RClass *klass = mrb_obj_class(mrb, self); int n; struct RStruct *st; mrb_struct_modify(self); n = num_members(mrb, klass); if (n < argc) { mrb_raise(mrb, E_ARGUMENT_ERROR, "struct size differs"); } st = RSTRUCT(self); st->ptr = (mrb_value *)mrb_calloc(mrb, sizeof(mrb_value), n); st->len = n; memcpy(st->ptr, argv, sizeof(mrb_value)*argc); return self; }
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 mrb_value mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_value self) { struct RClass *klass = mrb_obj_class(mrb, self); long n; struct RStruct *st; mrb_struct_modify(self); n = num_members(mrb, klass); if (n < argc) { mrb_raise(mrb, E_ARGUMENT_ERROR, "struct size differs"); } st = RSTRUCT(self); st->ptr = malloc(sizeof(mrb_value)*argc); st->len = n; memcpy(st->ptr, argv, sizeof(mrb_value)*argc); //if (n > argc) { // mrb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc); //} return self; }
static size_t memsize_of(VALUE obj) { size_t size = 0; if (SPECIAL_CONST_P(obj)) { return 0; } if (FL_TEST(obj, FL_EXIVAR)) { size += rb_generic_ivar_memsize(obj); } switch (BUILTIN_TYPE(obj)) { case T_OBJECT: if (!(RBASIC(obj)->flags & ROBJECT_EMBED) && ROBJECT(obj)->as.heap.ivptr) { size += ROBJECT(obj)->as.heap.numiv * sizeof(VALUE); } break; case T_MODULE: case T_CLASS: size += st_memsize(RCLASS_M_TBL(obj)); if (RCLASS_IV_TBL(obj)) { size += st_memsize(RCLASS_IV_TBL(obj)); } if (RCLASS_IV_INDEX_TBL(obj)) { size += st_memsize(RCLASS_IV_INDEX_TBL(obj)); } if (RCLASS(obj)->ptr->iv_tbl) { size += st_memsize(RCLASS(obj)->ptr->iv_tbl); } if (RCLASS(obj)->ptr->const_tbl) { size += st_memsize(RCLASS(obj)->ptr->const_tbl); } size += sizeof(rb_classext_t); break; case T_STRING: size += rb_str_memsize(obj); break; case T_ARRAY: size += rb_ary_memsize(obj); break; case T_HASH: if (RHASH(obj)->ntbl) { size += st_memsize(RHASH(obj)->ntbl); } break; case T_REGEXP: if (RREGEXP(obj)->ptr) { size += onig_memsize(RREGEXP(obj)->ptr); } break; case T_DATA: size += rb_objspace_data_type_memsize(obj); break; case T_MATCH: if (RMATCH(obj)->rmatch) { struct rmatch *rm = RMATCH(obj)->rmatch; size += sizeof(struct re_registers); /* TODO: onig_region_memsize(&rm->regs); */ size += sizeof(struct rmatch_offset) * rm->char_offset_num_allocated; size += sizeof(struct rmatch); } break; case T_FILE: if (RFILE(obj)->fptr) { size += rb_io_memsize(RFILE(obj)->fptr); } break; case T_RATIONAL: case T_COMPLEX: break; case T_ICLASS: /* iClass shares table with the module */ break; case T_FLOAT: break; case T_BIGNUM: if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) { size += RBIGNUM_LEN(obj) * sizeof(BDIGIT); } break; case T_NODE: switch (nd_type(obj)) { case NODE_SCOPE: if (RNODE(obj)->u1.tbl) { /* TODO: xfree(RANY(obj)->as.node.u1.tbl); */ } break; case NODE_ALLOCA: /* TODO: xfree(RANY(obj)->as.node.u1.node); */ ; } break; /* no need to free iv_tbl */ case T_STRUCT: if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 && RSTRUCT(obj)->as.heap.ptr) { size += sizeof(VALUE) * RSTRUCT_LEN(obj); } break; case T_ZOMBIE: break; default: rb_bug("objspace/memsize_of(): unknown data type 0x%x(%p)", BUILTIN_TYPE(obj), (void*)obj); } return size; }
static VALUE rb_struct_to_a(VALUE s) { return rb_ary_new4(RSTRUCT(s)->len, RSTRUCT(s)->ptr); }
static VALUE rb_struct_size(VALUE s) { return LONG2FIX(RSTRUCT(s)->len); }
static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT(obj)->ptr[9];}
static VALUE rb_struct_values_at(int argc, VALUE *argv, VALUE s) { return rb_values_at(s, RSTRUCT(s)->len, argc, argv, struct_entry); }