1 package shark.internal 2 3 /** 4 * Provides read access to a sub part of a larger array. 5 */ 6 internal class ByteSubArray( 7 private val array: ByteArray, 8 private val rangeStart: Int, 9 size: Int, 10 private val longIdentifiers: Boolean 11 ) { 12 13 private val endInclusive = size - 1 14 15 private var currentIndex = 0 16 readBytenull17 fun readByte(): Byte { 18 val index = currentIndex 19 currentIndex++ 20 require(index in 0..endInclusive) { 21 "Index $index should be between 0 and $endInclusive" 22 } 23 return array[rangeStart + index] 24 } 25 readIdnull26 fun readId(): Long { 27 return if (longIdentifiers) { 28 readLong() 29 } else { 30 readInt().toLong() 31 } 32 } 33 readIntnull34 fun readInt(): Int { 35 val index = currentIndex 36 currentIndex += 4 37 require(index >= 0 && index <= endInclusive - 3) { 38 "Index $index should be between 0 and ${endInclusive - 3}" 39 } 40 return array.readInt(rangeStart + index) 41 } 42 readTruncatedLongnull43 fun readTruncatedLong(byteCount: Int): Long { 44 val index = currentIndex 45 currentIndex += byteCount 46 require(index >= 0 && index <= endInclusive - (byteCount - 1)) { 47 "Index $index should be between 0 and ${endInclusive - (byteCount - 1)}" 48 } 49 var pos = rangeStart + index 50 val array = array 51 52 var value = 0L 53 54 var shift = (byteCount - 1) * 8 55 while (shift >= 8) { 56 value = value or (array[pos++] and 0xffL shl shift) 57 shift -= 8 58 } 59 value = value or (array[pos] and 0xffL) 60 return value 61 } 62 readLongnull63 fun readLong(): Long { 64 val index = currentIndex 65 currentIndex += 8 66 require(index >= 0 && index <= endInclusive - 7) { 67 "Index $index should be between 0 and ${endInclusive - 7}" 68 } 69 return array.readLong(rangeStart + index) 70 } 71 } 72 readShortnull73internal fun ByteArray.readShort(index: Int): Short { 74 var pos = index 75 val array = this 76 val valueAsInt = array[pos++] and 0xff shl 8 or (array[pos] and 0xff) 77 return valueAsInt.toShort() 78 } 79 readIntnull80internal fun ByteArray.readInt(index: Int): Int { 81 var pos = index 82 val array = this 83 return (array[pos++] and 0xff shl 24 84 or (array[pos++] and 0xff shl 16) 85 or (array[pos++] and 0xff shl 8) 86 or (array[pos] and 0xff)) 87 } 88 readLongnull89internal fun ByteArray.readLong(index: Int): Long { 90 var pos = index 91 val array = this 92 return (array[pos++] and 0xffL shl 56 93 or (array[pos++] and 0xffL shl 48) 94 or (array[pos++] and 0xffL shl 40) 95 or (array[pos++] and 0xffL shl 32) 96 or (array[pos++] and 0xffL shl 24) 97 or (array[pos++] and 0xffL shl 16) 98 or (array[pos++] and 0xffL shl 8) 99 or (array[pos] and 0xffL)) 100 } 101 102 @Suppress("NOTHING_TO_INLINE") // Syntactic sugar. andnull103private inline infix fun Byte.and(other: Long): Long = toLong() and other 104 105 @Suppress("NOTHING_TO_INLINE") // Syntactic sugar. 106 private inline infix fun Byte.and(other: Int): Int = toInt() and other