Permalink
Browse files

restructure Marshal.dump

  • Loading branch information...
Jeremy Roach
Jeremy Roach committed Jan 11, 2008
1 parent 82b801e commit 2828a281fbe96029f1776fdc61eca074fdc50a04
Showing with 156 additions and 116 deletions.
  1. +156 −116 kernel/core/marshal.rb
View
@@ -1,10 +1,145 @@
# depends on: module.rb
+class NilClass
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ (version ? Marshal::VERSION_STRING : '') +
+ Marshal::TYPE_NIL
+ end
+end
+
+class TrueClass
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ (version ? Marshal::VERSION_STRING : '') +
+ Marshal::TYPE_TRUE
+ end
+end
+
+class FalseClass
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ (version ? Marshal::VERSION_STRING : '') +
+ Marshal::TYPE_FALSE
+ end
+end
+
+class Class
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ (version ? Marshal::VERSION_STRING : '') +
+ Marshal::TYPE_CLASS +
+ Marshal::serialize_integer(self.name.length) + self.name
+ end
+end
+
+class Module
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ (version ? Marshal::VERSION_STRING : '') +
+ Marshal::TYPE_MODULE +
+ Marshal::serialize_integer(self.name.length) + self.name
+ end
+end
+
+class Symbol
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ str = self.to_s
+ (version ? Marshal::VERSION_STRING : '') +
+ Marshal::TYPE_SYMBOL +
+ Marshal::serialize_integer(str.length) + str
+ end
+end
+
+class String
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ ivar_prefix = Marshal::serialize_instance_variables_prefix(self)
+ ivar_suffix = Marshal::serialize_instance_variables_suffix(self, depth, false, subclass)
+ (version ? Marshal::VERSION_STRING : '') + ivar_prefix +
+ Marshal::serialize_extended_object(self, depth) +
+ Marshal::serialize_user_class(self, depth, false, subclass) +
+ Marshal::TYPE_STRING +
+ Marshal::serialize_integer(self.length) + self + ivar_suffix
+ end
+end
+
+class Integer
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ if self >= -2**30 and self <= (2**30 - 1)
+ to_marshal_fixnum(depth, version, subclass)
+ else
+ to_marshal_bignum(depth, version, subclass)
+ end
+ end
+
+ def to_marshal_fixnum(depth = -1, version = true, subclass = nil)
+ (version ? Marshal::VERSION_STRING : '') +
+ Marshal::TYPE_FIXNUM +
+ Marshal::serialize_integer(self)
+ end
+
+ def to_marshal_bignum(depth = -1, version = true, subclass = nil)
+ str = (version ? Marshal::VERSION_STRING : '') +
+ Marshal::TYPE_BIGNUM +
+ (self < 0 ? '-' : '+') + "\0"
+ size_index = str.length - 1
+ cnt = 0
+ num = self.abs
+ while num != 0
+ str << Marshal::to_byte(num & 0xFF)
+ num >>= 8
+ cnt += 1
+ end
+ if cnt % 2 == 1
+ str << "\0"
+ cnt += 1
+ end
+ str[size_index] = Marshal::to_byte(((cnt - 4) / 2) + 7)
+ str
+ end
+end
+
+class Regexp
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ str = self.source
+ ivar_prefix = Marshal::serialize_instance_variables_prefix(self)
+ ivar_suffix = Marshal::serialize_instance_variables_suffix(self, depth, false, subclass)
+ (version ? Marshal::VERSION_STRING : '') + ivar_prefix +
+ Marshal::serialize_extended_object(self, depth) +
+ Marshal::serialize_user_class(self, depth, false, subclass) +
+ Marshal::TYPE_REGEXP +
+ Marshal::serialize_integer(str.length) + str +
+ Marshal::to_byte(self.options & 0x7) + ivar_suffix
+ end
+end
+
+class Struct
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ str = (version ? Marshal::VERSION_STRING : '') +
+ Marshal::serialize_extended_object(self, depth) +
+ Marshal::TYPE_STRUCT +
+ self.class.name.to_sym.to_marshal(depth, false, subclass) +
+ Marshal::serialize_integer(self.length)
+ self.each_pair do |sym, val|
+ str << sym.to_marshal(depth, false, subclass) +
+ val.to_marshal(depth, false, subclass)
+ end
+ str
+ end
+end
+
+class Object
+ def to_marshal(depth = -1, version = true, subclass = nil)
+ ivar_suffix = Marshal::serialize_instance_variables_suffix(self, depth, false, subclass)
+ (version ? Marshal::VERSION_STRING : '') +
+ Marshal::serialize_extended_object(self, depth) +
+ Marshal::TYPE_OBJECT +
+ self.class.name.to_sym.to_marshal(depth, false, subclass) + ivar_suffix
+ end
+end
+
module Marshal
MAJOR_VERSION = 4
MINOR_VERSION = 8
+ VERSION_STRING = "\x04\x08"
+
TYPE_NIL = '0'
TYPE_TRUE = 'T'
TYPE_FALSE = 'F'
@@ -35,49 +170,25 @@ module Marshal
TYPE_LINK = '@'
def self.dump(obj, depth = -1, io = nil)
- cls = obj.class
- sup = get_superclass(cls)
-
- str = [MAJOR_VERSION, MINOR_VERSION].pack('CC')
- str << serialize(obj, cls, sup, depth)
- str
+ serialize(obj, depth)
end
- def self.serialize(obj, cls, sup, depth)
+ def self.serialize(obj, depth)
+ cls = obj.class
+ sup = get_superclass(cls)
[cls.to_s, sup.to_s].each do |class_name|
case class_name
- when 'NilClass'
- return serialize_nil(obj)
- when 'TrueClass'
- return serialize_true(obj)
- when 'FalseClass'
- return serialize_false(obj)
- when 'Class'
- return serialize_class(obj)
- when 'Module'
- return serialize_module(obj)
- when 'Symbol'
- return serialize_symbol(obj)
when 'String'
- ivar_prefix = serialize_instance_variables_prefix(obj)
- ivar_suffix = serialize_instance_variables_suffix(obj, cls, sup, depth)
- return ivar_prefix + serialize_string(obj) + ivar_suffix
- when / Integer | Fixnum | Bignum /x
- if obj >= -2**30 and obj <= (2**30 - 1)
- return serialize_fixnum(obj)
- else
- return serialize_bignum(obj)
+ if obj.class != String
+ return obj.to_marshal(depth, true, obj.class)
end
when 'Regexp'
- ivar_prefix = serialize_instance_variables_prefix(obj)
- ivar_suffix = serialize_instance_variables_suffix(obj, cls, sup, depth)
- return ivar_prefix + serialize_regexp(obj) + ivar_suffix
- when 'Struct'
- return serialize_struct(obj, depth)
+ if obj.class != Regexp
+ return obj.to_marshal(depth, true, obj.class)
+ end
end
end
- ivar_suffix = serialize_instance_variables_suffix(obj, cls, sup, depth)
- serialize_object(obj) + ivar_suffix
+ obj.to_marshal(depth)
end
def self.serialize_integer(n)
@@ -101,31 +212,6 @@ def self.serialize_integer(n)
s
end
- def self.serialize_nil(obj)
- TYPE_NIL
- end
-
- def self.serialize_true(obj)
- TYPE_TRUE
- end
-
- def self.serialize_false(obj)
- TYPE_FALSE
- end
-
- def self.serialize_symbol(obj)
- str = obj.to_s
- TYPE_SYMBOL + serialize_integer(str.length) + str
- end
-
- def self.serialize_class(obj)
- TYPE_CLASS + serialize_integer(obj.name.length) + obj.name
- end
-
- def self.serialize_module(obj)
- TYPE_MODULE + serialize_integer(obj.name.length) + obj.name
- end
-
def self.serialize_instance_variables_prefix(obj)
if obj.instance_variables.length > 0
TYPE_IVAR
@@ -134,83 +220,37 @@ def self.serialize_instance_variables_prefix(obj)
end
end
- def self.serialize_instance_variables_suffix(obj, cls, sup, depth)
- if cls == Object or obj.instance_variables.length > 0
+ def self.serialize_instance_variables_suffix(obj, depth = -1, version = false, subclass = nil)
+ if obj.class == Object or obj.instance_variables.length > 0
str = serialize_integer(obj.instance_variables.length)
obj.instance_variables.each do |ivar|
- o = obj.instance_variable_get(ivar.to_sym)
- str << serialize_symbol(ivar) +
- serialize(o, o.class, get_superclass(o.class), depth)
+ sym = ivar.to_sym
+ o = obj.instance_variable_get(sym)
+ str << sym.to_marshal(depth, false, subclass) +
+ o.to_marshal(depth, false, subclass)
end
str
else
''
end
end
- def self.serialize_extended_object(obj)
+ def self.serialize_extended_object(obj, depth = -1)
str = ''
get_module_names(obj).each do |mod_name|
- str << TYPE_EXTENDED + serialize_symbol(mod_name)
+ str << TYPE_EXTENDED + mod_name.to_sym.to_marshal(depth, false)
end
str
end
- def self.serialize_user_class(obj, cls)
- if obj.class != cls
- TYPE_UCLASS + serialize_symbol(obj.class.name)
+ def self.serialize_user_class(obj, depth, version, subclass)
+ if obj.class == subclass
+ TYPE_UCLASS + obj.class.name.to_sym.to_marshal(depth, false, subclass)
else
''
end
end
- def self.serialize_string(obj)
- serialize_extended_object(obj) +
- serialize_user_class(obj, String) +
- TYPE_STRING + serialize_integer(obj.length) + obj
- end
-
- def self.serialize_fixnum(obj)
- TYPE_FIXNUM + serialize_integer(obj)
- end
-
- def self.serialize_bignum(obj)
- str = TYPE_BIGNUM + (obj < 0 ? '-' : '+') + "\0"
- obj = obj.abs
- while obj != 0
- str << to_byte(obj & 0xFF)
- obj >>= 8
- end
- str << (str.length % 2 == 0 ? "\0" : '')
- str[2] = to_byte(((str.length - 7) / 2) + 7)
- str
- end
-
- def self.serialize_regexp(obj)
- str = obj.source
- serialize_extended_object(obj) +
- serialize_user_class(obj, Regexp) +
- TYPE_REGEXP + serialize_integer(str.length) +
- str + to_byte(obj.options & 0x7)
- end
-
- def self.serialize_object(obj)
- serialize_extended_object(obj) +
- TYPE_OBJECT + serialize_symbol(obj.class.name)
- end
-
- def self.serialize_struct(obj, depth)
- str = serialize_extended_object(obj) +
- TYPE_STRUCT + serialize_symbol(obj.class.name) +
- serialize_integer(obj.length)
-
- obj.each_pair do |sym, val|
- str << serialize_symbol(sym) +
- serialize(val, val.class, get_superclass(val.class), depth)
- end
- str
- end
-
def self.get_superclass(cls)
sup = cls.superclass
while sup and sup.superclass and sup.superclass != Object

0 comments on commit 2828a28

Please sign in to comment.