/// <returns>the offset for the nth member from an Array or Object type</returns> private int getNthOffset(int index) { int offset; byte head = head(); if (head == unchecked ((int)0x13) || head == unchecked ((int)0x14)) { // compact Array or Object offset = this.getNthOffsetFromCompact(index); } else { if (head == unchecked ((int)0x01) || head == unchecked ((int)0x0a)) { // special case: empty Array or empty Object throw new System.IndexOutOfRangeException(); } else { long n; int offsetsize = ObjectArrayUtil.getOffsetSize (head); long end = NumberUtil.toLong(this.vpack, this.start + 1, offsetsize); int dataOffset = this.findDataOffset(); if ((sbyte)head <= unchecked ((int)0x05)) { // array with no offset table or length VPackSlice first = new VPackSlice (this.vpack, this.start + dataOffset); n = (end - dataOffset) / first.getByteSize(); } else { 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 (index >= n) { throw new System.IndexOutOfRangeException(); } if ((sbyte)head <= unchecked ((int)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 = this.findDataOffset(); } offset = dataOffset + index * new VPackSlice(this.vpack, this.start + dataOffset).getByteSize(); } else { long ieBase = end - n * offsetsize + index * offsetsize - (offsetsize == 8 ? 8 : 0); offset = (int)NumberUtil.toLong(this.vpack, (int )(this.start + ieBase), offsetsize); } } } return(offset); }
public virtual int getByteSize() { long size; byte head = head(); int valueLength = ValueLengthUtil.get(head ); if (valueLength != 0) { size = valueLength; } else { switch (this.type()) { case ValueType.ARRAY: case ValueType.OBJECT: { if (head == unchecked ((int)0x13) || head == unchecked ((int)0x14)) { // compact Array or Object size = NumberUtil.readVariableValueLength( this.vpack, this.start + 1, false); } else { /* if (head <= 0x14) */ size = NumberUtil.toLong(this.vpack, this.start + 1, ObjectArrayUtil.getOffsetSize(head)); } break; } case ValueType.STRING: { // long UTF-8 String size = this.getLongStringLength() + 1 + 8; break; } case ValueType.BINARY: { size = 1 + head - unchecked ((byte)unchecked ((int)0xbf)) + this.getBinaryLengthUnchecked (); break; } case ValueType.BCD: { if ((sbyte)head <= unchecked ((int)0xcf)) { size = 1 + head + unchecked ((byte)unchecked ((int)0xc7)) + NumberUtil .toLong(this.vpack, this.start + 1, head - unchecked ((byte)unchecked ((int)0xc7))); } else { size = 1 + head - unchecked ((byte)unchecked ((int)0xcf)) + NumberUtil .toLong(this.vpack, this.start + 1, head - unchecked ((byte)unchecked ((int)0xcf))); } break; } case ValueType.CUSTOM: { if (head == unchecked ((int)0xf4) || head == unchecked ((int)0xf5) || head == unchecked ( (int)0xf6)) { size = 2 + NumberUtil.toLong(this.vpack, this.start + 1, 1); } else { if (head == unchecked ((int)0xf7) || head == unchecked ((int)0xf8) || head == unchecked ( (int)0xf9)) { size = 3 + NumberUtil.toLong(this.vpack, this.start + 1, 2); } else { if (head == unchecked ((int)0xfa) || head == unchecked ((int)0xfb) || head == unchecked ( (int)0xfc)) { size = 5 + NumberUtil.toLong(this.vpack, this.start + 1, 4); } else { /* if (head == 0xfd || head == 0xfe || head == 0xff) */ size = 9 + NumberUtil.toLong(this.vpack, this.start + 1, 8); } } } break; } default: { // TODO throw new java.lang.InternalError(); } } } return((int)size); }
/// <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); }
/// <returns>the number of members for an Array, Object or String</returns> public virtual int getLength() { long length; if (this.isString()) { length = this.getStringLength(); } else { if (!this.isArray() && !this.isObject()) { throw new VPackValueTypeException(ValueType .ARRAY, ValueType.OBJECT, ValueType .STRING); } else { byte head = head(); if (head == unchecked ((int)0x01) || head == unchecked ((int)0x0a)) { // empty length = 0; } else { if (head == unchecked ((int)0x13) || head == unchecked ((int)0x14)) { // compact array or object long end = NumberUtil.readVariableValueLength (this.vpack, this.start + 1, false); length = NumberUtil.readVariableValueLength (this.vpack, (int)(this.start + end - 1), true); } else { int offsetsize = ObjectArrayUtil.getOffsetSize (head); long end = NumberUtil.toLong(this.vpack, this.start + 1, offsetsize); if ((sbyte)head <= unchecked ((int)0x05)) { // array with no offset table or length int dataOffset = this.findDataOffset(); VPackSlice first = new VPackSlice (this.vpack, this.start + dataOffset); length = (end - dataOffset) / first.getByteSize(); } else { if (offsetsize < 8) { length = NumberUtil.toLong(this.vpack, this.start + 1 + offsetsize, offsetsize); } else { length = NumberUtil.toLong(this.vpack, (int)(this.start + end - offsetsize), offsetsize); } } } } } } return((int)length); }