public void PackTo(ref TupleWriter writer)
 {
     for (int i = 0; i < m_count; i++)
     {
         TuplePackers.SerializeObjectTo(ref writer, m_items[i + m_offset]);
     }
 }
        public void PackKey(ref SliceWriter writer, IFdbTuple items)
        {
            var tw = new TupleWriter(writer);

            FdbTuple.Pack(ref tw, items);
            writer = tw.Output;
        }
        /// <summary>Writes a char array encoded in UTF-8</summary>
        internal static unsafe void WriteChars(ref TupleWriter writer, char[] value, int offset, int count)
        {
            Contract.Requires(offset >= 0 && count >= 0);

            if (count == 0)
            {
                if (value == null)
                {                 // "00"
                    WriteNil(ref writer);
                }
                else
                {                 // "02 00"
                    writer.Output.WriteByte2(FdbTupleTypes.Utf8, 0x00);
                }
            }
            else
            {
                fixed(char *chars = value)
                {
                    if (!TryWriteUnescapedUtf8String(ref writer, chars + offset, count))
                    {                     // the string contains \0 chars, we need to do it the hard way
                        WriteNulEscapedBytes(ref writer, FdbTupleTypes.Utf8, Encoding.UTF8.GetBytes(value, 0, count));
                    }
                }
            }
        }
        /// <summary>Writes an Int32 at the end, and advance the cursor</summary>
        /// <param name="writer">Target buffer</param>
        /// <param name="value">Signed DWORD, 32 bits, High Endian</param>
        public static void WriteInt32(ref TupleWriter writer, int value)
        {
            if (value <= 255)
            {
                if (value == 0)
                {                 // zero
                    writer.Output.WriteByte(FdbTupleTypes.IntZero);
                    return;
                }

                if (value > 0)
                {                 // 1..255: frequent for array index
                    writer.Output.WriteByte2(FdbTupleTypes.IntPos1, (byte)value);
                    return;
                }

                if (value > -256)
                {                 // -255..-1
                    writer.Output.WriteByte2(FdbTupleTypes.IntNeg1, (byte)(255 + value));
                    return;
                }
            }

            WriteInt64Slow(ref writer, value);
        }
        /// <summary>Serialize a value of type <typeparamref name="T"/> into a tuple segment</summary>
        /// <param name="value">Value that will be serialized</param>
        /// <returns>Slice that contains the binary representation of <paramref name="value"/></returns>
        public static Slice Serialize(T value)
        {
            var writer = new TupleWriter();

            Encoder(ref writer, value);
            return(writer.Output.ToSlice());
        }
예제 #6
0
        /// <summary>Creates a key range containing all children of tuple, optionally including the tuple itself.</summary>
        /// <param name="tuple">Tuple that is the prefix of all keys</param>
        /// <param name="includePrefix">If true, the tuple key itself is included, if false only the children keys are included</param>
        /// <returns>Range of all keys suffixed by the tuple. The tuple itself will be included if <paramref name="includePrefix"/> is true</returns>
        public static KeyRange ToRange([NotNull] this ITuple tuple, bool includePrefix)
        {
            if (tuple == null)
            {
                throw new ArgumentNullException(nameof(tuple));
            }

            // We want to allocate only one byte[] to store both keys, and map both Slice to each chunk
            // So we will serialize the tuple two times in the same writer

            var writer = new TupleWriter();

            tuple.PackTo(ref writer);
            writer.Output.EnsureBytes(writer.Output.Position + 2);
            if (!includePrefix)
            {
                writer.Output.WriteByte(0);
            }
            int p0 = writer.Output.Position;

            tuple.PackTo(ref writer);
            writer.Output.WriteByte(0xFF);
            int p1 = writer.Output.Position;

            return(new KeyRange(
                       new Slice(writer.Output.Buffer, 0, p0),
                       new Slice(writer.Output.Buffer, p0, p1 - p0)
                       ));
        }
        private static void WriteUInt64Slow(ref TupleWriter writer, ulong value)
        {
            // We are only called for values >= 256

            // determine the number of bytes needed to encode the value
            int bytes = NumberOfBytes(value);

            writer.Output.EnsureBytes(bytes + 1);

            var buffer = writer.Output.Buffer;
            int p      = writer.Output.Position;

            // simple case (ulong can only be positive)
            buffer[p++] = (byte)(FdbTupleTypes.IntBase + bytes);

            if (bytes > 0)
            {
                // head
                --bytes;
                int shift = bytes << 3;

                while (bytes-- > 0)
                {
                    buffer[p++] = (byte)(value >> shift);
                    shift      -= 8;
                }
                // last
                buffer[p++] = (byte)value;
            }

            writer.Output.Position = p;
        }
예제 #8
0
        public Slice ToSlice()
        {
            var writer = new TupleWriter();

            PackTo(ref writer);
            return(writer.Output.ToSlice());
        }
 public void PackTo(ref TupleWriter writer)
 {
     if (m_packed.IsPresent)
     {
         writer.Output.WriteBytes(m_packed);
     }
 }
 /// <summary>Writes a char encoded in UTF-8</summary>
 public static void WriteChar(ref TupleWriter writer, char value)
 {
     if (value == 0)
     {             // NUL => "00 0F"
         // note: \0 is the only unicode character that will produce a zero byte when converted in UTF-8
         writer.Output.WriteByte4(FdbTupleTypes.Utf8, 0x00, 0xFF, 0x00);
     }
     else if (value < 0x80)
     {             // 0x00..0x7F => 0xxxxxxx
         writer.Output.WriteByte3(FdbTupleTypes.Utf8, (byte)value, 0x00);
     }
     else if (value < 0x800)
     {             // 0x80..0x7FF => 110xxxxx 10xxxxxx => two bytes
         writer.Output.WriteByte4(FdbTupleTypes.Utf8, (byte)(0xC0 | (value >> 6)), (byte)(0x80 | (value & 0x3F)), 0x00);
     }
     else
     {             // 0x800..0xFFFF => 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
         // note: System.Char is 16 bits, and thus cannot represent UNICODE chars above 0xFFFF.
         // => This means that a System.Char will never take more than 3 bytes in UTF-8 !
         var tmp = Encoding.UTF8.GetBytes(new string(value, 1));
         writer.Output.EnsureBytes(tmp.Length + 2);
         writer.Output.UnsafeWriteByte(FdbTupleTypes.Utf8);
         writer.Output.UnsafeWriteBytes(tmp, 0, tmp.Length);
         writer.Output.UnsafeWriteByte(0x00);
     }
 }
예제 #11
0
        public void PackTo(ref TupleWriter writer)
        {
            TuplePacker <T1> .Encoder(ref writer, this.Item1);

            TuplePacker <T2> .Encoder(ref writer, this.Item2);

            TuplePacker <T3> .Encoder(ref writer, this.Item3);
        }
        public void EncodeKey <T1>(ref SliceWriter writer, T1 item1)
        {
            var tw = new TupleWriter(writer);

            FdbTuplePacker <T1> .SerializeTo(ref tw, item1);

            writer = tw.Output;
        }
        public Slice ToSlice()
        {
            // merge all the slices making up this segment
            //TODO: should we get the sum of all slices to pre-allocated the buffer ?
            var writer = new TupleWriter();

            PackTo(ref writer);
            return(writer.Output.ToSlice());
        }
        public override void EncodeOrderedSelfTerm(ref SliceWriter output, T value)
        {
            //HACKHACK: we lose the current depth!
            var writer = new TupleWriter(output);

            TuplePacker <T> .Encoder(ref writer, value);

            output = writer.Output;
        }
        public void PackTo(ref TupleWriter writer)
        {
            var slices = m_slices;

            for (int n = m_count, p = m_offset; n > 0; n--)
            {
                writer.Output.WriteBytes(slices[p++]);
            }
        }
 /// <summary>Writes a binary string</summary>
 public static void WriteBytes(ref TupleWriter writer, byte[] value)
 {
     if (value == null)
     {
         WriteNil(ref writer);
     }
     else
     {
         WriteNulEscapedBytes(ref writer, FdbTupleTypes.Bytes, value);
     }
 }
 /// <summary>Writes a null value at the end, and advance the cursor</summary>
 public static void WriteNil(ref TupleWriter writer)
 {
     if (writer.Depth == 0)
     {             // at the top level, NILs are escaped as <00>
         writer.Output.WriteByte(FdbTupleTypes.Nil);
     }
     else
     {             // inside a tuple, NILs are escaped as <00><FF>
         writer.Output.WriteByte2(FdbTupleTypes.Nil, 0xFF);
     }
 }
 /// <summary>Writes an UInt8 at the end, and advance the cursor</summary>
 /// <param name="writer">Target buffer</param>
 /// <param name="value">Unsigned BYTE, 32 bits</param>
 public static void WriteByte(ref TupleWriter writer, byte value)
 {
     if (value == 0)
     {             // zero
         writer.Output.WriteByte(FdbTupleTypes.IntZero);
     }
     else
     {             // 1..255: frequent for array index
         writer.Output.WriteByte2(FdbTupleTypes.IntPos1, value);
     }
 }
 /// <summary>Writes a 64-bit UUID</summary>
 public static void WriteUuid64(ref TupleWriter writer, Uuid64 value)
 {
     writer.Output.EnsureBytes(9);
     writer.Output.UnsafeWriteByte(FdbTupleTypes.Uuid64);
     unsafe
     {
         byte *ptr = stackalloc byte[8];
         value.WriteTo(ptr);
         writer.Output.UnsafeWriteBytes(ptr, 8);
     }
 }
 /// <summary>Writes a RFC 4122 encoded 128-bit UUID</summary>
 public static void WriteUuid128(ref TupleWriter writer, Uuid128 value)
 {
     writer.Output.EnsureBytes(17);
     writer.Output.UnsafeWriteByte(FdbTupleTypes.Uuid128);
     unsafe
     {
         byte *ptr = stackalloc byte[16];
         value.WriteTo(ptr);
         writer.Output.UnsafeWriteBytes(ptr, 16);
     }
 }
예제 #21
0
        public void PackTo(ref TupleWriter writer)
        {
            FdbTuplePacker <T1> .Encoder(ref writer, this.Item1);

            FdbTuplePacker <T2> .Encoder(ref writer, this.Item2);

            FdbTuplePacker <T3> .Encoder(ref writer, this.Item3);

            FdbTuplePacker <T4> .Encoder(ref writer, this.Item4);

            FdbTuplePacker <T5> .Encoder(ref writer, this.Item5);
        }
 public static void WriteBool(ref TupleWriter writer, bool value)
 {
     // To be compatible with other bindings, we will encode False as the number 0, and True as the number 1
     if (value)
     {             // true => 15 01
         writer.Output.WriteByte2(FdbTupleTypes.IntPos1, 1);
     }
     else
     {             // false => 14
         writer.Output.WriteByte(FdbTupleTypes.IntZero);
     }
 }
        public void EncodeKey <T1, T2, T3>(ref SliceWriter writer, T1 item1, T2 item2, T3 item3)
        {
            var tw = new TupleWriter(writer);

            TuplePacker <T1> .SerializeTo(ref tw, item1);

            TuplePacker <T2> .SerializeTo(ref tw, item2);

            TuplePacker <T3> .SerializeTo(ref tw, item3);

            writer = tw.Output;
        }
        /// <summary>Writes a RFC 4122 encoded 16-byte Microsoft GUID</summary>
        public static void WriteGuid(ref TupleWriter writer, Guid value)
        {
            writer.Output.EnsureBytes(17);
            writer.Output.UnsafeWriteByte(FdbTupleTypes.Uuid128);
            unsafe
            {
                // UUIDs are stored using the RFC 4122 standard, so we need to swap some parts of the System.Guid

                byte *ptr = stackalloc byte[16];
                Uuid128.Write(value, ptr);
                writer.Output.UnsafeWriteBytes(ptr, 16);
            }
        }
        public void EncodeKey <T1, T2, T3, T4, T5>(ref SliceWriter writer, T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
        {
            var tw = new TupleWriter(writer);

            FdbTuplePacker <T1> .SerializeTo(ref tw, item1);

            FdbTuplePacker <T2> .SerializeTo(ref tw, item2);

            FdbTuplePacker <T3> .SerializeTo(ref tw, item3);

            FdbTuplePacker <T4> .SerializeTo(ref tw, item4);

            FdbTuplePacker <T5> .SerializeTo(ref tw, item5);

            writer = tw.Output;
        }
 /// <summary>Writes an UInt64 at the end, and advance the cursor</summary>
 /// <param name="writer">Target buffer</param>
 /// <param name="value">Signed QWORD, 64 bits, High Endian</param>
 public static void WriteUInt64(ref TupleWriter writer, ulong value)
 {
     if (value <= 255)
     {
         if (value == 0)
         {                 // 0
             writer.Output.WriteByte(FdbTupleTypes.IntZero);
         }
         else
         {                 // 1..255
             writer.Output.WriteByte2(FdbTupleTypes.IntPos1, (byte)value);
         }
     }
     else
     {             // >= 256
         WriteUInt64Slow(ref writer, value);
     }
 }
        private static void WriteInt64Slow(ref TupleWriter writer, long value)
        {
            // we are only called for values <= -256 or >= 256

            // determine the number of bytes needed to encode the absolute value
            int bytes = NumberOfBytes(value);

            writer.Output.EnsureBytes(bytes + 1);

            var buffer = writer.Output.Buffer;
            int p      = writer.Output.Position;

            ulong v;

            if (value > 0)
            {             // simple case
                buffer[p++] = (byte)(FdbTupleTypes.IntBase + bytes);
                v           = (ulong)value;
            }
            else
            {             // we will encode the one's complement of the absolute value
                // -1 => 0xFE
                // -256 => 0xFFFE
                // -65536 => 0xFFFFFE
                buffer[p++] = (byte)(FdbTupleTypes.IntBase - bytes);
                v           = (ulong)(~(-value));
            }

            if (bytes > 0)
            {
                // head
                --bytes;
                int shift = bytes << 3;

                while (bytes-- > 0)
                {
                    buffer[p++] = (byte)(v >> shift);
                    shift      -= 8;
                }
                // last
                buffer[p++] = (byte)v;
            }
            writer.Output.Position = p;
        }
        /// <summary>Writes a buffer with all instances of 0 escaped as '00 FF'</summary>
        internal static void WriteNulEscapedBytes(ref TupleWriter writer, byte type, [NotNull] byte[] value, int offset, int count)
        {
            int n = count;

            // we need to know if there are any NUL chars (\0) that need escaping...
            // (we will also need to add 1 byte to the buffer size per NUL)
            for (int i = offset, end = offset + count; i < end; ++i)
            {
                if (value[i] == 0)
                {
                    ++n;
                }
            }

            writer.Output.EnsureBytes(n + 2);
            var buffer = writer.Output.Buffer;
            int p      = writer.Output.Position;

            buffer[p++] = type;
            if (n > 0)
            {
                if (n == count)
                {                 // no NULs in the string, can copy all at once
                    SliceHelpers.CopyBytesUnsafe(buffer, p, value, offset, n);
                    p += n;
                }
                else
                {                 // we need to escape all NULs
                    for (int i = offset, end = offset + count; i < end; ++i)
                    {
                        byte b = value[i];
                        buffer[p++] = b;
                        if (b == 0)
                        {
                            buffer[p++] = 0xFF;
                        }
                    }
                }
            }
            buffer[p] = 0x00;
            writer.Output.Position = p + 1;
        }
        /// <summary>Writes an Double at the end, and advance the cursor</summary>
        /// <param name="writer">Target buffer</param>
        /// <param name="value">IEEE Floating point, 64 bits, High Endian</param>
        public static void WriteDouble(ref TupleWriter writer, double value)
        {
            // The double is converted to its Big-Endian IEEE binary representation
            // - If the sign bit is set, flip all the bits
            // - If the sign bit is not set, just flip the sign bit
            // This ensures that all negative numbers have their first byte < 0x80, and all positive numbers have their first byte >= 0x80

            // Special case for NaN: All variants are normalized to float.NaN !
            if (double.IsNaN(value))
            {
                value = double.NaN;
            }

            // note: we could use BitConverter.DoubleToInt64Bits(...), but it does the same thing, and also it does not exist for floats...
            ulong bits;

            unsafe { bits = *((ulong *)&value); }

            if ((bits & 0x8000000000000000UL) != 0)
            {             // negative
                bits = ~bits;
            }
            else
            {             // postive
                bits |= 0x8000000000000000UL;
            }
            writer.Output.EnsureBytes(9);
            var buffer = writer.Output.Buffer;
            int p      = writer.Output.Position;

            buffer[p]              = FdbTupleTypes.Double;
            buffer[p + 1]          = (byte)(bits >> 56);
            buffer[p + 2]          = (byte)(bits >> 48);
            buffer[p + 3]          = (byte)(bits >> 40);
            buffer[p + 4]          = (byte)(bits >> 32);
            buffer[p + 5]          = (byte)(bits >> 24);
            buffer[p + 6]          = (byte)(bits >> 16);
            buffer[p + 7]          = (byte)(bits >> 8);
            buffer[p + 8]          = (byte)(bits);
            writer.Output.Position = p + 9;
        }
        /// <summary>Writes a buffer with all instances of 0 escaped as '00 FF'</summary>
        private static void WriteNulEscapedBytes(ref TupleWriter writer, byte type, [NotNull] byte[] value)
        {
            int n = value.Length;

            // we need to know if there are any NUL chars (\0) that need escaping...
            // (we will also need to add 1 byte to the buffer size per NUL)
            foreach (byte b in value)
            {
                if (b == 0)
                {
                    ++n;
                }
            }

            writer.Output.EnsureBytes(n + 2);
            var buffer = writer.Output.Buffer;
            int p      = writer.Output.Position;

            buffer[p++] = type;
            if (n > 0)
            {
                if (n == value.Length)
                {                 // no NULs in the string, can copy all at once
                    SliceHelpers.CopyBytesUnsafe(buffer, p, value, 0, n);
                    p += n;
                }
                else
                {                 // we need to escape all NULs
                    foreach (byte b in value)
                    {
                        buffer[p++] = b;
                        if (b == 0)
                        {
                            buffer[p++] = 0xFF;
                        }
                    }
                }
            }
            buffer[p++]            = 0x00;
            writer.Output.Position = p;
        }