internal static void w_ivar(System.Collections.Generic.Dictionary<string, object> tbl, dump_call_arg arg, Frame caller) { if (tbl != null && tbl.Count > 0) { w_long(tbl.Count, arg.arg, caller); foreach (System.Collections.Generic.KeyValuePair<string, object> IDValuePair in tbl) { w_symbol((int)Symbol.rb_intern(IDValuePair.Key), arg.arg, caller); w_object(IDValuePair.Value, arg.arg, arg.limit, caller); } } else { w_long(0, arg.arg, caller); } }
internal static void w_object(object obj, dump_arg arg, int limit, Frame caller) { dump_call_arg c_arg = new dump_call_arg(); System.Collections.Generic.Dictionary<string, object> ivtbl = null; // st_data_t num; if (limit == 0) { throw new ArgumentError("exceed depth limit").raise(caller); } limit--; c_arg.limit = limit; c_arg.arg = arg; if (obj != null && arg.data.ContainsKey(obj)) { int num = arg.data[obj]; w_byte(TYPE_LINK, arg, caller); w_long(num, arg, caller); return; } ivtbl = Object.get_generic_ivars(obj); if (ivtbl != null) { w_byte(TYPE_IVAR, arg, caller); } if (obj == null) { w_byte(TYPE_NIL, arg, caller); } else if (obj is bool && (bool)obj == true) { w_byte(TYPE_TRUE, arg, caller); } else if (obj is bool && (bool)obj == false) { w_byte(TYPE_FALSE, arg, caller); } else if (obj is int) { w_byte((char)TYPE_FIXNUM, arg, caller); w_long((int)obj, arg, caller); } else if (obj is Symbol) { //FIXME: This code isn't being reached at the moment. //should be ok since the latest fixes - haven't tested this though w_symbol((int)((Symbol)obj).id_new, arg, caller); } else { if (((Basic)obj).Tainted) { arg.taint = true; } arg.data[obj] = arg.data.Count; if (Eval.RespondTo(obj, s_mdump)) { object v; v = Eval.CallPublic0(obj, caller, s_mdump, null); w_class(TYPE_USRMARSHAL, obj, arg, false, caller); w_object(v, arg, limit, caller); if (ivtbl != null) w_ivar(null, c_arg, caller); return; } if (Eval.RespondTo(obj, s_dump)) //TEST: { object v; v = Eval.CallPrivate(obj, caller, s_dump, null, limit); if (!(v is String)) { throw new TypeError("_dump() must return string").raise(caller); } if (ivtbl == null && (ivtbl = Object.get_generic_ivars(v)) != null) { w_byte(TYPE_IVAR, arg, caller); } w_class(TYPE_USERDEF, obj, arg, false, caller); w_bytes(((String)v).value, ((String)v).value.Length, arg, caller); if (ivtbl != null) { w_ivar(ivtbl, c_arg, caller); } return; } if (obj is Class) { if (((Class)obj)._type == Class.Type.Class) { if (((Class)obj)._type == Class.Type.Singleton) { throw new TypeError("singleton class can't be dumped").raise(caller); } w_byte(TYPE_CLASS, arg, caller); { object path = class2path(obj, caller); w_bytes(((String)path).value, ((String)path).value.Length, arg, caller); } } else if (((Class)obj)._type == Class.Type.Module)//TEST: { w_byte(TYPE_MODULE, arg, caller); { object path = class2path(obj, caller); w_bytes(((String)path).value, ((String)path).value.Length, arg, caller); } } } else if (obj is Float) { w_byte((char)TYPE_FLOAT, arg, caller); w_float(((Float)obj).value, arg, caller); } else if (obj is Bignum) { w_byte((char)TYPE_BIGNUM, arg, caller); { char sign = ((Bignum)(obj)).value.Sign < 0 ? '-' : '+'; long len = ((Bignum)(obj)).value.length; uint[] d = ((Bignum)(obj)).value.Data; w_byte((char)sign, arg, caller); w_long(shortlen(len, d), arg, caller); /* w_short? */ int dIndex = 0; while (len-- > 0) { uint num = d[dIndex]; int i; for (i = 0; i < SIZEOF_BDIGITS; i += SIZEOF_SHORT) { w_short((int)num & SHORTMASK, arg, caller); num = num >> BITSPERSHORT; if (len == 0 && num == 0) break; } dIndex++; } } } else if (obj is Struct) { w_class(TYPE_STRUCT, obj, arg, true, caller); { int len; object mem; len = StructLen(obj, caller); mem = rb_struct_members(obj, caller); w_long(len, arg, caller); for (int i = 0; i < len; i++) { string symbolString = (string)((Array)mem).value[i]; //no interning atm w_symbol((int)Symbol.rb_intern(symbolString), arg, caller); w_object(((Struct)obj).instance_vars[symbolString], arg, limit, caller); } } } else if (obj is String) { w_uclass(obj, Ruby.Runtime.Init.rb_cString, arg, caller); w_byte((char)TYPE_STRING, arg, caller); w_bytes(((String)obj).value, ((String)obj).value.Length, arg, caller); } else if (obj is Regexp) { w_uclass(obj, Ruby.Runtime.Init.rb_cRegexp, arg, caller); w_byte(TYPE_REGEXP, arg, caller); string regExpStr = ((Regexp)obj).value.ToString(); w_bytes(regExpStr, regExpStr.Length, arg, caller); w_byte((char)Regexp.rb_reg_options(caller, (Regexp)obj), arg, caller); } else if (obj is Array) { w_uclass(obj, Ruby.Runtime.Init.rb_cArray, arg, caller); w_byte((char)TYPE_ARRAY, arg, caller); { int len = ((Array)obj).Count; System.Collections.ArrayList ptr = ((Array)obj).value; w_long(len, arg, caller); foreach (object arrObj in ptr) { w_object(arrObj, arg, limit, caller); } } } else if (obj is Hash) { w_uclass(obj, Ruby.Runtime.Init.rb_cHash, arg, caller); if (((Hash)obj).defaultProc != null) throw new TypeError("cannot dump hash with default proc").raise(caller); else if (((Hash)obj).defaultValue == null) w_byte(TYPE_HASH, arg, caller); else w_byte(TYPE_HASH_DEF, arg, caller); w_long(((Hash)(obj)).value.Count, arg, caller); foreach (HashKeyValuePair pair in ((Hash)obj).value) { w_object(pair.Key.key, c_arg.arg, c_arg.limit, caller); w_object(pair.Value, c_arg.arg, c_arg.limit, caller); } if (((Hash)obj).defaultValue != null) w_object(((Hash)obj).defaultValue, arg, limit, caller); } else if (obj is Data) //TEST: { object v; w_class(TYPE_DATA, obj, arg, true, caller); if (!Eval.RespondTo(obj, s_dump_data)) throw new TypeError(string.Format(CultureInfo.InvariantCulture, "no marshal_dump is defined for class {0}", rb_obj_classname(obj, caller))).raise(caller); v = Eval.CallPrivate0(obj, caller, s_dump_data, null); w_object(v, arg, limit, caller); } else if (obj is Object)//TEST: { w_class(TYPE_OBJECT, obj, arg, true, caller); w_ivar(((Object)obj).instance_vars, c_arg, caller); } else throw new TypeError(string.Format(CultureInfo.InvariantCulture, "can't dump {0}", ((Basic)obj).my_class.classname())).raise(caller); } if (ivtbl != null) { w_ivar(ivtbl, c_arg, caller); } }
//---------------------------------------------------------------------------------- internal static object dump(dump_call_arg arg, Frame caller) { w_object(arg.obj, arg.arg, arg.limit, caller); if (arg.arg.dest != null) { rb_io_write(arg.arg.dest, arg.arg.str, caller); ((String)arg.arg.str).value = ""; } return null; }