[前][次][番号順一覧][スレッド一覧]

ruby-changes:23847

From: nobu <ko1@a...>
Date: Mon, 4 Jun 2012 11:40:39 +0900 (JST)
Subject: [ruby-changes:23847] nobu:r35898 (trunk): compatible loader

nobu	2012-06-04 11:40:30 +0900 (Mon, 04 Jun 2012)

  New Revision: 35898

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=35898

  Log:
    compatible loader
    
    * marshal.c (r_object0): also load TYPE_USRMARSHAL, TYPE_DATA using
      compatible loader.

  Added directories:
    trunk/ext/-test-/marshal/
    trunk/ext/-test-/marshal/compat/
    trunk/ext/-test-/marshal/usr/
    trunk/test/-ext-/marshal/
  Added files:
    trunk/ext/-test-/marshal/compat/extconf.rb
    trunk/ext/-test-/marshal/compat/usrcompat.c
    trunk/ext/-test-/marshal/usr/extconf.rb
    trunk/ext/-test-/marshal/usr/usrmarshal.c
    trunk/test/-ext-/marshal/test_usrmarshal.rb
  Modified files:
    trunk/ChangeLog
    trunk/marshal.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 35897)
+++ ChangeLog	(revision 35898)
@@ -1,3 +1,8 @@
+Mon Jun  4 11:40:28 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* marshal.c (r_object0): also load TYPE_USRMARSHAL, TYPE_DATA using
+	  compatible loader.
+
 Mon Jun  4 11:33:42 2012  NAKAMURA Usaku  <usa@r...>
 
 	* process.c (rb_run_exec_options_err): restore save_env() call for
Index: ext/-test-/marshal/compat/extconf.rb
===================================================================
--- ext/-test-/marshal/compat/extconf.rb	(revision 0)
+++ ext/-test-/marshal/compat/extconf.rb	(revision 35898)
@@ -0,0 +1 @@
+create_makefile("-test-/marshal/compat")

Property changes on: ext/-test-/marshal/compat/extconf.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ext/-test-/marshal/compat/usrcompat.c
===================================================================
--- ext/-test-/marshal/compat/usrcompat.c	(revision 0)
+++ ext/-test-/marshal/compat/usrcompat.c	(revision 35898)
@@ -0,0 +1,32 @@
+#include <ruby.h>
+
+static VALUE
+usr_dumper(VALUE self)
+{
+    return self;
+}
+
+static VALUE
+usr_loader(VALUE self, VALUE m)
+{
+    VALUE val = rb_ivar_get(m, rb_intern("@value"));
+    *(int *)DATA_PTR(self) = NUM2INT(val);
+    return self;
+}
+
+static VALUE
+compat_mload(VALUE self, VALUE data)
+{
+    rb_ivar_set(self, rb_intern("@value"), data);
+    return self;
+}
+
+void
+Init_compat(void)
+{
+    VALUE newclass = rb_path2class("Bug::Marshal::UsrMarshal");
+    VALUE oldclass = rb_define_class_under(newclass, "compat", rb_cObject);
+
+    rb_define_method(oldclass, "marshal_load", compat_mload, 1);
+    rb_marshal_define_compat(newclass, oldclass, usr_dumper, usr_loader);
+}

Property changes on: ext/-test-/marshal/compat/usrcompat.c
___________________________________________________________________
Added: svn:eol-style
   + LF


Property changes on: ext/-test-/marshal/compat
___________________________________________________________________
Added: svn:ignore
   + Makefile
extconf.h
mkmf.log


Index: ext/-test-/marshal/usr/usrmarshal.c
===================================================================
--- ext/-test-/marshal/usr/usrmarshal.c	(revision 0)
+++ ext/-test-/marshal/usr/usrmarshal.c	(revision 35898)
@@ -0,0 +1,35 @@
+#include <ruby.h>
+
+static VALUE
+usr_alloc(VALUE klass)
+{
+    int *p;
+    return Data_Make_Struct(klass, int, 0, RUBY_DEFAULT_FREE, p);
+}
+
+static VALUE
+usr_init(VALUE self, VALUE val)
+{
+    *(int *)DATA_PTR(self) = NUM2INT(val);
+    return self;
+}
+
+static VALUE
+usr_value(VALUE self)
+{
+    int val = *(int *)DATA_PTR(self);
+    return INT2NUM(val);
+}
+
+void
+Init_usr(void)
+{
+    VALUE mMarshal = rb_define_module_under(rb_define_module("Bug"), "Marshal");
+    VALUE newclass = rb_define_class_under(mMarshal, "UsrMarshal", rb_cObject);
+
+    rb_define_alloc_func(newclass, usr_alloc);
+    rb_define_method(newclass, "initialize", usr_init, 1);
+    rb_define_method(newclass, "value", usr_value, 0);
+    rb_define_method(newclass, "marshal_load", usr_init, 1);
+    rb_define_method(newclass, "marshal_dump", usr_value, 0);
+}

Property changes on: ext/-test-/marshal/usr/usrmarshal.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ext/-test-/marshal/usr/extconf.rb
===================================================================
--- ext/-test-/marshal/usr/extconf.rb	(revision 0)
+++ ext/-test-/marshal/usr/extconf.rb	(revision 35898)
@@ -0,0 +1 @@
+create_makefile("-test-/marshal/usr")

Property changes on: ext/-test-/marshal/usr/extconf.rb
___________________________________________________________________
Added: svn:eol-style
   + LF


Property changes on: ext/-test-/marshal/usr
___________________________________________________________________
Added: svn:ignore
   + Makefile
extconf.h
mkmf.log


Index: marshal.c
===================================================================
--- marshal.c	(revision 35897)
+++ marshal.c	(revision 35898)
@@ -1293,19 +1293,17 @@
 }
 
 static VALUE
-obj_alloc_by_path(VALUE path, struct load_arg *arg)
+obj_alloc_by_klass(VALUE klass, struct load_arg *arg, VALUE *oldclass)
 {
-    VALUE klass;
     st_data_t data;
     rb_alloc_func_t allocator;
 
-    klass = path2class(path);
-
     allocator = rb_get_alloc_func(klass);
     if (st_lookup(compat_allocator_tbl, (st_data_t)allocator, &data)) {
         marshal_compat_t *compat = (marshal_compat_t*)data;
         VALUE real_obj = rb_obj_alloc(klass);
         VALUE obj = rb_obj_alloc(compat->oldclass);
+	if (oldclass) *oldclass = compat->oldclass;
         st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
         return obj;
     }
@@ -1314,6 +1312,23 @@
 }
 
 static VALUE
+obj_alloc_by_path(VALUE path, struct load_arg *arg)
+{
+    return obj_alloc_by_klass(path2class(path), arg, 0);
+}
+
+static VALUE
+append_extmod(VALUE obj, VALUE extmod)
+{
+    long i = RARRAY_LEN(extmod);
+    while (i > 0) {
+	VALUE m = RARRAY_PTR(extmod)[--i];
+	rb_extend_object(obj, m);
+    }
+    return obj;
+}
+
+static VALUE
 r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
 {
     VALUE v = Qnil;
@@ -1347,7 +1362,7 @@
 	{
 	    VALUE m = path2module(r_unique(arg));
 
-            if (NIL_P(extmod)) extmod = rb_ary_new2(0);
+            if (NIL_P(extmod)) extmod = rb_ary_tmp_new(0);
             rb_ary_push(extmod, m);
 
 	    v = r_object0(arg, 0, extmod);
@@ -1607,14 +1622,13 @@
       case TYPE_USRMARSHAL:
         {
 	    VALUE klass = path2class(r_unique(arg));
+	    VALUE oldclass = 0;
 	    VALUE data;
 
-	    v = rb_obj_alloc(klass);
+	    v = obj_alloc_by_klass(klass, arg, &oldclass);
             if (!NIL_P(extmod)) {
-                while (RARRAY_LEN(extmod) > 0) {
-                    VALUE m = rb_ary_pop(extmod);
-                    rb_extend_object(v, m);
-                }
+		/* for the case marshal_load is overridden */
+		append_extmod(v, extmod);
             }
 	    if (!rb_respond_to(v, s_mload)) {
 		rb_raise(rb_eTypeError, "instance of %s needs to have method `marshal_load'",
@@ -1625,6 +1639,10 @@
 	    rb_funcall(v, s_mload, 1, data);
 	    check_load_arg(arg, s_mload);
             v = r_leave(v, arg);
+	    if (!NIL_P(extmod)) {
+		if (oldclass) append_extmod(v, extmod);
+		rb_ary_clear(extmod);
+	    }
 	}
         break;
 
@@ -1644,8 +1662,9 @@
       case TYPE_DATA:
 	{
 	    VALUE klass = path2class(r_unique(arg));
+	    VALUE oldclass = 0;
 
-	    v = rb_obj_alloc(klass);
+	    v = obj_alloc_by_klass(klass, arg, &oldclass);
 	    if (!RB_TYPE_P(v, T_DATA)) {
 		rb_raise(rb_eArgError, "dump format error");
 	    }
Index: test/-ext-/marshal/test_usrmarshal.rb
===================================================================
--- test/-ext-/marshal/test_usrmarshal.rb	(revision 0)
+++ test/-ext-/marshal/test_usrmarshal.rb	(revision 35898)
@@ -0,0 +1,34 @@
+require 'test/unit'
+require_relative '../../ruby/envutil'
+require '-test-/marshal/usr'
+
+module Bug end
+
+module Bug::Marshal
+  class TestUsrMarshal < Test::Unit::TestCase
+    def old_dump
+      @old_dump ||=
+        begin
+          src = "module Bug; module Marshal; class UsrMarshal; def initialize(val) @value = val; end; end; ::Marshal.dump(UsrMarshal.new(42), STDOUT); end; end"
+          EnvUtil.invoke_ruby([], src, true)[0]
+        end
+    end
+
+    def test_marshal
+      v = ::Marshal.load(::Marshal.dump(UsrMarshal.new(42)))
+      assert_instance_of(UsrMarshal, v)
+      assert_equal(42, v.value)
+    end
+
+    def test_incompat
+      e = assert_raise(ArgumentError) {::Marshal.load(old_dump)}
+      assert_equal("dump format error", e.message)
+    end
+
+    def test_compat
+      out, err = EnvUtil.invoke_ruby(["-r-test-/marshal/usr", "-r-test-/marshal/compat", "-e", "::Marshal.dump(::Marshal.load(STDIN), STDOUT)"], old_dump, true, true)
+      assert_equal(::Marshal.dump(UsrMarshal.new(42)), out)
+      assert_equal("", err)
+    end
+  end
+end

Property changes on: test/-ext-/marshal/test_usrmarshal.rb
___________________________________________________________________
Added: svn:eol-style
   + LF


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]