示例#1
0
        //Return the offset for the nth member from an Array or Object type
        int GetNthOffset(int index)
        {
            int  offset;
            byte head = TypeCode;

            if (head == 0x13 || head == 0x14)
            {
                // compact Array or Object
                offset = GetNthOffsetFromCompact(index);
            }
            else if (head == 0x01 || head == 0x0a)
            {
                // special case: empty Array or empty Object
                throw new IndexOutOfRangeException();
            }
            else
            {
                long n;
                int  offsetsize = ObjectArrayUtil.GetOffsetSize(head);
                long end        = NumberUtil.ToLong(vpack, start + 1, offsetsize);
                int  dataOffset = FindDataOffset();
                if (head <= 0x05)
                {
                    // array with no offset table or length
                    VPackSlice first = new VPackSlice(vpack, start + dataOffset);
                    n = (end - dataOffset) / first.GetByteSize();
                }
                else if (offsetsize < 8)
                {
                    n = NumberUtil.ToLong(vpack, start + 1 + offsetsize, offsetsize);
                }
                else
                {
                    n = NumberUtil.ToLong(vpack, (int)(start + end - offsetsize), offsetsize);
                }
                if (index >= n)
                {
                    throw new IndexOutOfRangeException();
                }
                if (head <= 0x05 || n == 1)
                {
                    // no index table, but all array items have the same length
                    // or only one item is in the array
                    // now fetch first item and determine its length
                    if (dataOffset == 0)
                    {
                        dataOffset = FindDataOffset();
                    }
                    offset = dataOffset + index * new VPackSlice(vpack, start + dataOffset).GetByteSize();
                }
                else
                {
                    long ieBase = end - n * offsetsize + index * offsetsize - (offsetsize == 8 ? 8 : 0);
                    offset = (int)NumberUtil.ToLong(vpack, (int)(start + ieBase), offsetsize);
                }
            }
            return(offset);
        }
示例#2
0
        public VPackSlice ValueAt(int index)
        {
            if (!IsType(SliceType.Object))
            {
                throw new VPackValueTypeException(SliceType.Object);
            }
            VPackSlice key = GetNthKey(index);

            return(new VPackSlice(vpack, key.start + key.GetByteSize()));
        }
示例#3
0
        private VPackSlice SearchObjectKeyLinear(
            string attribute,
            long ieBase,
            int offsetsize,
            long n)
        {
            bool       useTranslator = attributeTranslator != null;
            VPackSlice result        = new VPackSlice();

            for (long index = 0; index < n; index++)
            {
                long       offset   = ieBase + index * offsetsize;
                long       keyIndex = NumberUtil.ToLong(vpack, (int)(start + offset), offsetsize);
                VPackSlice key      = new VPackSlice(vpack, (int)(start + keyIndex));
                if (key.IsType(SliceType.String))
                {
                    if (!key.IsEqualString(attribute))
                    {
                        continue;
                    }
                }
                else if (key.IsInteger())
                {
                    // translate key
                    if (!useTranslator)
                    {
                        // no attribute translator
                        throw new VPackNeedAttributeTranslatorException();
                    }
                    if (!key.TranslateUnchecked().IsEqualString(attribute))
                    {
                        continue;
                    }
                }
                else
                {
                    // invalid key type
                    result = new VPackSlice();
                    break;
                }
                // key is identical. now return value
                result = new VPackSlice(vpack, key.start + key.GetByteSize());
                break;
            }
            return(result);
        }
示例#4
0
        VPackSlice SearchObjectKeyBinary(
            string attribute,
            long ieBase,
            int offsetsize,
            long n)
        {
            bool       useTranslator = attributeTranslator != null;
            VPackSlice result;
            long       l = 0;
            long       r = n - 1;

            for (;;)
            {
                // midpoint
                long       index    = l + ((r - l) / 2);
                long       offset   = ieBase + index * offsetsize;
                long       keyIndex = NumberUtil.ToLong(vpack, (int)(start + offset), offsetsize);
                VPackSlice key      = new VPackSlice(vpack, (int)(start + keyIndex));
                int        res      = 0;
                if (key.IsType(SliceType.String))
                {
                    res = key.CompareString(attribute);
                }
                else if (key.IsInteger())
                {
                    // translate key
                    if (!useTranslator)
                    {
                        // no attribute translator
                        throw new VPackNeedAttributeTranslatorException();
                    }
                    res = key.TranslateUnchecked().CompareString(attribute);
                }
                else
                {
                    // invalid key
                    result = new VPackSlice();
                    break;
                }
                if (res == 0)
                {
                    // found
                    result = new VPackSlice(vpack, key.start + key.GetByteSize());
                    break;
                }
                if (res > 0)
                {
                    if (index == 0)
                    {
                        result = new VPackSlice();
                        break;
                    }
                    r = index - 1;
                }
                else
                {
                    l = index + 1;
                }
                if (r < l)
                {
                    result = new VPackSlice();
                    break;
                }
            }
            return(result);
        }
示例#5
0
        /// <summary>
        /// Return object by attribute name
        /// </summary>
        /// <param name="attribute"></param>
        /// <returns></returns>
        public VPackSlice this[string attribute]
        {
            get
            {
                if (!IsType(SliceType.Object))
                {
                    throw new VPackValueTypeException(SliceType.Object);
                }
                byte       head   = TypeCode;
                VPackSlice result = new VPackSlice();
                if (head == 0x0a)
                {
                    // special case, empty object
                    result = new VPackSlice();
                }
                else if (head == 0x14)
                {
                    // compact Object
                    result = GetFromCompactObject(attribute);
                }
                else
                {
                    int  offsetsize = ObjectArrayUtil.GetOffsetSize(head);
                    long end        = NumberUtil.ToLong(vpack, start + 1, offsetsize);
                    long n;
                    if (offsetsize < 8)
                    {
                        n = NumberUtil.ToLong(vpack, start + 1 + offsetsize, offsetsize);
                    }
                    else
                    {
                        n = NumberUtil.ToLong(vpack, (int)(start + end - offsetsize), offsetsize);
                    }
                    if (n == 1)
                    {
                        // Just one attribute, there is no index table!
                        VPackSlice key = new VPackSlice(vpack, start + FindDataOffset());

                        if (key.IsType(SliceType.String))
                        {
                            if (key.IsEqualString(attribute))
                            {
                                result = new VPackSlice(vpack, key.start + key.GetByteSize());
                            }
                            else
                            {
                                // no match
                                result = new VPackSlice();
                            }
                        }
                        else if (key.IsInteger())
                        {
                            // translate key
                            if (attributeTranslator == null)
                            {
                                throw new VPackNeedAttributeTranslatorException();
                            }
                            if (key.TranslateUnchecked().IsEqualString(attribute))
                            {
                                result = new VPackSlice(vpack, key.start + key.GetByteSize());
                            }
                            else
                            {
                                // no match
                                result = new VPackSlice();
                            }
                        }
                        else
                        {
                            // no match
                            result = new VPackSlice();
                        }
                    }
                    else
                    {
                        long ieBase = end - n * offsetsize - (offsetsize == 8 ? 8 : 0);

                        // only use binary search for attributes if we have at least
                        // this many entries
                        // otherwise we'll always use the linear search
                        long sortedSearchEntriesThreshold = 4;

                        bool sorted = head >= 0x0b && head <= 0x0e;
                        if (sorted && n >= sortedSearchEntriesThreshold)
                        {
                            // This means, we have to handle the special case n == 1
                            // only in the linear search!
                            result = SearchObjectKeyBinary(attribute, ieBase, offsetsize, n);
                        }
                        else
                        {
                            result = SearchObjectKeyLinear(attribute, ieBase, offsetsize, n);
                        }
                    }
                }
                return(result);
            }
        }