/// <summary> /// Internal ToString routine with correct collections printout. /// </summary> /// <param name="sb">String builder.</param> /// <param name="obj">Object to print.</param> /// <param name="handled">Already handled objects.</param> /// <returns>The same string builder.</returns> private static void ToString0(StringBuilder sb, object obj, IDictionary <int, int> handled) { IEnumerable col = (obj is string) ? null : obj as IEnumerable; if (col == null) { PortableUserObject obj0 = obj as PortableUserObject; sb.Append(obj0 == null ? obj : obj0.ToString(handled)); } else { sb.Append('['); bool first = true; foreach (object elem in col) { if (first) { first = false; } else { sb.Append(", "); } ToString0(sb, elem, handled); } sb.Append(']'); } }
/// <summary> /// Process portable object inverting handles if needed. /// </summary> /// <param name="outStream">Output stream.</param> /// <param name="port">Portable.</param> internal void ProcessPortable(IPortableStream outStream, PortableUserObject port) { // Special case: writing portable object with correct inversions. PortableHeapStream inStream = new PortableHeapStream(port.Data); inStream.Seek(port.Offset, SeekOrigin.Begin); // Use fresh context to ensure correct portable inversion. Mutate0(new Context(), inStream, outStream, false, 0, EmptyVals); }
/// <summary> /// Constructor. /// </summary> /// <param name="portables">Portables.</param> /// <param name="parent">Parent builder.</param> /// <param name="obj">Initial portable object.</param> /// <param name="desc">Type descriptor.</param> public PortableBuilderImpl(PortablesImpl portables, PortableBuilderImpl parent, PortableUserObject obj, IPortableTypeDescriptor desc) { _portables = portables; _parent = parent ?? this; _obj = obj; _desc = desc; _hashCode = obj.GetHashCode(); }
/** <inheritDoc /> */ public IPortableBuilder Builder(IPortableObject obj) { IgniteArgumentCheck.NotNull(obj, "obj"); PortableUserObject obj0 = obj as PortableUserObject; if (obj0 == null) { throw new ArgumentException("Unsupported object type: " + obj.GetType()); } IPortableTypeDescriptor desc = _marsh.Descriptor(true, obj0.TypeId()); return(Builder0(null, obj0, desc)); }
internal void Write <T>(T obj, object handler) { // Apply detach mode if needed. PortableHandleDictionary <object, long> oldHnds = null; bool resetDetach = false; if (_detach) { _detach = false; _detachMode = true; resetDetach = true; oldHnds = _hnds; _hnds = null; } try { // Write null. if (obj == null) { _stream.WriteByte(PortableUtils.HdrNull); return; } if (_builder != null) { // Special case for portable object during build. PortableUserObject portObj = obj as PortableUserObject; if (portObj != null) { if (!WriteHandle(_stream.Position, portObj)) { _builder.ProcessPortable(_stream, portObj); } return; } // Special case for builder during build. PortableBuilderImpl portBuilder = obj as PortableBuilderImpl; if (portBuilder != null) { if (!WriteHandle(_stream.Position, portBuilder)) { _builder.ProcessBuilder(_stream, portBuilder); } return; } } // Try writting as well-known type. if (InvokeHandler(handler, handler as PortableSystemWriteDelegate, obj)) { return; } Type type = obj.GetType(); IPortableTypeDescriptor desc = _marsh.Descriptor(type); object typedHandler; PortableSystemWriteDelegate untypedHandler; if (desc == null) { typedHandler = null; untypedHandler = PortableSystemHandlers.WriteHandler(type); } else { typedHandler = desc.TypedHandler; untypedHandler = desc.UntypedHandler; } if (InvokeHandler(typedHandler, untypedHandler, obj)) { return; } if (desc == null) { if (!type.IsSerializable) { // If neither handler, nor descriptor exist, and not serializable, this is an exception. throw new PortableException("Unsupported object type [type=" + type + ", object=" + obj + ']'); } Write(new SerializableObjectHolder(obj)); return; } int pos = _stream.Position; // Dealing with handles. if (!(desc.Serializer is IPortableSystemTypeSerializer) && WriteHandle(pos, obj)) { return; } // Write header. _stream.WriteByte(PortableUtils.HdrFull); _stream.WriteBool(desc.UserType); _stream.WriteInt(desc.TypeId); _stream.WriteInt(obj.GetHashCode()); // Skip length as it is not known in the first place. _stream.Seek(8, SeekOrigin.Current); // Preserve old frame. int oldTypeId = _curTypeId; IPortableNameMapper oldConverter = _curConverter; IPortableIdMapper oldMapper = _curMapper; IPortableMetadataHandler oldMetaHnd = _curMetaHnd; bool oldRaw = _curRaw; long oldRawPos = _curRawPos; // Push new frame. _curTypeId = desc.TypeId; _curConverter = desc.NameConverter; _curMapper = desc.Mapper; _curMetaHnd = desc.MetadataEnabled ? _marsh.MetadataHandler(desc) : null; _curRaw = false; _curRawPos = 0; // Write object fields. desc.Serializer.WritePortable(obj, this); // Calculate and write length. int retPos = _stream.Position; _stream.Seek(pos + 10, SeekOrigin.Begin); int len = retPos - pos; _stream.WriteInt(len); if (_curRawPos != 0) { // When set, it is difference between object head and raw position. _stream.WriteInt((int)(_curRawPos - pos)); } else { // When no set, it is equal to object length. _stream.WriteInt(len); } _stream.Seek(retPos, SeekOrigin.Begin); // 13. Collect metadata. if (_curMetaHnd != null) { IDictionary <string, int> meta = _curMetaHnd.OnObjectWriteFinished(); if (meta != null) { SaveMetadata(_curTypeId, desc.TypeName, desc.AffinityKeyFieldName, meta); } } // Restore old frame. _curTypeId = oldTypeId; _curConverter = oldConverter; _curMapper = oldMapper; _curMetaHnd = oldMetaHnd; _curRaw = oldRaw; _curRawPos = oldRawPos; } finally { // Restore handles if needed. if (resetDetach) { // Add newly recorded handles without overriding already existing ones. if (_hnds != null) { if (oldHnds == null) { oldHnds = _hnds; } else { oldHnds.Merge(_hnds); } } _hnds = oldHnds; _detachMode = false; } } }
/// <summary> /// Internal builder creation routine. /// </summary> /// <param name="parent">Parent builder.</param> /// <param name="obj">Portable object.</param> /// <param name="desc">Type descriptor.</param> /// <returns>Builder.</returns> private PortableBuilderImpl Builder0(PortableBuilderImpl parent, PortableUserObject obj, IPortableTypeDescriptor desc) { return(new PortableBuilderImpl(this, parent, obj, desc)); }
/// <summary> /// Create child builder. /// </summary> /// <param name="parent">Parent builder.</param> /// <param name="obj">Portable object.</param> /// <returns></returns> internal PortableBuilderImpl ChildBuilder(PortableBuilderImpl parent, PortableUserObject obj) { IPortableTypeDescriptor desc = _marsh.Descriptor(true, obj.TypeId()); return(Builder0(null, obj, desc)); }
/** <inheritdoc /> */ public override bool Equals(object obj) { if (this == obj) { return(true); } PortableUserObject that = obj as PortableUserObject; if (that != null) { if (_data == that._data && _offset == that._offset) { return(true); } // 1. Check hash code and type IDs. if (_hashCode == that._hashCode && _typeId == that._typeId) { // 2. Check if objects have the same field sets. InitializeFields(); that.InitializeFields(); if (_fields.Keys.Count != that._fields.Keys.Count) { return(false); } foreach (int id in _fields.Keys) { if (!that._fields.Keys.Contains(id)) { return(false); } } // 3. Check if objects have the same field values. foreach (KeyValuePair <int, int> field in _fields) { object fieldVal = Field0 <object>(field.Value, null); object thatFieldVal = that.Field0 <object>(that._fields[field.Key], null); if (!Equals(fieldVal, thatFieldVal)) { return(false); } } // 4. Check if objects have the same raw data. IPortableStream stream = new PortableHeapStream(_data); stream.Seek(_offset + 10, SeekOrigin.Begin); int len = stream.ReadInt(); int rawOffset = stream.ReadInt(); IPortableStream thatStream = new PortableHeapStream(that._data); thatStream.Seek(_offset + 10, SeekOrigin.Begin); int thatLen = thatStream.ReadInt(); int thatRawOffset = thatStream.ReadInt(); return(PortableUtils.CompareArrays(_data, _offset + rawOffset, len - rawOffset, that._data, that._offset + thatRawOffset, thatLen - thatRawOffset)); } } return(false); }
/// <summary> /// Create child builder. /// </summary> /// <param name="obj">Portable object.</param> /// <returns>Child builder.</returns> public PortableBuilderImpl Child(PortableUserObject obj) { return(_portables.ChildBuilder(_parent, obj)); }
/// <summary> /// Constructor. /// </summary> /// <param name="portables">Portables.</param> /// <param name="obj">Initial portable object.</param> /// <param name="desc">Type descriptor.</param> public PortableBuilderImpl(PortablesImpl portables, PortableUserObject obj, IPortableTypeDescriptor desc) : this(portables, null, obj, desc) { // No-op. }
/** * <summary>Write portable object.</summary> */ private static void WritePortableTyped(IPortableStream stream, PortableUserObject obj) { stream.WriteByte(PortableUtils.TypePortable); PortableUtils.WritePortable(stream, obj); }