/// <exception cref="com.arangodb.velocypack.exception.VPackValueTypeException"/> /// <exception cref="com.arangodb.velocypack.exception.VPackNeedAttributeTranslatorException /// "/> private VPackSlice searchObjectKeyLinear(string attribute , long ieBase, int offsetsize, long n) { bool useTranslator = VPackSlice.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.getByteSize ()); break; } return(result); }
/// <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 == unchecked ((int)0x0a)) { // special case, empty object result = new VPackSlice(); } else { if (head == unchecked ((int)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.getByteSize ()); } else { // no match result = new VPackSlice(); } } else { if (key.isInteger()) { // translate key if (VPackSlice.attributeTranslator == null) { throw new VPackNeedAttributeTranslatorException (); } if (key.translateUnchecked().isEqualString(attribute)) { result = new VPackSlice(this.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 >= unchecked ((int)0x0b) && (sbyte)head <= unchecked ((int)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); }