Module: Marshal

Defined in:
marshal.c

Constant Summary collapse

MAJOR_VERSION =
INT2FIX(MARSHAL_MAJOR)
MINOR_VERSION =
INT2FIX(MARSHAL_MINOR)

Class Method Summary collapse

Class Method Details

.dump(obj[, anIO], limit = --1) ⇒ Object

Serializes obj and all descendent objects. If anIO is specified, the serialized data will be written to it, otherwise the data will be returned as a String. If limit is specified, the traversal of subobjects will be limited to that depth. If limit is negative, no checking of depth will be performed.

class Klass
  def initialize(str)
    @str = str
  end
  def sayHello
    @str
  end
end

(produces no output)

o = Klass.new("hello\n")
data = Marshal.dump(o)
obj = Marshal.load(data)
obj.sayHello   #=> "hello\n"


# File 'marshal.c'

/*
 * call-seq:
 *      dump( obj [, anIO] , limit=--1 ) => anIO
 *
 * Serializes obj and all descendent objects. If anIO is
 * specified, the serialized data will be written to it, otherwise the
 * data will be returned as a String. If limit is specified, the
 * traversal of subobjects will be limited to that depth. If limit is
 * negative, no checking of depth will be performed.
 *
 *     class Klass
 *       def initialize(str)
 *         @str = str
 *       end
 *       def sayHello
 *         @str
 *       end
 *     end
 *
 * (produces no output)
 *
 *     o = Klass.new("hello\n")
 *     data = Marshal.dump(o)
 *     obj = Marshal.load(data)
 *     obj.sayHello   #=> "hello\n"
 */
static VALUE
marshal_dump(argc, argv)
    int argc;
    VALUE* argv;
{
    VALUE obj, port, a1, a2;
    int limit = -1;
    struct dump_arg arg;
    struct dump_call_arg c_arg;

    port = Qnil;
    rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
    if (argc == 3) {
    if (!NIL_P(a2)) limit = NUM2INT(a2);
    if (NIL_P(a1)) goto type_error;
    port = a1;
    }
    else if (argc == 2) {
    if (FIXNUM_P(a1)) limit = FIX2INT(a1);
    else if (NIL_P(a1)) goto type_error;
    else port = a1;
    }
    arg.dest = 0;
    arg.symbols = st_init_numtable();
    arg.data    = st_init_numtable();
    arg.taint   = Qfalse;
    arg.str = rb_str_buf_new(0);
    RBASIC(arg.str)->klass = 0;
    arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg);
    if (!NIL_P(port)) {
    if (!rb_respond_to(port, s_write)) {
      type_error:
        rb_raise(rb_eTypeError, "instance of IO needed");
    }
    arg.dest = port;
    if (rb_respond_to(port, s_binmode)) {
        rb_funcall2(port, s_binmode, 0, 0);
        check_dump_arg(&arg, s_binmode);
    }
    }
    else {
    port = arg.str;
    }

    c_arg.obj   = obj;
    c_arg.arg   = &arg;
    c_arg.limit = limit;

    w_byte(MARSHAL_MAJOR, &arg);
    w_byte(MARSHAL_MINOR, &arg);

    rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg);
    RBASIC(arg.str)->klass = rb_cString;

    return port;
}

.load(source[, proc]) ⇒ Object .restore(source[, proc]) ⇒ Object

Returns the result of converting the serialized data in source into a Ruby object (possibly with associated subordinate objects). source may be either an instance of IO or an object that responds to to_str. If proc is specified, it will be passed each object as it is deserialized.



# File 'marshal.c'

/*
 * call-seq:
 *     load( source [, proc] ) => obj
 *     restore( source [, proc] ) => obj
 * 
 * Returns the result of converting the serialized data in source into a
 * Ruby object (possibly with associated subordinate objects). source
 * may be either an instance of IO or an object that responds to
 * to_str. If proc is specified, it will be passed each object as it
 * is deserialized.
 */
static VALUE
marshal_load(argc, argv)
    int argc;
    VALUE *argv;
{
    VALUE port, proc;
    int major, minor, taint = Qfalse;
    VALUE v;
    struct load_arg arg;

    rb_scan_args(argc, argv, "11", &port, &proc);
    v = rb_check_string_type(port);
    if (!NIL_P(v)) {
    taint = OBJ_TAINTED(port); /* original taintedness */
    port = v;
    }
    else if (rb_respond_to(port, s_getc) && rb_respond_to(port, s_read)) {
    if (rb_respond_to(port, s_binmode)) {
        rb_funcall2(port, s_binmode, 0, 0);
    }
    taint = Qtrue;
    }
    else {
    rb_raise(rb_eTypeError, "instance of IO needed");
    }
    arg.src = port;
    arg.offset = 0;
    arg.symbols = st_init_numtable();
    arg.data    = st_init_numtable();
    arg.proc = 0;
    arg.wrapper = Data_Wrap_Struct(rb_cData, mark_load_arg, 0, &arg);
    arg.taint = taint;

    major = r_byte(&arg);
    minor = r_byte(&arg);
    if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) {
    rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
\tformat version %d.%d required; %d.%d given",
         MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }
    if (RTEST(ruby_verbose) && minor != MARSHAL_MINOR) {
    rb_warn("incompatible marshal file format (can be read)\n\
\tformat version %d.%d required; %d.%d given",
        MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }

    if (!NIL_P(proc)) arg.proc = proc;
    v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg);

    return v;
}

.load(source[, proc]) ⇒ Object .restore(source[, proc]) ⇒ Object

Returns the result of converting the serialized data in source into a Ruby object (possibly with associated subordinate objects). source may be either an instance of IO or an object that responds to to_str. If proc is specified, it will be passed each object as it is deserialized.



# File 'marshal.c'

/*
 * call-seq:
 *     load( source [, proc] ) => obj
 *     restore( source [, proc] ) => obj
 * 
 * Returns the result of converting the serialized data in source into a
 * Ruby object (possibly with associated subordinate objects). source
 * may be either an instance of IO or an object that responds to
 * to_str. If proc is specified, it will be passed each object as it
 * is deserialized.
 */
static VALUE
marshal_load(argc, argv)
    int argc;
    VALUE *argv;
{
    VALUE port, proc;
    int major, minor, taint = Qfalse;
    VALUE v;
    struct load_arg arg;

    rb_scan_args(argc, argv, "11", &port, &proc);
    v = rb_check_string_type(port);
    if (!NIL_P(v)) {
    taint = OBJ_TAINTED(port); /* original taintedness */
    port = v;
    }
    else if (rb_respond_to(port, s_getc) && rb_respond_to(port, s_read)) {
    if (rb_respond_to(port, s_binmode)) {
        rb_funcall2(port, s_binmode, 0, 0);
    }
    taint = Qtrue;
    }
    else {
    rb_raise(rb_eTypeError, "instance of IO needed");
    }
    arg.src = port;
    arg.offset = 0;
    arg.symbols = st_init_numtable();
    arg.data    = st_init_numtable();
    arg.proc = 0;
    arg.wrapper = Data_Wrap_Struct(rb_cData, mark_load_arg, 0, &arg);
    arg.taint = taint;

    major = r_byte(&arg);
    minor = r_byte(&arg);
    if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) {
    rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
\tformat version %d.%d required; %d.%d given",
         MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }
    if (RTEST(ruby_verbose) && minor != MARSHAL_MINOR) {
    rb_warn("incompatible marshal file format (can be read)\n\
\tformat version %d.%d required; %d.%d given",
        MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
    }

    if (!NIL_P(proc)) arg.proc = proc;
    v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg);

    return v;
}