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; } } }
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)); }
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); }
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)); }
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)); }
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)); }
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); }
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); }
/// <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); }