forked from openrs2/openrs2
Signed-off-by: Graham <gpe@openrs2.org>bzip2
parent
ad0cdb6056
commit
2a6b97480c
@ -1,11 +1,36 @@ |
||||
package org.openrs2.asm.io |
||||
|
||||
import io.netty.buffer.ByteBufAllocator |
||||
import org.objectweb.asm.tree.ClassNode |
||||
import org.openrs2.asm.packclass.ConstantPool |
||||
import org.openrs2.asm.packclass.PackClass |
||||
import org.openrs2.buffer.use |
||||
import org.openrs2.cache.Js5Pack |
||||
import java.io.InputStream |
||||
import javax.inject.Inject |
||||
import javax.inject.Singleton |
||||
|
||||
public object PackClassLibraryReader : LibraryReader { |
||||
@Singleton |
||||
public class PackClassLibraryReader @Inject constructor( |
||||
private val alloc: ByteBufAllocator |
||||
) : LibraryReader { |
||||
override fun read(input: InputStream): Iterable<ClassNode> { |
||||
// TODO(gpe): implement |
||||
return emptyList() |
||||
Js5Pack.read(input, alloc).use { pack -> |
||||
// read constant pool |
||||
val constantPool = pack.read(PackClass.CONSTANT_POOL_GROUP, PackClass.CONSTANT_POOL_FILE).use { buf -> |
||||
ConstantPool.read(buf) |
||||
} |
||||
|
||||
// read classes |
||||
val classes = mutableListOf<ClassNode>() |
||||
|
||||
for (entry in pack.list(PackClass.CLASS_GROUP)) { |
||||
pack.read(PackClass.CLASS_GROUP, entry.id).use { buf -> |
||||
classes += PackClass.read(buf, constantPool) |
||||
} |
||||
} |
||||
|
||||
return classes |
||||
} |
||||
} |
||||
} |
||||
|
@ -1,11 +1,45 @@ |
||||
package org.openrs2.asm.io |
||||
|
||||
import io.netty.buffer.ByteBufAllocator |
||||
import org.objectweb.asm.tree.ClassNode |
||||
import org.openrs2.asm.classpath.ClassPath |
||||
import org.openrs2.asm.packclass.ConstantPool |
||||
import org.openrs2.asm.packclass.PackClass |
||||
import org.openrs2.buffer.use |
||||
import org.openrs2.cache.Js5Pack |
||||
import java.io.OutputStream |
||||
import javax.inject.Inject |
||||
import javax.inject.Singleton |
||||
|
||||
public object PackClassLibraryWriter : LibraryWriter { |
||||
@Singleton |
||||
public class PackClassLibraryWriter @Inject constructor( |
||||
private val alloc: ByteBufAllocator |
||||
) : LibraryWriter { |
||||
override fun write(output: OutputStream, classPath: ClassPath, classes: Iterable<ClassNode>) { |
||||
// TODO(gpe): implement |
||||
Js5Pack.create(alloc).use { pack -> |
||||
// create constant pool |
||||
val builder = ConstantPool.Builder() |
||||
for (clazz in classes) { |
||||
builder.add(clazz) |
||||
} |
||||
val constantPool = builder.build() |
||||
|
||||
// write classes |
||||
for ((i, clazz) in classes.withIndex()) { |
||||
alloc.buffer().use { buf -> |
||||
PackClass.write(buf, constantPool, clazz) |
||||
pack.write(PackClass.CLASS_GROUP, i, buf) |
||||
} |
||||
} |
||||
|
||||
// write constant pool |
||||
alloc.buffer().use { buf -> |
||||
constantPool.write(buf) |
||||
pack.write(PackClass.CONSTANT_POOL_GROUP, PackClass.CONSTANT_POOL_FILE, buf) |
||||
} |
||||
|
||||
// write pack |
||||
pack.write(output) |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,565 @@ |
||||
package org.openrs2.asm.packclass |
||||
|
||||
import io.netty.buffer.ByteBuf |
||||
import it.unimi.dsi.fastutil.doubles.DoubleAVLTreeSet |
||||
import it.unimi.dsi.fastutil.floats.FloatAVLTreeSet |
||||
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet |
||||
import it.unimi.dsi.fastutil.longs.LongAVLTreeSet |
||||
import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet |
||||
import org.objectweb.asm.Type |
||||
import org.objectweb.asm.tree.ClassNode |
||||
import org.objectweb.asm.tree.FieldInsnNode |
||||
import org.objectweb.asm.tree.LdcInsnNode |
||||
import org.objectweb.asm.tree.MethodInsnNode |
||||
import org.objectweb.asm.tree.MultiANewArrayInsnNode |
||||
import org.objectweb.asm.tree.TypeInsnNode |
||||
import org.openrs2.buffer.readString |
||||
import org.openrs2.buffer.writeString |
||||
import org.openrs2.util.charset.ModifiedUtf8Charset |
||||
|
||||
public class ConstantPool private constructor( |
||||
private val strings: Array<String>, |
||||
private val fieldNamesAndTypes: Array<NameAndType>, |
||||
private val methodNamesAndTypes: Array<NameAndType>, |
||||
private val fieldRefs: Array<MemberRef>, |
||||
private val methodRefs: Array<MemberRef>, |
||||
private val interfaceMethodRefs: Array<MemberRef>, |
||||
private val ints: IntArray, |
||||
private val longs: LongArray, |
||||
private val floats: FloatArray, |
||||
private val doubles: DoubleArray |
||||
) { |
||||
public class Builder { |
||||
private val strings = ObjectAVLTreeSet<String>() |
||||
private val fieldNamesAndTypes = ObjectAVLTreeSet<NameAndType>() |
||||
private val methodNamesAndTypes = ObjectAVLTreeSet<NameAndType>() |
||||
private val fieldRefs = ObjectAVLTreeSet<MemberRef>() |
||||
private val methodRefs = ObjectAVLTreeSet<MemberRef>() |
||||
private val interfaceMethodRefs = ObjectAVLTreeSet<MemberRef>() |
||||
private val ints = IntAVLTreeSet() |
||||
private val longs = LongAVLTreeSet() |
||||
private val floats = FloatAVLTreeSet() |
||||
private val doubles = DoubleAVLTreeSet() |
||||
|
||||
public fun add(clazz: ClassNode): Builder { |
||||
if (clazz.sourceFile != null) { |
||||
strings += clazz.sourceFile |
||||
} |
||||
|
||||
strings += clazz.name |
||||
strings += clazz.superName |
||||
|
||||
strings.addAll(clazz.interfaces) |
||||
|
||||
for (method in clazz.methods) { |
||||
addMethodNameAndType(NameAndType(method.name, method.desc)) |
||||
|
||||
strings += method.exceptions |
||||
|
||||
for (tryCatch in method.tryCatchBlocks) { |
||||
if (tryCatch.type != null) { |
||||
strings += tryCatch.type |
||||
} |
||||
} |
||||
|
||||
for (insn in method.instructions) { |
||||
when (insn) { |
||||
is LdcInsnNode -> addConstant(insn.cst) |
||||
is MultiANewArrayInsnNode -> strings += insn.desc |
||||
is MethodInsnNode -> { |
||||
val methodRef = MemberRef(insn.owner, insn.name, insn.desc) |
||||
if (insn.itf) { |
||||
addInterfaceMethodRef(methodRef) |
||||
} else { |
||||
addMethodRef(methodRef) |
||||
} |
||||
} |
||||
is FieldInsnNode -> addFieldRef(MemberRef(insn.owner, insn.name, insn.desc)) |
||||
is TypeInsnNode -> strings += insn.desc |
||||
} |
||||
} |
||||
} |
||||
|
||||
for (field in clazz.fields) { |
||||
addFieldNameAndType(NameAndType(field.name, field.desc)) |
||||
|
||||
if (field.value != null) { |
||||
addConstant(field.value) |
||||
} |
||||
} |
||||
|
||||
return this |
||||
} |
||||
|
||||
private fun addFieldNameAndType(nameAndType: NameAndType) { |
||||
strings += nameAndType.name |
||||
strings += nameAndType.descriptor |
||||
fieldNamesAndTypes += nameAndType |
||||
} |
||||
|
||||
private fun addMethodNameAndType(nameAndType: NameAndType) { |
||||
strings += nameAndType.name |
||||
strings += nameAndType.descriptor |
||||
methodNamesAndTypes += nameAndType |
||||
} |
||||
|
||||
private fun addFieldRef(fieldRef: MemberRef) { |
||||
strings += fieldRef.clazz |
||||
addFieldNameAndType(fieldRef.nameAndType) |
||||
fieldRefs += fieldRef |
||||
} |
||||
|
||||
private fun addMethodRef(methodRef: MemberRef) { |
||||
strings += methodRef.clazz |
||||
addMethodNameAndType(methodRef.nameAndType) |
||||
methodRefs += methodRef |
||||
} |
||||
|
||||
private fun addInterfaceMethodRef(methodRef: MemberRef) { |
||||
strings += methodRef.clazz |
||||
addMethodNameAndType(methodRef.nameAndType) |
||||
interfaceMethodRefs += methodRef |
||||
} |
||||
|
||||
private fun addConstant(value: Any) { |
||||
when (value) { |
||||
is Int -> ints += value |
||||
is Long -> longs += value |
||||
is Float -> floats += value |
||||
is Double -> doubles += value |
||||
is String -> strings += value |
||||
is Type -> { |
||||
if (value.sort == Type.OBJECT) { |
||||
strings += value.internalName |
||||
} else { |
||||
throw IllegalArgumentException("Unsupported constant type: ${value.sort}") |
||||
} |
||||
} |
||||
else -> throw IllegalArgumentException("Unsupported constant type: ${value.javaClass.name}") |
||||
} |
||||
} |
||||
|
||||
public fun build(): ConstantPool { |
||||
strings.remove(CODE) |
||||
strings.remove(EXCEPTIONS) |
||||
strings.remove(SYNTHETIC) |
||||
strings.remove(CONSTANT_VALUE) |
||||
strings.remove(SOURCE_FILE) |
||||
strings.remove(LINE_NUMBER_TABLE) |
||||
|
||||
val it = strings.iterator() |
||||
val stringArray = Array(6 + strings.size) { i -> |
||||
when (i) { |
||||
0 -> CODE |
||||
1 -> EXCEPTIONS |
||||
2 -> SYNTHETIC |
||||
3 -> CONSTANT_VALUE |
||||
4 -> SOURCE_FILE |
||||
5 -> LINE_NUMBER_TABLE |
||||
else -> it.next() |
||||
} |
||||
} |
||||
|
||||
return ConstantPool( |
||||
stringArray, |
||||
fieldNamesAndTypes.toTypedArray(), |
||||
methodNamesAndTypes.toTypedArray(), |
||||
fieldRefs.toTypedArray(), |
||||
methodRefs.toTypedArray(), |
||||
interfaceMethodRefs.toTypedArray(), |
||||
ints.toIntArray(), |
||||
longs.toLongArray(), |
||||
floats.toFloatArray(), |
||||
doubles.toDoubleArray() |
||||
) |
||||
} |
||||
} |
||||
|
||||
public fun readString(buf: ByteBuf): String { |
||||
val index = buf.readUnsignedShort() |
||||
return strings[index] |
||||
} |
||||
|
||||
private fun getStringIndex(value: String): Int { |
||||
return when (value) { |
||||
CODE -> 0 |
||||
EXCEPTIONS -> 1 |
||||
SYNTHETIC -> 2 |
||||
CONSTANT_VALUE -> 3 |
||||
SOURCE_FILE -> 4 |
||||
LINE_NUMBER_TABLE -> 5 |
||||
else -> strings.binarySearch(value, 6) |
||||
} |
||||
} |
||||
|
||||
public fun writeString(buf: ByteBuf, value: String) { |
||||
buf.writeShort(getStringIndex(value)) |
||||
} |
||||
|
||||
public fun readOptionalString(buf: ByteBuf): String? { |
||||
val index = buf.readUnsignedShort() |
||||
return if (index != 0) { |
||||
strings[index - 1] |
||||
} else { |
||||
null |
||||
} |
||||
} |
||||
|
||||
public fun writeOptionalString(buf: ByteBuf, value: String?) { |
||||
if (value != null) { |
||||
buf.writeShort(getStringIndex(value) + 1) |
||||
} else { |
||||
buf.writeShort(0) |
||||
} |
||||
} |
||||
|
||||
public fun readFieldNameAndType(buf: ByteBuf): NameAndType { |
||||
val index = buf.readUnsignedShort() |
||||
return fieldNamesAndTypes[index] |
||||
} |
||||
|
||||
public fun writeFieldNameAndType(buf: ByteBuf, value: NameAndType) { |
||||
buf.writeShort(fieldNamesAndTypes.binarySearch(value)) |
||||
} |
||||
|
||||
public fun readMethodNameAndType(buf: ByteBuf): NameAndType { |
||||
val index = buf.readUnsignedShort() |
||||
return methodNamesAndTypes[index] |
||||
} |
||||
|
||||
public fun writeMethodNameAndType(buf: ByteBuf, value: NameAndType) { |
||||
buf.writeShort(methodNamesAndTypes.binarySearch(value)) |
||||
} |
||||
|
||||
public fun readFieldRef(buf: ByteBuf): MemberRef { |
||||
val index = buf.readUnsignedShort() |
||||
return fieldRefs[index] |
||||
} |
||||
|
||||
public fun writeFieldRef(buf: ByteBuf, value: MemberRef) { |
||||
buf.writeShort(fieldRefs.binarySearch(value)) |
||||
} |
||||
|
||||
public fun readMethodRef(buf: ByteBuf): MemberRef { |
||||
val index = buf.readUnsignedShort() |
||||
return methodRefs[index] |
||||
} |
||||
|
||||
public fun writeMethodRef(buf: ByteBuf, value: MemberRef) { |
||||
buf.writeShort(methodRefs.binarySearch(value)) |
||||
} |
||||
|
||||
public fun readInterfaceMethodRef(buf: ByteBuf): MemberRef { |
||||
val index = buf.readUnsignedShort() |
||||
return interfaceMethodRefs[index] |
||||
} |
||||
|
||||
public fun writeInterfaceMethodRef(buf: ByteBuf, value: MemberRef) { |
||||
buf.writeShort(interfaceMethodRefs.binarySearch(value)) |
||||
} |
||||
|
||||
public fun readInt(buf: ByteBuf): Int { |
||||
val index = buf.readUnsignedShort() |
||||
return ints[index] |
||||
} |
||||
|
||||
public fun writeInt(buf: ByteBuf, value: Int) { |
||||
buf.writeShort(ints.binarySearch(value)) |
||||
} |
||||
|
||||
public fun readLong(buf: ByteBuf): Long { |
||||
val index = buf.readUnsignedShort() |
||||
return longs[index] |
||||
} |
||||
|
||||
public fun writeLong(buf: ByteBuf, value: Long) { |
||||
buf.writeShort(longs.binarySearch(value)) |
||||
} |
||||
|
||||
public fun readFloat(buf: ByteBuf): Float { |
||||
val index = buf.readUnsignedShort() |
||||
return floats[index] |
||||
} |
||||
|
||||
public fun writeFloat(buf: ByteBuf, value: Float) { |
||||
buf.writeShort(floats.binarySearch(value)) |
||||
} |
||||
|
||||
public fun readDouble(buf: ByteBuf): Double { |
||||
val index = buf.readUnsignedShort() |
||||
return doubles[index] |
||||
} |
||||
|
||||
public fun writeDouble(buf: ByteBuf, value: Double) { |
||||
buf.writeShort(doubles.binarySearch(value)) |
||||
} |
||||
|
||||
public fun write(buf: ByteBuf) { |
||||
writeStrings(buf) |
||||
|
||||
writeNameAndTypeNames(buf, fieldNamesAndTypes) |
||||
writeNameAndTypeNames(buf, methodNamesAndTypes) |
||||
writeNameAndTypeDescriptors(buf, fieldNamesAndTypes) |
||||
writeNameAndTypeDescriptors(buf, methodNamesAndTypes) |
||||
|
||||
writeMemberRefClasses(buf, fieldRefs) |
||||
writeMemberRefClasses(buf, methodRefs) |
||||
writeMemberRefClasses(buf, interfaceMethodRefs) |
||||
writeFieldRefNamesAndTypes(buf) |
||||
writeMethodRefNamesAndTypes(buf, methodRefs) |
||||
writeMethodRefNamesAndTypes(buf, interfaceMethodRefs) |
||||
|
||||
writeInts(buf, ints) |
||||
writeLongs(buf, longs) |
||||
writeFloats(buf) |
||||
writeDoubles(buf) |
||||
|
||||
buf.writeShort(strings.size) |
||||
buf.writeShort(ints.size) |
||||
buf.writeShort(longs.size) |
||||
buf.writeShort(floats.size) |
||||
buf.writeShort(doubles.size) |
||||
buf.writeShort(fieldNamesAndTypes.size) |
||||
buf.writeShort(methodNamesAndTypes.size) |
||||
buf.writeShort(fieldRefs.size) |
||||
buf.writeShort(methodRefs.size) |
||||
buf.writeShort(interfaceMethodRefs.size) |
||||
} |
||||
|
||||
private fun writeStrings(buf: ByteBuf) { |
||||
for (i in 6 until strings.size) { |
||||
buf.writeString(strings[i], ModifiedUtf8Charset) |
||||
} |
||||
} |
||||
|
||||
private fun writeNameAndTypeNames(buf: ByteBuf, namesAndTypes: Array<NameAndType>) { |
||||
for (nameAndType in namesAndTypes) { |
||||
writeString(buf, nameAndType.name) |
||||
} |
||||
} |
||||
|
||||
private fun writeNameAndTypeDescriptors(buf: ByteBuf, namesAndTypes: Array<NameAndType>) { |
||||
for (nameAndType in namesAndTypes) { |
||||
writeString(buf, nameAndType.descriptor) |
||||
} |
||||
} |
||||
|
||||
private fun writeMemberRefClasses(buf: ByteBuf, memberRefs: Array<MemberRef>) { |
||||
for (memberRef in memberRefs) { |
||||
writeString(buf, memberRef.clazz) |
||||
} |
||||
} |
||||
|
||||
private fun writeFieldRefNamesAndTypes(buf: ByteBuf) { |
||||
for (fieldRef in fieldRefs) { |
||||
writeFieldNameAndType(buf, fieldRef.nameAndType) |
||||
} |
||||
} |
||||
|
||||
private fun writeMethodRefNamesAndTypes(buf: ByteBuf, methodRefs: Array<MemberRef>) { |
||||
for (methodRef in methodRefs) { |
||||
writeMethodNameAndType(buf, methodRef.nameAndType) |
||||
} |
||||
} |
||||
|
||||
private fun writeInts(buf: ByteBuf, values: IntArray) { |
||||
for (i in 24 downTo 0 step 8) { |
||||
var previous = 0 |
||||
for (value in values) { |
||||
buf.writeByte((value - previous) shr i) |
||||
previous = value |
||||
} |
||||
} |
||||
} |
||||
|
||||
private fun writeLongs(buf: ByteBuf, values: LongArray) { |
||||
for (i in 56 downTo 0 step 8) { |
||||
var previous = 0L |
||||
for (value in values) { |
||||
buf.writeByte(((value - previous) shr i).toInt()) |
||||
previous = value |
||||
} |
||||
} |
||||
} |
||||
|
||||
private fun writeFloats(buf: ByteBuf) { |
||||
writeInts(buf, IntArray(floats.size) { i -> |
||||
floats[i].toRawBits() |
||||
}) |
||||
} |
||||
|
||||
private fun writeDoubles(buf: ByteBuf) { |
||||
writeLongs(buf, LongArray(doubles.size) { i -> |
||||
doubles[i].toRawBits() |
||||
}) |
||||
} |
||||
|
||||
public companion object { |
||||
public const val CODE: String = "Code" |
||||
public const val EXCEPTIONS: String = "Exceptions" |
||||
public const val SYNTHETIC: String = "Synthetic" |
||||
public const val CONSTANT_VALUE: String = "ConstantValue" |
||||
public const val SOURCE_FILE: String = "SourceFile" |
||||
public const val LINE_NUMBER_TABLE: String = "LineNumberTable" |
||||
|
||||
private const val TRAILER_LEN = 20 |
||||
|
||||
public fun read(buf: ByteBuf): ConstantPool { |
||||
// read trailer |
||||
buf.markReaderIndex() |
||||
buf.readerIndex(buf.writerIndex() - TRAILER_LEN) |
||||
|
||||
val stringCount = buf.readUnsignedShort() |
||||
val intCount = buf.readUnsignedShort() |
||||
val longCount = buf.readUnsignedShort() |
||||
val floatCount = buf.readUnsignedShort() |
||||
val doubleCount = buf.readUnsignedShort() |
||||
val fieldNameAndTypeCount = buf.readUnsignedShort() |
||||
val methodNameAndTypeCount = buf.readUnsignedShort() |
||||
val fieldRefCount = buf.readUnsignedShort() |
||||
val methodRefCount = buf.readUnsignedShort() |
||||
val interfaceMethodRefCount = buf.readUnsignedShort() |
||||
|
||||
buf.resetReaderIndex() |
||||
|
||||
// read UTF-8 entries |
||||
val strings = readStrings(buf, stringCount) |
||||
|
||||
// read NameAndType entries |
||||
val fieldNames = readStringPointers(buf, fieldNameAndTypeCount, strings) |
||||
val methodNames = readStringPointers(buf, methodNameAndTypeCount, strings) |
||||
val fieldDescriptors = readStringPointers(buf, fieldNameAndTypeCount, strings) |
||||
val methodDescriptors = readStringPointers(buf, methodNameAndTypeCount, strings) |
||||
|
||||
val fieldNamesAndTypes = createNamesAndTypes(fieldNames, fieldDescriptors) |
||||
val methodNamesAndTypes = createNamesAndTypes(methodNames, methodDescriptors) |
||||
|
||||
// read FieldRef, MethodRef and InterfaceMethodRef entries |
||||
val fieldRefClasses = readStringPointers(buf, fieldRefCount, strings) |
||||
val methodRefClasses = readStringPointers(buf, methodRefCount, strings) |
||||
val interfaceRefMethodClasses = readStringPointers(buf, interfaceMethodRefCount, strings) |
||||
|
||||
val fieldRefNamesAndTypes = readNameAndTypePointers(buf, fieldRefCount, fieldNamesAndTypes) |
||||
val methodRefNamesAndTypes = readNameAndTypePointers(buf, methodRefCount, methodNamesAndTypes) |
||||
val interfaceMethodRefNamesAndTypes = readNameAndTypePointers( |
||||
buf, |
||||
interfaceMethodRefCount, |
||||
methodNamesAndTypes |
||||
) |
||||
|
||||
val fieldRefs = createMembers(fieldRefClasses, fieldRefNamesAndTypes) |
||||
val methodRefs = createMembers(methodRefClasses, methodRefNamesAndTypes) |
||||
val interfaceMethodRefs = createMembers(interfaceRefMethodClasses, interfaceMethodRefNamesAndTypes) |
||||
|
||||
// read numeric entries |
||||
val ints = readInts(buf, intCount) |
||||
val longs = readLongs(buf, longCount) |
||||
val floats = readFloats(buf, floatCount) |
||||
val doubles = readDoubles(buf, doubleCount) |
||||
|
||||
// skip trailer |
||||
buf.skipBytes(TRAILER_LEN) |
||||
|
||||
return ConstantPool( |
||||
strings, |
||||
fieldNamesAndTypes, |
||||
methodNamesAndTypes, |
||||
fieldRefs, |
||||
methodRefs, |
||||
interfaceMethodRefs, |
||||
ints, |
||||
longs, |
||||
floats, |
||||
doubles |
||||
) |
||||
} |
||||
|
||||
private fun readStrings(buf: ByteBuf, size: Int): Array<String> { |
||||
require(size >= 6) |
||||
|
||||
return Array(size) { i -> |
||||
when (i) { |
||||
0 -> CODE |
||||
1 -> EXCEPTIONS |
||||
2 -> SYNTHETIC |
||||
3 -> CONSTANT_VALUE |
||||
4 -> SOURCE_FILE |
||||
5 -> LINE_NUMBER_TABLE |
||||
else -> buf.readString(ModifiedUtf8Charset) |
||||
} |
||||
} |
||||
} |
||||
|
||||
private fun readStringPointers(buf: ByteBuf, size: Int, entries: Array<String>): Array<String> { |
||||
return Array(size) { |
||||
val index = buf.readUnsignedShort() |
||||
entries[index] |
||||
} |
||||
} |
||||
|
||||
private fun createNamesAndTypes(names: Array<String>, descriptors: Array<String>): Array<NameAndType> { |
||||
check(names.size == descriptors.size) |
||||
|
||||
return Array(names.size) { i -> |
||||
NameAndType(names[i], descriptors[i]) |
||||
} |
||||
} |
||||
|
||||
private fun readNameAndTypePointers(buf: ByteBuf, size: Int, entries: Array<NameAndType>): Array<NameAndType> { |
||||
return Array(size) { |
||||
val index = buf.readUnsignedShort() |
||||
entries[index] |
||||
} |
||||
} |
||||
|
||||
private fun createMembers(classes: Array<String>, namesAndTypes: Array<NameAndType>): Array<MemberRef> { |
||||
check(classes.size == namesAndTypes.size) |
||||
|
||||
return Array(classes.size) { i -> |
||||
MemberRef(classes[i], namesAndTypes[i]) |
||||
} |
||||
} |
||||
|
||||
private fun readInts(buf: ByteBuf, size: Int): IntArray { |
||||
val entries = IntArray(size) |
||||
|
||||
for (i in 24 downTo 0 step 8) { |
||||
var accumulator = 0 |
||||
for (j in entries.indices) { |
||||
accumulator += buf.readUnsignedByte().toInt() shl i |
||||
entries[j] += accumulator |
||||
} |
||||
} |
||||
|
||||
return entries |
||||
} |
||||
|
||||
private fun readLongs(buf: ByteBuf, size: Int): LongArray { |
||||
val entries = LongArray(size) |
||||
|
||||
for (i in 56 downTo 0 step 8) { |
||||
var accumulator = 0L |
||||
for (j in entries.indices) { |
||||
accumulator += buf.readUnsignedByte().toLong() shl i |
||||
entries[j] += accumulator |
||||
} |
||||
} |
||||
|
||||
return entries |
||||
} |
||||
|
||||
private fun readFloats(buf: ByteBuf, size: Int): FloatArray { |
||||
val entries = readInts(buf, size) |
||||
return FloatArray(entries.size) { i -> |
||||
Float.fromBits(entries[i]) |
||||
} |
||||
} |
||||
|
||||
private fun readDoubles(buf: ByteBuf, size: Int): DoubleArray { |
||||
val entries = readLongs(buf, size) |
||||
return DoubleArray(entries.size) { i -> |
||||
Double.fromBits(entries[i]) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
package org.openrs2.asm.packclass |
||||
|
||||
public data class MemberRef( |
||||
public val clazz: String, |
||||
public val nameAndType: NameAndType |
||||
) : Comparable<MemberRef> { |
||||
public constructor(clazz: String, name: String, descriptor: String) : this(clazz, NameAndType(name, descriptor)) |
||||
|
||||
public val name: String = nameAndType.name |
||||
public val descriptor: String = nameAndType.descriptor |
||||
|
||||
override fun compareTo(other: MemberRef): Int { |
||||
return compareValuesBy(this, other, MemberRef::clazz, MemberRef::nameAndType) |
||||
} |
||||
} |
@ -0,0 +1,10 @@ |
||||
package org.openrs2.asm.packclass |
||||
|
||||
public data class NameAndType( |
||||
public val name: String, |
||||
public val descriptor: String |
||||
) : Comparable<NameAndType> { |
||||
override fun compareTo(other: NameAndType): Int { |
||||
return compareValuesBy(this, other, NameAndType::name, NameAndType::descriptor) |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue