1 package shark.internal 2 3 import shark.HprofRecord.HeapDumpRecord.ObjectRecord.InstanceDumpRecord 4 5 /** 6 * Simplified version of [FieldValuesReader] class that can only read an ID or skip a certain 7 * amount of bytes. 8 */ 9 internal class FieldIdReader( 10 private val record: InstanceDumpRecord, 11 private val identifierByteSize: Int 12 ) { 13 14 private var position = 0 15 readIdnull16 fun readId(): Long { 17 // As long as we don't interpret IDs, reading signed values here is fine. 18 val value = when (identifierByteSize) { 19 1 -> readByteId(position, record.fieldValues) 20 2 -> readShortId(position, record.fieldValues) 21 4 -> readIntId(position, record.fieldValues) 22 8 -> readLongId(position, record.fieldValues) 23 else -> error("ID Length must be 1, 2, 4, or 8") 24 } 25 position += identifierByteSize 26 return value 27 } 28 skipBytesnull29 fun skipBytes(count: Int) { 30 position += count 31 } 32 readByteIdnull33 private fun readByteId( 34 index: Int, 35 array: ByteArray 36 ) = 37 array[index].toLong() 38 39 private fun readShortId( 40 index: Int, 41 array: ByteArray 42 ): Long { 43 var pos = index 44 return (array[pos++] and 0xff shl 8 45 or (array[pos] and 0xff)).toLong() 46 } 47 readIntIdnull48 private fun readIntId( 49 index: Int, 50 array: ByteArray 51 ): Long { 52 var pos = index 53 return (array[pos++] and 0xff shl 24 54 or (array[pos++] and 0xff shl 16) 55 or (array[pos++] and 0xff shl 8) 56 or (array[pos] and 0xff)).toLong() 57 } 58 readLongIdnull59 private fun readLongId( 60 index: Int, 61 array: ByteArray 62 ): Long { 63 var pos = index 64 return (array[pos++] and 0xffL shl 56 65 or (array[pos++] and 0xffL shl 48) 66 or (array[pos++] and 0xffL shl 40) 67 or (array[pos++] and 0xffL shl 32) 68 or (array[pos++] and 0xffL shl 24) 69 or (array[pos++] and 0xffL shl 16) 70 or (array[pos++] and 0xffL shl 8) 71 or (array[pos] and 0xffL)) 72 } 73 74 @Suppress("NOTHING_TO_INLINE") // Syntactic sugar. andnull75 private inline infix fun Byte.and(other: Long): Long = toLong() and other 76 77 @Suppress("NOTHING_TO_INLINE") // Syntactic sugar. 78 private inline infix fun Byte.and(other: Int): Int = toInt() and other 79 }