예제 #1
0
        /// <summary>
        ///     static void w_object(VALUE obj, struct dump_arg *arg, int limit)
        /// </summary>
        /// <param name="obj"></param>
        public void WriteObject(object obj)
        {
            int num;

            if (_m_objects.TryGetValue(obj, out num))
            {
                WriteByte(RubyMarshal.Types.LINK);
                WriteLong(num);
                return;
            }
            if (obj == null || obj == RubyNil.Instance)
            {
                WriteByte(RubyMarshal.Types.NIL);
            }
            else if (obj is bool && (bool)obj)
            {
                WriteByte(RubyMarshal.Types.TRUE);
            }
            else if (obj is bool && (bool)obj == false)
            {
                WriteByte(RubyMarshal.Types.FALSE);
            }
            else if (obj is RubyBool ruby_bool)
            {
                WriteByte(ruby_bool.Value ? RubyMarshal.Types.TRUE : RubyMarshal.Types.FALSE);
            }
            else if (obj is int || obj is long || obj is RubyFixnum)
            {
                long v;
                if (obj is int | obj is long)
                {
                    v = (long)obj;
                }
                else
                {
                    v = ((RubyFixnum)obj).Value;
                }
                // (2**30).class   => Bignum
                // (2**30-1).class => Fixnum
                // (-2**30-1).class=> Bignum
                // (-2**30).class  => Fixnum
                if (v <= RubyFixnum.MaxValue && v >= RubyFixnum.MinValue)
                {
                    WriteByte(RubyMarshal.Types.FIXNUM);
                    WriteLong((int)v);
                }
                else
                {
                    WriteObject(RubyBignum.Create(v));
                }
            }
            else if (obj is RubySymbol ruby_symbol)
            {
                WriteSymbol(ruby_symbol);
            }

            else
            {
                var fobj  = obj as RubyObject;
                var hasiv = false;
                if (fobj != null)
                {
                    hasiv = (obj is RubyArray || obj is RubyHash) && fobj.InstanceVariables.Count > 0;
                }
                if (fobj is RubyString ruby_string)
                {
                    hasiv |= StringStyle == RubyMarshal.StringStyleType.Style19 && fobj.Encoding != null &&
                             ruby_string.Text.Length > 0;
                }

                if (obj is DefaultRubyUserDefinedMarshalDumpObject default_ruby_user_defined_marshal_dump_object)
                {
                    if (hasiv)
                    {
                        WriteByte(RubyMarshal.Types.INSTANCE_VARIABLE);
                    }
                    WriteClass(RubyMarshal.Types.USER_MARSHAL, obj, false);
                    default_ruby_user_defined_marshal_dump_object.Write(_m_writer);
                    if (hasiv)
                    {
                        WriteObjectInstanceVariable(fobj);
                    }
                    _m_objects.Add(obj, _m_objects.Count);
                    return;
                }
                if (obj is RubyUserDefinedObject ruby_user_defined_object)
                {
                    if (hasiv)
                    {
                        WriteByte(RubyMarshal.Types.INSTANCE_VARIABLE);
                    }
                    _m_writer.Write(RubyMarshal.Types.USER_DEFINED);
                    WriteSymbol(fobj.ClassName);
                    ruby_user_defined_object.Write(_m_writer);
                    if (hasiv)
                    {
                        WriteObjectInstanceVariable(fobj);
                    }
                    _m_objects.Add(obj, _m_objects.Count);
                    return;
                }

                _m_objects.Add(obj, _m_objects.Count);

                if (hasiv)
                {
                    WriteByte(RubyMarshal.Types.INSTANCE_VARIABLE);
                }

                if (obj is RubyClass ruby_class)
                {
                    WriteByte(RubyMarshal.Types.CLASS);
                    WriteCString(ruby_class.Name);
                }
                else if (obj is RubyModule ruby_module)
                {
                    WriteByte(RubyMarshal.Types.MODULE);
                    WriteCString(ruby_module.Name);
                }
                else if (obj is float _float)
                {
                    WriteByte(RubyMarshal.Types.FLOAT);
                    WriteFloat(_float);
                }
                else if (obj is double _double)
                {
                    WriteByte(RubyMarshal.Types.FLOAT);
                    WriteFloat(_double);
                }
                else if (obj is RubyFloat ruby_float)
                {
                    WriteByte(RubyMarshal.Types.FLOAT);
                    WriteFloat(ruby_float);
                }
                else if (obj is RubyBignum ruby_bignum)
                {
                    char ch;
                    if (ruby_bignum.Sign > 0)
                    {
                        ch = '+';
                    }
                    else if (ruby_bignum.Sign < 0)
                    {
                        ch = '-';
                    }
                    else
                    {
                        ch = '0';
                    }
                    _m_writer.Write((byte)ch);
                    var words = ruby_bignum.GetWords();
                    var num2  = words.Length * 2;
                    var index = words.Length - 1;

                    /*
                     * var flag = false;
                     * if (words.Length > 0 && words[index] >> 0x10 == 0)
                     * {
                     *  num--;
                     *  flag = true;
                     * }*/
                    var flag = words.Length > 0 && words[index] >> 0x10 == 0;
                    WriteLong(num2);
                    for (var i = 0; i < words.Length; i++)
                    {
                        if (flag && i == index)
                        {
                            _m_writer.Write((ushort)words[i]);
                        }
                        else
                        {
                            _m_writer.Write(words[i]);
                        }
                    }
                }
                else if (obj is RubyString || obj is string)
                {
                    RubyString v;
                    if (obj is string _string)
                    {
                        v = new RubyString(_string);
                    }
                    else
                    {
                        v = (RubyString)obj;
                    }
                    WriteUserClass(v, RubyClass.GetClass("String"));
                    WriteByte(RubyMarshal.Types.STRING);
                    WriteBytes(v.Raw);
                }
                else if (obj is RubyRegexp ruby_regexp)
                {
                    WriteUserClass(obj, RubyClass.GetClass("Regexp"));
                    WriteByte(RubyMarshal.Types.REGEXP);
                    WriteBytes(ruby_regexp.pattern.Raw);
                    WriteByte((byte)ruby_regexp.options);
                }
                else if (obj is RubyArray || obj is List <object> )
                {
                    RubyArray v;
                    if (obj is List <object> list)
                    {
                        v = new RubyArray(list);
                    }
                    else
                    {
                        v = (RubyArray)obj;
                    }
                    WriteUserClass(v, RubyClass.GetClass("Array"));
                    WriteByte(RubyMarshal.Types.ARRAY);
                    WriteLong(v.Length);
                    foreach (var t in v)
                    {
                        WriteObject(t);
                    }
                }
                else if (obj is RubyHash ruby_hash)
                {
                    WriteUserClass(obj, RubyClass.GetClass("Hash"));
                    WriteByte(ruby_hash.DefaultValue != null
                        ? RubyMarshal.Types.HASH_WITH_DEFAULT
                        : RubyMarshal.Types.HASH);
                    WriteLong(ruby_hash.Length);
                    foreach (var item in ruby_hash)
                    {
                        WriteObject(item.Key);
                        WriteObject(item.Value);
                    }
                    if (ruby_hash.DefaultValue != null)
                    {
                        WriteObject(ruby_hash.DefaultValue);
                    }
                }
                else if (obj is RubyStruct ruby_struct)
                {
                    WriteUserClass(obj, RubyClass.GetClass("Struct"));
                    WriteLong(ruby_struct.InstanceVariables.Count);
                    foreach (var item in ruby_struct.InstanceVariables)
                    {
                        WriteObject(item.Key);
                        WriteObject(item.Value);
                    }
                }
                else if (obj is RubyObject ruby_object)
                {
                    WriteClass(RubyMarshal.Types.OBJECT, obj, true);
                    WriteObjectInstanceVariable(ruby_object);
                }
                else
                {
                    throw new InvalidDataException($"can't dump {obj.GetType().FullName}");
                }
                if (hasiv)
                {
                    WriteInstanceVariable(fobj, fobj.InstanceVariables);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// static void w_object(VALUE obj, struct dump_arg *arg, int limit)
        /// </summary>
        /// <param name="obj"></param>
        public void WriteObject(object obj)
        {
            int num;

            if (this.m_objects.TryGetValue(obj, out num))
            {
                WriteByte(RubyMarshal.Types.Link);
                WriteLong(num);
                return;
            }
            if (obj == null || obj == RubyNil.Instance)
            {
                WriteByte(RubyMarshal.Types.Nil);
            }
            else if (obj is bool && (bool)obj == true)
            {
                WriteByte(RubyMarshal.Types.True);
            }
            else if (obj is bool && (bool)obj == false)
            {
                WriteByte(RubyMarshal.Types.False);
            }
            else if (obj is int)
            {
                int v = (int)obj;
                // (2**30).class   => Bignum
                // (2**30-1).class => Fixnum
                // (-2**30-1).class=> Bignum
                // (-2**30).class  => Fixnum
                if (v <= 1073741823 && v >= -1073741824)
                {
                    WriteByte(RubyMarshal.Types.Fixnum);
                    WriteLong(v);
                }
                else
                {
                    WriteObject(RubyBignum.Create(v));
                }
            }
            else if (obj is RubySymbol)
            {
                WriteSymbol(obj as RubySymbol);
            }
            else
            {
                RubyObject fobj  = obj as RubyObject;
                bool       hasiv = false;
                if (fobj != null)
                {
                    hasiv = (obj as RubyObject).InstanceVariables.Count > 0 || fobj.Encoding != null;
                }

                if (obj is IRubyUserdefinedMarshalDumpObject)
                {
                    this.m_objects.Add(obj, this.m_objects.Count);
                    object result = (obj as IRubyUserdefinedMarshalDumpObject).Dump();
                    if (hasiv)
                    {
                        WriteByte(RubyMarshal.Types.InstanceVariable);
                    }
                    WriteClass(RubyMarshal.Types.UserMarshal, obj, false);
                    WriteObject(result);
                    if (hasiv)
                    {
                        WriteObjectInstanceVariable(fobj);
                    }
                    return;
                }
                if (obj is IRubyUserdefinedDumpObject)
                {
                    byte[] result = (obj as IRubyUserdefinedDumpObject).Dump();
                    if (hasiv)
                    {
                        WriteByte(RubyMarshal.Types.InstanceVariable);
                    }
                    WriteClass(RubyMarshal.Types.UserDefined, obj, false);
                    WriteBytes(result, result.Length);
                    if (hasiv)
                    {
                        WriteObjectInstanceVariable(fobj);
                    }
                    this.m_objects.Add(obj, this.m_objects.Count);
                    return;
                }
                this.m_objects.Add(obj, this.m_objects.Count);

                /*
                 * {
                 *  st_data_t compat_data;
                 *  rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
                 *  if (st_lookup(compat_allocator_tbl,
                 *                (st_data_t)allocator,
                 *                &compat_data)) {
                 *      marshal_compat_t *compat = (marshal_compat_t*)compat_data;
                 *      VALUE real_obj = obj;
                 *      obj = compat->dumper(real_obj);
                 *      st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
                 *      if (obj != real_obj && !ivtbl) hasiv = 0;
                 *  }
                 * }*/

                if (hasiv)
                {
                    WriteByte(RubyMarshal.Types.InstanceVariable);
                }

                if (obj is RubyClass)
                {
                    WriteByte(RubyMarshal.Types.Class);
                    WriteCString((obj as RubyClass).Name);
                }
                else if (obj is RubyModule)
                {
                    WriteByte(RubyMarshal.Types.Module);
                    WriteCString((obj as RubyModule).Name);
                }
                else if (obj is float)
                {
                    WriteByte(RubyMarshal.Types.Float);
                    WriteFloat((float)obj);
                }
                else if (obj is double)
                {
                    WriteByte(RubyMarshal.Types.Float);
                    WriteFloat((double)obj);
                }
                else if (obj is RubyFloat)
                {
                    WriteByte(RubyMarshal.Types.Float);
                    WriteFloat((RubyFloat)obj);
                }
                else if (obj is RubyBignum)
                {
                    RubyBignum value = (RubyBignum)obj;
                    char       ch;
                    if (value.Sign > 0)
                    {
                        ch = '+';
                    }
                    else if (value.Sign < 0)
                    {
                        ch = '-';
                    }
                    else
                    {
                        ch = '0';
                    }
                    this.m_writer.Write((byte)ch);
                    uint[] words = value.GetWords();
                    int    num2  = words.Length * 2;
                    int    index = words.Length - 1;
                    bool   flag  = false;
                    if ((words.Length > 0) && ((words[index] >> 0x10) == 0))
                    {
                        num--;
                        flag = true;
                    }
                    this.WriteLong(num2);
                    for (int i = 0; i < words.Length; i++)
                    {
                        if (flag && (i == index))
                        {
                            this.m_writer.Write((ushort)words[i]);
                        }
                        else
                        {
                            this.m_writer.Write(words[i]);
                        }
                    }
                }
                else if (obj is RubyString || obj is string)
                {
                    RubyString v;
                    if (obj is string)
                    {
                        v = new RubyString(obj as string);
                    }
                    else
                    {
                        v = (RubyString)obj;
                    }
                    WriteUserClass(v, RubyClass.GetClass("String"));
                    WriteByte(RubyMarshal.Types.String);
                    WriteBytes(v.Raw);
                }
                else if (obj is RubyRegexp)
                {
                    RubyRegexp v = (RubyRegexp)obj;
                    WriteUserClass(obj, RubyClass.GetClass("Regexp"));
                    WriteByte(RubyMarshal.Types.Regexp);
                    WriteBytes(v.Pattern.Raw);
                    WriteByte((byte)v.Options);
                }
                else if (obj is RubyArray || obj is List <object> )
                {
                    RubyArray v;
                    if (obj is List <object> )
                    {
                        v = new RubyArray(obj as List <object>);
                    }
                    else
                    {
                        v = (RubyArray)obj;
                    }
                    WriteUserClass(v, RubyClass.GetClass("Array"));
                    WriteByte(RubyMarshal.Types.Array);
                    WriteLong(v.Length);
                    for (int i = 0; i < v.Count; i++)
                    {
                        WriteObject(v[i]);
                    }
                }
                else if (obj is RubyHash)
                {
                    RubyHash v = (RubyHash)obj;
                    WriteUserClass(obj, RubyClass.GetClass("Hash"));
                    WriteByte(v.DefaultValue != null ? RubyMarshal.Types.HashWithDefault : RubyMarshal.Types.Hash);
                    WriteLong(v.Length);
                    foreach (KeyValuePair <object, object> item in v)
                    {
                        WriteObject(item.Key);
                        WriteObject(item.Value);
                    }
                    if (v.DefaultValue != null)
                    {
                        WriteObject(v.DefaultValue);
                    }
                }
                else if (obj is RubyStruct)
                {
                    RubyStruct v = (RubyStruct)obj;
                    WriteUserClass(obj, RubyClass.GetClass("Struct"));
                    WriteLong(v.InstanceVariables.Count);
                    foreach (KeyValuePair <RubySymbol, object> item in v.InstanceVariables)
                    {
                        WriteObject(item.Key);
                        WriteObject(item.Value);
                    }
                }
                else if (obj is RubyObject)
                {
                    WriteClass(RubyMarshal.Types.Object, obj, true);
                    WriteObjectInstanceVariable((RubyObject)obj);
                }

                /* TODO: Data
                 * case T_DATA:
                 *  {
                 *      VALUE v;
                 *
                 *      if (!rb_respond_to(obj, s_dump_data)) {
                 *          rb_raise(rb_eTypeError,
                 *                   "no _dump_data is defined for class %s",
                 *                   rb_obj_classname(obj));
                 *      }
                 *      v = rb_funcall(obj, s_dump_data, 0);
                 *      check_dump_arg(arg, s_dump_data);
                 *      w_class(TYPE_DATA, obj, arg, TRUE);
                 *      w_object(v, arg, limit);
                 *  }
                 *  break;*/
                else
                {
                    throw new InvalidDataException(string.Format("can't dump {0}", obj.GetType().FullName));
                }
                if (hasiv)
                {
                    WriteInstanceVariable(fobj, fobj.InstanceVariables);
                }
            }
        }