コード例 #1
0
        /// <summary>
        /// Writes the contents of a stream to the archive (from the current position up to the end of the stream).
        /// </summary>
        /// <param name="s">Stream to write.</param>
        public void Write(Stream s)
        {
            // write payload type
            var buffer = mBufferWriter.GetSpan(1);

            buffer[0] = (byte)PayloadType.Buffer;
            mBufferWriter.Advance(1);

            // write data chunkwise
            while (true)
            {
                // read a chunk of data
                int maxBytesToRead = Serializer.MaxChunkSize - Leb128EncodingHelper.MaxBytesFor32BitValue;
                mSerializer.EnsureTemporaryByteBufferSize(maxBytesToRead);
                int bytesRead = s.Read(mSerializer.TempBuffer_Buffer, 0, maxBytesToRead);
                if (bytesRead == 0)
                {
                    break;
                }

                // write the chunk into the archive
                buffer = mBufferWriter.GetSpan(Leb128EncodingHelper.MaxBytesFor32BitValue + bytesRead);
                int bufferIndex = Leb128EncodingHelper.Write(buffer, bytesRead);
                mSerializer.TempBuffer_Buffer.AsSpan().Slice(0, bytesRead).CopyTo(buffer.Slice(bufferIndex));
                bufferIndex += bytesRead;
                mBufferWriter.Advance(bufferIndex);
            }
        }
コード例 #2
0
        /// <summary>
        /// Reads an array of <see cref="System.Decimal"/> from a stream (for arrays with zero-based indexing).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <returns>The read array.</returns>
        private decimal[] ReadArrayOfDecimal(Stream stream)
        {
            // read array length
            int length = Leb128EncodingHelper.ReadInt32(stream);
            int size   = 16 * length;

            // read data from stream
            if (mTempBuffer_BigBuffer.Length < length)
            {
                mTempBuffer_BigBuffer = new byte[size];
            }
            stream.Read(mTempBuffer_BigBuffer, 0, size);

            // read array data
            decimal[] array = new decimal[length];
            int       index = 0;

            for (int i = 0; i < length; i++)
            {
                Buffer.BlockCopy(mTempBuffer_BigBuffer, index, mTempBuffer_Int32, 0, 16);
                array[i] = new decimal(mTempBuffer_Int32);
                index   += 16;
            }

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #3
0
        /// <summary>
        /// Writes an array of <see cref="System.String"/> values (for arrays with zero-based indexing).
        /// </summary>
        /// <param name="array">Array to write.</param>
        /// <param name="stream">Stream to write the array to.</param>
        private void WriteArrayOfString(string[] array, Stream stream)
        {
            // write type and array length
            mTempBuffer_Buffer[0] = (byte)PayloadType.ArrayOfString;
            int count = Leb128EncodingHelper.Write(mTempBuffer_Buffer, 1, array.Length);

            stream.Write(mTempBuffer_Buffer, 0, 1 + count);

            // write array data
            for (int i = 0; i < array.Length; i++)
            {
                string s = array[i];
                uint   id;
                if (s == null)
                {
                    stream.WriteByte((byte)PayloadType.NullReference);
                }
                else if (mSerializedObjectIdTable.TryGetValue(s, out id))
                {
                    SerializeObjectId(stream, id);
                }
                else
                {
                    WritePrimitive_String(s, stream);
                }
            }

            mSerializedObjectIdTable.Add(array, mNextSerializedObjectId++);
        }
コード例 #4
0
        /// <summary>
        /// Writes an array of <see cref="System.Decimal"/> (for arrays with non-zero-based indexing and/or multiple dimensions).
        /// </summary>
        /// <param name="array">Array to write.</param>
        /// <param name="stream">Stream to write the array to.</param>
        private void WriteMultidimensionalArrayOfDecimal(Array array, Stream stream)
        {
            //int totalCount = 1;
            stream.WriteByte((byte)PayloadType.MultidimensionalArrayOfDecimal);             // payload type
            Leb128EncodingHelper.Write(stream, array.Rank);                                 // number of dimensions
            int[] indices = new int[array.Rank];
            for (int i = 0; i < array.Rank; i++)
            {
                // ...dimension information...
                indices[i] = array.GetLowerBound(i);
                Leb128EncodingHelper.Write(stream, indices[i]);            // lower bound of the dimension
                int count = array.GetLength(i);
                Leb128EncodingHelper.Write(stream, count);                 // number of elements in the dimension
                //totalCount *= count;
            }

            // write array elements
            for (int i = 0; i < array.Length; i++)
            {
                decimal value = (decimal)array.GetValue(indices);
                int[]   bits  = decimal.GetBits(value);
                Buffer.BlockCopy(bits, 0, mTempBuffer_Buffer, 0, 16);
                stream.Write(mTempBuffer_Buffer, 0, 16);
                IncrementArrayIndices(indices, array);
            }

            mSerializedObjectIdTable.Add(array, mNextSerializedObjectId++);
        }
コード例 #5
0
        /// <summary>
        /// Reads an array of primitive value types (for arrays with non-zero-based indexing and/or multiple dimensions).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <param name="type">Type of an array element.</param>
        /// <param name="elementSize">Size of an array element.</param>
        /// <returns>The read array.</returns>
        private Array ReadMultidimensionalArrayOfPrimitives(Stream stream, Type type, int elementSize)
        {
            // read header
            int totalCount = 1;
            int ranks      = Leb128EncodingHelper.ReadInt32(stream);

            int[] lowerBounds = new int[ranks];
            int[] lengths     = new int[ranks];
            for (int i = 0; i < ranks; i++)
            {
                lowerBounds[i] = Leb128EncodingHelper.ReadInt32(stream);
                lengths[i]     = Leb128EncodingHelper.ReadInt32(stream);
                totalCount    *= lengths[i];
            }

            // create an array of the specified type
            Array array = Array.CreateInstance(type, lengths, lowerBounds);

            // read array data
            int size = totalCount * elementSize;

            if (mTempBuffer_BigBuffer.Length < size)
            {
                mTempBuffer_BigBuffer = new byte[size];
            }
            stream.Read(mTempBuffer_BigBuffer, 0, size);
            Buffer.BlockCopy(mTempBuffer_BigBuffer, 0, array, 0, size);

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #6
0
        /// <summary>
        /// Reads an array of <see cref="System.String"/> from a stream (for arrays with non-zero-based indexing and/or multiple dimensions).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <returns>The read array.</returns>
        private Array ReadMultidimensionalStringArray(Stream stream)
        {
            // read header
            int totalCount = 1;
            int ranks      = Leb128EncodingHelper.ReadInt32(stream);

            int[] lowerBounds = new int[ranks];
            int[] lengths     = new int[ranks];
            int[] indices     = new int[ranks];
            for (int i = 0; i < ranks; i++)
            {
                lowerBounds[i] = Leb128EncodingHelper.ReadInt32(stream);
                lengths[i]     = Leb128EncodingHelper.ReadInt32(stream);
                indices[i]     = lowerBounds[i];
                totalCount    *= lengths[i];
            }

            // create an array of strings
            Array array = Array.CreateInstance(typeof(string), lengths, lowerBounds);

            // read array elements
            for (int i = 0; i < array.Length; i++)
            {
                object obj = InnerDeserialize(stream, null);
                array.SetValue(obj, indices);
                IncrementArrayIndices(indices, array);
            }

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #7
0
        /// <summary>
        /// Writes a <see cref="System.Char"/> value.
        /// </summary>
        /// <param name="value">Value to write.</param>
        /// <param name="stream">Stream to write the value to.</param>
        internal void WritePrimitive_Char(char value, Stream stream)
        {
            mTempBuffer_Buffer[0] = (byte)PayloadType.Char;
            int count = Leb128EncodingHelper.Write(mTempBuffer_Buffer, 1, (uint)value);

            stream.Write(mTempBuffer_Buffer, 0, 1 + count);
        }
コード例 #8
0
        /// <summary>
        /// Reads an array of <see cref="System.Decimal"/> from a stream (for arrays with non-zero-based indexing and/or multiple dimensions).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <returns>The read array.</returns>
        private Array ReadMultidimensionalArrayOfDecimal(Stream stream)
        {
            // read header
            int totalCount = 1;
            int ranks      = Leb128EncodingHelper.ReadInt32(stream);

            int[] lowerBounds = new int[ranks];
            int[] lengths     = new int[ranks];
            int[] indices     = new int[ranks];
            for (int i = 0; i < ranks; i++)
            {
                lowerBounds[i] = Leb128EncodingHelper.ReadInt32(stream);
                lengths[i]     = Leb128EncodingHelper.ReadInt32(stream);
                indices[i]     = lowerBounds[i];
                totalCount    *= lengths[i];
            }

            // create an array of decimals
            Array array = Array.CreateInstance(typeof(decimal), lengths, lowerBounds);

            // read array elements
            for (int i = 0; i < array.Length; i++)
            {
                stream.Read(mTempBuffer_Buffer, 0, 16);
                Buffer.BlockCopy(mTempBuffer_Buffer, 0, mTempBuffer_Int32, 0, 16);
                decimal value = new decimal(mTempBuffer_Int32);
                array.SetValue(value, indices);
                IncrementArrayIndices(indices, array);
            }

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #9
0
        /// <summary>
        /// Writes a <see cref="System.UInt64"/> value.
        /// </summary>
        /// <param name="value">Value to write.</param>
        /// <param name="stream">Stream to write the value to.</param>
        internal void WritePrimitive_UInt64(ulong value, Stream stream)
        {
            mTempBuffer_Buffer[0] = (byte)PayloadType.UInt64;
            int count = Leb128EncodingHelper.Write(mTempBuffer_Buffer, 1, value);

            stream.Write(mTempBuffer_Buffer, 0, 1 + count);
        }
コード例 #10
0
        /// <summary>
        /// Reads an array of <see cref="System.DateTime"/> from a stream (for arrays with non-zero-based indexing and/or multiple dimensions).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <returns>The read array.</returns>
        private Array ReadMultidimensionalDateTimeArray(Stream stream)
        {
            // read header
            int totalCount = 1;
            int ranks      = Leb128EncodingHelper.ReadInt32(stream);

            int[] lowerBounds = new int[ranks];
            int[] lengths     = new int[ranks];
            int[] indices     = new int[ranks];
            for (int i = 0; i < ranks; i++)
            {
                lowerBounds[i] = Leb128EncodingHelper.ReadInt32(stream);
                lengths[i]     = Leb128EncodingHelper.ReadInt32(stream);
                indices[i]     = lowerBounds[i];
                totalCount    *= lengths[i];
            }

            // create an array of datetimes
            Array array = Array.CreateInstance(typeof(DateTime), lengths, lowerBounds);

            // read array elements
            for (int i = 0; i < array.Length; i++)
            {
                stream.Read(mTempBuffer_Buffer, 0, 8);
                long l = BitConverter.ToInt64(mTempBuffer_Buffer, 0);
                array.SetValue(DateTime.FromBinary(l), indices);
                IncrementArrayIndices(indices, array);
            }

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #11
0
        /// <summary>
        /// Writes a <see cref="System.Int16"/> value.
        /// </summary>
        /// <param name="value">Value to write.</param>
        /// <param name="stream">Stream to write the value to.</param>
        internal void WritePrimitive_Int16(short value, Stream stream)
        {
            mTempBuffer_Buffer[0] = (byte)PayloadType.Int16;
            int count = Leb128EncodingHelper.Write(mTempBuffer_Buffer, 1, value);

            stream.Write(mTempBuffer_Buffer, 0, 1 + count);
        }
コード例 #12
0
        /// <summary>
        /// Reads an array of objects (for arrays with non-zero-based indexing and/or multiple dimensions).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <param name="context">Context object to pass to an internal/external object serializer class.</param>
        /// <returns>The read array.</returns>
        /// <exception cref="SerializationException">Stream ended unexpectedly.</exception>
        private object ReadMultidimensionalArrayOfObjects(Stream stream, object context)
        {
            Type type = mCurrentDeserializedType.Type;

            // read header
            int totalCount = 1;
            int ranks      = Leb128EncodingHelper.ReadInt32(stream);

            int[] lowerBounds = new int[ranks];
            int[] lengths     = new int[ranks];
            int[] indices     = new int[ranks];
            for (int i = 0; i < ranks; i++)
            {
                lowerBounds[i] = Leb128EncodingHelper.ReadInt32(stream);
                lengths[i]     = Leb128EncodingHelper.ReadInt32(stream);
                indices[i]     = lowerBounds[i];
                totalCount    *= lengths[i];
            }

            // create an array with elements of the specified type
            Array array = Array.CreateInstance(type, lengths, lowerBounds);

            // read array elements
            for (int i = 0; i < array.Length; i++)
            {
                object obj = InnerDeserialize(stream, null);
                array.SetValue(obj, indices);
                IncrementArrayIndices(indices, array);
            }

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #13
0
        /// <summary>
        /// Writes an array of primitive value types (for arrays with non-zero-based indexing and/or multiple dimensions).
        /// </summary>
        /// <param name="type">Payload type corresponding to the type of the array.</param>
        /// <param name="array">Array to write.</param>
        /// <param name="elementSize">Size of an array element.</param>
        /// <param name="stream">Stream to write the array to.</param>
        private void WriteMultidimensionalArrayOfPrimitives(
            PayloadType type,
            Array array,
            int elementSize,
            Stream stream)
        {
            int totalCount = 1;

            stream.WriteByte((byte)type);                               // payload type
            Leb128EncodingHelper.Write(stream, array.Rank);             // number of dimensions
            for (int i = 0; i < array.Rank; i++)
            {
                // ...dimension information...
                Leb128EncodingHelper.Write(stream, array.GetLowerBound(i)); // lower bound of the dimension
                int count = array.GetLength(i);
                Leb128EncodingHelper.Write(stream, count);                  // number of elements in the dimension
                totalCount *= count;
            }

            int size = totalCount * elementSize;

            if (mTempBuffer_BigBuffer.Length < size)
            {
                mTempBuffer_BigBuffer = new byte[size];
            }
            Buffer.BlockCopy(array, 0, mTempBuffer_BigBuffer, 0, size);
            stream.Write(mTempBuffer_BigBuffer, 0, size);

            mSerializedObjectIdTable.Add(array, mNextSerializedObjectId++);
        }
コード例 #14
0
        /// <summary>
        /// Prepares an archive for deserializing the base class of a serializable class.
        /// </summary>
        /// <param name="context">Context object to pass to the serializer of the base class.</param>
        /// <returns>Deserialization archive for the base class.</returns>
        /// <exception cref="ArgumentException">Type does not have a base type or it is not serializable.</exception>
        /// <exception cref="SerializationException">
        /// The serializer version in the archive is greater than the maximum supported version of the base class.
        /// </exception>
        public DeserializationArchive PrepareBaseArchive(object context)
        {
            var type = DataType.BaseType ?? throw new ArgumentException($"{DataType.FullName} does not have a base type.");

            // read payload type (expecting a base class archive)
            ReadAndCheckPayloadType(PayloadType.BaseArchiveStart);

            // read version number
            uint deserializedVersion = Leb128EncodingHelper.ReadUInt32(mStream);

            // check maximum supported version number
            uint currentVersion = Serializer.GetSerializerVersion(type);             // throws ArgumentException if type is not serializable

            if (deserializedVersion > currentVersion)
            {
                // version of the archive that is about to be deserialized is greater than
                // the version the internal object serializer supports
                string error = $"Deserializing type '{type.FullName}' failed due to a version conflict (got version: {deserializedVersion}, max. supported version: {currentVersion}).";
                sLog.Write(LogLevel.Error, error);
                throw new SerializationException(error);
            }

            // version is ok, create archive...
            return(new DeserializationArchive(mSerializer, mStream, type, deserializedVersion, context));
        }
コード例 #15
0
        /// <summary>
        /// Writes an array of <see cref="System.Byte"/> values (for arrays with zero-based indexing).
        /// </summary>
        /// <param name="array">Array to write.</param>
        /// <param name="stream">Stream to write the array to.</param>
        private void WriteArrayOfByte(byte[] array, Stream stream)
        {
            mTempBuffer_Buffer[0] = (byte)PayloadType.ArrayOfByte;
            int count = Leb128EncodingHelper.Write(mTempBuffer_Buffer, 1, array.Length);

            stream.Write(mTempBuffer_Buffer, 0, 1 + count);
            stream.Write(array, 0, array.Length);
            mSerializedObjectIdTable.Add(array, mNextSerializedObjectId++);
        }
コード例 #16
0
        /// <summary>
        /// Reads a byte buffer using a stream.
        /// </summary>
        /// <returns>Stream containing data to read.</returns>
        /// <exception cref="SerializationException">Thrown if deserialization fails due to some reason.</exception>
        public Stream ReadStream()
        {
            // read payload type and size of the following buffer
            ReadAndCheckPayloadType(PayloadType.Buffer);
            long length = Leb128EncodingHelper.ReadInt64(mStream);

            mArchiveStream = new SerializerArchiveStream(mStream, length);
            return(mArchiveStream);
        }
コード例 #17
0
        /// <summary>
        /// Opens a base archive and calls the serializer of the derived type (for base class serialization).
        /// </summary>
        /// <param name="context">Context object to pass to the serializer of the base class.</param>
        /// <exception cref="ArgumentException">Specified type is not serializable.</exception>
        public void WriteBaseArchive(object context = null)
        {
            var baseClassType = DataType.BaseType ?? throw new ArgumentException($"{DataType.FullName} does not have a base class.");

            // try internal object serializer
            var ios = Serializer.GetInternalObjectSerializer(mObjectToSerialize, baseClassType, out uint version);

            if (ios != null)
            {
                // consider serializer version overrides...
                if (mSerializer.GetSerializerVersionOverride(baseClassType, out uint versionOverride))
                {
                    version = versionOverride;
                }

                // write base archive header
                var buffer      = mBufferWriter.GetSpan(1 + Leb128EncodingHelper.MaxBytesFor32BitValue);
                int bufferIndex = 0;
                buffer[bufferIndex++] = (byte)PayloadType.BaseArchiveStart;
                bufferIndex          += Leb128EncodingHelper.Write(buffer.Slice(bufferIndex), version);
                mBufferWriter.Advance(bufferIndex);

                // call the Serialize() method of the base class
                var archive           = new SerializationArchive(mSerializer, mBufferWriter, baseClassType, mObjectToSerialize, version, context);
                var serializeDelegate = Serializer.GetInternalObjectSerializerSerializeCaller(baseClassType);
                serializeDelegate(ios, archive);
                return;
            }

            // try external object serializer
            var eos = ExternalObjectSerializerFactory.GetExternalObjectSerializer(baseClassType, out version);

            if (eos != null)
            {
                // consider serializer version overrides...
                if (mSerializer.GetSerializerVersionOverride(baseClassType, out uint versionOverride))
                {
                    version = versionOverride;
                }

                // write base archive header
                var buffer      = mBufferWriter.GetSpan(1 + Leb128EncodingHelper.MaxBytesFor32BitValue);
                int bufferIndex = 0;
                buffer[bufferIndex++] = (byte)PayloadType.BaseArchiveStart;
                bufferIndex          += Leb128EncodingHelper.Write(buffer.Slice(bufferIndex), version);
                mBufferWriter.Advance(bufferIndex);

                // serialize object
                var archive = new SerializationArchive(mSerializer, mBufferWriter, baseClassType, mObjectToSerialize, version, context);
                eos.Serialize(archive, mObjectToSerialize);
                return;
            }

            // specified type is not serializable...
            throw new ArgumentException($"Specified type ({baseClassType.FullName}) is not serializable.", nameof(baseClassType));
        }
コード例 #18
0
        /// <summary>
        /// Reads an array of <see cref="System.Byte"/> from a stream (for arrays with zero-based indexing).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <returns>The read array.</returns>
        private byte[] ReadArrayOfByte(Stream stream)
        {
            // read array length
            int length = Leb128EncodingHelper.ReadInt32(stream);

            // read array data
            byte[] array = new byte[length];
            stream.Read(array, 0, length);
            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #19
0
        /// <summary>
        /// Writes a multidimensional array of <see cref="System.String"/> to a stream  (for arrays with non-zero-based indexing and/or multiple dimensions).
        /// </summary>
        /// <param name="array">Array to serialize.</param>
        /// <param name="stream">Stream to serialize the array to.</param>
        private void WriteMultidimensionalArrayOfString(Array array, Stream stream)
        {
            int totalCount = 1;

            stream.WriteByte((byte)PayloadType.MultidimensionalArrayOfString);             // payload type
            Leb128EncodingHelper.Write(stream, array.Rank);                                // number of dimensions
            for (int i = 0; i < array.Rank; i++)
            {
                // ...dimension information...
                Leb128EncodingHelper.Write(stream, array.GetLowerBound(i)); // lower bound of the dimension
                int count = array.GetLength(i);
                Leb128EncodingHelper.Write(stream, count);                  // number of elements in the dimension
                totalCount *= count;
            }

            // prepare indexing array
            int[] indices = new int[array.Rank];
            for (int i = 0; i < array.Rank; i++)
            {
                indices[i] = array.GetLowerBound(i);
            }

            // write array elements
            for (int i = 0; i < array.Length; i++)
            {
                string s = (string)array.GetValue(indices);

                if (s != null)
                {
                    uint id;
                    if (mSerializedObjectIdTable.TryGetValue(s, out id))
                    {
                        SerializeObjectId(stream, id);
                    }
                    else
                    {
                        WritePrimitive_String(s, stream);
                    }
                }
                else
                {
                    stream.WriteByte((byte)PayloadType.NullReference);
                }

                IncrementArrayIndices(indices, array);
            }

            mSerializedObjectIdTable.Add(array, mNextSerializedObjectId++);
        }
コード例 #20
0
        /// <summary>
        /// Reads an array of <see cref="System.String"/> from a stream (for arrays with zero-based indexing).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <returns>The read array.</returns>
        private string[] ReadStringArray(Stream stream)
        {
            // read array length
            int length = Leb128EncodingHelper.ReadInt32(stream);

            // read array data
            string[] array = new string[length];
            for (int i = 0; i < length; i++)
            {
                object obj = InnerDeserialize(stream, null);
                array[i] = (string)obj;
            }

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #21
0
        /// <summary>
        /// Reads a <see cref="System.String"/> object.
        /// </summary>
        /// <param name="stream">Stream to read the string object from.</param>
        /// <returns>The read string.</returns>
        internal string ReadPrimitive_String(Stream stream)
        {
            int size = Leb128EncodingHelper.ReadInt32(stream);

            // read encoded string
            if (mTempBuffer_BigBuffer.Length < size)
            {
                mTempBuffer_BigBuffer = new byte[size];
            }
            stream.Read(mTempBuffer_BigBuffer, 0, size);

            // decode string
            string s = Encoding.UTF8.GetString(mTempBuffer_BigBuffer, 0, size);

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, s);
            return(s);
        }
コード例 #22
0
        /// <summary>
        /// Prepares a buffer for array serialization
        /// (inits payload type, the length field and reserves space for the value)
        /// </summary>
        /// <param name="type">Type of the payload.</param>
        /// <param name="length">Length of the array (in elements).</param>
        /// <param name="elementSize">Size of an element (in bytes).</param>
        /// <param name="size">Receives the number of valid bytes in <see cref="mTempBuffer_BigBuffer"/>.</param>
        /// <returns>Index in the returned buffer where the array data part begins.</returns>
        private int PrepareArrayBuffer(
            PayloadType type,
            int length,
            int elementSize,
            out int size)
        {
            int sizeByteCount = Leb128EncodingHelper.GetByteCount(length);

            size = 1 + sizeByteCount + length * elementSize;
            if (mTempBuffer_BigBuffer.Length < size)
            {
                mTempBuffer_BigBuffer = new byte[size];
            }

            mTempBuffer_BigBuffer[0] = (byte)type;
            Leb128EncodingHelper.Write(mTempBuffer_BigBuffer, 1, length);
            return(1 + sizeByteCount);
        }
コード例 #23
0
 /// <summary>
 /// Writes a <see cref="System.UInt64"/> value.
 /// </summary>
 /// <param name="value">Value to write.</param>
 /// <param name="writer">Buffer writer to write the value to.</param>
 internal void WritePrimitive_UInt64(ulong value, IBufferWriter <byte> writer)
 {
     if (SerializationOptimization == SerializationOptimization.Speed || !IsLeb128EncodingMoreEfficient(value))
     {
         // use native encoding
         var buffer = writer.GetSpan(9);
         buffer[0] = (byte)PayloadType.UInt64_Native;
         MemoryMarshal.Write(buffer.Slice(1), ref value);
         writer.Advance(9);
     }
     else
     {
         // use LEB128 encoding
         var buffer = writer.GetSpan(1 + Leb128EncodingHelper.MaxBytesFor64BitValue);
         buffer[0] = (byte)PayloadType.UInt64_LEB128;
         int count = Leb128EncodingHelper.Write(buffer.Slice(1), value);
         writer.Advance(1 + count);
     }
 }
コード例 #24
0
        /// <summary>
        /// Writes an array of objects (for arrays with zero-based indexing).
        /// </summary>
        /// <param name="array">Array to write.</param>
        /// <param name="stream">Stream to write the array to.</param>
        private void WriteArrayOfObjects(Array array, Stream stream)
        {
            // write type metadata
            WriteTypeMetadata(stream, array.GetType().GetElementType());

            // write type and array length
            mTempBuffer_Buffer[0] = (byte)PayloadType.ArrayOfObjects;
            int count = Leb128EncodingHelper.Write(mTempBuffer_Buffer, 1, array.Length);

            stream.Write(mTempBuffer_Buffer, 0, 1 + count);

            // write array data
            for (int i = 0; i < array.Length; i++)
            {
                InnerSerialize(stream, array.GetValue(i), null);
            }

            mSerializedObjectIdTable.Add(array, mNextSerializedObjectId++);
        }
コード例 #25
0
        /// <summary>
        /// Reads an array of primitive value types (for arrays with zero-based indexing).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <param name="type">Type of an array element.</param>
        /// <param name="elementSize">Size of an array element.</param>
        /// <returns>The read array.</returns>
        private Array ReadArrayOfPrimitives(Stream stream, Type type, int elementSize)
        {
            // read array length
            int length = Leb128EncodingHelper.ReadInt32(stream);
            int size   = length * elementSize;

            // read array data
            Array array = FastActivator.CreateArray(type, length);

            if (mTempBuffer_BigBuffer.Length < length)
            {
                mTempBuffer_BigBuffer = new byte[size];
            }
            stream.Read(mTempBuffer_BigBuffer, 0, size);
            Buffer.BlockCopy(mTempBuffer_BigBuffer, 0, array, 0, size);

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #26
0
        /// <summary>
        /// Writes a <see cref="System.String"/> object.
        /// </summary>
        /// <param name="value">String to write.</param>
        /// <param name="writer">Buffer writer to write the string to.</param>
        internal void WritePrimitive_String(string value, IBufferWriter <byte> writer)
        {
            if (SerializationOptimization == SerializationOptimization.Speed)
            {
                // use UTF-16 encoding
                // => .NET strings are always UTF-16 encoded itself, so no further encoding steps are needed...

                // write the encoded string
                int valueByteCount = value.Length * sizeof(char);
                int maxSize        = 1 + Leb128EncodingHelper.MaxBytesFor32BitValue + valueByteCount;
                var buffer         = writer.GetSpan(maxSize);
                int bufferIndex    = 0;
                buffer[bufferIndex++] = (byte)PayloadType.String_UTF16;
                bufferIndex          += Leb128EncodingHelper.Write(buffer.Slice(bufferIndex), value.Length);
                MemoryMarshal.AsBytes(value.AsSpan()).CopyTo(buffer.Slice(bufferIndex));
                bufferIndex += valueByteCount;
                writer.Advance(bufferIndex);
            }
            else
            {
                // use UTF-8 encoding

                // resize temporary buffer for the encoding the string
                int size = sUtf8Encoding.GetMaxByteCount(value.Length);
                EnsureTemporaryByteBufferSize(size);

                // encode the string
                int valueByteCount = sUtf8Encoding.GetBytes(value, 0, value.Length, TempBuffer_Buffer, 0);

                // write the encoded string
                int maxSize     = 1 + Leb128EncodingHelper.MaxBytesFor32BitValue + valueByteCount;
                var buffer      = writer.GetSpan(maxSize);
                int bufferIndex = 0;
                buffer[bufferIndex++] = (byte)PayloadType.String_UTF8;
                bufferIndex          += Leb128EncodingHelper.Write(buffer.Slice(1), valueByteCount);
                TempBuffer_Buffer.AsSpan().Slice(0, valueByteCount).CopyTo(buffer.Slice(bufferIndex));
                bufferIndex += valueByteCount;
                writer.Advance(bufferIndex);
            }

            // assign an object id to the serialized string
            mSerializedObjectIdTable.Add(value, mNextSerializedObjectId++);
        }
コード例 #27
0
        /// <summary>
        /// Writes a multidimensional array of <see cref="System.DateTime"/> to a stream (for arrays with non-zero-based indexing and/or multiple dimensions).
        /// </summary>
        /// <param name="array">Array to serialize.</param>
        /// <param name="stream">Stream to serialize the array to.</param>
        private void WriteMultidimensionalArrayOfDateTime(Array array, Stream stream)
        {
            int totalCount = 1;

            stream.WriteByte((byte)PayloadType.MultidimensionalArrayOfDateTime);             // payload type
            Leb128EncodingHelper.Write(stream, array.Rank);                                  // number of dimensions
            for (int i = 0; i < array.Rank; i++)
            {
                // ...dimension information...
                Leb128EncodingHelper.Write(stream, array.GetLowerBound(i)); // lower bound of the dimension
                int count = array.GetLength(i);
                Leb128EncodingHelper.Write(stream, count);                  // number of elements in the dimension
                totalCount *= count;
            }

            // prepare indexing array
            int[] indices = new int[array.Rank];
            for (int i = 0; i < array.Rank; i++)
            {
                indices[i] = array.GetLowerBound(i);
            }

            // resize temporary buffer, if necessary
            int size = 8 * totalCount;

            if (mTempBuffer_BigBuffer.Length < size)
            {
                mTempBuffer_BigBuffer = new byte[size];
            }

            // convert array elements
            for (int i = 0; i < array.Length; i++)
            {
                DateTime dt = (DateTime)array.GetValue(indices);
                mTempBuffer_Int64[0] = dt.ToBinary();
                Buffer.BlockCopy(mTempBuffer_Int64, 0, mTempBuffer_BigBuffer, 8 * i, 8);
                IncrementArrayIndices(indices, array);
            }

            // write to stream
            stream.Write(mTempBuffer_BigBuffer, 0, size);
            mSerializedObjectIdTable.Add(array, mNextSerializedObjectId++);
        }
コード例 #28
0
        /// <summary>
        /// Reads an array of objects (for arrays with zero-based indexing).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <param name="context">Context object to pass to an internal/external object serializer class.</param>
        /// <returns>The read array.</returns>
        /// <exception cref="SerializationException">Stream ended unexpectedly.</exception>
        private object ReadArrayOfObjects(Stream stream, object context)
        {
            // assembly and type metadata has been read already

            Type t = mCurrentDeserializedType.Type;

            // read array length
            int length = Leb128EncodingHelper.ReadInt32(stream);

            // read array elements
            Array array = FastActivator.CreateArray(t, length);

            for (int i = 0; i < length; i++)
            {
                array.SetValue(InnerDeserialize(stream, context), i);
            }

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }
コード例 #29
0
        /// <summary>
        /// Reads a <see cref="System.String"/> object (UTF-16 encoding).
        /// </summary>
        /// <param name="stream">Stream to read the string object from.</param>
        /// <returns>The read string.</returns>
        internal unsafe string ReadPrimitive_String_UTF16(Stream stream)
        {
            // read the number of UTF-16 code units
            int codeUnitCount = Leb128EncodingHelper.ReadInt32(stream);
            int size          = codeUnitCount * sizeof(char);

            // read encoded string
            EnsureTemporaryByteBufferSize(size);
            int bytesRead = stream.Read(TempBuffer_Buffer, 0, size);

            if (bytesRead < size)
            {
                throw new SerializationException("Unexpected end of stream.");
            }

            // swap bytes to fix endianness issues, if necessary
            var buffer = MemoryMarshal.Cast <byte, char>(TempBuffer_Buffer.AsSpan(0, bytesRead));

            if (mDeserializingLittleEndian != BitConverter.IsLittleEndian)
            {
                for (int i = 0; i < buffer.Length; i++)
                {
                    EndiannessHelper.SwapBytes(ref buffer[i]);
                }
            }

            // create a string from the buffer
#if NETSTANDARD2_0 || NET461
            string s;
            fixed(char *p = buffer)
            {
                s = new string(p, 0, buffer.Length);
            }
#elif NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
            string s = new string(buffer);
#else
                        #error Unhandled .NET framework
#endif
            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, s);
            return(s);
        }
コード例 #30
0
        /// <summary>
        /// Reads an array of <see cref="System.DateTime"/> from a stream (for arrays with zero-based indexing).
        /// </summary>
        /// <param name="stream">Stream to read the array from.</param>
        /// <returns>The read array.</returns>
        private DateTime[] ReadDateTimeArray(Stream stream)
        {
            // read array length
            int length = Leb128EncodingHelper.ReadInt32(stream);
            int size   = 8 * length;

            // read array data
            DateTime[] array = new DateTime[length];
            if (mTempBuffer_BigBuffer.Length < size)
            {
                mTempBuffer_BigBuffer = new byte[size];
            }
            stream.Read(mTempBuffer_BigBuffer, 0, size);
            for (int i = 0; i < length; i++)
            {
                array[i] = DateTime.FromBinary(BitConverter.ToInt64(mTempBuffer_BigBuffer, 8 * i));
            }

            mDeserializedObjectIdTable.Add(mNextDeserializedObjectId++, array);
            return(array);
        }