diff options
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | eval_method.ci | 13 | ||||
-rw-r--r-- | include/ruby/intern.h | 5 | ||||
-rw-r--r-- | inits.c | 2 | ||||
-rw-r--r-- | marshal.c | 145 | ||||
-rw-r--r-- | range.c | 136 |
6 files changed, 279 insertions, 52 deletions
@@ -1,3 +1,24 @@ +Sat Sep 8 23:55:56 2007 Tanaka Akira <akr@fsij.org> + + * eval_method.ci (rb_get_alloc_func): new function to get allocation + function. + + * include/ruby/intern.h (rb_alloc_func_t): declared. + (rb_define_alloc_func): declared. + (rb_marshal_define_compat): declared. + + * range.c: use T_STRUCT for Range. + + * inits.c: move Init_marshal() prior to Init_Range() because + Init_Range calls rb_marshal_define_compat which needs + marshal's compat_allocator_tbl initialized. + + * marshal.c: support marshal format compatibility layer designed for + marshaling T_STRUCT Range using T_OBJECT format. + (rb_marshal_define_compat): defined. + + [ruby-dev:31710] + Sat Sep 8 10:05:14 2007 Yukihiro Matsumoto <matz@ruby-lang.org> * struct.c (rb_struct_s_members): check if __members__ is an @@ -129,6 +150,8 @@ Sat Sep 1 20:56:07 2007 Tanaka Akira <akr@fsij.org> * .gdbinit: support embedded small bignums. + [ruby-dev:31689] + Sat Sep 1 19:59:43 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp> * ext/win32ole/win32ole.c (ole_event_free): IConnectionPoint should be @@ -241,9 +264,11 @@ Thu Aug 30 08:00:12 2007 Tanaka Akira <akr@fsij.org> * ext/tk/tkutil/tkutil.c: ditto. + [ruby-dev:31678] + Wed Aug 29 18:36:06 2007 Tanaka Akira <akr@fsij.org> - * lib/open-uri.rb: add :ftp_active_mode option. + * lib/open-uri.rb: add :ftp_active_mode option. [ruby-dev:31677] Wed Aug 29 14:55:28 2007 Yukihiro Matsumoto <matz@ruby-lang.org> @@ -271,6 +296,8 @@ Wed Aug 29 11:30:10 2007 Tanaka Akira <akr@fsij.org> (st_foreach): ditto. (st_reverse_foreach): ditto. (unpack_entries): new function for converting to unpacked mode. + + [ruby-list:43954] Wed Aug 29 10:46:37 2007 Yukihiro Matsumoto <matz@ruby-lang.org> @@ -761,6 +788,7 @@ Wed Aug 22 03:51:07 2007 Koichi Sasada <ko1@atdot.net> Tue Aug 21 21:09:48 2007 Tanaka Akira <akr@fsij.org> * lib/tmpdir.rb (Dir.mktmpdir): make directory suffix specifiable. + suggested by knu. [ruby-dev:31568] Tue Aug 21 15:00:23 2007 Koichi Sasada <ko1@atdot.net> diff --git a/eval_method.ci b/eval_method.ci index 5a30596198..08ba953374 100644 --- a/eval_method.ci +++ b/eval_method.ci @@ -192,6 +192,19 @@ rb_undef_alloc_func(VALUE klass) rb_add_method(CLASS_OF(klass), ID_ALLOCATOR, 0, NOEX_UNDEF); } +rb_alloc_func_t +rb_get_alloc_func(VALUE klass) +{ + NODE *n; + Check_Type(klass, T_CLASS); + n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR); + if (!n) return 0; + if (nd_type(n) != NODE_METHOD) return 0; + n = n->nd_body; + if (nd_type(n) != NODE_CFUNC) return 0; + return n->nd_cfnc; +} + static NODE * search_method(VALUE klass, ID id, VALUE *klassp) { diff --git a/include/ruby/intern.h b/include/ruby/intern.h index e3776b8c6b..ecfbe95a8a 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -219,8 +219,10 @@ void rb_remove_method(VALUE, const char*); #define rb_disable_super(klass, name) ((void)0) #define rb_enable_super(klass, name) ((void)0) #define HAVE_RB_DEFINE_ALLOC_FUNC 1 -void rb_define_alloc_func(VALUE, VALUE (*)(VALUE)); +typedef VALUE (*rb_alloc_func_t)(VALUE); +void rb_define_alloc_func(VALUE, rb_alloc_func_t); void rb_undef_alloc_func(VALUE); +rb_alloc_func_t rb_get_alloc_func(VALUE); void rb_clear_cache(void); void rb_clear_cache_by_class(VALUE); void rb_alias(VALUE, ID, ID); @@ -356,6 +358,7 @@ void rb_write_error2(const char*, long); /* marshal.c */ VALUE rb_marshal_dump(VALUE, VALUE); VALUE rb_marshal_load(VALUE); +void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE)); /* numeric.c */ void rb_num_zerodiv(void); VALUE rb_num_coerce_bin(VALUE, VALUE); @@ -76,6 +76,7 @@ rb_call_inits() Init_Struct(); Init_Regexp(); Init_pack(); + Init_marshal(); Init_Range(); Init_IO(); Init_Dir(); @@ -88,7 +89,6 @@ rb_call_inits() Init_Binding(); Init_Math(); Init_GC(); - Init_marshal(); Init_Enumerator(); Init_VM(); Init_ISeq(); @@ -82,12 +82,45 @@ static ID s_dump, s_load, s_mdump, s_mload; static ID s_dump_data, s_load_data, s_alloc; static ID s_getc, s_read, s_write, s_binmode; +typedef struct { + VALUE newclass; + VALUE oldclass; + VALUE (*dumper)(VALUE); + VALUE (*loader)(VALUE, VALUE); +} marshal_compat_t; + +static st_table *compat_allocator_tbl; + +void +rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE)) +{ + marshal_compat_t *compat; + rb_alloc_func_t allocator = rb_get_alloc_func(newclass); + + if (!allocator) { + rb_raise(rb_eTypeError, "no allocator"); + } + + compat = ALLOC(marshal_compat_t); + compat->newclass = Qnil; + compat->oldclass = Qnil; + rb_gc_register_address(&compat->newclass); + rb_gc_register_address(&compat->oldclass); + compat->newclass = newclass; + compat->oldclass = oldclass; + compat->dumper = dumper; + compat->loader = loader; + + st_insert(compat_allocator_tbl, (st_data_t)allocator, (st_data_t)compat); +} + struct dump_arg { VALUE obj; VALUE str, dest; st_table *symbols; st_table *data; int taint; + st_table *compat_tbl; }; struct dump_call_arg { @@ -363,8 +396,13 @@ w_class(char type, VALUE obj, struct dump_arg *arg, int check) { volatile VALUE p; char *path; + VALUE real_obj; + VALUE klass; - VALUE klass = CLASS_OF(obj); + if (st_lookup(arg->compat_tbl, (st_data_t)obj, (st_data_t*)&real_obj)) { + obj = real_obj; + } + klass = CLASS_OF(obj); w_extended(klass, arg, check); w_byte(type, arg); p = class2path(rb_class_real(klass)); @@ -459,6 +497,19 @@ w_object(VALUE obj, struct dump_arg *arg, int limit) if (OBJ_TAINTED(obj)) arg->taint = Qtrue; st_add_direct(arg->data, obj, arg->data->num_entries); + + { + marshal_compat_t *compat; + rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass); + if (st_lookup(compat_allocator_tbl, + (st_data_t)allocator, + (st_data_t*)&compat)) { + VALUE real_obj = obj; + obj = compat->dumper(real_obj); + st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj); + } + } + if (rb_respond_to(obj, s_mdump)) { VALUE v; @@ -720,6 +771,7 @@ marshal_dump(int argc, VALUE *argv) arg.symbols = st_init_numtable(); arg.data = st_init_numtable(); arg.taint = Qfalse; + arg.compat_tbl = st_init_numtable(); c_arg.obj = obj; c_arg.arg = &arg; c_arg.limit = limit; @@ -739,6 +791,7 @@ struct load_arg { VALUE data; VALUE proc; int taint; + st_table *compat_tbl; }; static VALUE r_entry(VALUE v, struct load_arg *arg); @@ -899,14 +952,41 @@ r_string(struct load_arg *arg) static VALUE r_entry(VALUE v, struct load_arg *arg) { - rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v); - if (arg->taint) OBJ_TAINT(v); + VALUE real_obj = Qundef; + if (st_lookup(arg->compat_tbl, v, (st_data_t*)&real_obj)) { + rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), real_obj); + } + else { + rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v); + } + if (arg->taint) { + OBJ_TAINT(v); + if (real_obj != Qundef) + OBJ_TAINT(real_obj); + } if (arg->proc) { v = rb_funcall(arg->proc, rb_intern("call"), 1, v); } return v; } +static VALUE +r_leave(VALUE v, struct load_arg *arg) +{ + VALUE real_obj; + marshal_compat_t *compat; + if (st_lookup(arg->compat_tbl, v, &real_obj)) { + rb_alloc_func_t allocator = rb_get_alloc_func(CLASS_OF(real_obj)); + st_data_t key = v; + if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, (st_data_t*)&compat)) { + compat->loader(real_obj, v); + } + st_delete(arg->compat_tbl, &key, 0); + return real_obj; + } + return v; +} + static void r_ivar(VALUE obj, struct load_arg *arg) { @@ -945,6 +1025,26 @@ path2module(const char *path) } static VALUE +obj_alloc_by_path(const char *path, struct load_arg *arg) +{ + VALUE klass; + marshal_compat_t *compat; + rb_alloc_func_t allocator; + + klass = path2class(path); + + allocator = rb_get_alloc_func(klass); + if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, (st_data_t*)&compat)) { + VALUE real_obj = rb_obj_alloc(klass); + VALUE obj = rb_obj_alloc(compat->oldclass); + st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj); + return obj; + } + + return rb_obj_alloc(klass); +} + +static VALUE r_object0(struct load_arg *arg, int *ivp, VALUE extmod) { VALUE v = Qnil; @@ -1049,6 +1149,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) } v = rb_float_new(d); v = r_entry(v, arg); + v = r_leave(v, arg); } break; @@ -1094,11 +1195,13 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) } v = rb_big_norm((VALUE)big); v = r_entry(v, arg); + v = r_leave(v, arg); } break; case TYPE_STRING: v = r_entry(r_string(arg), arg); + v = r_leave(v, arg); break; case TYPE_REGEXP: @@ -1106,6 +1209,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) volatile VALUE str = r_bytes(arg); int options = r_byte(arg); v = r_entry(rb_reg_new(str, options), arg); + v = r_leave(v, arg); } break; @@ -1118,6 +1222,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) while (len--) { rb_ary_push(v, r_object(arg)); } + v = r_leave(v, arg); } break; @@ -1136,12 +1241,14 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) if (type == TYPE_HASH_DEF) { RHASH(v)->ifnone = r_object(arg); } + v = r_leave(v, arg); } break; case TYPE_STRUCT: { - VALUE klass, mem, values; + VALUE klass, mem; + volatile VALUE values; volatile long i; /* gcc 2.7.2.3 -O2 bug?? */ long len; ID slot; @@ -1150,12 +1257,14 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) mem = rb_struct_s_members(klass); len = r_long(arg); - values = rb_ary_new2(len); - for (i=0; i<len; i++) { - rb_ary_push(values, Qnil); - } - v = rb_struct_alloc(klass, values); + if (RARRAY_LEN(mem) != len) { + rb_raise(rb_eTypeError, "struct %s not compatible (struct size differs)", + rb_class2name(klass)); + } + + v = rb_obj_alloc(klass); v = r_entry(v, arg); + values = rb_ary_new2(len); for (i=0; i<len; i++) { slot = r_symbol(arg); @@ -1165,8 +1274,10 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) rb_id2name(slot), rb_id2name(SYM2ID(RARRAY_PTR(mem)[i]))); } - rb_struct_aset(v, LONG2FIX(i), r_object(arg)); + rb_ary_push(values, r_object(arg)); } + rb_obj_call_init(v, RARRAY_LEN(values), RARRAY_PTR(values)); + v = r_leave(v, arg); } break; @@ -1186,6 +1297,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) } v = rb_funcall(klass, s_load, 1, data); v = r_entry(v, arg); + v = r_leave(v, arg); } break; @@ -1208,19 +1320,19 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) v = r_entry(v, arg); data = r_object(arg); rb_funcall(v, s_mload, 1, data); + v = r_leave(v, arg); } break; case TYPE_OBJECT: { - VALUE klass = path2class(r_unique(arg)); - - v = rb_obj_alloc(klass); + v = obj_alloc_by_path(r_unique(arg), arg); if (TYPE(v) != T_OBJECT) { rb_raise(rb_eArgError, "dump format error"); } v = r_entry(v, arg); r_ivar(v, arg); + v = r_leave(v, arg); } break; @@ -1248,6 +1360,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) rb_class2name(klass)); } rb_funcall(v, s_load_data, 1, r_object0(arg, 0, extmod)); + v = r_leave(v, arg); } break; @@ -1257,6 +1370,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) v = rb_path2class(RSTRING_PTR(str)); v = r_entry(v, arg); + v = r_leave(v, arg); } break; @@ -1266,6 +1380,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) v = path2class(RSTRING_PTR(str)); v = r_entry(v, arg); + v = r_leave(v, arg); } break; @@ -1275,6 +1390,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) v = path2module(RSTRING_PTR(str)); v = r_entry(v, arg); + v = r_leave(v, arg); } break; @@ -1347,6 +1463,7 @@ marshal_load(int argc, VALUE *argv) } arg.src = port; arg.offset = 0; + arg.compat_tbl = st_init_numtable(); major = r_byte(&arg); minor = r_byte(&arg); @@ -1426,6 +1543,8 @@ Init_marshal(void) rb_define_const(rb_mMarshal, "MAJOR_VERSION", INT2FIX(MARSHAL_MAJOR)); rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR)); + + compat_allocator_tbl = st_init_numtable(); } VALUE @@ -15,8 +15,32 @@ VALUE rb_cRange; static ID id_cmp, id_succ, id_beg, id_end, id_excl; -#define EXCL(r) RTEST(rb_ivar_get((r), id_excl)) -#define SET_EXCL(r,v) rb_ivar_set((r), id_excl, (v) ? Qtrue : Qfalse) +#define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0]) +#define RANGE_END(r) (RSTRUCT(r)->as.ary[1]) +#define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2]) + +#define EXCL(r) RTEST(RANGE_EXCL(r)) +#define SET_EXCL(r,v) (RSTRUCT(r)->as.ary[2] = (v) ? Qtrue : Qfalse) + +#define FL_INITIALIZED FL_USER3 + +static VALUE +range_alloc(VALUE klass) +{ + long n; + NEWOBJ(r, struct RStruct); + OBJSETUP(r, klass, T_STRUCT); + + n = 3; + + RBASIC(r)->flags &= ~RSTRUCT_EMBED_LEN_MASK; + RBASIC(r)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT; + rb_mem_clear(r->as.ary, n); + + RBASIC(r)->flags &= ~FL_INITIALIZED; + + return (VALUE)r; +} static VALUE range_failed(void) @@ -48,8 +72,8 @@ range_init(VALUE range, VALUE beg, VALUE end, int exclude_end) } SET_EXCL(range, exclude_end); - rb_ivar_set(range, id_beg, beg); - rb_ivar_set(range, id_end, end); + RSTRUCT(range)->as.ary[0] = beg; + RSTRUCT(range)->as.ary[1] = end; } VALUE @@ -77,9 +101,10 @@ range_initialize(int argc, VALUE *argv, VALUE range) rb_scan_args(argc, argv, "21", &beg, &end, &flags); /* Ranges are immutable, so that they should be initialized only once. */ - if (rb_ivar_defined(range, id_beg)) { + if (RBASIC(range)->flags & FL_INITIALIZED) { rb_name_error(rb_intern("initialize"), "`initialize' called twice"); } + RBASIC(range)->flags |= FL_INITIALIZED; range_init(range, beg, end, RTEST(flags)); return Qnil; } @@ -121,9 +146,9 @@ range_eq(VALUE range, VALUE obj) if (!rb_obj_is_instance_of(obj, rb_obj_class(range))) return Qfalse; - if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg))) + if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj))) return Qfalse; - if (!rb_equal(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end))) + if (!rb_equal(RANGE_END(range), RANGE_END(obj))) return Qfalse; if (EXCL(range) != EXCL(obj)) @@ -183,9 +208,9 @@ range_eql(VALUE range, VALUE obj) if (!rb_obj_is_instance_of(obj, rb_obj_class(range))) return Qfalse; - if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg))) + if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj))) return Qfalse; - if (!rb_eql(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end))) + if (!rb_eql(RANGE_END(range), RANGE_END(obj))) return Qfalse; if (EXCL(range) != EXCL(obj)) @@ -209,9 +234,9 @@ range_hash(VALUE range) long hash = EXCL(range); VALUE v; - v = rb_hash(rb_ivar_get(range, id_beg)); + v = rb_hash(RANGE_BEG(range)); hash ^= v << 1; - v = rb_hash(rb_ivar_get(range, id_end)); + v = rb_hash(RANGE_END(range)); hash ^= v << 9; hash ^= EXCL(range) << 24; @@ -289,8 +314,8 @@ range_step(int argc, VALUE *argv, VALUE range) RETURN_ENUMERATOR(range, argc, argv); - b = rb_ivar_get(range, id_beg); - e = rb_ivar_get(range, id_end); + b = RANGE_BEG(range); + e = RANGE_END(range); if (rb_scan_args(argc, argv, "01", &step) == 0) { step = INT2FIX(1); } @@ -382,8 +407,8 @@ range_each(VALUE range) RETURN_ENUMERATOR(range, 0, 0); - beg = rb_ivar_get(range, id_beg); - end = rb_ivar_get(range, id_end); + beg = RANGE_BEG(range); + end = RANGE_END(range); if (!rb_respond_to(beg, id_succ)) { rb_raise(rb_eTypeError, "can't iterate from %s", @@ -423,7 +448,7 @@ range_each(VALUE range) static VALUE range_first(VALUE range) { - return rb_ivar_get(range, id_beg); + return RANGE_BEG(range); } @@ -442,7 +467,7 @@ range_first(VALUE range) static VALUE range_last(VALUE range) { - return rb_ivar_get(range, id_end); + return RANGE_END(range); } /* @@ -464,8 +489,8 @@ range_min(VALUE range) return rb_call_super(0, 0); } else { - VALUE b = rb_ivar_get(range, id_beg); - VALUE e = rb_ivar_get(range, id_end); + VALUE b = RANGE_BEG(range); + VALUE e = RANGE_END(range); int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e); if (c > 0 || (c == 0 && EXCL(range))) @@ -489,14 +514,14 @@ range_min(VALUE range) static VALUE range_max(VALUE range) { - VALUE e = rb_ivar_get(range, id_end); + VALUE e = RANGE_END(range); int ip = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cInteger); if (rb_block_given_p() || (EXCL(range) && !ip)) { return rb_call_super(0, 0); } else { - VALUE b = rb_ivar_get(range, id_beg); + VALUE b = RANGE_BEG(range); int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e); if (c > 0) @@ -519,8 +544,8 @@ rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err) long beg, end, excl; if (rb_obj_is_kind_of(range, rb_cRange)) { - b = rb_ivar_get(range, id_beg); - e = rb_ivar_get(range, id_end); + b = RANGE_BEG(range); + e = RANGE_END(range); excl = EXCL(range); } else { @@ -578,8 +603,8 @@ range_to_s(VALUE range) { VALUE str, str2; - str = rb_obj_as_string(rb_ivar_get(range, id_beg)); - str2 = rb_obj_as_string(rb_ivar_get(range, id_end)); + str = rb_obj_as_string(RANGE_BEG(range)); + str2 = rb_obj_as_string(RANGE_END(range)); str = rb_str_dup(str); rb_str_cat(str, "...", EXCL(range) ? 3 : 2); rb_str_append(str, str2); @@ -616,8 +641,8 @@ range_inspect(VALUE range) { VALUE str, str2; - str = rb_inspect(rb_ivar_get(range, id_beg)); - str2 = rb_inspect(rb_ivar_get(range, id_end)); + str = rb_inspect(RANGE_BEG(range)); + str2 = rb_inspect(RANGE_END(range)); str = rb_str_dup(str); rb_str_cat(str, "...", EXCL(range) ? 3 : 2); rb_str_append(str, str2); @@ -668,8 +693,8 @@ range_eqq(VALUE range, VALUE val) static VALUE range_include(VALUE range, VALUE val) { - VALUE beg = rb_ivar_get(range, id_beg); - VALUE end = rb_ivar_get(range, id_end); + VALUE beg = RANGE_BEG(range); + VALUE end = RANGE_END(range); int nv = FIXNUM_P(beg) || FIXNUM_P(end) || rb_obj_is_kind_of(beg, rb_cNumeric) || rb_obj_is_kind_of(end, rb_cNumeric); @@ -711,8 +736,8 @@ range_cover(VALUE range, VALUE val) { VALUE beg, end; - beg = rb_ivar_get(range, id_beg); - end = rb_ivar_get(range, id_end); + beg = RANGE_BEG(range); + end = RANGE_END(range); if (r_le(beg, val)) { if (EXCL(range)) { if (r_lt(val, end)) @@ -726,6 +751,33 @@ range_cover(VALUE range, VALUE val) return Qfalse; } +static VALUE +range_dumper(VALUE range) +{ + VALUE v; + NEWOBJ(m, struct RObject); + OBJSETUP(m, rb_cObject, T_OBJECT); + + v = (VALUE)m; + + rb_ivar_set(v, id_excl, EXCL(range) ? Qtrue : Qfalse); + rb_ivar_set(v, id_beg, RANGE_BEG(range)); + rb_ivar_set(v, id_end, RANGE_END(range)); + return v; +} + +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); + SET_EXCL(range, RTEST(rb_ivar_get(obj, id_excl))); + return range; +} /* A <code>Range</code> represents an interval---a set of values with a * start and an end. Ranges may be constructed using the @@ -782,8 +834,25 @@ range_cover(VALUE range, VALUE val) void Init_Range(void) { + VALUE members; + + id_cmp = rb_intern("<=>"); + id_succ = rb_intern("succ"); + id_beg = rb_intern("begin"); + id_end = rb_intern("end"); + id_excl = rb_intern("excl"); + rb_cRange = rb_define_class("Range", rb_cObject); + + /* compatibility for rb_struct_members, etc. */ + members = rb_ary_new3(3, ID2SYM(id_beg), ID2SYM(id_end), ID2SYM(id_excl)); + OBJ_FREEZE(members); + rb_iv_set(rb_cRange, "__size__", INT2FIX(3)); + rb_iv_set(rb_cRange, "__members__", members); + + rb_define_alloc_func(rb_cRange, range_alloc); rb_include_module(rb_cRange, rb_mEnumerable); + rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper, range_loader); rb_define_method(rb_cRange, "initialize", range_initialize, -1); rb_define_method(rb_cRange, "==", range_eq, 1); rb_define_method(rb_cRange, "===", range_eqq, 1); @@ -807,9 +876,4 @@ Init_Range(void) rb_define_method(rb_cRange, "include?", range_include, 1); rb_define_method(rb_cRange, "cover?", range_cover, 1); - id_cmp = rb_intern("<=>"); - id_succ = rb_intern("succ"); - id_beg = rb_intern("begin"); - id_end = rb_intern("end"); - id_excl = rb_intern("excl"); } |