public static void EncodeValue(PropertyBlock block, int keyId, Value value, DynamicRecordAllocator stringAllocator, DynamicRecordAllocator arrayAllocator, bool allowStorePointsAndTemporal) { if (value is ArrayValue) { object asObject = value.AsObject(); // Try short array first, i.e. inlined in the property block if (ShortArray.encode(keyId, asObject, block, PropertyType.PayloadSize)) { return; } // Fall back to dynamic array store IList <DynamicRecord> arrayRecords = new List <DynamicRecord>(); AllocateArrayRecords(arrayRecords, asObject, arrayAllocator, allowStorePointsAndTemporal); SetSingleBlockValue(block, keyId, PropertyType.Array, Iterables.first(arrayRecords).Id); foreach (DynamicRecord valueRecord in arrayRecords) { valueRecord.SetType(PropertyType.Array.intValue()); } block.ValueRecords = arrayRecords; } else { value.WriteTo(new PropertyBlockValueWriter(block, keyId, stringAllocator, allowStorePointsAndTemporal)); } }
private static sbyte[] CreateBitCompactedArray(ShortArray type, object array, int offsetBytes) { Type componentType = array.GetType().GetElementType(); bool isPrimitiveByteArray = componentType.Equals(Byte.TYPE); bool isByteArray = componentType.Equals(typeof(Byte)) || isPrimitiveByteArray; int arrayLength = Array.getLength(array); int requiredBits = isByteArray ? (sizeof(sbyte) * 8) : type.calculateRequiredBitsForArray(array, arrayLength); int totalBits = requiredBits * arrayLength; int bitsUsedInLastByte = totalBits % 8; bitsUsedInLastByte = bitsUsedInLastByte == 0 ? 8 : bitsUsedInLastByte; if (isByteArray) { return(CreateBitCompactedByteArray(type, isPrimitiveByteArray, array, bitsUsedInLastByte, requiredBits, offsetBytes)); } else { int numberOfBytes = (totalBits - 1) / 8 + 1; numberOfBytes += NUMBER_HEADER_SIZE; // type + rest + requiredBits header. TODO no need to use full bytes Bits bits = Bits.bits(numberOfBytes); bits.Put(( sbyte )type.intValue()); bits.Put(( sbyte )bitsUsedInLastByte); bits.Put(( sbyte )requiredBits); type.writeAll(array, arrayLength, requiredBits, bits); return(bits.AsBytes(offsetBytes)); } }
private void AssertCanEncodeAndDecodeToSameValue(object value, int payloadSize) { PropertyBlock target = new PropertyBlock(); bool encoded = ShortArray.encode(0, value, target, payloadSize); assertTrue(encoded); assertEquals(Values.of(value), ShortArray.decode(target)); }
public static Value GetRightArray(Pair <sbyte[], sbyte[]> data) { sbyte[] header = data.First(); sbyte[] bArray = data.Other(); sbyte typeId = header[0]; if (typeId == PropertyType.String.intValue()) { ByteBuffer headerBuffer = ByteBuffer.wrap(header, 1, header.Length - 1); int arrayLength = headerBuffer.Int; string[] result = new string[arrayLength]; ByteBuffer dataBuffer = ByteBuffer.wrap(bArray); for (int i = 0; i < arrayLength; i++) { int byteLength = dataBuffer.Int; sbyte[] stringByteArray = new sbyte[byteLength]; dataBuffer.get(stringByteArray); result[i] = PropertyStore.DecodeString(stringByteArray); } return(Values.stringArray(result)); } else if (typeId == PropertyType.Geometry.intValue()) { GeometryType.GeometryHeader geometryHeader = GeometryType.GeometryHeader.fromArrayHeaderBytes(header); return(GeometryType.decodeGeometryArray(geometryHeader, bArray)); } else if (typeId == PropertyType.Temporal.intValue()) { TemporalType.TemporalHeader temporalHeader = TemporalType.TemporalHeader.fromArrayHeaderBytes(header); return(TemporalType.decodeTemporalArray(temporalHeader, bArray)); } else { ShortArray type = ShortArray.typeOf(typeId); int bitsUsedInLastByte = header[1]; int requiredBits = header[2]; if (requiredBits == 0) { return(type.createEmptyArray()); } if (type == ShortArray.Byte && requiredBits == (sizeof(sbyte) * 8)) { // Optimization for byte arrays (probably large ones) return(Values.byteArray(bArray)); } else { // Fallback to the generic approach, which is a slower Bits bits = Bits.bitsFromBytes(bArray); int length = (bArray.Length * 8 - (8 - bitsUsedInLastByte)) / requiredBits; return(type.createArray(length, bits, requiredBits)); } } }
private static sbyte[] CreateUncompactedArray(ShortArray type, object array, int offsetBytes) { int arrayLength = Array.getLength(array); int bytesPerElement = type.maxBits / 8; sbyte[] bytes = new sbyte[NUMBER_HEADER_SIZE + bytesPerElement * arrayLength + offsetBytes]; bytes[offsetBytes + 0] = ( sbyte )type.intValue(); bytes[offsetBytes + 1] = ( sbyte )8; bytes[offsetBytes + 2] = ( sbyte )type.maxBits; type.writeAll(array, bytes, NUMBER_HEADER_SIZE + offsetBytes); return(bytes); }
public static sbyte[] EncodeFromNumbers(object array, int offsetBytes) { ShortArray type = ShortArray.typeOf(array); if (type == null) { throw new System.ArgumentException(array + " not a valid array type."); } if (type == ShortArray.Double || type == ShortArray.Float) { // Skip array compaction for floating point numbers where compaction makes very little difference return(CreateUncompactedArray(type, array, offsetBytes)); } else { return(CreateBitCompactedArray(type, array, offsetBytes)); } }
private static sbyte[] CreateBitCompactedByteArray(ShortArray type, bool isPrimitiveByteArray, object array, int bitsUsedInLastByte, int requiredBits, int offsetBytes) { int arrayLength = Array.getLength(array); sbyte[] bytes = new sbyte[NUMBER_HEADER_SIZE + arrayLength + offsetBytes]; bytes[offsetBytes + 0] = ( sbyte )type.intValue(); bytes[offsetBytes + 1] = ( sbyte )bitsUsedInLastByte; bytes[offsetBytes + 2] = ( sbyte )requiredBits; if (isPrimitiveByteArray) { arraycopy(array, 0, bytes, NUMBER_HEADER_SIZE + offsetBytes, arrayLength); } else { sbyte?[] source = ( sbyte?[] )array; for (int i = 0; i < source.Length; i++) { bytes[NUMBER_HEADER_SIZE + offsetBytes + i] = source[i].Value; } } return(bytes); }
public static ArrayValue ReadArrayFromBuffer(ByteBuffer buffer) { if (buffer.limit() <= 0) { throw new System.InvalidOperationException("Given buffer is empty"); } sbyte typeId = buffer.get(); buffer.order(ByteOrder.BIG_ENDIAN); try { if (typeId == PropertyType.String.intValue()) { int arrayLength = buffer.Int; string[] result = new string[arrayLength]; for (int i = 0; i < arrayLength; i++) { int byteLength = buffer.Int; result[i] = UTF8.decode(buffer.array(), buffer.position(), byteLength); buffer.position(buffer.position() + byteLength); } return(Values.stringArray(result)); } else if (typeId == PropertyType.Geometry.intValue()) { GeometryType.GeometryHeader header = GeometryType.GeometryHeader.fromArrayHeaderByteBuffer(buffer); sbyte[] byteArray = new sbyte[buffer.limit() - buffer.position()]; buffer.get(byteArray); return(GeometryType.decodeGeometryArray(header, byteArray)); } else if (typeId == PropertyType.Temporal.intValue()) { TemporalType.TemporalHeader header = TemporalType.TemporalHeader.fromArrayHeaderByteBuffer(buffer); sbyte[] byteArray = new sbyte[buffer.limit() - buffer.position()]; buffer.get(byteArray); return(TemporalType.decodeTemporalArray(header, byteArray)); } else { ShortArray type = ShortArray.typeOf(typeId); int bitsUsedInLastByte = buffer.get(); int requiredBits = buffer.get(); if (requiredBits == 0) { return(type.createEmptyArray()); } if (type == ShortArray.Byte && requiredBits == (sizeof(sbyte) * 8)) { // Optimization for byte arrays (probably large ones) sbyte[] byteArray = new sbyte[buffer.limit() - buffer.position()]; buffer.get(byteArray); return(Values.byteArray(byteArray)); } else { // Fallback to the generic approach, which is a slower Bits bits = Bits.bitsFromBytes(buffer.array(), buffer.position()); int length = ((buffer.limit() - buffer.position()) * 8 - (8 - bitsUsedInLastByte)) / requiredBits; return(type.createArray(length, bits, requiredBits)); } } } finally { buffer.order(ByteOrder.LITTLE_ENDIAN); } }
private void AssertCanNotEncode(object intArray, int payloadSize) { assertFalse(ShortArray.encode(0, intArray, new PropertyBlock(), payloadSize)); }