Esempio n. 1
0
 /// <summary>
 /// Copy a previously-encoded UTF-8 string value into this byte array.
 /// A call to this method must be preceded by a call to "encodeTag"
 /// or "encodeTagArray". The caller must ensure the byte array is a
 /// valid UTF-8 encoded string; no checking is performed.
 /// </summary>
 /// <param name="value">The byte array containing a UTF-8 string
 ///                     to be included in the output message.</param>
 /// <param name="offset">The offset in <paramref name="offset"/>
 ///                     where the encoded UTF-8 string begins.</param>
 /// <param name="length">The length of the UTF-8 encoded stirng,
 ///   in bytes, to be written to the output message.</param>
 /// <returns>This builder.</returns>
 public BFlatBuilder encode(byte[] value, int offset, int length)
 {
     Leb128.encodeUnsigned(this, (uint)length);
     Array.Copy(value, offset, data, position, length);
     position += length;
     return(this);
 }
Esempio n. 2
0
        // Internal version just uses a "byte" as the first parameter.
        internal BFlatBuilder encodeTag(byte type, String tagName)
        {
            if (tagName.Length == 0)
            {
                throw new BFlatException("Zero length tags are not allowed.");
            }
            uint tagLen = (uint)tagName.Length;

            if (tagLen < 8)
            {
                // see if fit the tag len into the byte0
                int  byte0  = position++;
                uint actual = encodeString(tagName);
                if (actual < 8)
                {
                    data[byte0] = (byte)(type | actual);
                }
                else
                {
                    // since the tag <8 characters we know that the # of bytes
                    // it will fit in is representable with a one byte leb128
                    data[byte0] = (byte)type;
                    Array.Copy(data, byte0 + 1, data, byte0 + 2, actual);
                    data[byte0 + 1] = (byte)actual;
                    ++position;
                }
            }
            else
            {
                data[position++] = (byte)type;
                int  start     = position;
                int  leblength = Leb128.encodeUnsigned(this, tagLen);
                uint actual    = encodeString(tagName);
                if (actual != tagLen)
                {
                    int end = position;
                    position = start;
                    int actual_leblength = Leb128.encodeUnsigned(this, actual);
                    // do we need to reserialize the data?
                    if (actual_leblength != leblength)
                    {
                        encodeString(tagName);
                    }
                    else
                    {
                        position = end;
                    }
                }
            }
            return(this);
        }
Esempio n. 3
0
        /// <summary>
        /// Encode a string value into this byte array. A call to this method
        /// must be preceded by a call to "encodeTag" or "encodeTagArray."
        /// </summary>
        /// <param name="value">The value to encode into this array.</param>
        /// <returns>This builder.</returns>
        public BFlatBuilder encode(String value)
        {
            int  charcount = value.Length;
            int  start     = position;
            int  leblength = Leb128.encodeUnsigned(this, (uint)charcount);
            uint bytecount = encodeString(value);
            int  end       = position;

            if (bytecount != charcount) // non ascii
            {
                position = start;
                int actual_leblength = Leb128.encodeUnsigned(this, bytecount);
                if (actual_leblength != leblength)
                {
                    //reserialize the string
                    encodeString(value);
                }
                else
                {
                    position = end;
                }
            }
            return(this);
        }
Esempio n. 4
0
        // Internal version of encodeTag takes a byte as the first parameter.
        internal BFlatBuilder encodeTag(byte type, byte[] tagName)
        {
            if (tagName.Length == 0)
            {
                throw new BFlatException("Zero length tags are not allowed.");
            }
            int tagLen = tagName.Length;

            if (tagLen < 8)
            {
                // fit the tag len into the byte0
                data[position++] = (byte)((int)type | tagLen);
                Array.Copy(tagName, 0, data, position, tagLen);
                position += tagLen;
            }
            else
            {
                data[position++] = (byte)type;
                Leb128.encodeUnsigned(this, (uint)tagLen);
                Array.Copy(tagName, 0, data, position, tagLen);
                position += tagLen;
            }
            return(this);
        }
Esempio n. 5
0
        BFlatValue parseNext()
        {
            if (position >= _end)
            {
                return(null);
            }
            BFlatValue value = (_current != null && _current.isReuse())
          ? _current.reset(data) : new BFlatValue(data);


            byte byte0     = data[position++];
            byte type      = (byte)(byte0 & BFlatEncoding.TypeMask);
            bool isArray   = (byte0 & BFlatEncoding.ArrayMask) != 0;
            int  tagLength = byte0 & BFlatEncoding.LengthMask;
            int  tagStart  = position;

            if (tagLength == 0)
            {
                tagLength = (int)(Leb128.decodeUnsigned(this));
                if (tagLength == 0)
                {
                    throw new BFlatException("zero-length tag", position);
                }
                tagStart = position;
            }
            value.setTag(tagStart, tagLength);
            position += tagLength;
            int dataStart = position;

            int elementCount = 1;

            if (isArray)
            {
                elementCount = (int)(Leb128.decodeUnsigned(this));
                dataStart    = position;
            }

            value.setData(position, byte0, elementCount);
            // for variable length types we have to parse the array contents
            switch ((BFlatEncoding.Type)type)
            {
            case BFlatEncoding.Type.String:
            case BFlatEncoding.Type.Binary:
                for (int i = 0; i < elementCount; ++i)
                {
                    int length = (int)(Leb128.decodeUnsigned(this));
                    value.setStringOffsetAndLen(i, position, length);
                    position += length;
                }
                break;

            case BFlatEncoding.Type.Leb128:
                for (int i = 0; i < elementCount; ++i)
                {
                    long leb128 = Leb128.decodeSigned(this);
                    value.setLeb128Value(i, leb128);
                }
                break;

            case BFlatEncoding.Type.Int8:
                position += elementCount;
                break;

            case BFlatEncoding.Type.Int16:
                position += elementCount * 2;
                break;

            case BFlatEncoding.Type.Int32:
                position += elementCount * 4;
                break;

            case BFlatEncoding.Type.Int64:
            case BFlatEncoding.Type.Double:
            case BFlatEncoding.Type.Datetime:
                position += elementCount * 8;
                break;

            case BFlatEncoding.Type.Null:
                break;

            default:
                throw new BFlatException("unknown value type", position);
            }
            return(value);
        }
Esempio n. 6
0
 encodeTagArray(BFlatEncoding.Type type, String tagName, int count)
 {
     encodeTag((byte)((byte)type | BFlatEncoding.ArrayMask), tagName);
     Leb128.encodeUnsigned(this, (uint)count);
     return(this);
 }