mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* include/ruby/ruby.h: support write barrier protection for T_STRUCT.
Introduce the following C APIs: * RSTRUCT_RAWPTR(st) returns pointer (do WB on your risk). The type of returned pointer is (const VALUE *). * RSTRUCT_GET(st, idx) returns idx-th value of struct. * RSTRUCT_SET(st, idx, v) set idx-th value by v with WB. And * RSTRUCT_PTR(st) returns pointer with shady operation. The type of returned pointer is (VALUE *). * struct.c, re.c, gc.c, marshal.c: rewrite with above APIs. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41534 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c54a1abde3
commit
6a1101f23e
6 changed files with 102 additions and 80 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
Fri Jun 21 20:15:49 2013 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* include/ruby/ruby.h: support write barrier protection for T_STRUCT.
|
||||||
|
Introduce the following C APIs:
|
||||||
|
* RSTRUCT_RAWPTR(st) returns pointer (do WB on your risk).
|
||||||
|
The type of returned pointer is (const VALUE *).
|
||||||
|
* RSTRUCT_GET(st, idx) returns idx-th value of struct.
|
||||||
|
* RSTRUCT_SET(st, idx, v) set idx-th value by v with WB.
|
||||||
|
And
|
||||||
|
* RSTRUCT_PTR(st) returns pointer with shady operation.
|
||||||
|
The type of returned pointer is (VALUE *).
|
||||||
|
|
||||||
|
* struct.c, re.c, gc.c, marshal.c: rewrite with above APIs.
|
||||||
|
|
||||||
Fri Jun 21 19:38:37 2013 Tanaka Akira <akr@fsij.org>
|
Fri Jun 21 19:38:37 2013 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
* bignum.c (BDIGMAX): Use BIGRAD.
|
* bignum.c (BDIGMAX): Use BIGRAD.
|
||||||
|
|
4
gc.c
4
gc.c
|
@ -1283,7 +1283,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
|
||||||
case T_STRUCT:
|
case T_STRUCT:
|
||||||
if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
|
if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
|
||||||
RANY(obj)->as.rstruct.as.heap.ptr) {
|
RANY(obj)->as.rstruct.as.heap.ptr) {
|
||||||
xfree(RANY(obj)->as.rstruct.as.heap.ptr);
|
xfree((void *)RANY(obj)->as.rstruct.as.heap.ptr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3386,7 +3386,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
|
||||||
case T_STRUCT:
|
case T_STRUCT:
|
||||||
{
|
{
|
||||||
long len = RSTRUCT_LEN(obj);
|
long len = RSTRUCT_LEN(obj);
|
||||||
VALUE *ptr = RSTRUCT_PTR(obj);
|
const VALUE *ptr = RSTRUCT_RAWPTR(obj);
|
||||||
|
|
||||||
while (len--) {
|
while (len--) {
|
||||||
gc_mark(objspace, *ptr++);
|
gc_mark(objspace, *ptr++);
|
||||||
|
|
|
@ -709,6 +709,9 @@ VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type);
|
||||||
#ifndef RGENGC_WB_PROTECTED_HASH
|
#ifndef RGENGC_WB_PROTECTED_HASH
|
||||||
#define RGENGC_WB_PROTECTED_HASH 1
|
#define RGENGC_WB_PROTECTED_HASH 1
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef RGENGC_WB_PROTECTED_STRUCT
|
||||||
|
#define RGENGC_WB_PROTECTED_STRUCT 1
|
||||||
|
#endif
|
||||||
#ifndef RGENGC_WB_PROTECTED_STRING
|
#ifndef RGENGC_WB_PROTECTED_STRING
|
||||||
#define RGENGC_WB_PROTECTED_STRING 1
|
#define RGENGC_WB_PROTECTED_STRING 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -1109,9 +1112,9 @@ struct RStruct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
long len;
|
long len;
|
||||||
VALUE *ptr;
|
const VALUE *ptr;
|
||||||
} heap;
|
} heap;
|
||||||
VALUE ary[RSTRUCT_EMBED_LEN_MAX];
|
const VALUE ary[RSTRUCT_EMBED_LEN_MAX];
|
||||||
} as;
|
} as;
|
||||||
};
|
};
|
||||||
#define RSTRUCT_EMBED_LEN_MASK (FL_USER2|FL_USER1)
|
#define RSTRUCT_EMBED_LEN_MASK (FL_USER2|FL_USER1)
|
||||||
|
@ -1121,11 +1124,15 @@ struct RStruct {
|
||||||
(long)((RBASIC(st)->flags >> RSTRUCT_EMBED_LEN_SHIFT) & \
|
(long)((RBASIC(st)->flags >> RSTRUCT_EMBED_LEN_SHIFT) & \
|
||||||
(RSTRUCT_EMBED_LEN_MASK >> RSTRUCT_EMBED_LEN_SHIFT)) : \
|
(RSTRUCT_EMBED_LEN_MASK >> RSTRUCT_EMBED_LEN_SHIFT)) : \
|
||||||
RSTRUCT(st)->as.heap.len)
|
RSTRUCT(st)->as.heap.len)
|
||||||
#define RSTRUCT_PTR(st) \
|
|
||||||
((RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ? \
|
|
||||||
RSTRUCT(st)->as.ary : \
|
|
||||||
RSTRUCT(st)->as.heap.ptr)
|
|
||||||
#define RSTRUCT_LENINT(st) rb_long2int(RSTRUCT_LEN(st))
|
#define RSTRUCT_LENINT(st) rb_long2int(RSTRUCT_LEN(st))
|
||||||
|
#define RSTRUCT_RAWPTR(st) \
|
||||||
|
((RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ? \
|
||||||
|
RSTRUCT(st)->as.ary : \
|
||||||
|
RSTRUCT(st)->as.heap.ptr)
|
||||||
|
#define RSTRUCT_PTR(st) ((VALUE *)RSTRUCT_RAWPTR(RGENGC_WB_PROTECTED_STRUCT ? OBJ_WB_GIVEUP((VALUE)st) : (VALUE)st))
|
||||||
|
|
||||||
|
#define RSTRUCT_SET(st, idx, v) OBJ_WRITE(st, (VALUE *)&RSTRUCT_RAWPTR(st)[idx], v)
|
||||||
|
#define RSTRUCT_GET(st, idx) (RSTRUCT_RAWPTR(st)[idx])
|
||||||
|
|
||||||
#define RBIGNUM_EMBED_LEN_MAX ((int)((sizeof(VALUE)*3)/sizeof(BDIGIT)))
|
#define RBIGNUM_EMBED_LEN_MAX ((int)((sizeof(VALUE)*3)/sizeof(BDIGIT)))
|
||||||
struct RBignum {
|
struct RBignum {
|
||||||
|
|
|
@ -821,7 +821,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
|
||||||
mem = rb_struct_members(obj);
|
mem = rb_struct_members(obj);
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
w_symbol(SYM2ID(RARRAY_AREF(mem, i)), arg);
|
w_symbol(SYM2ID(RARRAY_AREF(mem, i)), arg);
|
||||||
w_object(RSTRUCT_PTR(obj)[i], arg, limit);
|
w_object(RSTRUCT_GET(obj, i), arg, limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
17
range.c
17
range.c
|
@ -27,7 +27,12 @@ static ID id_cmp, id_succ, id_beg, id_end, id_excl, id_integer_p, id_div;
|
||||||
#define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
|
#define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
|
||||||
|
|
||||||
#define EXCL(r) RTEST(RANGE_EXCL(r))
|
#define EXCL(r) RTEST(RANGE_EXCL(r))
|
||||||
#define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse)
|
static inline VALUE
|
||||||
|
SET_EXCL(VALUE r, VALUE v)
|
||||||
|
{
|
||||||
|
RSTRUCT_SET(r, 2, v);
|
||||||
|
return v ? Qtrue : Qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
range_failed(void)
|
range_failed(void)
|
||||||
|
@ -59,8 +64,8 @@ range_init(VALUE range, VALUE beg, VALUE end, int exclude_end)
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_EXCL(range, exclude_end);
|
SET_EXCL(range, exclude_end);
|
||||||
RSTRUCT(range)->as.ary[0] = beg;
|
RSTRUCT_SET(range, 0, beg);
|
||||||
RSTRUCT(range)->as.ary[1] = end;
|
RSTRUCT_SET(range, 1, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
@ -1228,9 +1233,9 @@ range_loader(VALUE range, VALUE obj)
|
||||||
rb_raise(rb_eTypeError, "not a dumped range object");
|
rb_raise(rb_eTypeError, "not a dumped range object");
|
||||||
}
|
}
|
||||||
|
|
||||||
RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
|
RSTRUCT_SET(range, 0, rb_ivar_get(obj, id_beg));
|
||||||
RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
|
RSTRUCT_SET(range, 1, rb_ivar_get(obj, id_end));
|
||||||
RSTRUCT(range)->as.ary[2] = rb_ivar_get(obj, id_excl);
|
RSTRUCT_SET(range, 2, rb_ivar_get(obj, id_excl));
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
126
struct.c
126
struct.c
|
@ -89,17 +89,15 @@ rb_struct_members_m(VALUE obj)
|
||||||
VALUE
|
VALUE
|
||||||
rb_struct_getmember(VALUE obj, ID id)
|
rb_struct_getmember(VALUE obj, ID id)
|
||||||
{
|
{
|
||||||
VALUE members, slot, *ptr, *ptr_members;
|
VALUE members, slot;
|
||||||
long i, len;
|
long i, len;
|
||||||
|
|
||||||
ptr = RSTRUCT_PTR(obj);
|
|
||||||
members = rb_struct_members(obj);
|
members = rb_struct_members(obj);
|
||||||
ptr_members = RARRAY_PTR(members);
|
|
||||||
slot = ID2SYM(id);
|
slot = ID2SYM(id);
|
||||||
len = RARRAY_LEN(members);
|
len = RARRAY_LEN(members);
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
if (ptr_members[i] == slot) {
|
if (RARRAY_AREF(members, i) == slot) {
|
||||||
return ptr[i];
|
return RSTRUCT_GET(obj, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rb_name_error(id, "%s is not struct member", rb_id2name(id));
|
rb_name_error(id, "%s is not struct member", rb_id2name(id));
|
||||||
|
@ -113,16 +111,16 @@ rb_struct_ref(VALUE obj)
|
||||||
return rb_struct_getmember(obj, rb_frame_this_func());
|
return rb_struct_getmember(obj, rb_frame_this_func());
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_PTR(obj)[0];}
|
static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);}
|
||||||
static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_PTR(obj)[1];}
|
static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);}
|
||||||
static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_PTR(obj)[2];}
|
static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);}
|
||||||
static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_PTR(obj)[3];}
|
static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_GET(obj, 3);}
|
||||||
static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_PTR(obj)[4];}
|
static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_GET(obj, 4);}
|
||||||
static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_PTR(obj)[5];}
|
static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_GET(obj, 5);}
|
||||||
static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_PTR(obj)[6];}
|
static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_GET(obj, 6);}
|
||||||
static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_PTR(obj)[7];}
|
static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_GET(obj, 7);}
|
||||||
static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_PTR(obj)[8];}
|
static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_GET(obj, 8);}
|
||||||
static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_PTR(obj)[9];}
|
static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_GET(obj, 9);}
|
||||||
|
|
||||||
#define N_REF_FUNC numberof(ref_func)
|
#define N_REF_FUNC numberof(ref_func)
|
||||||
|
|
||||||
|
@ -149,18 +147,16 @@ rb_struct_modify(VALUE s)
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_struct_set(VALUE obj, VALUE val)
|
rb_struct_set(VALUE obj, VALUE val)
|
||||||
{
|
{
|
||||||
VALUE members, slot, *ptr, *ptr_members;
|
VALUE members, slot;
|
||||||
long i, len;
|
long i, len;
|
||||||
|
|
||||||
members = rb_struct_members(obj);
|
members = rb_struct_members(obj);
|
||||||
ptr_members = RARRAY_PTR(members);
|
|
||||||
len = RARRAY_LEN(members);
|
len = RARRAY_LEN(members);
|
||||||
rb_struct_modify(obj);
|
rb_struct_modify(obj);
|
||||||
ptr = RSTRUCT_PTR(obj);
|
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
slot = ptr_members[i];
|
slot = RARRAY_AREF(members, i);
|
||||||
if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) {
|
if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) {
|
||||||
return ptr[i] = val;
|
return RSTRUCT_SET(obj, i, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
|
rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
|
||||||
|
@ -390,16 +386,18 @@ static VALUE
|
||||||
rb_struct_initialize_m(int argc, VALUE *argv, VALUE self)
|
rb_struct_initialize_m(int argc, VALUE *argv, VALUE self)
|
||||||
{
|
{
|
||||||
VALUE klass = rb_obj_class(self);
|
VALUE klass = rb_obj_class(self);
|
||||||
long n;
|
long i, n;
|
||||||
|
|
||||||
rb_struct_modify(self);
|
rb_struct_modify(self);
|
||||||
n = num_members(klass);
|
n = num_members(klass);
|
||||||
if (n < argc) {
|
if (n < argc) {
|
||||||
rb_raise(rb_eArgError, "struct size differs");
|
rb_raise(rb_eArgError, "struct size differs");
|
||||||
}
|
}
|
||||||
MEMCPY(RSTRUCT_PTR(self), argv, VALUE, argc);
|
for (i=0; i<argc; i++) {
|
||||||
|
RSTRUCT_SET(self, i, argv[i]);
|
||||||
|
}
|
||||||
if (n > argc) {
|
if (n > argc) {
|
||||||
rb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc);
|
rb_mem_clear((VALUE *)RSTRUCT_RAWPTR(self)+argc, n-argc);
|
||||||
}
|
}
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
@ -414,18 +412,18 @@ static VALUE
|
||||||
struct_alloc(VALUE klass)
|
struct_alloc(VALUE klass)
|
||||||
{
|
{
|
||||||
long n;
|
long n;
|
||||||
NEWOBJ_OF(st, struct RStruct, klass, T_STRUCT);
|
NEWOBJ_OF(st, struct RStruct, klass, T_STRUCT | (RGENGC_WB_PROTECTED_STRUCT ? FL_WB_PROTECTED : 0));
|
||||||
|
|
||||||
n = num_members(klass);
|
n = num_members(klass);
|
||||||
|
|
||||||
if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
|
if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
|
||||||
RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
|
RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
|
||||||
RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
|
RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
|
||||||
rb_mem_clear(st->as.ary, n);
|
rb_mem_clear((VALUE *)st->as.ary, n);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
st->as.heap.ptr = ALLOC_N(VALUE, n);
|
st->as.heap.ptr = ALLOC_N(VALUE, n);
|
||||||
rb_mem_clear(st->as.heap.ptr, n);
|
rb_mem_clear((VALUE *)st->as.heap.ptr, n);
|
||||||
st->as.heap.len = n;
|
st->as.heap.len = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +486,7 @@ rb_struct_each(VALUE s)
|
||||||
|
|
||||||
RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
|
RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
|
||||||
for (i=0; i<RSTRUCT_LEN(s); i++) {
|
for (i=0; i<RSTRUCT_LEN(s); i++) {
|
||||||
rb_yield(RSTRUCT_PTR(s)[i]);
|
rb_yield(RSTRUCT_GET(s, i));
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -522,7 +520,7 @@ rb_struct_each_pair(VALUE s)
|
||||||
members = rb_struct_members(s);
|
members = rb_struct_members(s);
|
||||||
for (i=0; i<RSTRUCT_LEN(s); i++) {
|
for (i=0; i<RSTRUCT_LEN(s); i++) {
|
||||||
VALUE key = rb_ary_entry(members, i);
|
VALUE key = rb_ary_entry(members, i);
|
||||||
VALUE value = RSTRUCT_PTR(s)[i];
|
VALUE value = RSTRUCT_GET(s, i);
|
||||||
rb_yield(rb_assoc_new(key, value));
|
rb_yield(rb_assoc_new(key, value));
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
@ -533,7 +531,6 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
|
||||||
{
|
{
|
||||||
VALUE cname = rb_class_name(rb_obj_class(s));
|
VALUE cname = rb_class_name(rb_obj_class(s));
|
||||||
VALUE members, str = rb_str_new2("#<struct ");
|
VALUE members, str = rb_str_new2("#<struct ");
|
||||||
VALUE *ptr, *ptr_members;
|
|
||||||
long i, len;
|
long i, len;
|
||||||
char first = RSTRING_PTR(cname)[0];
|
char first = RSTRING_PTR(cname)[0];
|
||||||
|
|
||||||
|
@ -545,9 +542,8 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
|
||||||
}
|
}
|
||||||
|
|
||||||
members = rb_struct_members(s);
|
members = rb_struct_members(s);
|
||||||
ptr_members = RARRAY_PTR(members);
|
|
||||||
ptr = RSTRUCT_PTR(s);
|
|
||||||
len = RSTRUCT_LEN(s);
|
len = RSTRUCT_LEN(s);
|
||||||
|
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
VALUE slot;
|
VALUE slot;
|
||||||
ID id;
|
ID id;
|
||||||
|
@ -558,7 +554,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
|
||||||
else if (first != '#') {
|
else if (first != '#') {
|
||||||
rb_str_cat2(str, " ");
|
rb_str_cat2(str, " ");
|
||||||
}
|
}
|
||||||
slot = ptr_members[i];
|
slot = RARRAY_AREF(members, i);
|
||||||
id = SYM2ID(slot);
|
id = SYM2ID(slot);
|
||||||
if (rb_is_local_id(id) || rb_is_const_id(id)) {
|
if (rb_is_local_id(id) || rb_is_const_id(id)) {
|
||||||
rb_str_append(str, rb_id2str(id));
|
rb_str_append(str, rb_id2str(id));
|
||||||
|
@ -567,7 +563,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
|
||||||
rb_str_append(str, rb_inspect(slot));
|
rb_str_append(str, rb_inspect(slot));
|
||||||
}
|
}
|
||||||
rb_str_cat2(str, "=");
|
rb_str_cat2(str, "=");
|
||||||
rb_str_append(str, rb_inspect(ptr[i]));
|
rb_str_append(str, rb_inspect(RSTRUCT_GET(s, i)));
|
||||||
}
|
}
|
||||||
rb_str_cat2(str, ">");
|
rb_str_cat2(str, ">");
|
||||||
OBJ_INFECT(str, s);
|
OBJ_INFECT(str, s);
|
||||||
|
@ -604,7 +600,7 @@ rb_struct_inspect(VALUE s)
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_struct_to_a(VALUE s)
|
rb_struct_to_a(VALUE s)
|
||||||
{
|
{
|
||||||
return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_PTR(s));
|
return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_RAWPTR(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -626,7 +622,7 @@ rb_struct_to_h(VALUE s)
|
||||||
long i;
|
long i;
|
||||||
|
|
||||||
for (i=0; i<RSTRUCT_LEN(s); i++) {
|
for (i=0; i<RSTRUCT_LEN(s); i++) {
|
||||||
rb_hash_aset(h, rb_ary_entry(members, i), RSTRUCT_PTR(s)[i]);
|
rb_hash_aset(h, rb_ary_entry(members, i), RSTRUCT_GET(s, i));
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
@ -635,11 +631,16 @@ rb_struct_to_h(VALUE s)
|
||||||
VALUE
|
VALUE
|
||||||
rb_struct_init_copy(VALUE copy, VALUE s)
|
rb_struct_init_copy(VALUE copy, VALUE s)
|
||||||
{
|
{
|
||||||
|
long i, len;
|
||||||
|
|
||||||
if (!OBJ_INIT_COPY(copy, s)) return copy;
|
if (!OBJ_INIT_COPY(copy, s)) return copy;
|
||||||
if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
|
if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
|
||||||
rb_raise(rb_eTypeError, "struct size mismatch");
|
rb_raise(rb_eTypeError, "struct size mismatch");
|
||||||
}
|
}
|
||||||
MEMCPY(RSTRUCT_PTR(copy), RSTRUCT_PTR(s), VALUE, RSTRUCT_LEN(copy));
|
|
||||||
|
for (i=0, len=RSTRUCT_LEN(copy); i<len; i++) {
|
||||||
|
RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i));
|
||||||
|
}
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
@ -647,16 +648,12 @@ rb_struct_init_copy(VALUE copy, VALUE s)
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_struct_aref_id(VALUE s, ID id)
|
rb_struct_aref_id(VALUE s, ID id)
|
||||||
{
|
{
|
||||||
VALUE *ptr, members, *ptr_members;
|
VALUE members = rb_struct_members(s);
|
||||||
long i, len;
|
long i, len = RARRAY_LEN(members);
|
||||||
|
|
||||||
ptr = RSTRUCT_PTR(s);
|
|
||||||
members = rb_struct_members(s);
|
|
||||||
ptr_members = RARRAY_PTR(members);
|
|
||||||
len = RARRAY_LEN(members);
|
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
if (SYM2ID(ptr_members[i]) == id) {
|
if (SYM2ID(RARRAY_AREF(members, i)) == id) {
|
||||||
return ptr[i];
|
return RSTRUCT_GET(s, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
|
rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
|
||||||
|
@ -706,27 +703,24 @@ rb_struct_aref(VALUE s, VALUE idx)
|
||||||
if (RSTRUCT_LEN(s) <= i)
|
if (RSTRUCT_LEN(s) <= i)
|
||||||
rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
|
rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
|
||||||
i, RSTRUCT_LEN(s));
|
i, RSTRUCT_LEN(s));
|
||||||
return RSTRUCT_PTR(s)[i];
|
return RSTRUCT_GET(s, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_struct_aset_id(VALUE s, ID id, VALUE val)
|
rb_struct_aset_id(VALUE s, ID id, VALUE val)
|
||||||
{
|
{
|
||||||
VALUE members, *ptr, *ptr_members;
|
VALUE members = rb_struct_members(s);
|
||||||
long i, len;
|
long i, len = RARRAY_LEN(members);
|
||||||
|
|
||||||
members = rb_struct_members(s);
|
|
||||||
len = RARRAY_LEN(members);
|
|
||||||
rb_struct_modify(s);
|
|
||||||
if (RSTRUCT_LEN(s) != len) {
|
if (RSTRUCT_LEN(s) != len) {
|
||||||
rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
|
rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
|
||||||
len, RSTRUCT_LEN(s));
|
len, RSTRUCT_LEN(s));
|
||||||
}
|
}
|
||||||
ptr = RSTRUCT_PTR(s);
|
|
||||||
ptr_members = RARRAY_PTR(members);
|
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
if (SYM2ID(ptr_members[i]) == id) {
|
if (SYM2ID(RARRAY_AREF(members, i)) == id) {
|
||||||
ptr[i] = val;
|
rb_struct_modify(s);
|
||||||
|
RSTRUCT_SET(s, i, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -782,7 +776,8 @@ rb_struct_aset(VALUE s, VALUE idx, VALUE val)
|
||||||
i, RSTRUCT_LEN(s));
|
i, RSTRUCT_LEN(s));
|
||||||
}
|
}
|
||||||
rb_struct_modify(s);
|
rb_struct_modify(s);
|
||||||
return RSTRUCT_PTR(s)[i] = val;
|
RSTRUCT_SET(s, i, val);
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -835,8 +830,8 @@ rb_struct_select(int argc, VALUE *argv, VALUE s)
|
||||||
RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
|
RETURN_SIZED_ENUMERATOR(s, 0, 0, rb_struct_size);
|
||||||
result = rb_ary_new();
|
result = rb_ary_new();
|
||||||
for (i = 0; i < RSTRUCT_LEN(s); i++) {
|
for (i = 0; i < RSTRUCT_LEN(s); i++) {
|
||||||
if (RTEST(rb_yield(RSTRUCT_PTR(s)[i]))) {
|
if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
|
||||||
rb_ary_push(result, RSTRUCT_PTR(s)[i]);
|
rb_ary_push(result, RSTRUCT_GET(s, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,12 +841,12 @@ rb_struct_select(int argc, VALUE *argv, VALUE s)
|
||||||
static VALUE
|
static VALUE
|
||||||
recursive_equal(VALUE s, VALUE s2, int recur)
|
recursive_equal(VALUE s, VALUE s2, int recur)
|
||||||
{
|
{
|
||||||
VALUE *ptr, *ptr2;
|
const VALUE *ptr, *ptr2;
|
||||||
long i, len;
|
long i, len;
|
||||||
|
|
||||||
if (recur) return Qtrue; /* Subtle! */
|
if (recur) return Qtrue; /* Subtle! */
|
||||||
ptr = RSTRUCT_PTR(s);
|
ptr = RSTRUCT_RAWPTR(s);
|
||||||
ptr2 = RSTRUCT_PTR(s2);
|
ptr2 = RSTRUCT_RAWPTR(s2);
|
||||||
len = RSTRUCT_LEN(s);
|
len = RSTRUCT_LEN(s);
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
if (!rb_equal(ptr[i], ptr2[i])) return Qfalse;
|
if (!rb_equal(ptr[i], ptr2[i])) return Qfalse;
|
||||||
|
@ -892,11 +887,12 @@ recursive_hash(VALUE s, VALUE dummy, int recur)
|
||||||
{
|
{
|
||||||
long i, len;
|
long i, len;
|
||||||
st_index_t h;
|
st_index_t h;
|
||||||
VALUE n, *ptr;
|
VALUE n;
|
||||||
|
const VALUE *ptr;
|
||||||
|
|
||||||
h = rb_hash_start(rb_hash(rb_obj_class(s)));
|
h = rb_hash_start(rb_hash(rb_obj_class(s)));
|
||||||
if (!recur) {
|
if (!recur) {
|
||||||
ptr = RSTRUCT_PTR(s);
|
ptr = RSTRUCT_RAWPTR(s);
|
||||||
len = RSTRUCT_LEN(s);
|
len = RSTRUCT_LEN(s);
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
n = rb_hash(ptr[i]);
|
n = rb_hash(ptr[i]);
|
||||||
|
@ -923,12 +919,12 @@ rb_struct_hash(VALUE s)
|
||||||
static VALUE
|
static VALUE
|
||||||
recursive_eql(VALUE s, VALUE s2, int recur)
|
recursive_eql(VALUE s, VALUE s2, int recur)
|
||||||
{
|
{
|
||||||
VALUE *ptr, *ptr2;
|
const VALUE *ptr, *ptr2;
|
||||||
long i, len;
|
long i, len;
|
||||||
|
|
||||||
if (recur) return Qtrue; /* Subtle! */
|
if (recur) return Qtrue; /* Subtle! */
|
||||||
ptr = RSTRUCT_PTR(s);
|
ptr = RSTRUCT_RAWPTR(s);
|
||||||
ptr2 = RSTRUCT_PTR(s2);
|
ptr2 = RSTRUCT_RAWPTR(s2);
|
||||||
len = RSTRUCT_LEN(s);
|
len = RSTRUCT_LEN(s);
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
if (!rb_eql(ptr[i], ptr2[i])) return Qfalse;
|
if (!rb_eql(ptr[i], ptr2[i])) return Qfalse;
|
||||||
|
|
Loading…
Add table
Reference in a new issue