private void Recurse(XmlElement xmlElement) { var typestr = xmlElement.Attributes["__type"]?.Value; var sizestr = xmlElement.Attributes["__count"]?.Value; if (typestr == null) { _nodeBuffer.WriteU8(1); _nodeBuffer.WriteString(xmlElement.Name); } else { var typeid = TypeDictionary.ReverseTypeMap[typestr]; if (sizestr != null) { _nodeBuffer.WriteU8((byte)(typeid | 0x40)); } else { _nodeBuffer.WriteU8(typeid); } _nodeBuffer.WriteString(xmlElement.Name); if (typestr == "str") { _dataBuffer.WriteString(xmlElement.InnerText); } else if (typestr == "bin") { _dataBuffer.WriteBinary(xmlElement.InnerText); } else { var type = TypeDictionary.TypeMap[typeid]; var value = xmlElement.InnerText.Split(' '); var size = (uint)(type.Size * type.Count); if (sizestr != null) { size *= uint.Parse(sizestr); _dataBuffer.WriteU32(size); } var values = new List <byte>(); for (var i = 0; i < size / type.Size; i++) { values.AddRange(type.ToBytes(value[i])); } _dataBuffer.WriteBytes(values.ToArray()); } } foreach (XmlAttribute attribute in xmlElement.Attributes) { if (attribute.Name != "__type" && attribute.Name != "__size" && attribute.Name != "__count") { _nodeBuffer.WriteU8(0x2E); _nodeBuffer.WriteString(attribute.Name); _dataBuffer.WriteString(attribute.Value); } } foreach (XmlNode childNode in xmlElement.ChildNodes) { if (childNode is XmlElement) { Recurse((XmlElement)childNode); } } _nodeBuffer.WriteU8(0xFE); }
private byte[] WriteRaw() { using (var textReader = new StringReader(_rawXml)) using (var reader = XmlReader.Create(textReader, new XmlReaderSettings { IgnoreWhitespace = true })) { var holdingAttrs = new SortedDictionary <string, string>(StringComparer.Ordinal); string holdingValue = ""; string typeStr = null, sizeStr = null; byte typeid = 0; void EnsureHolding() { if (typeStr != null) { if (typeStr == "str") { _dataBuffer.WriteString(holdingValue); } else if (typeStr == "bin") { _dataBuffer.WriteBinary(holdingValue); } else { var type = TypeDictionary.TypeMap[typeid]; var value = holdingValue.SpanSplit(' '); var size = (uint)(type.Size * type.Count); if (sizeStr != null) { size *= uint.Parse(sizeStr); _dataBuffer.WriteU32(size); } var arr = new byte[size]; int i = 0; foreach (var s in value) { if (i == arr.Length) { break; } #if NETSTANDARD2_1 || NET5_0_OR_GREATER var buffer = type.GetBytes(s); buffer.CopyTo(arr.AsSpan().Slice(i, type.Size)); #elif NETSTANDARD2_0 var buffer = type.GetBytes(s).ToArray(); buffer.CopyTo(arr, i); #endif i += type.Size; } _dataBuffer.WriteBytes(arr); } typeStr = null; sizeStr = null; holdingValue = ""; typeid = 0; } if (holdingAttrs.Count > 0) { foreach (var attribute in holdingAttrs) { _nodeBuffer.WriteU8(0x2E); _nodeBuffer.WriteString(attribute.Key); _dataBuffer.WriteString(attribute.Value); } holdingAttrs.Clear(); } } while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: EnsureHolding(); //Console.WriteLine("Start Element {0}", reader.Name); if (reader.AttributeCount > 0) { for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); if (reader.Name == "__type") { typeStr = reader.Value; } else if (reader.Name == "__count") { sizeStr = reader.Value; } else { holdingAttrs.Add(reader.Name, reader.Value); } } reader.MoveToElement(); } if (typeStr == null) { _nodeBuffer.WriteU8(1); _nodeBuffer.WriteString(reader.Name); } else { typeid = TypeDictionary.ReverseTypeMap[typeStr]; if (sizeStr != null) { _nodeBuffer.WriteU8((byte)(typeid | 0x40)); } else { _nodeBuffer.WriteU8(typeid); } _nodeBuffer.WriteString(reader.Name); } if (reader.IsEmptyElement) { EnsureHolding(); _nodeBuffer.WriteU8(0xFE); } break; case XmlNodeType.Text: holdingValue = reader.Value; break; case XmlNodeType.EndElement: EnsureHolding(); _nodeBuffer.WriteU8(0xFE); break; default: //Console.WriteLine("Other node {0} with value {1}", // reader.NodeType, reader.Value); break; } } EnsureHolding(); } _nodeBuffer.WriteU8(255); _nodeBuffer.Pad(); _dataBuffer.Pad(); //Write header data using (var output = new BigEndianBinaryBuffer()) { output.WriteU8(0xA0); //Magic output.WriteU8(0x42); //Compression flag output.WriteU8(EncodingDictionary.ReverseEncodingMap[_encoding]); output.WriteU8((byte)~EncodingDictionary.ReverseEncodingMap[_encoding]); //Write node buffer length and contents. var buffer = _nodeBuffer.ToArray(); output.WriteS32(buffer.Length); output.WriteBytes(buffer); //Write data buffer length and contents. var array = _dataBuffer.ToArray(); output.WriteS32(array.Length); output.WriteBytes(array); return(output.ToArray()); } }