public void Serialize(BinaryStream stream, int baseOffset = 0) { if (Type == DataType.RML) { throw new InvalidOperationException("Cannot serialize RML data directly!"); } var ptr = (int)stream.Position; var oldSize = Size; if (Size > 0) { var writeData = true; if (CanBeCached) { if (WriteCache.IsCached(this)) { var cache = WriteCache.GetData(this); if (cache.Size == Size) { stream.Position = (cache.Offset + 1); var buf = stream.ReadBytes(cache.Size); var key = Memory.GetCRC32(Buffer); var bufKey = Memory.GetCRC32(buf); stream.Position = ptr; // slow as f**k, but there's no room for error if (key == bufKey) { var nD = DescriptorTag.CreateReference(cache.Offset, ReferenceType.Offset); nD.WriteTo(stream, baseOffset); writeData = false; } } } else { WriteCache.Cache(ptr, this); } } if (writeData) { var nD = DescriptorTag.Create(Size); nD.WriteTo(stream, baseOffset); stream.Write(Buffer); } } else { // nothing to write! stream.WriteByte(0); } }
protected void WriteAttributeData(BinaryStream stream, NomadValue attr, int baseOffset = 0) { var ptr = (int)stream.Position + baseOffset; var data = attr.Data; var type = data.Type; var size = data.Size; var buffer = data.Buffer; if (data.Type == DataType.RML) { throw new InvalidOperationException("Cannot serialize RML data directly!"); } var oldSize = size; var attrData = (Format != FormatType.Resource) ? Utils.GetAttributeDataMiniBuffer(buffer, type) : Utils.GetAttributeDataBuffer(buffer, type); size = attrData.Length; var writeData = true; if (size > 4) { // return cached instance, else cache it and return empty var cache = WriteCache.PreCache(ptr, attrData, size); if (!cache.IsEmpty) { // sizes must match if (cache.Size == size) { var nD = DescriptorTag.CreateReference(cache.Offset, ReferenceType.Offset); nD.WriteTo(stream, baseOffset); writeData = false; } } } if (writeData) { var nD = DescriptorTag.Create(size); nD.WriteTo(stream); stream.Write(attrData); } }
protected void WriteObject_FmtA(BinaryStream stream, NomadObject obj) { Context.State = ContextStateType.Object; Context.ObjectIndex++; var ptr = (int)stream.Position; var idx = NomadCache.Find(obj); if (idx != -1) { var cached = NomadCache.Refs[idx]; var tag = DescriptorTag.CreateReference(Context.GetIdx(cached), ReferenceType.Index); tag.WriteTo(stream); } else { var nChildren = DescriptorTag.Create(obj.Children.Count); var nAttributes = DescriptorTag.Create(obj.Attributes.Count); Context.AddRef(obj, ptr); nChildren.WriteTo(stream); stream.Write(obj.Id.Hash); if (obj.IsRml) { WriteRmlData(stream, obj); } else { nAttributes.WriteTo(stream); Context.State = ContextStateType.Member; foreach (var attr in obj.Attributes) { WriteAttribute_FmtA(stream, attr); } foreach (var child in obj.Children) { WriteObject_FmtA(stream, child); } } } }
protected void WriteAttributesData_FmtB(BinaryStream stream, List <NomadValue> attributes, int baseOffset) { var ptr = (int)stream.Position + baseOffset; var nAttrs = attributes.Count; if (nAttrs > 0) { var attrData = new byte[nAttrs * 4]; using (var bs = new BinaryStream(attrData)) { foreach (var attr in attributes) { bs.Write(attr.Id.Hash); } } var cache = WriteCache.PreCache(ptr, attrData, nAttrs); if (!cache.IsEmpty) { var ndAttrs = DescriptorTag.CreateReference(cache.Offset, ReferenceType.Offset); ndAttrs.WriteTo(stream, baseOffset); } else { var count = DescriptorTag.Create(nAttrs); count.WriteTo(stream); stream.Write(attrData); } foreach (var attr in attributes) { WriteAttribute_FmtB(stream, attr, baseOffset); } } else { // nothing to write stream.WriteByte(0); } }
private void WriteAttributeHashes(BinaryStream stream) { var ptr = (int)stream.Position; var nAttrs = Attributes.Count; if (nAttrs > 0) { var attrHBuf = new byte[(nAttrs * 4) + 1]; using (var buf = new BinaryStream(attrHBuf)) { buf.WriteByte(nAttrs); foreach (var attr in Attributes) { attr.Serialize(buf, true); } } if (WriteCache.IsCached(attrHBuf, nAttrs)) { var cache = WriteCache.GetData(attrHBuf, nAttrs); var nhD = DescriptorTag.CreateReference(cache.Offset, ReferenceType.Offset); nhD.WriteTo(stream); } else { WriteCache.Cache(ptr, attrHBuf, nAttrs); stream.Write(attrHBuf); } } else { // nothing to write stream.WriteByte(0); } }
protected void WriteObject_FmtB(BinaryStream stream, NomadObject obj) { Context.State = ContextStateType.Object; Context.ObjectIndex++; var ptr = (int)stream.Position; var idx = NomadCache.Find(obj); if (idx != -1) { var cached = NomadCache.Refs[idx]; var offset = (int)Context.GetPtr(cached); var tag = DescriptorTag.CreateReference(offset, ReferenceType.Offset); tag.WriteTo(stream); } else { var reference = new NomadReference(obj); var cached = reference.Get(); Context.AddRef(cached, ptr); var count = DescriptorTag.Create(obj.Children.Count); count.WriteTo(stream); stream.Write(obj.Id.Hash); WriteAttributesList_FmtB(stream, obj); foreach (var child in obj.Children) { WriteObject_FmtB(stream, child); } } }
public override void Serialize(BinaryStream stream) { Offset = (int)stream.Position; var nChildren = Children.Count; var nAttributes = Attributes.Count; var writeData = true; if (Size > 16) { if (WriteCache.IsCached(this)) { var cache = WriteCache.GetData(this); var obj = cache.Object as NodeClass; if ((obj != null) && obj.Equals(this)) { Debug.WriteLine($">> [Class:{Offset:X8}] Instance cached @ {cache.Offset:X8} with key {cache.Checksum:X8}"); var nD = DescriptorTag.CreateReference(cache.Offset, ReferenceType.Offset); nD.WriteTo(stream); writeData = false; } else { Debug.WriteLine($">> [Class:{Offset:X8}] !!! FALSE POSITIVE !!!"); } } else { Debug.WriteLine($">> [Class:{Offset:X8}] Caching new instance with key {GetHashCode():X8}"); WriteCache.Cache(Offset, this); } } if (writeData) { var nD = DescriptorTag.Create(nChildren); nD.WriteTo(stream); stream.Write(Hash); // skip size parameter for now stream.Position += 2; var attrsPtr = stream.Position; if (nAttributes > 0) { WriteAttributeHashes(stream); // write attribute data foreach (var attribute in Attributes) { attribute.Serialize(stream); } } else { // no attributes to write! stream.WriteByte(0); } var childrenPtr = stream.Position; var attrsSize = (int)(childrenPtr - attrsPtr); if (attrsSize > 65535) { throw new InvalidOperationException("Attribute data too large."); } // write attributes size stream.Position = (attrsPtr - 2); stream.Write((short)attrsSize); // now write the children out stream.Position = childrenPtr; foreach (var child in Children) { child.Serialize(stream); } } }