Exemplo n.º 1
0
        /// <exception cref="VPackValueTypeException"/>
        /// <exception cref="VPackNeedAttributeTranslatorException
        ///     "/>
        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(this.vpack, (int)(this.start + offset), offsetsize);
                VPackSlice key      = new VPackSlice(this.vpack, (int)(this.start + keyIndex));
                if (key.IsString)
                {
                    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(this.vpack, key.start + key.ByteSize);
                break;
            }

            return(result);
        }
Exemplo n.º 2
0
        /// <exception cref="VPackValueTypeException"/>
        /// <exception cref="VPackNeedAttributeTranslatorException
        ///     "/>
        private 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(this.vpack, (int)(this.start + offset), offsetsize);
                VPackSlice key      = new VPackSlice(this.vpack, (int)(this.start + keyIndex));
                int        res      = 0;
                if (key.IsString)
                {
                    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(this.vpack, key.start + key.ByteSize);
                    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);
        }
Exemplo n.º 3
0
        /// <exception cref="VPackException"/>
        public virtual VPackSlice Get(string attribute)
        {
            if (!this.IsObject)
            {
                throw new VPackValueTypeException(ValueType.OBJECT);
            }

            byte       head   = Head;
            VPackSlice result = new VPackSlice();

            if (head == 0x0a)
            {
                // special case, empty object
                result = new VPackSlice();
            }
            else
            {
                if (head == 0x14)
                {
                    // compact Object
                    result = this.GetFromCompactObject(attribute);
                }
                else
                {
                    int  offsetsize = ObjectArrayUtil.GetOffsetSize(head);
                    long end        = NumberUtil.ToLong(this.vpack, this.start + 1, offsetsize);
                    long n;
                    if (offsetsize < 8)
                    {
                        n = NumberUtil.ToLong(this.vpack, this.start + 1 + offsetsize, offsetsize);
                    }
                    else
                    {
                        n = NumberUtil.ToLong(this.vpack, (int)(this.start + end - offsetsize), offsetsize);
                    }

                    if (n == 1)
                    {
                        // Just one attribute, there is no index table!
                        VPackSlice key = new VPackSlice(this.vpack, this.start + this.FindDataOffset());
                        if (key.IsString)
                        {
                            if (key.IsEqualString(attribute))
                            {
                                result = new VPackSlice(this.vpack, key.start + key.ByteSize);
                            }
                            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(this.vpack, key.start + key.ByteSize);
                                }
                                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 && (sbyte)head <= 0x0e;
                        if (sorted && n >= sortedSearchEntriesThreshold)
                        {
                            // This means, we have to handle the special case n == 1
                            // only in the linear search!
                            result = this.SearchObjectKeyBinary(attribute, ieBase, offsetsize, n);
                        }
                        else
                        {
                            result = this.SearchObjectKeyLinear(attribute, ieBase, offsetsize, n);
                        }
                    }
                }
            }

            return(result);
        }