Beispiel #1
0
 [ExcludeFromCodeCoverage]   // big-endian only
 private void Write(IBinaryStream stream)
 {
     stream.WriteByte(Header);
     stream.WriteByte(Version);
     stream.WriteShort((short)Flags);
     stream.WriteInt(Length);
     stream.WriteInt(TypeId);
     stream.WriteInt(HashCode);
     stream.WriteInt(SchemaId);
     stream.WriteInt(SchemaOffset);
 }
Beispiel #2
0
        /// <summary>
        /// Writes the peek modes.
        /// </summary>
        private static void WritePeekModes(ICollection <CachePeekMode> modes, IBinaryStream w)
        {
            if (modes == null)
            {
                w.WriteInt(0);
            }
            else
            {
                w.WriteInt(modes.Count);

                foreach (var m in modes)
                {
                    // Convert bit flag to ordinal.
                    byte val     = 0;
                    var  flagVal = (int)m;

                    while ((flagVal = flagVal >> 1) > 0)
                    {
                        val++;
                    }

                    w.WriteByte(val);
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Writes to the specified writer.
        /// </summary>
        public void Write(IBinaryStream stream)
        {
            Debug.Assert(stream != null);

            stream.WriteByte(BinaryTypeId.OptimizedMarshaller);
            stream.WriteInt(_data.Length);
            stream.WriteByteArray(_data);
        }
Beispiel #4
0
        /// <summary>
        /// Writes the request.
        /// </summary>
        private void WriteRequest(Action <BinaryWriter> writeAction, IBinaryStream stream)
        {
            stream.WriteInt(_id);

            var writer = _marsh.StartMarshal(stream);

            if (_expiryPolicy != null)
            {
                stream.WriteByte((byte)ClientCacheRequestFlag.WithExpiryPolicy);
                ExpiryPolicySerializer.WritePolicy(writer, _expiryPolicy);
            }
            else
            {
                stream.WriteByte((byte)ClientCacheRequestFlag.None);  // Flags (skipStore, etc).
            }
            if (writeAction != null)
            {
                writeAction(writer);

                _marsh.FinishMarshal(writer);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Writes the request.
        /// </summary>
        private void WriteRequest(Action <BinaryWriter> writeAction, IBinaryStream stream)
        {
            stream.WriteInt(_id);
            stream.WriteByte(0); // Flags (skipStore, etc).

            if (writeAction != null)
            {
                var writer = _marsh.StartMarshal(stream);

                writeAction(writer);

                _marsh.FinishMarshal(writer);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Writes an array of fields to a stream.
        /// </summary>
        /// <param name="fields">Fields.</param>
        /// <param name="stream">Stream.</param>
        /// <param name="offset">Offset in the array.</param>
        /// <param name="count">Field count to write.</param>
        /// <param name="compact">Compact mode without field ids.</param>
        /// <returns>
        /// Flags according to offset sizes: <see cref="BinaryObjectHeader.Flag.OffsetOneByte" />,
        /// <see cref="BinaryObjectHeader.Flag.OffsetTwoBytes" />, or 0.
        /// </returns>
        public static unsafe BinaryObjectHeader.Flag WriteSchema(BinaryObjectSchemaField[] fields, IBinaryStream stream, int offset,
                                                                 int count, bool compact)
        {
            Debug.Assert(fields != null);
            Debug.Assert(stream != null);
            Debug.Assert(count > 0);
            Debug.Assert(offset >= 0);
            Debug.Assert(offset < fields.Length);

            unchecked
            {
                // Last field is the farthest in the stream
                var maxFieldOffset = fields[offset + count - 1].Offset;

                if (compact)
                {
                    if (maxFieldOffset <= byte.MaxValue)
                    {
                        for (int i = offset; i < count + offset; i++)
                        {
                            stream.WriteByte((byte)fields[i].Offset);
                        }

                        return(BinaryObjectHeader.Flag.OffsetOneByte);
                    }

                    if (maxFieldOffset <= ushort.MaxValue)
                    {
                        for (int i = offset; i < count + offset; i++)
                        {
                            stream.WriteShort((short)fields[i].Offset);
                        }

                        return(BinaryObjectHeader.Flag.OffsetTwoBytes);
                    }

                    for (int i = offset; i < count + offset; i++)
                    {
                        stream.WriteInt(fields[i].Offset);
                    }
                }
                else
                {
                    if (maxFieldOffset <= byte.MaxValue)
                    {
                        for (int i = offset; i < count + offset; i++)
                        {
                            var field = fields[i];

                            stream.WriteInt(field.Id);
                            stream.WriteByte((byte)field.Offset);
                        }

                        return(BinaryObjectHeader.Flag.OffsetOneByte);
                    }

                    if (maxFieldOffset <= ushort.MaxValue)
                    {
                        for (int i = offset; i < count + offset; i++)
                        {
                            var field = fields[i];

                            stream.WriteInt(field.Id);

                            stream.WriteShort((short)field.Offset);
                        }

                        return(BinaryObjectHeader.Flag.OffsetTwoBytes);
                    }

                    if (BitConverter.IsLittleEndian)
                    {
                        fixed(BinaryObjectSchemaField *ptr = &fields[offset])
                        {
                            stream.Write((byte *)ptr, count * BinaryObjectSchemaField.Size);
                        }
                    }
                    else
                    {
                        for (int i = offset; i < count + offset; i++)
                        {
                            var field = fields[i];

                            stream.WriteInt(field.Id);
                            stream.WriteInt(field.Offset);
                        }
                    }
                }


                return(BinaryObjectHeader.Flag.None);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Tests the stream.
        /// </summary>
        private static unsafe void TestStream(IBinaryStream stream, bool sameArr, Action flush)
        {
            Action seek = () => Assert.AreEqual(0, stream.Seek(0, SeekOrigin.Begin));

            Action<Action, Func<object>, object> check = (write, read, expectedResult) =>
            {
                seek();
                write();
                flush();
                seek();
                Assert.AreEqual(expectedResult, read());
            };

            // Arrays.
            Assert.AreEqual(sameArr, stream.IsSameArray(stream.GetArray()));
            Assert.IsFalse(stream.IsSameArray(new byte[1]));
            Assert.IsFalse(stream.IsSameArray(stream.GetArrayCopy()));

            // byte*
            byte* bytes = stackalloc byte[10];
            *bytes = 1;
            *(bytes + 1) = 2;

            stream.Write(bytes, 2);
            Assert.AreEqual(2, stream.Position);
            flush();

            seek();
            Assert.AreEqual(sameArr ? 256 : 2, stream.Remaining);
            byte* bytes2 = stackalloc byte[2];
            stream.Read(bytes2, 2);
            Assert.AreEqual(1, *bytes2);
            Assert.AreEqual(2, *(bytes2 + 1));

            // char*
            seek();
            char* chars = stackalloc char[10];
            *chars = 'a';
            *(chars + 1) = 'b';

            Assert.AreEqual(2, stream.WriteString(chars, 2, 2, Encoding.ASCII));
            flush();

            seek();
            stream.Read(bytes2, 2);
            Assert.AreEqual('a', *bytes2);
            Assert.AreEqual('b', *(bytes2 + 1));

            // Others.
            check(() => stream.Write(new byte[] {3, 4, 5}, 1, 2), () => stream.ReadByteArray(2), new byte[] {4, 5});

            check(() => stream.WriteBool(true), () => stream.ReadBool(), true);
            check(() => stream.WriteBoolArray(new[] {true, false}), () => stream.ReadBoolArray(2), 
                new[] {true, false});

            check(() => stream.WriteByte(4), () => stream.ReadByte(), 4);
            check(() => stream.WriteByteArray(new byte[] {4, 5, 6}), () => stream.ReadByteArray(3), 
                new byte[] {4, 5, 6});

            check(() => stream.WriteChar('x'), () => stream.ReadChar(), 'x');
            check(() => stream.WriteCharArray(new[] {'a', 'b'}), () => stream.ReadCharArray(2), new[] {'a', 'b'});

            check(() => stream.WriteDouble(4), () => stream.ReadDouble(), 4d);
            check(() => stream.WriteDoubleArray(new[] {4d}), () => stream.ReadDoubleArray(1), new[] {4d});

            check(() => stream.WriteFloat(4), () => stream.ReadFloat(), 4f);
            check(() => stream.WriteFloatArray(new[] {4f}), () => stream.ReadFloatArray(1), new[] {4f});

            check(() => stream.WriteInt(4), () => stream.ReadInt(), 4);
            check(() => stream.WriteInt(0, 4), () => stream.ReadInt(), 4);
            check(() => stream.WriteIntArray(new[] {4}), () => stream.ReadIntArray(1), new[] {4});

            check(() => stream.WriteLong(4), () => stream.ReadLong(), 4L);
            check(() => stream.WriteLongArray(new[] {4L}), () => stream.ReadLongArray(1), new[] {4L});

            check(() => stream.WriteShort(4), () => stream.ReadShort(), (short)4);
            check(() => stream.WriteShortArray(new short[] {4}), () => stream.ReadShortArray(1), new short[] {4});
        }
Beispiel #8
0
        /// <summary>
        /// Write object as a predefined type if possible.
        /// </summary>
        /// <param name="hdr">Header.</param>
        /// <param name="inStream">Input stream.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="ctx">Context.</param>
        /// <returns><c>True</c> if was written.</returns>
        private bool WriteAsPredefined(byte hdr, BinaryHeapStream inStream, IBinaryStream outStream,
                                       Context ctx)
        {
            switch (hdr)
            {
            case BinaryTypeId.Byte:
                TransferBytes(inStream, outStream, 1);

                break;

            case BinaryTypeId.Short:
                TransferBytes(inStream, outStream, 2);

                break;

            case BinaryTypeId.Int:
                TransferBytes(inStream, outStream, 4);

                break;

            case BinaryTypeId.Long:
                TransferBytes(inStream, outStream, 8);

                break;

            case BinaryTypeId.Float:
                TransferBytes(inStream, outStream, 4);

                break;

            case BinaryTypeId.Double:
                TransferBytes(inStream, outStream, 8);

                break;

            case BinaryTypeId.Char:
                TransferBytes(inStream, outStream, 2);

                break;

            case BinaryTypeId.Bool:
                TransferBytes(inStream, outStream, 1);

                break;

            case BinaryTypeId.Decimal:
                TransferBytes(inStream, outStream, 4); // Transfer scale

                int magLen = inStream.ReadInt();       // Transfer magnitude length.

                outStream.WriteInt(magLen);

                TransferBytes(inStream, outStream, magLen);     // Transfer magnitude.

                break;

            case BinaryTypeId.String:
                BinaryUtils.WriteString(BinaryUtils.ReadString(inStream), outStream);

                break;

            case BinaryTypeId.Guid:
                TransferBytes(inStream, outStream, 16);

                break;

            case BinaryTypeId.Timestamp:
                TransferBytes(inStream, outStream, 12);

                break;

            case BinaryTypeId.ArrayByte:
                TransferArray(inStream, outStream, 1);

                break;

            case BinaryTypeId.ArrayShort:
                TransferArray(inStream, outStream, 2);

                break;

            case BinaryTypeId.ArrayInt:
                TransferArray(inStream, outStream, 4);

                break;

            case BinaryTypeId.ArrayLong:
                TransferArray(inStream, outStream, 8);

                break;

            case BinaryTypeId.ArrayFloat:
                TransferArray(inStream, outStream, 4);

                break;

            case BinaryTypeId.ArrayDouble:
                TransferArray(inStream, outStream, 8);

                break;

            case BinaryTypeId.ArrayChar:
                TransferArray(inStream, outStream, 2);

                break;

            case BinaryTypeId.ArrayBool:
                TransferArray(inStream, outStream, 1);

                break;

            case BinaryTypeId.ArrayDecimal:
            case BinaryTypeId.ArrayString:
            case BinaryTypeId.ArrayGuid:
            case BinaryTypeId.ArrayTimestamp:
                int arrLen = inStream.ReadInt();

                outStream.WriteInt(arrLen);

                for (int i = 0; i < arrLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, null);
                }

                break;

            case BinaryTypeId.ArrayEnum:
            case BinaryTypeId.Array:
                int type = inStream.ReadInt();

                outStream.WriteInt(type);

                if (type == BinaryTypeId.Unregistered)
                {
                    outStream.WriteByte(inStream.ReadByte());                             // String header.

                    BinaryUtils.WriteString(BinaryUtils.ReadString(inStream), outStream); // String data.
                }

                arrLen = inStream.ReadInt();

                outStream.WriteInt(arrLen);

                for (int i = 0; i < arrLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, EmptyVals);
                }

                break;

            case BinaryTypeId.Collection:
                int colLen = inStream.ReadInt();

                outStream.WriteInt(colLen);

                outStream.WriteByte(inStream.ReadByte());

                for (int i = 0; i < colLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, EmptyVals);
                }

                break;

            case BinaryTypeId.Dictionary:
                int dictLen = inStream.ReadInt();

                outStream.WriteInt(dictLen);

                outStream.WriteByte(inStream.ReadByte());

                for (int i = 0; i < dictLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, EmptyVals);
                    Mutate0(ctx, inStream, outStream, false, EmptyVals);
                }

                break;

            case BinaryTypeId.Binary:
                TransferArray(inStream, outStream, 1);     // Data array.
                TransferBytes(inStream, outStream, 4);     // Offset in array.

                break;

            case BinaryTypeId.Enum:
                TransferBytes(inStream, outStream, 8);     // int typeId, int value.

                break;

            default:
                return(false);
            }

            return(true);
        }
Beispiel #9
0
        /// <summary>
        /// Internal mutation routine.
        /// </summary>
        /// <param name="inStream">Input stream.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="ctx">Context.</param>
        /// <param name="changeHash">WHether hash should be changed.</param>
        /// <param name="vals">Values to be replaced.</param>
        /// <returns>Mutated object.</returns>
        private void Mutate0(Context ctx, BinaryHeapStream inStream, IBinaryStream outStream,
                             bool changeHash, IDictionary <int, BinaryBuilderField> vals)
        {
            int inStartPos  = inStream.Position;
            int outStartPos = outStream.Position;

            byte inHdr = inStream.ReadByte();

            if (inHdr == BinaryUtils.HdrNull)
            {
                outStream.WriteByte(BinaryUtils.HdrNull);
            }
            else if (inHdr == BinaryUtils.HdrHnd)
            {
                int inHnd = inStream.ReadInt();

                int oldPos = inStartPos - inHnd;
                int newPos;

                if (ctx.OldToNew(oldPos, out newPos))
                {
                    // Handle is still valid.
                    outStream.WriteByte(BinaryUtils.HdrHnd);
                    outStream.WriteInt(outStartPos - newPos);
                }
                else
                {
                    // Handle is invalid, write full object.
                    int inRetPos = inStream.Position;

                    inStream.Seek(oldPos, SeekOrigin.Begin);

                    Mutate0(ctx, inStream, outStream, false, EmptyVals);

                    inStream.Seek(inRetPos, SeekOrigin.Begin);
                }
            }
            else if (inHdr == BinaryUtils.HdrFull)
            {
                var inHeader = BinaryObjectHeader.Read(inStream, inStartPos);

                BinaryUtils.ValidateProtocolVersion(inHeader.Version);

                int hndPos;

                if (ctx.AddOldToNew(inStartPos, outStartPos, out hndPos))
                {
                    // Object could be cached in parent builder.
                    BinaryBuilderField cachedVal;

                    if (_parent._cache != null && _parent._cache.TryGetValue(inStartPos, out cachedVal))
                    {
                        WriteField(ctx, cachedVal);
                    }
                    else
                    {
                        // New object, write in full form.
                        var inSchema = BinaryObjectSchemaSerializer.ReadSchema(inStream, inStartPos, inHeader,
                                                                               _desc.Schema, _binary.Marshaller.Ignite);

                        var outSchema = BinaryObjectSchemaHolder.Current;
                        var schemaIdx = outSchema.PushSchema();

                        try
                        {
                            // Skip header as it is not known at this point.
                            outStream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current);

                            if (inSchema != null)
                            {
                                foreach (var inField in inSchema)
                                {
                                    BinaryBuilderField fieldVal;

                                    var fieldFound = vals.TryGetValue(inField.Id, out fieldVal);

                                    if (fieldFound && fieldVal == BinaryBuilderField.RmvMarker)
                                    {
                                        continue;
                                    }

                                    outSchema.PushField(inField.Id, outStream.Position - outStartPos);

                                    if (!fieldFound)
                                    {
                                        fieldFound = _parent._cache != null &&
                                                     _parent._cache.TryGetValue(inField.Offset + inStartPos,
                                                                                out fieldVal);
                                    }

                                    if (fieldFound)
                                    {
                                        WriteField(ctx, fieldVal);

                                        vals.Remove(inField.Id);
                                    }
                                    else
                                    {
                                        // Field is not tracked, re-write as is.
                                        inStream.Seek(inField.Offset + inStartPos, SeekOrigin.Begin);

                                        Mutate0(ctx, inStream, outStream, false, EmptyVals);
                                    }
                                }
                            }

                            // Write remaining new fields.
                            foreach (var valEntry in vals)
                            {
                                if (valEntry.Value == BinaryBuilderField.RmvMarker)
                                {
                                    continue;
                                }

                                outSchema.PushField(valEntry.Key, outStream.Position - outStartPos);

                                WriteField(ctx, valEntry.Value);
                            }

                            var flags = inHeader.IsUserType
                                ? BinaryObjectHeader.Flag.UserType
                                : BinaryObjectHeader.Flag.None;

                            if (inHeader.IsCustomDotNetType)
                            {
                                flags |= BinaryObjectHeader.Flag.CustomDotNetType;
                            }

                            // Write raw data.
                            int outRawOff = outStream.Position - outStartPos;

                            if (inHeader.HasRaw)
                            {
                                var inRawOff = inHeader.GetRawOffset(inStream, inStartPos);
                                var inRawLen = inHeader.SchemaOffset - inRawOff;

                                flags |= BinaryObjectHeader.Flag.HasRaw;

                                outStream.Write(inStream.InternalArray, inStartPos + inRawOff, inRawLen);
                            }

                            // Write schema
                            int outSchemaOff = outRawOff;
                            var schemaPos    = outStream.Position;
                            int outSchemaId;

                            if (inHeader.IsCompactFooter)
                            {
                                flags |= BinaryObjectHeader.Flag.CompactFooter;
                            }

                            var hasSchema = outSchema.WriteSchema(outStream, schemaIdx, out outSchemaId, ref flags);

                            if (hasSchema)
                            {
                                outSchemaOff = schemaPos - outStartPos;

                                flags |= BinaryObjectHeader.Flag.HasSchema;

                                if (inHeader.HasRaw)
                                {
                                    outStream.WriteInt(outRawOff);
                                }

                                if (_desc.Schema.Get(outSchemaId) == null)
                                {
                                    _desc.Schema.Add(outSchemaId, outSchema.GetSchema(schemaIdx));
                                }
                            }

                            var outLen = outStream.Position - outStartPos;

                            var outHash = inHeader.HashCode;

                            if (changeHash)
                            {
                                // Get from identity resolver.
                                outHash = BinaryArrayEqualityComparer.GetHashCode(outStream,
                                                                                  outStartPos + BinaryObjectHeader.Size,
                                                                                  schemaPos - outStartPos - BinaryObjectHeader.Size);
                            }

                            var outHeader = new BinaryObjectHeader(inHeader.TypeId, outHash, outLen,
                                                                   outSchemaId, outSchemaOff, flags);

                            BinaryObjectHeader.Write(outHeader, outStream, outStartPos);

                            outStream.Seek(outStartPos + outLen, SeekOrigin.Begin);  // seek to the end of the object
                        }
                        finally
                        {
                            outSchema.PopSchema(schemaIdx);
                        }
                    }
                }
                else
                {
                    // Object has already been written, write as handle.
                    outStream.WriteByte(BinaryUtils.HdrHnd);
                    outStream.WriteInt(outStartPos - hndPos);
                }

                // Synchronize input stream position.
                inStream.Seek(inStartPos + inHeader.Length, SeekOrigin.Begin);
            }
            else
            {
                // Try writing as well-known type with fixed size.
                outStream.WriteByte(inHdr);

                if (!WriteAsPredefined(inHdr, inStream, outStream, ctx))
                {
                    throw new IgniteException("Unexpected header [position=" + (inStream.Position - 1) +
                                              ", header=" + inHdr + ']');
                }
            }
        }
Beispiel #10
0
        /// <summary>
        /// Write named boolean value.
        /// </summary>
        /// <param name="fieldName">Field name.</param>
        /// <param name="val">Boolean value.</param>
        public void WriteBoolean(string fieldName, bool val)
        {
            WriteFieldId(fieldName, BinaryUtils.TypeBool);

            _stream.WriteByte(BinaryUtils.TypeBool);
            _stream.WriteBool(val);
        }
Beispiel #11
0
 /// <summary>
 /// Writes the boolean field.
 /// </summary>
 /// <param name="val">if set to <c>true</c> [value].</param>
 internal void WriteBooleanField(bool val)
 {
     _stream.WriteByte(BinaryUtils.TypeBool);
     _stream.WriteBool(val);
 }
        /// <summary>
        /// Tests the stream.
        /// </summary>
        private static unsafe void TestStream(IBinaryStream stream, bool sameArr, Action flush)
        {
            Action seek = () => Assert.AreEqual(0, stream.Seek(0, SeekOrigin.Begin));

            Action <Action, Func <object>, object> check = (write, read, expectedResult) =>
            {
                seek();
                write();
                flush();
                seek();
                Assert.AreEqual(expectedResult, read());
            };

            // Arrays.
            if (stream.CanGetArray)
            {
                Assert.AreEqual(sameArr, stream.IsSameArray(stream.GetArray()));
            }
            Assert.IsFalse(stream.IsSameArray(new byte[1]));
            Assert.IsFalse(stream.IsSameArray(stream.GetArrayCopy()));

            // byte*
            byte *bytes = stackalloc byte[10];

            *bytes = 1;
            *(bytes + 1) = 2;

            stream.Write(bytes, 2);
            Assert.AreEqual(2, stream.Position);

            var proc = new SumStreamProcessor();

            Assert.AreEqual(0, stream.Apply(proc, 0));
            Assert.AreEqual(1, stream.Apply(proc, 1));
            Assert.AreEqual(3, stream.Apply(proc, 2));

            flush();

            seek();
            Assert.AreEqual(sameArr ? 256 : 2, stream.Remaining);
            byte *bytes2 = stackalloc byte[2];

            stream.Read(bytes2, 2);
            Assert.AreEqual(1, *bytes2);
            Assert.AreEqual(2, *(bytes2 + 1));

            // char*
            seek();
            char *chars = stackalloc char[10];

            *chars = 'a';
            *(chars + 1) = 'b';

            Assert.AreEqual(2, stream.WriteString(chars, 2, 2, Encoding.ASCII));
            flush();

            seek();
            stream.Read(bytes2, 2);
            Assert.AreEqual('a', *bytes2);
            Assert.AreEqual('b', *(bytes2 + 1));

            // Others.
            check(() => stream.Write(new byte[] { 3, 4, 5 }, 1, 2), () => stream.ReadByteArray(2), new byte[] { 4, 5 });

            check(() => stream.WriteBool(true), () => stream.ReadBool(), true);
            check(() => stream.WriteBoolArray(new[] { true, false }), () => stream.ReadBoolArray(2),
                  new[] { true, false });

            check(() => stream.WriteByte(4), () => stream.ReadByte(), 4);
            check(() => stream.WriteByteArray(new byte[] { 4, 5, 6 }), () => stream.ReadByteArray(3),
                  new byte[] { 4, 5, 6 });

            check(() => stream.WriteChar('x'), () => stream.ReadChar(), 'x');
            check(() => stream.WriteCharArray(new[] { 'a', 'b' }), () => stream.ReadCharArray(2), new[] { 'a', 'b' });

            check(() => stream.WriteDouble(4), () => stream.ReadDouble(), 4d);
            check(() => stream.WriteDoubleArray(new[] { 4d }), () => stream.ReadDoubleArray(1), new[] { 4d });

            check(() => stream.WriteFloat(4), () => stream.ReadFloat(), 4f);
            check(() => stream.WriteFloatArray(new[] { 4f }), () => stream.ReadFloatArray(1), new[] { 4f });

            check(() => stream.WriteInt(4), () => stream.ReadInt(), 4);
            check(() => stream.WriteInt(0, 4), () => stream.ReadInt(), 4);
            check(() => stream.WriteIntArray(new[] { 4 }), () => stream.ReadIntArray(1), new[] { 4 });

            check(() => stream.WriteLong(4), () => stream.ReadLong(), 4L);
            check(() => stream.WriteLongArray(new[] { 4L }), () => stream.ReadLongArray(1), new[] { 4L });

            check(() => stream.WriteShort(4), () => stream.ReadShort(), (short)4);
            check(() => stream.WriteShortArray(new short[] { 4 }), () => stream.ReadShortArray(1), new short[] { 4 });
        }
Beispiel #13
0
        /// <summary>
        /// Write object as a predefined type if possible.
        /// </summary>
        /// <param name="hdr">Header.</param>
        /// <param name="inStream">Input stream.</param>
        /// <param name="outStream">Output stream.</param>
        /// <param name="ctx">Context.</param>
        /// <returns><c>True</c> if was written.</returns>
        private bool WriteAsPredefined(byte hdr, BinaryHeapStream inStream, IBinaryStream outStream,
                                       Context ctx)
        {
            switch (hdr)
            {
            case BinaryUtils.TypeByte:
                TransferBytes(inStream, outStream, 1);

                break;

            case BinaryUtils.TypeShort:
                TransferBytes(inStream, outStream, 2);

                break;

            case BinaryUtils.TypeInt:
                TransferBytes(inStream, outStream, 4);

                break;

            case BinaryUtils.TypeLong:
                TransferBytes(inStream, outStream, 8);

                break;

            case BinaryUtils.TypeFloat:
                TransferBytes(inStream, outStream, 4);

                break;

            case BinaryUtils.TypeDouble:
                TransferBytes(inStream, outStream, 8);

                break;

            case BinaryUtils.TypeChar:
                TransferBytes(inStream, outStream, 2);

                break;

            case BinaryUtils.TypeBool:
                TransferBytes(inStream, outStream, 1);

                break;

            case BinaryUtils.TypeDecimal:
                TransferBytes(inStream, outStream, 4); // Transfer scale

                int magLen = inStream.ReadInt();       // Transfer magnitude length.

                outStream.WriteInt(magLen);

                TransferBytes(inStream, outStream, magLen);     // Transfer magnitude.

                break;

            case BinaryUtils.TypeString:
                BinaryUtils.WriteString(BinaryUtils.ReadString(inStream), outStream);

                break;

            case BinaryUtils.TypeGuid:
                TransferBytes(inStream, outStream, 16);

                break;

            case BinaryUtils.TypeTimestamp:
                TransferBytes(inStream, outStream, 12);

                break;

            case BinaryUtils.TypeArrayByte:
                TransferArray(inStream, outStream, 1);

                break;

            case BinaryUtils.TypeArrayShort:
                TransferArray(inStream, outStream, 2);

                break;

            case BinaryUtils.TypeArrayInt:
                TransferArray(inStream, outStream, 4);

                break;

            case BinaryUtils.TypeArrayLong:
                TransferArray(inStream, outStream, 8);

                break;

            case BinaryUtils.TypeArrayFloat:
                TransferArray(inStream, outStream, 4);

                break;

            case BinaryUtils.TypeArrayDouble:
                TransferArray(inStream, outStream, 8);

                break;

            case BinaryUtils.TypeArrayChar:
                TransferArray(inStream, outStream, 2);

                break;

            case BinaryUtils.TypeArrayBool:
                TransferArray(inStream, outStream, 1);

                break;

            case BinaryUtils.TypeArrayDecimal:
            case BinaryUtils.TypeArrayString:
            case BinaryUtils.TypeArrayGuid:
            case BinaryUtils.TypeArrayTimestamp:
            case BinaryUtils.TypeArrayEnum:
            case BinaryUtils.TypeArray:
                int arrLen = inStream.ReadInt();

                outStream.WriteInt(arrLen);

                for (int i = 0; i < arrLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, 0, null);
                }

                break;

            case BinaryUtils.TypeCollection:
                int colLen = inStream.ReadInt();

                outStream.WriteInt(colLen);

                outStream.WriteByte(inStream.ReadByte());

                for (int i = 0; i < colLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);
                }

                break;

            case BinaryUtils.TypeDictionary:
                int dictLen = inStream.ReadInt();

                outStream.WriteInt(dictLen);

                outStream.WriteByte(inStream.ReadByte());

                for (int i = 0; i < dictLen; i++)
                {
                    Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);
                    Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);
                }

                break;

            case BinaryUtils.TypeMapEntry:
                Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);
                Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);

                break;

            case BinaryUtils.TypeBinary:
                TransferArray(inStream, outStream, 1);     // Data array.
                TransferBytes(inStream, outStream, 4);     // Offset in array.

                break;

            case BinaryUtils.TypeEnum:
                TransferBytes(inStream, outStream, 4);     // Integer ordinal.

                break;

            default:
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Writes an array of fields to a stream.
        /// </summary>
        /// <param name="fields">Fields.</param>
        /// <param name="stream">Stream.</param>
        /// <param name="offset">Offset in the array.</param>
        /// <param name="count">Field count to write.</param>
        /// <param name="compact">Compact mode without field ids.</param>
        /// <returns>
        /// Flags according to offset sizes: <see cref="BinaryObjectHeader.Flag.OffsetOneByte" />,
        /// <see cref="BinaryObjectHeader.Flag.OffsetTwoBytes" />, or 0.
        /// </returns>
        public static unsafe BinaryObjectHeader.Flag WriteSchema(BinaryObjectSchemaField[] fields, IBinaryStream stream, int offset,
            int count, bool compact)
        {
            Debug.Assert(fields != null);
            Debug.Assert(stream != null);
            Debug.Assert(count > 0);
            Debug.Assert(offset >= 0);
            Debug.Assert(offset < fields.Length);

            unchecked
            {
                // Last field is the farthest in the stream
                var maxFieldOffset = fields[offset + count - 1].Offset;

                if (compact)
                {
                    if (maxFieldOffset <= byte.MaxValue)
                    {
                        for (int i = offset; i < count + offset; i++)
                            stream.WriteByte((byte)fields[i].Offset);

                        return BinaryObjectHeader.Flag.OffsetOneByte;
                    }

                    if (maxFieldOffset <= ushort.MaxValue)
                    {
                        for (int i = offset; i < count + offset; i++)
                            stream.WriteShort((short)fields[i].Offset);

                        return BinaryObjectHeader.Flag.OffsetTwoBytes;
                    }

                    for (int i = offset; i < count + offset; i++)
                        stream.WriteInt(fields[i].Offset);
                }
                else
                {
                    if (maxFieldOffset <= byte.MaxValue)
                    {
                        for (int i = offset; i < count + offset; i++)
                        {
                            var field = fields[i];

                            stream.WriteInt(field.Id);
                            stream.WriteByte((byte)field.Offset);
                        }

                        return BinaryObjectHeader.Flag.OffsetOneByte;
                    }

                    if (maxFieldOffset <= ushort.MaxValue)
                    {
                        for (int i = offset; i < count + offset; i++)
                        {
                            var field = fields[i];

                            stream.WriteInt(field.Id);

                            stream.WriteShort((short)field.Offset);
                        }

                        return BinaryObjectHeader.Flag.OffsetTwoBytes;
                    }

                    if (BitConverter.IsLittleEndian)
                    {
                        fixed (BinaryObjectSchemaField* ptr = &fields[offset])
                        {
                            stream.Write((byte*)ptr, count / BinaryObjectSchemaField.Size);
                        }
                    }
                    else
                    {
                        for (int i = offset; i < count + offset; i++)
                        {
                            var field = fields[i];

                            stream.WriteInt(field.Id);
                            stream.WriteInt(field.Offset);
                        }
                    }
                }

                return BinaryObjectHeader.Flag.None;
            }
        }