Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
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);
            }
        }