From 020caa3fc8b2ce78591eaa04e674907b48e5b7b0 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 17 Oct 2002 10:20:52 +0000 Subject: * marshal.c (w_byten): added; write n bytes from s to arg. * marshal.c (dump): flush buffered data. * marshal.c (marshal_dump, r_byte, r_bytes0, marshal_load): unify marshaling I/O. [ruby-talk:53368] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2967 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- marshal.c | 105 ++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 30 deletions(-) (limited to 'marshal.c') diff --git a/marshal.c b/marshal.c index 1f50848073..cc0ccbb35d 100644 --- a/marshal.c +++ b/marshal.c @@ -76,11 +76,12 @@ shortlen(len, ds) static ID s_dump, s_load; static ID s_dump_data, s_load_data, s_alloc; +static ID s_getc, s_read, s_write; struct dump_arg { VALUE obj; FILE *fp; - VALUE str; + VALUE str, dest; st_table *symbol; st_table *data; int taint; @@ -94,13 +95,32 @@ struct dump_call_arg { static void w_long _((long, struct dump_arg*)); +static void +w_byten(s, n, arg) + char *s; + int n; + struct dump_arg *arg; +{ + if (arg->fp) { + fwrite(s, 1, n, arg->fp); + } + else { + VALUE buf = arg->str; + rb_str_buf_cat(buf, s, n); + if (arg->dest && RSTRING(buf)->len >= BUFSIZ) { + if (arg->taint) OBJ_TAINT(buf); + rb_io_write(arg->dest, buf); + rb_str_resize(buf, 0); + } + } +} + static void w_byte(c, arg) char c; struct dump_arg *arg; { - if (arg->fp) putc(c, arg->fp); - else rb_str_buf_cat(arg->str, &c, 1); + w_byten(&c, 1, arg); } static void @@ -110,12 +130,7 @@ w_bytes(s, n, arg) struct dump_arg *arg; { w_long(n, arg); - if (arg->fp) { - fwrite(s, 1, n, arg->fp); - } - else { - rb_str_buf_cat(arg->str, s, n); - } + w_byten(s, n, arg); } static void @@ -551,6 +566,10 @@ dump(arg) struct dump_call_arg *arg; { w_object(arg->obj, arg->arg, arg->limit); + if (arg->arg->dest) { + rb_io_write(arg->arg->dest, arg->arg->str); + rb_str_resize(arg->arg->str, 0); + } return 0; } @@ -586,6 +605,7 @@ marshal_dump(argc, argv) if (FIXNUM_P(a1)) limit = FIX2INT(a1); else port = a1; } + arg.dest = 0; if (port) { if (rb_obj_is_kind_of(port, rb_cIO)) { OpenFile *fptr; @@ -595,6 +615,11 @@ marshal_dump(argc, argv) rb_io_check_writable(fptr); arg.fp = (fptr->f2) ? fptr->f2 : fptr->f; } + else if (rb_respond_to(port, s_write)) { + arg.fp = 0; + arg.str = rb_str_buf_new(0); + arg.dest = port; + } else { rb_raise(rb_eTypeError, "instance of IO needed"); } @@ -641,6 +666,12 @@ r_byte(arg) c = rb_getc(arg->fp); if (c == EOF) rb_eof_error(); } + else if (!arg->end) { + VALUE src = (VALUE)arg->ptr; + VALUE v = rb_funcall2(src, s_getc, 0, 0); + if (NIL_P(v)) rb_eof_error(); + c = (unsigned char)FIX2INT(v); + } else if (arg->ptr < arg->end) { c = *(unsigned char*)arg->ptr++; } @@ -650,18 +681,6 @@ r_byte(arg) return c; } -static unsigned short -r_short(arg) - struct load_arg *arg; -{ - unsigned short x; - - x = r_byte(arg); - x |= r_byte(arg)<<8; - - return x; -} - static void long_toobig(size) int size; @@ -728,6 +747,15 @@ r_bytes0(len, arg) rb_raise(rb_eArgError, "marshal data too short"); } } + else if (!arg->end) { + VALUE src = (VALUE)arg->ptr; + VALUE n = LONG2NUM(len); + str = rb_funcall2(src, s_read, 1, &n); + if (NIL_P(str)) goto too_short; + Check_Type(str, T_STRING); + if (RSTRING(str)->len != len) goto too_short; + if (OBJ_TAINTED(str)) arg->taint = Qtrue; + } else { if (arg->ptr + len > arg->end) { goto too_short; @@ -933,34 +961,41 @@ r_object0(arg, proc) { long len; BDIGIT *digits; + VALUE data; NEWOBJ(big, struct RBignum); OBJSETUP(big, rb_cBignum, T_BIGNUM); big->sign = (r_byte(arg) == '+'); len = r_long(arg); + data = r_bytes0(len * 2, arg); #if SIZEOF_BDIGITS == SIZEOF_SHORT big->len = len; #else big->len = (len + 1) * 2 / sizeof(BDIGIT); #endif big->digits = digits = ALLOC_N(BDIGIT, big->len); - while (len > 0) { + MEMCPY(digits, RSTRING(data)->ptr, char, len * 2); #if SIZEOF_BDIGITS > SIZEOF_SHORT + MEMZERO((char *)digits + len * 2, char, + big->len * sizeof(BDIGIT) - len * 2); +#endif + len = big->len; + while (len > 0) { + unsigned char *p = (unsigned char *)digits; BDIGIT num = 0; +#if SIZEOF_BDIGITS > SIZEOF_SHORT int shift = 0; int i; - for (i=0; iptr; arg.end = arg.ptr + RSTRING(port)->len; } + else if (rb_respond_to(port, s_getc) && rb_respond_to(port, s_read)) { + arg.taint = Qfalse; + arg.fp = 0; + arg.ptr = (char *)port; + arg.end = 0; + } else { rb_raise(rb_eTypeError, "instance of IO needed"); } @@ -1225,6 +1266,10 @@ Init_marshal() s_dump_data = rb_intern("_dump_data"); s_load_data = rb_intern("_load_data"); s_alloc = rb_intern("_alloc"); + s_getc = rb_intern("getc"); + s_read = rb_intern("read"); + s_write = rb_intern("write"); + rb_define_module_function(rb_mMarshal, "dump", marshal_dump, -1); rb_define_module_function(rb_mMarshal, "load", marshal_load, -1); rb_define_module_function(rb_mMarshal, "restore", marshal_load, -1); -- cgit v1.2.3