Пример #1
0
            private void _read()
            {
                _code = ((RubyMarshal.Codes)m_io.ReadU1());
                switch (Code)
                {
                case RubyMarshal.Codes.PackedInt: {
                    _body = new PackedInt(m_io, this, m_root);
                    break;
                }

                case RubyMarshal.Codes.Bignum: {
                    _body = new Bignum(m_io, this, m_root);
                    break;
                }

                case RubyMarshal.Codes.RubyArray: {
                    _body = new RubyArray(m_io, this, m_root);
                    break;
                }

                case RubyMarshal.Codes.RubySymbolLink: {
                    _body = new PackedInt(m_io, this, m_root);
                    break;
                }

                case RubyMarshal.Codes.RubyStruct: {
                    _body = new RubyStruct(m_io, this, m_root);
                    break;
                }

                case RubyMarshal.Codes.RubyString: {
                    _body = new RubyString(m_io, this, m_root);
                    break;
                }

                case RubyMarshal.Codes.InstanceVar: {
                    _body = new InstanceVar(m_io, this, m_root);
                    break;
                }

                case RubyMarshal.Codes.RubyHash: {
                    _body = new RubyHash(m_io, this, m_root);
                    break;
                }

                case RubyMarshal.Codes.RubySymbol: {
                    _body = new RubySymbol(m_io, this, m_root);
                    break;
                }

                case RubyMarshal.Codes.RubyObjectLink: {
                    _body = new PackedInt(m_io, this, m_root);
                    break;
                }
                }
            }
Пример #2
0
        public static MutableString TagUri(RubyStruct /*!*/ self)
        {
            MutableString str          = MutableString.Create("tag:ruby.yaml.org,2002:struct:");
            string        name         = self.Class.Name;
            string        structPrefix = "Struct::";

            if (name.StartsWith(structPrefix))
            {
                name = name.Substring(structPrefix.Length);
            }
            return(str.Append(name));
        }
Пример #3
0
        private static object ConstructRubyStruct(RubyConstructor /*!*/ ctor, string /*!*/ structName, Node /*!*/ node)
        {
            MappingNode mapping = node as MappingNode;

            if (mapping == null)
            {
                throw new ConstructorException("can only construct struct from mapping node");
            }

            if (structName.Length == 0)
            {
                // TODO:
                throw new NotSupportedException("anonymous structs not supported");
            }

            RubyContext context = ctor.GlobalScope.Context;
            RubyModule  module;

            // TODO: MRI calls "members" on an arbitrary object

            // MRI checks Struct first, then falls back to Object
            if (!context.TryGetModule(ctor.GlobalScope, "Struct::" + structName, out module) &&
                !context.TryGetModule(ctor.GlobalScope, structName, out module))
            {
                throw RubyExceptions.CreateTypeError("Undefined struct `{0}'", structName);
            }

            RubyClass cls = module as RubyClass;

            if (cls == null)
            {
                throw RubyExceptions.CreateTypeError("`{0}' is not a class", structName);
            }

            RubyStruct newStruct = RubyStruct.Create(cls);

            foreach (var pair in ctor.ConstructMapping(mapping))
            {
                var attributeName = pair.Key as MutableString;
                int index;

                // TODO: encoding
                if (attributeName != null && newStruct.TryGetIndex(attributeName.ToString(), out index))
                {
                    newStruct[index] = pair.Value;
                }
            }
            return(newStruct);
        }
Пример #4
0
        public static MutableString /*!*/ TagUri(RubyStruct /*!*/ self)
        {
            MutableString str  = MutableString.CreateMutable("tag:ruby.yaml.org,2002:struct:", self.ImmediateClass.Context.GetIdentifierEncoding());
            string        name = self.ImmediateClass.GetNonSingletonClass().Name;

            if (name != null)
            {
                string structPrefix = "Struct::";
                if (name.StartsWith(structPrefix, StringComparison.Ordinal))
                {
                    name = name.Substring(structPrefix.Length);
                }
            }
            return(str.Append(name));
        }
Пример #5
0
        public static Node /*!*/ ToYamlNode(RubyStruct /*!*/ self, [NotNull] RubyRepresenter /*!*/ rep)
        {
            var fieldNames = self.GetNames();

            var fields = new Dictionary <Node, Node>(fieldNames.Count);

            for (int i = 0; i < fieldNames.Count; i++)
            {
                fields[rep.Scalar(null, fieldNames[i], ScalarQuotingStyle.None)] = rep.RepresentItem(self.Values[i]);
            }

            var map = new Dictionary <object, object>();

            rep.AddYamlProperties(map, self, false);
            return(rep.Map(fields, rep.GetTagUri(self), map, FlowStyle.Block));
        }
Пример #6
0
        public static Node ToYamlNode(RubyStruct /*!*/ self, [NotNull] RubyRepresenter /*!*/ rep)
        {
            RubyContext context = self.Class.Context;
            RubyArray   members = _Members.Target(_Members, context, self);
            RubyArray   values  = _Values.Target(_Values, context, self);

            if (members.Count != values.Count)
            {
                throw new ArgumentException("Struct values and members returned arrays of different lengths");
            }

            Hash map = new Hash(self.Class.Context);

            for (int i = 0; i < members.Count; i++)
            {
                IDictionaryOps.SetElement(context, map, members[i], values[i]);
            }
            RubyRepresenter.AddYamlProperties(context, self, map);
            return(rep.Map(self, map));
        }
Пример #7
0
        public static object /*!*/ CreateObject(RubyClass /*!*/ theClass)
        {
            Assert.NotNull(theClass);

            Type baseType = theClass.GetUnderlyingSystemType();

            if (baseType == typeof(RubyStruct))
            {
                return(RubyStruct.Create(theClass));
            }

            object          result;
            BindingFlags    bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
            ConstructorInfo ci;

            if (IsAvailable(ci = baseType.GetConstructor(bindingFlags, null, Type.EmptyTypes, null)))
            {
                result = ci.Invoke(new object[0] {
                });
            }
            else if (IsAvailable(ci = baseType.GetConstructor(bindingFlags, null, _ccTypes1, null)))
            {
                result = ci.Invoke(new object[1] {
                    theClass
                });
            }
            else if (IsAvailable(ci = baseType.GetConstructor(bindingFlags, null, _ccTypes2, null)))
            {
                result = ci.Invoke(new object[1] {
                    theClass.Context
                });
            }
            else
            {
                string message = String.Format("Class {0} does not have a valid constructor", theClass.Name);
                throw new NotSupportedException(message);
            }
            return(result);
        }
Пример #8
0
        public static object ConstructRubyStruct(IConstructor ctor, string className, Node node)
        {
            MappingNode mapping = node as MappingNode;

            if (mapping == null)
            {
                throw new ConstructorException("can only construct struct from mapping node");
            }

            RubyScope  scope = ctor.Scope;
            RubyModule module;
            RubyClass  cls;

            if (scope.RubyContext.TryGetModule(scope.GlobalScope, className, out module))
            {
                cls = module as RubyClass;
                if (cls == null)
                {
                    throw new ConstructorException("Struct type name must be Ruby class");
                }
            }
            else
            {
                RubyModule structModule = scope.RubyContext.GetModule(typeof(RubyStruct));
                cls = RubyUtils.GetConstant(scope, structModule, className, false) as RubyClass;
                if (cls == null)
                {
                    throw new ConstructorException(String.Format("Cannot find struct class \"{0}\"", className));
                }
            }

            RubyStruct newStruct = RubyStruct.Create(cls);

            foreach (var pair in ctor.ConstructMapping(mapping))
            {
                RubyStructOps.SetValue(newStruct, SymbolTable.StringToId(pair.Key.ToString()), pair.Value);
            }
            return(newStruct);
        }
 public static object TransformToNativeModel(this RubyStruct self)
 {
     return(self);
 }
Пример #10
0
        /// <summary>
        ///     static VALUE r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
        /// </summary>
        /// <param name="hasivp"></param>
        /// <param name="ivp"></param>
        /// <param name="extmod"></param>
        /// <returns></returns>
        public object ReadObject0(bool hasivp, ref bool ivp, List <RubyModule> extmod)
        {
            object v    = null;
            var    type = ReadByte();

            switch (type)
            {
            case RubyMarshal.Types.LINK:
                var    id = ReadLong();
                object link;
                if (!_m_objects.TryGetValue(id, out link))
                {
                    throw new InvalidDataException("dump format error (unlinked)");
                }
                v = link;
                if (_m_proc != null)
                {
                    v = _m_proc(v);
                }
                break;

            case RubyMarshal.Types.INSTANCE_VARIABLE:
            {
                var ivar = true;
                v = ReadObject0(ref ivar, extmod);
                var hasenc = false;
                if (ivar)
                {
                    ReadInstanceVariable(v, ref hasenc);
                }
            }
            break;

            case RubyMarshal.Types.EXTENDED:
            {
                var m = RubyModule.GetModule(ReadUnique());
                if (extmod == null)
                {
                    extmod = new List <RubyModule>();
                }
                extmod.Add(m);
                v = ReadObject0(extmod);
                if (v is RubyObject fobj)
                {
                    fobj.ExtendModules.AddRange(extmod);
                }
            }
            break;

            case RubyMarshal.Types.USER_CLASS:
            {
                var c = RubyClass.GetClass(ReadUnique());
                v = ReadObject0(extmod);
                if (v is RubyObject)
                {
                    (v as RubyObject).ClassName = c.Symbol;
                }
            }
            break;

            case RubyMarshal.Types.NIL:
                v = RubyNil.Instance;
                v = Leave(v);
                break;

            case RubyMarshal.Types.TRUE:
                v = RubyBool.True;
                v = Leave(v);
                break;

            case RubyMarshal.Types.FALSE:
                v = RubyBool.False;
                v = Leave(v);
                break;

            case RubyMarshal.Types.FIXNUM:
                v = ReadLong();
                v = new RubyFixnum(Convert.ToInt64(v));
                v = Leave(v);
                break;

            case RubyMarshal.Types.FLOAT:
            {
                double d;
                var    fstr = ReadString();
                var    str  = fstr.Text;

                switch (str)
                {
                case "inf":
                    d = double.PositiveInfinity;
                    break;

                case "-inf":
                    d = double.NegativeInfinity;
                    break;

                case "nan":
                    d = double.NaN;
                    break;

                default:
                    if (str.Contains("\0"))
                    {
                        str = str.Remove(str.IndexOf("\0", StringComparison.Ordinal));
                    }

                    d = Convert.ToDouble(str);
                    break;
                }
                v = new RubyFloat(d);
                v = Entry(v);
                v = Leave(v);
            }
            break;

            case RubyMarshal.Types.BIGNUM:
            {
                var sign = 0;
                switch (ReadByte())
                {
                case 0x2b:
                    sign = 1;
                    break;

                case 0x2d:
                    sign = -1;
                    break;

                default:
                    sign = 0;
                    break;
                }
                var num3  = ReadLong();
                var index = num3 / 2;
                var num5  = (num3 + 1) / 2;
                var data  = new uint[num5];
                for (var i = 0; i < index; i++)
                {
                    data[i] = _m_reader.ReadUInt32();
                }
                if (index != num5)
                {
                    data[index] = _m_reader.ReadUInt16();
                }
                v = new RubyBignum(sign, data);
                v = Entry(v);
                v = Leave(v);
            }
            break;

            case RubyMarshal.Types.STRING:
                v = Entry(ReadString());
                v = Leave(v);
                break;

            case RubyMarshal.Types.REGEXP:
            {
                var str          = ReadString();
                var options      = ReadByte();
                var has_encoding = false;
                var idx          = Prepare();
                if (hasivp)
                {
                    ReadInstanceVariable(str, ref has_encoding);
                    ivp = false;
                }
                if (!has_encoding)
                {
                    // TODO: 1.8 compatibility; remove escapes undefined in 1.8

                    /*
                     * char *ptr = RSTRING_PTR(str), *dst = ptr, *src = ptr;
                     * long len = RSTRING_LEN(str);
                     * long bs = 0;
                     * for (; len-- > 0; *dst++ = *src++) {
                     *  switch (*src) {
                     *      case '\\': bs++; break;
                     *      case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
                     *      case 'm': case 'o': case 'p': case 'q': case 'u': case 'y':
                     *      case 'E': case 'F': case 'H': case 'I': case 'J': case 'K':
                     *      case 'L': case 'N': case 'O': case 'P': case 'Q': case 'R':
                     *      case 'S': case 'T': case 'U': case 'V': case 'X': case 'Y':
                     *      if (bs & 1) --dst;
                     *      default: bs = 0; break;
                     *  }
                     * }
                     * rb_str_set_len(str, dst - ptr);
                     */
                }
                v = Entry0(new RubyRegexp(str, (RubyRegexpOptions)options), idx);
                v = Leave(v);
            }
            break;

            case RubyMarshal.Types.ARRAY:
            {
                var len = ReadLong();
                var ary = new RubyArray();
                v = ary;
                v = Entry(v);
                while (len-- > 0)
                {
                    ary.Push(ReadObject());
                }
                v = Leave(v);
            }
            break;

            case RubyMarshal.Types.HASH:
            case RubyMarshal.Types.HASH_WITH_DEFAULT:
            {
                var len  = ReadLong();
                var hash = new RubyHash();
                v = hash;
                v = Entry(v);
                while (len-- > 0)
                {
                    var key   = ReadObject();
                    var value = ReadObject();
                    hash.Add(key, value);
                }
                if (type == RubyMarshal.Types.HASH_WITH_DEFAULT)
                {
                    hash.DefaultValue = ReadObject();
                }
                v = Leave(v);
            }
            break;

            case RubyMarshal.Types.STRUCT:
            {
                var idx   = Prepare();
                var obj   = new RubyStruct();
                var klass = ReadUnique();
                obj.ClassName = klass;
                var len = ReadLong();
                v = obj;
                v = Entry0(v, idx);
                while (len-- > 0)
                {
                    var key   = ReadSymbol();
                    var value = ReadObject();
                    obj.InstanceVariable[key] = value;
                }
                v = Leave(v);
            }
            break;

            case RubyMarshal.Types.USER_DEFINED:
            {
                var klass = ReadUnique();
                var obj   = RubyUserDefinedObject.TryGetUserDefinedObject(klass.Name);
                if (obj == null)
                {
                    var data = ReadString();
                    if (hasivp)
                    {
                        ReadInstanceVariable(data);
                        ivp = false;
                    }
                    obj = new DefaultRubyUserDefinedDumpObject {
                        Raw = data.Raw
                    };
                }
                else
                {
                    obj.Read(_m_reader);
                }
                obj.ClassName = klass;
                v             = obj;
                v             = Entry(v);
                v             = Leave(v);
            }
            break;

            case RubyMarshal.Types.USER_MARSHAL:
            {
                var klass = ReadUnique();
                var obj   = new DefaultRubyUserDefinedMarshalDumpObject();
                v = obj;
                if (extmod != null)
                {
                    AppendExtendedModule(obj, extmod);
                }
                v = Entry(v);
                var data = ReadObject();
                obj.ClassName    = klass;
                obj.DumpedObject = data;
                v = Leave(v);
                extmod?.Clear();
            }
            break;

            case RubyMarshal.Types.OBJECT:
            {
                var idx   = Prepare();
                var obj   = new RubyObject();
                var klass = ReadUnique();
                obj.ClassName = klass;
                v             = obj;
                v             = Entry0(v, idx);
                ReadInstanceVariable(v);
                v = Leave(v);
            }
            break;

            case RubyMarshal.Types.CLASS:
            {
                var str = ReadString();
                v = RubyClass.GetClass(RubySymbol.GetSymbol(str));
                v = Entry(v);
                v = Leave(v);
            }
            break;

            case RubyMarshal.Types.MODULE:
            {
                var str = ReadString();
                v = RubyModule.GetModule(RubySymbol.GetSymbol(str));
                v = Entry(v);
                v = Leave(v);
            }
            break;

            case RubyMarshal.Types.SYMBOL:
                if (hasivp)
                {
                    v   = ReadSymbolReal(ivp);
                    ivp = false;
                }
                else
                {
                    v = ReadSymbolReal(false);
                }
                v = Leave(v);
                break;

            case RubyMarshal.Types.SYMBOL_LINK:
                v = ReadSymbolLink();
                break;

            case RubyMarshal.Types.DATA:
            /*  TODO: Data Support
             *  {
             *      VALUE klass = path2class(r_unique(arg));
             *      VALUE oldclass = 0;
             *
             *      v = obj_alloc_by_klass(klass, arg, &oldclass);
             *      if (!RB_TYPE_P(v, T_DATA)) {
             *          rb_raise(rb_eArgError, "dump format error");
             *      }
             *      v = r_entry(v, arg);
             *      if (!rb_respond_to(v, s_load_data)) {
             *          rb_raise(rb_eTypeError, "class %s needs to have instance method `_load_data'", rb_class2name(klass));
             *      }
             *      rb_funcall(v, s_load_data, 1, r_object0(arg, 0, extmod));
             *      check_load_arg(arg, s_load_data);
             *      v = r_leave(v, arg);
             *  }
             */
            case RubyMarshal.Types.MODULE_OLD:
            /*
             *  TODO: ModuleOld Support
             *  {
             *      volatile VALUE str = r_bytes(arg);
             *      v = rb_path_to_class(str);
             *      v = r_entry(v, arg);
             *      v = r_leave(v, arg);
             *  }
             */
            default:
                throw new InvalidDataException($"dump format error(0x{type:X2})");
            }
            return(v);
        }