/// <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();
            }
        }
示例#10
0
        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);
                }
            }
        }
示例#11
0
        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));
        }
示例#12
0
 private void WriteIntValue(int value)
 {
     ProperBitConverter.GetBytes(this.buffer, 0, value);
     this.Stream.Write(this.buffer, 0, 4);
 }