/// <summary> /// Begins an array node of the given length. /// </summary> /// <param name="length">The length of the array to come.</param> public override void BeginArrayNode(long length) { this.Stream.WriteByte((byte)BinaryEntryType.StartOfArray); ProperBitConverter.GetBytes(this.buffer, 0, length); this.Stream.Write(this.buffer, 0, 8); this.PushArray(); }
/// <summary> /// Reads a primitive array value. This call will succeed if the next entry is an <see cref="EntryType.PrimitiveArray" />. /// <para /> /// If the call fails (and returns <c>false</c>), it will skip the current entry value, unless that entry is an <see cref="EntryType.EndOfNode" /> or an <see cref="EntryType.EndOfArray" />. /// </summary> /// <typeparam name="T">The element type of the primitive array. Valid element types can be determined using <see cref="FormatterUtilities.IsPrimitiveArrayType(Type)" />.</typeparam> /// <param name="array">The resulting primitive array.</param> /// <returns> /// <c>true</c> if reading a primitive array succeeded, otherwise <c>false</c> /// </returns> /// <exception cref="System.ArgumentException">Type + typeof(T).Name + is not a valid primitive array type.</exception> public override bool ReadPrimitiveArray <T>(out T[] array) { if (FormatterUtilities.IsPrimitiveArrayType(typeof(T)) == false) { throw new ArgumentException("Type " + typeof(T).Name + " is not a valid primitive array type."); } if (this.peekedEntryType != EntryType.PrimitiveArray) { this.SkipEntry(); array = null; return(false); } if (typeof(T) == typeof(byte)) { array = (T[])(object)ProperBitConverter.HexStringToBytes(this.peekedEntryData); return(true); } else { this.PeekEntry(); long length; if (this.peekedEntryType != EntryType.PrimitiveArray) { this.Context.Config.DebugContext.LogError("Expected entry of type '" + EntryType.StartOfArray + "' when reading primitive array but got entry of type '" + this.peekedEntryType + "'."); this.SkipEntry(); array = new T[0]; return(false); } if (!long.TryParse(this.peekedEntryData, NumberStyles.Any, CultureInfo.InvariantCulture, out length)) { this.Context.Config.DebugContext.LogError("Failed to parse primitive array length from entry data '" + this.peekedEntryData + "'."); this.SkipEntry(); array = new T[0]; return(false); } this.ConsumeCurrentEntry(); this.PushArray(); array = new T[length]; Func <T> reader = (Func <T>) this.primitiveTypeReaders[typeof(T)]; for (int i = 0; i < length; i++) { array[i] = reader(); } this.ExitArray(); return(true); } }
/// <summary> /// Writes a primitive array to the stream. /// </summary> /// <typeparam name="T">The element type of the primitive array. Valid element types can be determined using <see cref="FormatterUtilities.IsPrimitiveArrayType(Type)" />.</typeparam> /// <param name="array">The primitive array to write.</param> /// <exception cref="System.ArgumentException">Type + typeof(T).Name + is not a valid primitive array type.</exception> public override void WritePrimitiveArray <T>(T[] array) { if (FormatterUtilities.IsPrimitiveArrayType(typeof(T)) == false) { throw new ArgumentException("Type " + typeof(T).Name + " is not a valid primitive array type."); } int bytesPerElement = PrimitiveSizes[typeof(T)]; int byteCount = array.Length * bytesPerElement; // Write entry flag this.Stream.WriteByte((byte)BinaryEntryType.PrimitiveArray); // Write array length ProperBitConverter.GetBytes(this.buffer, 0, array.Length); this.Stream.Write(this.buffer, 0, 4); // Write size of an element in bytes ProperBitConverter.GetBytes(this.buffer, 0, bytesPerElement); this.Stream.Write(this.buffer, 0, 4); // Write the actual array content if (typeof(T) == typeof(byte)) { // We can include a special case for byte arrays, as there's no need to copy that to a buffer var byteArray = (byte[])(object)array; this.Stream.Write(byteArray, 0, byteCount); } else { // Otherwise we copy to a buffer in order to write the entire array into the stream with one call using (var tempBuffer = Buffer <byte> .Claim(byteCount)) { if (BitConverter.IsLittleEndian) { // We always store in little endian, so we can do a direct memory mapping, which is a lot faster UnsafeUtilities.MemoryCopy(array, tempBuffer.Array, byteCount, 0, 0); } else { // We have to convert each individual element to bytes, since the byte order has to be reversed Action <byte[], int, T> toBytes = (Action <byte[], int, T>)PrimitiveGetBytesMethods[typeof(T)]; var b = tempBuffer.Array; for (int i = 0; i < array.Length; i++) { toBytes(b, i * bytesPerElement, array[i]); } } this.Stream.Write(tempBuffer.Array, 0, byteCount); } } }
/// <summary> /// Writes an <see cref="ushort" /> value to the stream. /// </summary> /// <param name="name">The name of the value. If this is null, no name will be written.</param> /// <param name="value">The value to write.</param> public override void WriteUInt16(string name, ushort value) { if (name != null) { this.Stream.WriteByte((byte)BinaryEntryType.NamedUShort); this.WriteStringValue(name); } else { this.Stream.WriteByte((byte)BinaryEntryType.UnnamedUShort); } ProperBitConverter.GetBytes(this.buffer, 0, value); this.Stream.Write(this.buffer, 0, 2); }
/// <summary> /// Writes a <see cref="float" /> value to the stream. /// </summary> /// <param name="name">The name of the value. If this is null, no name will be written.</param> /// <param name="value">The value to write.</param> public override void WriteSingle(string name, float value) { if (name != null) { this.Stream.WriteByte((byte)BinaryEntryType.NamedFloat); this.WriteStringValue(name); } else { this.Stream.WriteByte((byte)BinaryEntryType.UnnamedFloat); } ProperBitConverter.GetBytes(this.buffer, 0, value); this.Stream.Write(this.buffer, 0, 4); }
/// <summary> /// Writes an internal reference to the stream. /// </summary> /// <param name="name">The name of the value. If this is null, no name will be written.</param> /// <param name="id">The value to write.</param> public override void WriteInternalReference(string name, int id) { if (name != null) { this.Stream.WriteByte((byte)BinaryEntryType.NamedInternalReference); this.WriteStringValue(name); } else { this.Stream.WriteByte((byte)BinaryEntryType.UnnamedInternalReference); } ProperBitConverter.GetBytes(this.buffer, 0, id); this.Stream.Write(this.buffer, 0, 4); }
/// <summary> /// Writes a <see cref="long" /> value to the stream. /// </summary> /// <param name="name">The name of the value. If this is null, no name will be written.</param> /// <param name="value">The value to write.</param> public override void WriteInt64(string name, long value) { if (name != null) { this.Stream.WriteByte((byte)BinaryEntryType.NamedLong); this.WriteStringValue(name); } else { this.Stream.WriteByte((byte)BinaryEntryType.UnnamedLong); } ProperBitConverter.GetBytes(this.buffer, 0, value); this.Stream.Write(this.buffer, 0, 8); }
/// <summary> /// Writes a <see cref="Guid" /> value to the stream. /// </summary> /// <param name="name">The name of the value. If this is null, no name will be written.</param> /// <param name="value">The value to write.</param> public override void WriteGuid(string name, Guid value) { if (name != null) { this.Stream.WriteByte((byte)BinaryEntryType.NamedGuid); this.WriteStringValue(name); } else { this.Stream.WriteByte((byte)BinaryEntryType.UnnamedGuid); } ProperBitConverter.GetBytes(this.buffer, 0, value); this.Stream.Write(this.buffer, 0, 16); }
/// <summary> /// Not yet documented. /// </summary> public override void WritePrimitiveArray <T>(T[] array) { if (FormatterUtilities.IsPrimitiveArrayType(typeof(T)) == false) { throw new ArgumentException("Type " + typeof(T).Name + " is not a valid primitive array type."); } if (typeof(T) == typeof(byte)) { string hex = ProperBitConverter.BytesToHexString((byte[])(object)array); this.Nodes.Add(new SerializationNode() { Name = string.Empty, Entry = EntryType.PrimitiveArray, Data = hex }); } else { this.Nodes.Add(new SerializationNode() { Name = string.Empty, Entry = EntryType.PrimitiveArray, Data = array.LongLength.ToString(CultureInfo.InvariantCulture) }); this.PushArray(); Action <string, T> writer = (Action <string, T>) this.primitiveTypeWriters[typeof(T)]; for (int i = 0; i < array.Length; i++) { writer(string.Empty, array[i]); } this.EndArrayNode(); } }
private void WriteStringValue(string value) { bool twoByteString = this.StringRequires16BitSupport(value); if (twoByteString) { this.Stream.WriteByte(1); // Write 16 bit flag ProperBitConverter.GetBytes(this.buffer, 0, value.Length); this.Stream.Write(this.buffer, 0, 4); using (var tempBuffer = Buffer <byte> .Claim(value.Length * 2)) { var array = tempBuffer.Array; UnsafeUtilities.StringToBytes(array, value, true); this.Stream.Write(array, 0, value.Length * 2); } } else { this.Stream.WriteByte(0); // Write 8 bit flag ProperBitConverter.GetBytes(this.buffer, 0, value.Length); this.Stream.Write(this.buffer, 0, 4); using (var tempBuffer = Buffer <byte> .Claim(value.Length)) { var array = tempBuffer.Array; for (int i = 0; i < value.Length; i++) { array[i] = (byte)value[i]; } this.Stream.Write(array, 0, value.Length); } } }
public override string GetDataDump() { if (!this.Stream.CanRead) { return("Binary data stream for writing cannot be read; cannot dump data."); } if (!this.Stream.CanSeek) { return("Binary data stream cannot seek; cannot dump data."); } var oldPosition = this.Stream.Position; var bytes = new byte[oldPosition]; this.Stream.Position = 0; this.Stream.Read(bytes, 0, (int)oldPosition); this.Stream.Position = oldPosition; return("Binary hex dump: " + ProperBitConverter.BytesToHexString(bytes)); }
private void WriteIntValue(int value) { ProperBitConverter.GetBytes(this.buffer, 0, value); this.Stream.Write(this.buffer, 0, 4); }