diff options
Diffstat (limited to 'ext/marshal/marshal.c')
-rw-r--r-- | ext/marshal/marshal.c | 702 |
1 files changed, 385 insertions, 317 deletions
diff --git a/ext/marshal/marshal.c b/ext/marshal/marshal.c index eae8d7fe09..47cb0fcd2a 100644 --- a/ext/marshal/marshal.c +++ b/ext/marshal/marshal.c @@ -13,131 +13,167 @@ #include "io.h" #include "st.h" -#define MARSHAL_MAJOR 2 -#define MARSHAL_MINOR 1 +#define MARSHAL_MAJOR 4 +#define MARSHAL_MINOR 0 #define TYPE_NIL '0' #define TYPE_TRUE 'T' #define TYPE_FALSE 'F' #define TYPE_FIXNUM 'i' +#define TYPE_UCLASS 'C' #define TYPE_OBJECT 'o' #define TYPE_USERDEF 'u' #define TYPE_FLOAT 'f' #define TYPE_BIGNUM 'l' #define TYPE_STRING '"' -#define TYPE_STRING2 '\'' #define TYPE_REGEXP '/' #define TYPE_ARRAY '[' -#define TYPE_ARRAY2 ']' #define TYPE_HASH '{' -#define TYPE_HASH2 '}' #define TYPE_STRUCT 'S' +#define TYPE_MODULE 'M' #define TYPE_SYMBOL ':' #define TYPE_SYMLINK ';' -VALUE cString; -VALUE cArray; -VALUE cHash; +#define TYPE_LINK '@' + +extern VALUE cString; +extern VALUE cRegexp; +extern VALUE cArray; +extern VALUE cHash; -char *rb_class2path(); VALUE rb_path2class(); static ID s_dump, s_load; -#if (defined(linux) && defined(USE_DLN_A_OUT)) || !defined(HAVE_TMPNAM) -#define tmpnam(s) ltmpnam(s) -static char * -tmpnam(s) - char *s; -{ - static int n = 0; +struct dump_arg { + VALUE obj; + FILE *fp; + struct RString *str; + st_table *symbol; + st_table *data; +}; + +struct dump_call_arg { + VALUE obj; + struct dump_arg *arg; + int limit; +}; + +static void w_long _((long, struct dump_arg*)); - sprintf(s, "/tmp/rb-mrsr-%x%x", getpid(), n++); - return s; +static void +w_byte(c, arg) + char c; + struct dump_arg *arg; +{ + if (arg->fp) putc(c, arg->fp); + else str_cat(arg->str, &c, 1); } -#endif -#define w_byte(c, fp) putc((c), fp) -#define w_bytes(s, n, fp) (w_long((n), fp),fwrite(s, 1, n, fp)) +static void +w_bytes(s, n, arg) + char *s; + int n; + struct dump_arg *arg; +{ + w_long(n, arg); + if (arg->fp) { + fwrite(s, 1, n, arg->fp); + } + else { + str_cat(arg->str, s, n); + } +} static void -w_short(x, fp) +w_short(x, arg) int x; - FILE *fp; + struct dump_arg *arg; { - w_byte( x & 0xff, fp); - w_byte((x>> 8) & 0xff, fp); + w_byte( x & 0xff, arg); + w_byte((x>> 8) & 0xff, arg); } static void -w_long(x, fp) +w_long(x, arg) long x; - FILE *fp; + struct dump_arg *arg; { - w_byte((int)( x & 0xff), fp); - w_byte((int)((x>> 8) & 0xff), fp); - w_byte((int)((x>>16) & 0xff), fp); - w_byte((int)((x>>24) & 0xff), fp); + char buf[sizeof(long)+1]; + int i, len = 0; + + if (x == 0) { + w_byte(0, arg); + return; + } + for (i=1;i<sizeof(long)+1;i++) { + buf[i] = x & 0xff; + x = RSHIFT(x,8); + if (x == 0) { + buf[0] = i; + break; + } + if (x == -1) { + buf[0] = -i; + break; + } + } + len = i; + for (i=0;i<=len;i++) { + w_byte(buf[i], arg); + } } static void -w_float(d, fp) +w_float(d, arg) double d; - FILE *fp; + struct dump_arg *arg; { char buf[100]; sprintf(buf, "%.12g", d); - w_bytes(buf, strlen(buf), fp); + w_bytes(buf, strlen(buf), arg); } static void -w_symbol(id, fp, table) +w_symbol(id, arg) ID id; - FILE *fp; - st_table *table; + struct dump_arg *arg; { char *sym = rb_id2name(id); int num; - if (st_lookup(table, id, &num)) { - w_byte(TYPE_SYMLINK, fp); - w_long(num, fp); + if (st_lookup(arg->symbol, id, &num)) { + w_byte(TYPE_SYMLINK, arg); + w_long(num, arg); } else { - w_byte(TYPE_SYMBOL, fp); - w_bytes(sym, strlen(sym), fp); - st_insert(table, id, table->num_entries); + w_byte(TYPE_SYMBOL, arg); + w_bytes(sym, strlen(sym), arg); + st_insert(arg->symbol, id, arg->symbol->num_entries); } } static void -w_unique(s, fp, table) +w_unique(s, arg) char *s; - FILE *fp; - st_table *table; + struct dump_arg *arg; { - w_symbol(rb_intern(s), fp, table); + w_symbol(rb_intern(s), arg); } -static void w_object(); -extern VALUE cBignum, cStruct; - -struct each_arg { - FILE *fp; - VALUE limit; - st_table *table; -}; +static void w_object _((VALUE,struct dump_arg*,int)); +extern VALUE cIO, cBignum, cStruct; static int hash_each(key, value, arg) VALUE key, value; - struct each_arg *arg; + struct dump_call_arg *arg; { - w_object(key, arg->fp, arg->limit, arg->table); - w_object(value, arg->fp, arg->limit, arg->table); + w_object(key, arg->arg, arg->limit); + w_object(value, arg->arg, arg->limit); return ST_CONTINUE; } @@ -145,154 +181,166 @@ static int obj_each(id, value, arg) ID id; VALUE value; - struct each_arg *arg; + struct dump_call_arg *arg; { - w_symbol(id, arg->fp, arg->table); - w_object(value, arg->fp, arg->limit, arg->table); + w_symbol(id, arg->arg); + w_object(value, arg->arg, arg->limit); return ST_CONTINUE; } static void -w_object(obj, fp, limit, table) +w_uclass(obj, class, arg) + VALUE obj, class; + struct dump_arg *arg; +{ + if (CLASS_OF(obj) != class) { + w_byte(TYPE_UCLASS, arg); + w_unique(rb_class2name(CLASS_OF(obj)), arg); + } +} + +static void +w_object(obj, arg, limit) VALUE obj; - FILE *fp; + struct dump_arg *arg; int limit; - st_table *table; { - struct each_arg arg; int n; + struct dump_call_arg c_arg; if (limit == 0) { Fail("exceed depth limit"); } limit--; - - arg.fp = fp; - arg.limit = limit; - arg.table = table; + c_arg.limit = limit; + c_arg.arg = arg; if (obj == Qnil) { - w_byte(TYPE_NIL, fp); + w_byte(TYPE_NIL, arg); } else if (obj == TRUE) { - w_byte(TYPE_TRUE, fp); + w_byte(TYPE_TRUE, arg); } else if (obj == FALSE) { - w_byte(TYPE_FALSE, fp); + w_byte(TYPE_FALSE, arg); } else if (FIXNUM_P(obj)) { if (sizeof(long) == 4) { - w_byte(TYPE_FIXNUM, fp); - w_long(FIX2INT(obj), fp); + w_byte(TYPE_FIXNUM, arg); + w_long(FIX2INT(obj), arg); } } else { + int num; + + if (st_lookup(arg->data, obj, &num)) { + w_byte(TYPE_LINK, arg); + w_long(num, arg); + return; + } + st_insert(arg->data, obj, arg->data->num_entries); if (rb_respond_to(obj, s_dump)) { VALUE v; - w_byte(TYPE_USERDEF, fp); - w_unique(rb_class2path(CLASS_OF(obj)), fp, table); + w_byte(TYPE_USERDEF, arg); + w_unique(rb_class2name(CLASS_OF(obj)), arg); v = rb_funcall(obj, s_dump, 1, limit); if (TYPE(v) != T_STRING) { TypeError("_dump_to must return String"); } - w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, fp); + w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg); return; } + switch (BUILTIN_TYPE(obj)) { + case T_MODULE: + case T_CLASS: + w_byte(TYPE_MODULE, arg); + { + VALUE path = rb_class_path(obj); + w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg); + } + return; + case T_FLOAT: - w_byte(TYPE_FLOAT, fp); - w_float(RFLOAT(obj)->value, fp); + w_byte(TYPE_FLOAT, arg); + w_float(RFLOAT(obj)->value, arg); return; case T_BIGNUM: - w_byte(TYPE_BIGNUM, fp); + w_byte(TYPE_BIGNUM, arg); { char sign = RBIGNUM(obj)->sign?'+':'-'; int len = RBIGNUM(obj)->len; USHORT *d = RBIGNUM(obj)->digits; - w_byte(sign, fp); - w_long(len, fp); + w_byte(sign, arg); + w_long(len, arg); while (len--) { - w_short(d, fp); + w_short(*d, arg); d++; } } return; - } - switch (BUILTIN_TYPE(obj)) { case T_STRING: - if (CLASS_OF(obj) == cString) { - w_byte(TYPE_STRING, fp); - w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp); - } - else { - w_byte(TYPE_STRING2, fp); - w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp); - w_unique(rb_class2path(CLASS_OF(obj)), fp, table); - } + w_uclass(obj, cString, arg); + w_byte(TYPE_STRING, arg); + w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, arg); return; case T_REGEXP: - w_byte(TYPE_REGEXP, fp); - w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, fp); - w_byte(FL_TEST(obj, FL_USER1), fp); + w_uclass(obj, cRegexp, arg); + w_byte(TYPE_REGEXP, arg); + w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, arg); + w_byte(FL_TEST(obj, FL_USER1), arg); return; case T_ARRAY: - if (CLASS_OF(obj) == cArray) w_byte(TYPE_ARRAY, fp); - else w_byte(TYPE_ARRAY2, fp); + w_uclass(obj, cArray, arg); + w_byte(TYPE_ARRAY, arg); { int len = RARRAY(obj)->len; VALUE *ptr = RARRAY(obj)->ptr; - w_long(len, fp); + w_long(len, arg); while (len--) { - w_object(*ptr, fp, limit, table); + w_object(*ptr, arg, limit); ptr++; } } - if (CLASS_OF(obj) != cArray) { - w_unique(rb_class2path(CLASS_OF(obj)), fp, table); - } break; case T_HASH: - if (CLASS_OF(obj) == cHash) w_byte(TYPE_HASH, fp); - else w_byte(TYPE_HASH2, fp); - w_byte(TYPE_HASH, fp); - w_long(RHASH(obj)->tbl->num_entries, fp); - st_foreach(RHASH(obj)->tbl, hash_each, &arg); - if (CLASS_OF(obj) != cHash) { - w_unique(rb_class2path(CLASS_OF(obj)), fp, table); - } + w_uclass(obj, cHash, arg); + w_byte(TYPE_HASH, arg); + w_long(RHASH(obj)->tbl->num_entries, arg); + st_foreach(RHASH(obj)->tbl, hash_each, &c_arg); break; case T_STRUCT: - w_byte(TYPE_STRUCT, fp); + w_byte(TYPE_STRUCT, arg); { int len = RSTRUCT(obj)->len; - char *path = rb_class2path(CLASS_OF(obj)); + char *path = rb_class2name(CLASS_OF(obj)); VALUE mem; int i; - w_unique(path, fp, table); - w_long(len, fp); + w_unique(path, arg); + w_long(len, arg); mem = rb_ivar_get(CLASS_OF(obj), rb_intern("__member__")); if (mem == Qnil) { Fatal("non-initialized struct"); } for (i=0; i<len; i++) { - w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), fp, table); - w_object(RSTRUCT(obj)->ptr[i], fp, limit, table); + w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), arg); + w_object(RSTRUCT(obj)->ptr[i], arg, limit); } } break; case T_OBJECT: - w_byte(TYPE_OBJECT, fp); + w_byte(TYPE_OBJECT, arg); { VALUE class = CLASS_OF(obj); char *path; @@ -300,14 +348,14 @@ w_object(obj, fp, limit, table) if (FL_TEST(class, FL_SINGLETON)) { TypeError("singleton can't be dumped"); } - path = rb_class2path(class); - w_unique(path, fp, table); + path = rb_class2name(class); + w_unique(path, arg); if (ROBJECT(obj)->iv_tbl) { - w_long(ROBJECT(obj)->iv_tbl->num_entries, fp); - st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &arg); + w_long(ROBJECT(obj)->iv_tbl->num_entries, arg); + st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &c_arg); } else { - w_long(0, fp); + w_long(0, arg); } } break; @@ -319,146 +367,157 @@ w_object(obj, fp, limit, table) } } -struct dump_arg { - VALUE obj; - FILE *fp; - int limit; - st_table *table; -}; - static VALUE dump(arg) - struct dump_arg *arg; + struct dump_call_arg *arg; { - w_object(arg->obj, arg->fp, arg->limit, arg->table); + w_object(arg->obj, arg->arg, arg->limit); } static VALUE dump_ensure(arg) struct dump_arg *arg; { - st_free_table(arg->table); + st_free_table(arg->symbol); + st_free_table(arg->data); } static VALUE -dump_on(obj, port, limit) - VALUE obj, port; - int limit; +marshal_dump(argc, argv) + int argc; + VALUE argv; { + VALUE obj, port, a1, a2; + int limit = -1; extern VALUE cIO; - FILE *fp; - OpenFile *fptr; struct dump_arg arg; + struct dump_call_arg c_arg; - if (obj_is_kind_of(port, cIO)) { - GetOpenFile(port, fptr); - io_writable(fptr); - fp = (fptr->f2) ? fptr->f2 : fptr->f; + port = 0; + rb_scan_args(argc, argv, "12", &obj, &a1, &a2); + if (argc == 3) { + limit = NUM2INT(a2); + port = a1; + } + else if (argc == 2) { + if (FIXNUM_P(a1)) limit = FIX2INT(a1); + else port = a1; + } + if (port) { + if (obj_is_kind_of(port, cIO)) { + OpenFile *fptr; + + io_binmode(port); + GetOpenFile(port, fptr); + io_writable(fptr); + arg.fp = (fptr->f2) ? fptr->f2 : fptr->f; + } + else { + TypeError("instance of IO needed"); + } } else { - TypeError("instance of IO needed"); + arg.fp = 0; + port = str_new(0, 0); + arg.str = RSTRING(port); } - w_byte(MARSHAL_MAJOR, fp); - w_byte(MARSHAL_MINOR, fp); - - arg.obj = obj; - arg.fp = fp; - arg.limit = limit; - arg.table = st_init_numtable(); - rb_ensure(dump, &arg, dump_ensure, &arg); - - return Qnil; -} + arg.symbol = st_init_numtable(); + arg.data = st_init_numtable(); + c_arg.obj = obj; + c_arg.arg = &arg; + c_arg.limit = limit; -static VALUE -marshal_dump(argc, argv) - int argc; - VALUE argv; -{ - VALUE obj, port, lim; - int limit; + w_byte(MARSHAL_MAJOR, &arg); + w_byte(MARSHAL_MINOR, &arg); - rb_scan_args(argc, argv, "21", &obj, &port, &lim); - if (NIL_P(lim)) limit = 100; - else limit = NUM2INT(lim); + rb_ensure(dump, &c_arg, dump_ensure, &arg); - dump_on(obj, port, limit); + return port; } -static VALUE -marshal_dumps(argc, argv) - int argc; - VALUE argv; -{ - VALUE obj, lim; - int limit; - VALUE str = str_new(0, 0); - VALUE port; - FILE *fp = 0; - char buf[BUFSIZ]; - int n; - - rb_scan_args(argc, argv, "11", &obj, &lim); - if (NIL_P(lim)) limit = 100; - else limit = NUM2INT(lim); - - tmpnam(buf); - port = file_open(buf, "w"); - fp = rb_fopen(buf, "r"); -#if !defined(MSDOS) && !defined(__BOW__) - unlink(buf); -#endif - - dump_on(obj, port, limit); - io_close(port); -#if defined(MSDOS) || defined(__BOW__) - unlink(buf); -#endif - - while (n = fread(buf, 1, BUFSIZ, fp)) { - str_cat(str, buf, n); - } +struct load_arg { + FILE *fp; + UCHAR *ptr, *end; + st_table *symbol; + st_table *data; +}; - return str; +static int +r_byte(arg) + struct load_arg *arg; +{ + if (arg->fp) return getc(arg->fp); + if (arg->ptr < arg->end) return *arg->ptr++; + return EOF; } -#define r_byte(fp) getc(fp) - static int -r_short(fp) - FILE *fp; +r_short(arg) + struct load_arg *arg; { register short x; - x = r_byte(fp); - x |= r_byte(fp) << 8; + x = r_byte(arg); + x |= r_byte(arg) << 8; /* XXX If your short is > 16 bits, add sign-extension here!!! */ return x; } +static void +long_toobig(size) + int size; +{ + TypeError("long too big for this architecture (size %d, given %d)", + sizeof(long), size); +} + static long -r_long(fp) - FILE *fp; +r_long(arg) + struct load_arg *arg; { + char c = r_byte(arg), i; register long x; - x = r_byte(fp); - x |= (long)r_byte(fp) << 8; - x |= (long)r_byte(fp) << 16; - x |= (long)r_byte(fp) << 24; - /* XXX If your long is > 32 bits, add sign-extension here!!! */ + + if (c == 0) return 0; + if (c > 0) { + if (c > sizeof(long)) long_toobig((int)c); + x = 0; + for (i=0;i<c;i++) { + x |= (long)r_byte(arg) << (8*i); + } + } + else if (c < 0) { + c = -c; + if (c > sizeof(long)) long_toobig((int)c); + x = -1; + for (i=0;i<c;i++) { + x &= ~(0xff << (8*i)); + x |= (long)r_byte(arg) << (8*i); + } + } return x; } -#define r_bytes(s, fp) \ - (s = (char*)r_long(fp), r_bytes0(&s,ALLOCA_N(char,(int)s),(int)s,fp)) +#define r_bytes(s, arg) \ + (s = (char*)r_long(arg), r_bytes0(&s,ALLOCA_N(char,(int)s),(int)s,arg)) -static char -r_bytes0(sp, s, len, fp) +static int +r_bytes0(sp, s, len, arg) char **sp, *s; int len; - FILE *fp; + struct load_arg *arg; { - fread(s, 1, len, fp); + if (arg->fp) { + len = fread(s, 1, len, arg->fp); + } + else { + if (arg->ptr + len > arg->end) { + len = arg->end - arg->ptr; + } + memcpy(s, arg->ptr, len); + arg->ptr += len; + } + (s)[len] = '\0'; *sp = s; @@ -466,63 +525,84 @@ r_bytes0(sp, s, len, fp) } static ID -r_symbol(fp, table) - FILE *fp; - st_table *table; +r_symbol(arg) + struct load_arg *arg; { char *buf; ID id; char type; - if (r_byte(fp) == TYPE_SYMLINK) { - int num = r_long(fp); + if (r_byte(arg) == TYPE_SYMLINK) { + int num = r_long(arg); - if (st_lookup(table, num, &id)) { + if (st_lookup(arg->symbol, num, &id)) { return id; } TypeError("bad symbol"); } - r_bytes(buf, fp); + r_bytes(buf, arg); id = rb_intern(buf); - st_insert(table, table->num_entries, id); + st_insert(arg->symbol, arg->symbol->num_entries, id); return id; } static char* -r_unique(fp, table) - FILE *fp; - st_table *table; +r_unique(arg) + struct load_arg *arg; { - return rb_id2name(r_symbol(fp, table)); + return rb_id2name(r_symbol(arg)); } static VALUE -r_string(fp) - FILE *fp; +r_string(arg) + struct load_arg *arg; { char *buf; - int len = r_bytes(buf, fp); - VALUE v; + int len = r_bytes(buf, arg); - v = str_new(buf, len); + return str_taint(str_new(buf, len)); +} +static VALUE +r_regist(v, arg) + VALUE v; + struct load_arg *arg; +{ + st_insert(arg->data, arg->data->num_entries, v); return v; } static VALUE -r_object(fp, table) - FILE *fp; - st_table *table; +r_object(arg) + struct load_arg *arg; { VALUE v; - int type = r_byte(fp); + int type = r_byte(arg); switch (type) { case EOF: eof_error("EOF read where object expected"); return Qnil; + case TYPE_LINK: + if (st_lookup(arg->data, r_long(arg), &v)) { + return v; + } + ArgError("dump format error (unlinked)"); + break; + + case TYPE_UCLASS: + { + VALUE c = rb_path2class(r_unique(arg)); + v = r_object(arg); + if (rb_special_const_p(v)) { + ArgError("dump format error (user class)"); + } + RBASIC(v)->class = c; + return v; + } + case TYPE_NIL: return Qnil; @@ -534,7 +614,7 @@ r_object(fp, table) case TYPE_FIXNUM: { - int i = r_long(fp); + int i = r_long(arg); return INT2FIX(i); } @@ -543,9 +623,9 @@ r_object(fp, table) double atof(); char *buf; - r_bytes(buf, fp); + r_bytes(buf, arg); v = float_new(atof(buf)); - return v; + return r_regist(v, arg); } case TYPE_BIGNUM: @@ -555,50 +635,46 @@ r_object(fp, table) NEWOBJ(big, struct RBignum); OBJSETUP(big, cBignum, T_BIGNUM); - big->sign = (r_byte(fp) == '+'); - big->len = len = r_long(fp); + big->sign = (r_byte(arg) == '+'); + big->len = len = r_long(arg); big->digits = digits = ALLOC_N(USHORT, len); while (len--) { - *digits++ = r_short(fp); + *digits++ = r_short(arg); } - return (VALUE)big; + return r_regist(big, arg); } case TYPE_STRING: - return r_string(fp); - - case TYPE_STRING2: - v = r_string(fp); - RBASIC(v)->class = rb_path2class(r_unique(fp, table)); - return v; + return r_regist(r_string(arg), arg); case TYPE_REGEXP: { char *buf; - int len = r_bytes(buf, fp); - int ci = r_byte(fp); - v = reg_new(buf, len, ci); - return v; + int len = r_bytes(buf, arg); + int ci = r_byte(arg); + return r_regist(reg_new(buf, len, ci), arg); } case TYPE_ARRAY: { - int len = r_long(fp); + volatile int len = r_long(arg); v = ary_new2(len); + r_regist(v, arg); while (len--) { - ary_push(v, r_object(fp, table)); + ary_push(v, r_object(arg)); } return v; } case TYPE_HASH: { - int len = r_long(fp); + int len = r_long(arg); v = hash_new(); + r_regist(v, arg); while (len--) { - VALUE key = r_object(fp, table); - VALUE value = r_object(fp, table); + VALUE key = r_object(arg); + VALUE value = r_object(arg); hash_aset(v, key, value); } return v; @@ -608,23 +684,27 @@ r_object(fp, table) { VALUE class, mem, values; int i, len; + int num = arg->data->num_entries; - class = rb_path2class(r_unique(fp, table)); + st_insert(arg->data, num, 15); /* temp reg. */ + class = rb_path2class(r_unique(arg)); mem = rb_ivar_get(class, rb_intern("__member__")); if (mem == Qnil) { Fatal("non-initialized struct"); } - len = r_long(fp); + len = r_long(arg); values = ary_new2(len); i = 0; for (i=0; i<len; i++) { - ID slot = r_symbol(fp, table); + ID slot = r_symbol(arg); if (RARRAY(mem)->ptr[i] != INT2FIX(slot)) TypeError("struct not compatible"); - ary_push(values, r_object(fp, table)); + ary_push(values, r_object(arg)); } v = struct_alloc(class, values); + st_insert(arg->data, num, v); /* re-regist */ + return v; } break; @@ -633,112 +713,101 @@ r_object(fp, table) VALUE class; int len; - class = rb_path2class(r_unique(fp, table)); + class = rb_path2class(r_unique(arg)); if (rb_respond_to(class, s_load)) { - v = rb_funcall(class, s_load, 1, r_string(fp)); - } - else { - TypeError("class %s needs to have method `_load_from'", - rb_class2name(class)); + v = rb_funcall(class, s_load, 1, r_string(arg)); + return r_regist(v, arg); } + TypeError("class %s needs to have method `_load_from'", + rb_class2name(class)); } break; + case TYPE_OBJECT: { VALUE class; int len; - class = rb_path2class(r_unique(fp, table)); - len = r_long(fp); + class = rb_path2class(r_unique(arg)); + len = r_long(arg); v = obj_alloc(class); + r_regist(v, arg); if (len > 0) { while (len--) { - ID id = r_symbol(fp, table); - VALUE val = r_object(fp, table); + ID id = r_symbol(arg); + VALUE val = r_object(arg); rb_ivar_set(v, id, val); } } + return v; } break; + case TYPE_MODULE: + { + char *buf; + r_bytes(buf, arg); + return rb_path2class(buf); + } + default: ArgError("dump format error(0x%x)", type); break; } - return v; } -struct load_arg { - FILE *fp; - st_table *table; -}; - static VALUE load(arg) struct load_arg *arg; { - return r_object(arg->fp, arg->table); + return r_object(arg); } static VALUE load_ensure(arg) struct load_arg *arg; { - st_free_table(arg->table); + st_free_table(arg->symbol); + st_free_table(arg->data); } static VALUE marshal_load(self, port) VALUE self, port; { - extern VALUE cIO; FILE *fp; int major; VALUE v; OpenFile *fptr; - char buf[32]; -#if defined(MSDOS) || defined(__BOW__) - int need_unlink_tmp = 0; -#endif struct load_arg arg; if (TYPE(port) == T_STRING) { - tmpnam(buf); - fp = rb_fopen(buf, "w"); - v = file_open(buf, "r"); -#if defined(MSDOS) || defined(__BOW__) - need_unlink_tmp = 0; -#else - unlink(buf); -#endif - - fwrite(RSTRING(port)->ptr, RSTRING(port)->len, 1, fp); - fclose(fp); - port = v; - } - - if (obj_is_kind_of(port, cIO)) { - GetOpenFile(port, fptr); - io_readable(fptr); - fp = fptr->f; + arg.fp = 0; + arg.ptr = RSTRING(port)->ptr; + arg.end = arg.ptr + RSTRING(port)->len; } else { - TypeError("instance of IO needed"); + if (obj_is_kind_of(port, cIO)) { + io_binmode(port); + GetOpenFile(port, fptr); + io_readable(fptr); + arg.fp = fptr->f; + } + else { + TypeError("instance of IO needed"); + } } - major = r_byte(fp); + major = r_byte(&arg); if (major == MARSHAL_MAJOR) { - if (r_byte(fp) != MARSHAL_MINOR) { + if (r_byte(&arg) != MARSHAL_MINOR) { Warning("Old marshal file format (can be read)"); } - arg.fp = fp; - arg.table = st_init_numtable(); + arg.symbol = st_init_numtable(); + arg.data = st_init_numtable(); v = rb_ensure(load, &arg, load_ensure, &arg); } -#if defined(MSDOS) || defined(__BOW__) - if (need_unlink_tmp) unlink(buf); -#endif - if (major != MARSHAL_MAJOR) { + else { TypeError("Old marshal file format (can't read)"); } @@ -752,7 +821,6 @@ Init_marshal() s_dump = rb_intern("_dump_to"); s_load = rb_intern("_load_from"); rb_define_module_function(mMarshal, "dump", marshal_dump, -1); - rb_define_module_function(mMarshal, "dumps", marshal_dumps, -1); rb_define_module_function(mMarshal, "load", marshal_load, 1); rb_define_module_function(mMarshal, "restore", marshal_load, 1); } |