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); }
/// <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); } }