From 1d3973d4942977f1a155fa6a9f3f6f6e88bcc3a5 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@ruby-lang.org>
Date: Mon, 4 Jun 2012 06:10:17 +0900
Subject: [PATCH 1/4] compatible marshal loader

* complex.c, rational.c: compatible marshal loader for compatibilities
  with 1.8.
---
 complex.c  |   40 +++++++++++++++++++++++++++++-----------
 rational.c |   40 ++++++++++++++++++++++++++++++----------
 2 files changed, 59 insertions(+), 21 deletions(-)

diff --git a/complex.c b/complex.c
index 1aae3b6..b3279f3 100644
--- a/complex.c
+++ b/complex.c
@@ -21,7 +21,8 @@ VALUE rb_cComplex;
 static ID id_abs, id_abs2, id_arg, id_cmp, id_conj, id_convert,
     id_denominator, id_divmod, id_eqeq_p, id_expt, id_fdiv,  id_floor,
     id_idiv, id_imag, id_inspect, id_negate, id_numerator, id_quo,
-    id_real, id_real_p, id_to_f, id_to_i, id_to_r, id_to_s;
+    id_real, id_real_p, id_to_f, id_to_i, id_to_r, id_to_s,
+    id_i_real, id_i_imag;
 
 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
 
@@ -1244,13 +1245,31 @@ nucomp_inspect(VALUE self)
 
 /* :nodoc: */
 static VALUE
+nucomp_dumper(VALUE self)
+{
+    return self;
+}
+
+/* :nodoc: */
+static VALUE
+nucomp_loader(VALUE self, VALUE a)
+{
+    get_dat1(self);
+
+    dat->real = rb_ivar_get(a, id_i_real);
+    dat->imag = rb_ivar_get(a, id_i_imag);
+
+    return self;
+}
+
+/* :nodoc: */
+static VALUE
 nucomp_marshal_dump(VALUE self)
 {
     VALUE a;
     get_dat1(self);
 
     a = rb_assoc_new(dat->real, dat->imag);
-    rb_copy_generic_ivar(a, self);
     return a;
 }
 
@@ -1258,17 +1277,11 @@ nucomp_marshal_dump(VALUE self)
 static VALUE
 nucomp_marshal_load(VALUE self, VALUE a)
 {
-    get_dat1(self);
-
-    rb_check_frozen(self);
-    rb_check_trusted(self);
-
     Check_Type(a, T_ARRAY);
     if (RARRAY_LEN(a) != 2)
 	rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a));
-    dat->real = RARRAY_PTR(a)[0];
-    dat->imag = RARRAY_PTR(a)[1];
-    rb_copy_generic_ivar(self, a);
+    rb_ivar_set(self, id_i_real, RARRAY_PTR(a)[0]);
+    rb_ivar_set(self, id_i_imag, RARRAY_PTR(a)[1]);
     return self;
 }
 
@@ -1833,6 +1846,7 @@ float_arg(VALUE self)
 void
 Init_Complex(void)
 {
+    VALUE compat;
 #undef rb_intern
 #define rb_intern(str) rb_intern_const(str)
 
@@ -1862,6 +1876,8 @@ Init_Complex(void)
     id_to_i = rb_intern("to_i");
     id_to_r = rb_intern("to_r");
     id_to_s = rb_intern("to_s");
+    id_i_real = rb_intern("@real");
+    id_i_imag = rb_intern("@image");
 
     rb_cComplex = rb_define_class("Complex", rb_cNumeric);
 
@@ -1951,7 +1967,9 @@ Init_Complex(void)
     rb_define_method(rb_cComplex, "inspect", nucomp_inspect, 0);
 
     rb_define_method(rb_cComplex, "marshal_dump", nucomp_marshal_dump, 0);
-    rb_define_method(rb_cComplex, "marshal_load", nucomp_marshal_load, 1);
+    compat = rb_define_class_under(rb_cComplex, "compatible", rb_cObject);
+    rb_define_method(compat, "marshal_load", nucomp_marshal_load, 1);
+    rb_marshal_define_compat(rb_cComplex, compat, nucomp_dumper, nucomp_loader);
 
     /* --- */
 
diff --git a/rational.c b/rational.c
index c4469c8..e7a296a 100644
--- a/rational.c
+++ b/rational.c
@@ -25,7 +25,7 @@ VALUE rb_cRational;
 
 static ID id_abs, id_cmp, id_convert, id_eqeq_p, id_expt, id_fdiv,
     id_floor, id_idiv, id_inspect, id_integer_p, id_negate, id_to_f,
-    id_to_i, id_to_s, id_truncate;
+    id_to_i, id_to_s, id_truncate, id_i_num, id_i_den;
 
 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
 
@@ -1590,13 +1590,31 @@ nurat_inspect(VALUE self)
 
 /* :nodoc: */
 static VALUE
+nurat_dumper(VALUE self)
+{
+    return self;
+}
+
+/* :nodoc: */
+static VALUE
+nurat_loader(VALUE self, VALUE a)
+{
+    get_dat1(self);
+
+    dat->num = rb_ivar_get(a, id_i_num);
+    dat->den = rb_ivar_get(a, id_i_den);
+
+    return self;
+}
+
+/* :nodoc: */
+static VALUE
 nurat_marshal_dump(VALUE self)
 {
     VALUE a;
     get_dat1(self);
 
     a = rb_assoc_new(dat->num, dat->den);
-    rb_copy_generic_ivar(a, self);
     return a;
 }
 
@@ -1604,21 +1622,18 @@ nurat_marshal_dump(VALUE self)
 static VALUE
 nurat_marshal_load(VALUE self, VALUE a)
 {
-    get_dat1(self);
-
     rb_check_frozen(self);
     rb_check_trusted(self);
 
     Check_Type(a, T_ARRAY);
     if (RARRAY_LEN(a) != 2)
 	rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
-    dat->num = RARRAY_PTR(a)[0];
-    dat->den = RARRAY_PTR(a)[1];
-    rb_copy_generic_ivar(self, a);
-
-    if (f_zero_p(dat->den))
+    if (f_zero_p(RARRAY_PTR(a)[1]))
 	rb_raise_zerodiv();
 
+    rb_ivar_set(self, id_i_num, RARRAY_PTR(a)[0]);
+    rb_ivar_set(self, id_i_den, RARRAY_PTR(a)[1]);
+
     return self;
 }
 
@@ -2295,6 +2310,7 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass)
 void
 Init_Rational(void)
 {
+    VALUE compat;
 #undef rb_intern
 #define rb_intern(str) rb_intern_const(str)
 
@@ -2315,6 +2331,8 @@ Init_Rational(void)
     id_to_i = rb_intern("to_i");
     id_to_s = rb_intern("to_s");
     id_truncate = rb_intern("truncate");
+    id_i_num = rb_intern("@numerator");
+    id_i_den = rb_intern("@denominator");
 
     rb_cRational = rb_define_class("Rational", rb_cNumeric);
 
@@ -2375,7 +2393,9 @@ Init_Rational(void)
     rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
 
     rb_define_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
-    rb_define_method(rb_cRational, "marshal_load", nurat_marshal_load, 1);
+    compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
+    rb_define_method(compat, "marshal_load", nurat_marshal_load, 1);
+    rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
 
     /* --- */
 
-- 
1.7.10.2

