forked from openrs2/openrs2
parent
fae51b8eb5
commit
9bb511369d
@ -0,0 +1,15 @@ |
|||||||
|
<component name="ProjectRunConfigurationManager"> |
||||||
|
<configuration default="false" name="GenerateBuffer" type="JetRunConfigurationType"> |
||||||
|
<module name="openrs2.buffer-generator.main" /> |
||||||
|
<option name="VM_PARAMETERS" value="" /> |
||||||
|
<option name="PROGRAM_PARAMETERS" value="" /> |
||||||
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> |
||||||
|
<option name="ALTERNATIVE_JRE_PATH" /> |
||||||
|
<option name="PASS_PARENT_ENVS" value="true" /> |
||||||
|
<option name="MAIN_CLASS_NAME" value="org.openrs2.buffer.generator.GenerateBufferCommandKt" /> |
||||||
|
<option name="WORKING_DIRECTORY" value="" /> |
||||||
|
<method v="2"> |
||||||
|
<option name="Make" enabled="true" /> |
||||||
|
</method> |
||||||
|
</configuration> |
||||||
|
</component> |
@ -0,0 +1,33 @@ |
|||||||
|
plugins { |
||||||
|
`maven-publish` |
||||||
|
application |
||||||
|
kotlin("jvm") |
||||||
|
} |
||||||
|
|
||||||
|
application { |
||||||
|
mainClass.set("org.openrs2.buffer.generator.GenerateBufferCommand") |
||||||
|
} |
||||||
|
|
||||||
|
dependencies { |
||||||
|
api(libs.clikt) |
||||||
|
|
||||||
|
implementation(libs.kotlinPoet) |
||||||
|
implementation(libs.netty.buffer) |
||||||
|
} |
||||||
|
|
||||||
|
publishing { |
||||||
|
publications.create<MavenPublication>("maven") { |
||||||
|
from(components["java"]) |
||||||
|
|
||||||
|
pom { |
||||||
|
packaging = "jar" |
||||||
|
name.set("OpenRS2 Buffer Generator") |
||||||
|
description.set( |
||||||
|
""" |
||||||
|
Tool for generating Jagex-specific ByteBuf extension methods |
||||||
|
automatically. |
||||||
|
""".trimIndent() |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
package org.openrs2.buffer.generator |
||||||
|
|
||||||
|
public enum class ArrayOrder(public val suffix: String) { |
||||||
|
FORWARD(""), |
||||||
|
REVERSE("Reverse") |
||||||
|
} |
@ -0,0 +1,582 @@ |
|||||||
|
package org.openrs2.buffer.generator |
||||||
|
|
||||||
|
import com.squareup.kotlinpoet.FileSpec |
||||||
|
import com.squareup.kotlinpoet.FunSpec |
||||||
|
import io.netty.buffer.ByteBuf |
||||||
|
import io.netty.buffer.Unpooled |
||||||
|
|
||||||
|
public class ByteBufExtensionGenerator { |
||||||
|
public fun generate(): String { |
||||||
|
val builder = FileSpec.builder("org.openrs2.buffer", "GeneratedByteBufExtensions") |
||||||
|
builder.indent(" ") |
||||||
|
builder.addComment("This file is generated automatically. DO NOT EDIT.") |
||||||
|
|
||||||
|
for (type in IntType.values()) { |
||||||
|
for (order in ByteOrder.values()) { |
||||||
|
for (transformation in Transformation.values()) { |
||||||
|
// only integers can be middle-endian |
||||||
|
if (type != IntType.INT && (order == ByteOrder.ALT3 || order == ByteOrder.ALT3_REVERSE)) { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
// only bytes and shorts can be transformed |
||||||
|
if (type != IntType.BYTE && type != IntType.SHORT && transformation != Transformation.IDENTITY) { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
// supplied by Netty |
||||||
|
if ( |
||||||
|
(order == ByteOrder.LITTLE || order == ByteOrder.BIG) && |
||||||
|
transformation == Transformation.IDENTITY |
||||||
|
) { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
// byte order doesn't make sense for individual bytes |
||||||
|
if (type == IntType.BYTE && order != ByteOrder.BIG) { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
for (signedness in Signedness.values()) { |
||||||
|
// unsigned integers not supported |
||||||
|
if (type == IntType.INT && signedness == Signedness.UNSIGNED) { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
builder.addFunction(createGetIntFunction(type, order, transformation, signedness)) |
||||||
|
builder.addFunction(createReadIntFunction(type, order, transformation, signedness)) |
||||||
|
} |
||||||
|
|
||||||
|
builder.addFunction(createSetIntFunction(type, order, transformation)) |
||||||
|
builder.addFunction(createWriteIntFunction(type, order, transformation)) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (order in ArrayOrder.values()) { |
||||||
|
for (transformation in Transformation.values()) { |
||||||
|
// supplied by Netty |
||||||
|
if (order == ArrayOrder.FORWARD && transformation == Transformation.IDENTITY) { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
builder.addFunction(createGetArrayFunction(order, transformation)) |
||||||
|
builder.addFunction(createGetArrayIndexLenFunction(order, transformation)) |
||||||
|
builder.addFunction(createGetByteBufFunction(order, transformation)) |
||||||
|
builder.addFunction(createGetByteBufLenFunction(order, transformation)) |
||||||
|
builder.addFunction(createGetByteBufIndexLenFunction(order, transformation)) |
||||||
|
|
||||||
|
builder.addFunction(createReadArrayFunction(order, transformation)) |
||||||
|
builder.addFunction(createReadArrayIndexLenFunction(order, transformation)) |
||||||
|
builder.addFunction(createReadByteBufFunction(order, transformation)) |
||||||
|
builder.addFunction(createReadByteBufLenFunction(order, transformation)) |
||||||
|
builder.addFunction(createReadByteBufIndexLenFunction(order, transformation)) |
||||||
|
builder.addFunction(createReadByteBufAllocFunction(order, transformation)) |
||||||
|
|
||||||
|
builder.addFunction(createSetArrayFunction(order, transformation)) |
||||||
|
builder.addFunction(createSetArrayIndexLenFunction(order, transformation)) |
||||||
|
builder.addFunction(createSetByteBufFunction(order, transformation)) |
||||||
|
builder.addFunction(createSetByteBufLenFunction(order, transformation)) |
||||||
|
builder.addFunction(createSetByteBufIndexLenFunction(order, transformation)) |
||||||
|
|
||||||
|
builder.addFunction(createWriteArrayFunction(order, transformation)) |
||||||
|
builder.addFunction(createWriteArrayIndexLenFunction(order, transformation)) |
||||||
|
builder.addFunction(createWriteByteBufFunction(order, transformation)) |
||||||
|
builder.addFunction(createWriteByteBufLenFunction(order, transformation)) |
||||||
|
builder.addFunction(createWriteByteBufIndexLenFunction(order, transformation)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
for (transformation in Transformation.values()) { |
||||||
|
// supplied by Netty |
||||||
|
if (transformation == Transformation.IDENTITY) { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
|
builder.addFunction(createGetBooleanFunction(transformation)) |
||||||
|
builder.addFunction(createReadBooleanFunction(transformation)) |
||||||
|
builder.addFunction(createSetBooleanFunction(transformation)) |
||||||
|
builder.addFunction(createWriteBooleanFunction(transformation)) |
||||||
|
} |
||||||
|
|
||||||
|
val file = builder.build() |
||||||
|
return file.toString() |
||||||
|
.replace("import kotlin.Boolean\n", "") |
||||||
|
.replace("import kotlin.Byte\n", "") |
||||||
|
.replace("import kotlin.ByteArray\n", "") |
||||||
|
.replace("import kotlin.Int\n", "") |
||||||
|
.replace("import kotlin.Short\n", "") |
||||||
|
.replace("import kotlin.Unit\n", "") |
||||||
|
.replace(": Unit {", " {") |
||||||
|
} |
||||||
|
|
||||||
|
private fun createGetIntFunction( |
||||||
|
type: IntType, |
||||||
|
order: ByteOrder, |
||||||
|
transformation: Transformation, |
||||||
|
signedness: Signedness |
||||||
|
): FunSpec { |
||||||
|
val name = "${signedness.prefix}${type.prettyName}${order.suffix}${transformation.suffix}" |
||||||
|
|
||||||
|
val builder = FunSpec.builder("get$name") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
|
||||||
|
val readType = type.getReadType(signedness) |
||||||
|
builder.returns(readType) |
||||||
|
|
||||||
|
builder.addStatement("var value = 0") |
||||||
|
|
||||||
|
for (i in 0 until type.width) { |
||||||
|
val shift = order.getShift(i, type.width) |
||||||
|
|
||||||
|
val pre: String |
||||||
|
val post: String |
||||||
|
if (shift == 0) { |
||||||
|
pre = transformation.preTransform |
||||||
|
post = transformation.postReadTransform |
||||||
|
} else { |
||||||
|
pre = "" |
||||||
|
post = "" |
||||||
|
} |
||||||
|
|
||||||
|
builder.addStatement( |
||||||
|
"value = value or (((${pre}getByte(index + %L).toInt()$post) and 0xFF) shl %L)", |
||||||
|
i, |
||||||
|
shift |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
builder.addStatement("return value.%N()", "to${readType.simpleName}") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createReadIntFunction( |
||||||
|
type: IntType, |
||||||
|
order: ByteOrder, |
||||||
|
transformation: Transformation, |
||||||
|
signedness: Signedness |
||||||
|
): FunSpec { |
||||||
|
val name = "${signedness.prefix}${type.prettyName}${order.suffix}${transformation.suffix}" |
||||||
|
|
||||||
|
val builder = FunSpec.builder("read$name") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.returns(type.getReadType(signedness)) |
||||||
|
|
||||||
|
builder.addStatement("val index = readerIndex()") |
||||||
|
builder.addStatement("val result = %N(index)", "get$name") |
||||||
|
builder.addStatement("readerIndex(index + %L)", type.width) |
||||||
|
builder.addStatement("return result") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createSetIntFunction(type: IntType, order: ByteOrder, transformation: Transformation): FunSpec { |
||||||
|
val name = "${type.prettyName}${order.suffix}${transformation.suffix}" |
||||||
|
|
||||||
|
val builder = FunSpec.builder("set$name") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("value", type.writeType) |
||||||
|
|
||||||
|
for (i in 0 until type.width) { |
||||||
|
val shift = order.getShift(i, type.width) |
||||||
|
|
||||||
|
val pre: String |
||||||
|
val post: String |
||||||
|
if (shift == 0) { |
||||||
|
pre = transformation.preTransform |
||||||
|
post = transformation.postWriteTransform |
||||||
|
} else { |
||||||
|
pre = "" |
||||||
|
post = "" |
||||||
|
} |
||||||
|
|
||||||
|
builder.addStatement("setByte(index + %L, $pre(value shr %L)$post)", i, shift) |
||||||
|
} |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createWriteIntFunction(type: IntType, order: ByteOrder, transformation: Transformation): FunSpec { |
||||||
|
val name = "${type.prettyName}${order.suffix}${transformation.suffix}" |
||||||
|
|
||||||
|
val builder = FunSpec.builder("write$name") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("value", type.writeType) |
||||||
|
|
||||||
|
builder.addStatement("val index = writerIndex()") |
||||||
|
builder.addStatement("ensureWritable(%L)", type.width) |
||||||
|
builder.addStatement("%N(index, value)", "set$name") |
||||||
|
builder.addStatement("writerIndex(index + %L)", type.width) |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createGetBooleanFunction(transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("getBoolean$transformation") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.returns(Boolean::class) |
||||||
|
|
||||||
|
builder.addStatement("return %N(index).toInt() != 0", "getByte$transformation") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createReadBooleanFunction(transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("readBoolean$transformation") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.returns(Boolean::class) |
||||||
|
|
||||||
|
builder.addStatement("return %N().toInt() != 0", "readByte$transformation") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createSetBooleanFunction(transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("setBoolean$transformation") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("value", Boolean::class) |
||||||
|
|
||||||
|
builder.beginControlFlow("if (value)") |
||||||
|
builder.addStatement("%N(index, 1)", "setByte$transformation") |
||||||
|
builder.nextControlFlow("else") |
||||||
|
builder.addStatement("%N(index, 0)", "setByte$transformation") |
||||||
|
builder.endControlFlow() |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createWriteBooleanFunction(transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("writeBoolean$transformation") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("value", Boolean::class) |
||||||
|
|
||||||
|
builder.beginControlFlow("if (value)") |
||||||
|
builder.addStatement("%N(1)", "writeByte$transformation") |
||||||
|
builder.nextControlFlow("else") |
||||||
|
builder.addStatement("%N(0)", "writeByte$transformation") |
||||||
|
builder.endControlFlow() |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createGetArrayFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("getBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("dst", ByteArray::class) |
||||||
|
|
||||||
|
builder.addStatement("%N(index, dst, 0, dst.size)", "getBytes${order.suffix}${transformation.suffix}") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createGetArrayIndexLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("getBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("dst", ByteArray::class) |
||||||
|
builder.addParameter("dstIndex", Int::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.addStatement("getBytes(index, dst, dstIndex, len)") |
||||||
|
builder.beginControlFlow("for (i in 0 until len)") |
||||||
|
builder.addStatement( |
||||||
|
"dst[dstIndex + i] = " + |
||||||
|
"(${transformation.preTransform}dst[dstIndex + i].toInt()${transformation.postReadTransform}).toByte()" |
||||||
|
) |
||||||
|
builder.endControlFlow() |
||||||
|
|
||||||
|
if (order == ArrayOrder.REVERSE) { |
||||||
|
builder.addStatement("dst.reverse(dstIndex, dstIndex + len)") |
||||||
|
} |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createGetByteBufFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("getBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("dst", ByteBuf::class) |
||||||
|
|
||||||
|
builder.addStatement("val dstIndex = dst.writerIndex()") |
||||||
|
builder.addStatement("val len = dst.writableBytes()") |
||||||
|
builder.addStatement("dst.ensureWritable(len)") |
||||||
|
builder.addStatement("%N(index, dst, dstIndex, len)", "getBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("dst.writerIndex(dstIndex + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createGetByteBufLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("getBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("dst", ByteBuf::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.addStatement("val dstIndex = dst.writerIndex()") |
||||||
|
builder.addStatement("dst.ensureWritable(len)") |
||||||
|
builder.addStatement("%N(index, dst, dstIndex, len)", "getBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("dst.writerIndex(dstIndex + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createGetByteBufIndexLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("getBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("dst", ByteBuf::class) |
||||||
|
builder.addParameter("dstIndex", Int::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
val srcIndex = if (order == ArrayOrder.FORWARD) { |
||||||
|
"i" |
||||||
|
} else { |
||||||
|
"len - i - 1" |
||||||
|
} |
||||||
|
|
||||||
|
builder.beginControlFlow("for (i in 0 until len)") |
||||||
|
builder.addStatement( |
||||||
|
"dst.setByte(dstIndex + i, %N(index + $srcIndex).toInt())", |
||||||
|
"getByte${transformation.suffix}" |
||||||
|
) |
||||||
|
builder.endControlFlow() |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createReadByteBufAllocFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("readBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
builder.returns(ByteBuf::class) |
||||||
|
|
||||||
|
builder.beginControlFlow("if (len == 0)") |
||||||
|
builder.addStatement("return %T.EMPTY_BUFFER", Unpooled::class) |
||||||
|
builder.endControlFlow() |
||||||
|
|
||||||
|
builder.beginControlFlow("alloc().buffer(len).use { dst ->") |
||||||
|
builder.addStatement("%N(dst, len)", "readBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("return dst.retain()") |
||||||
|
builder.endControlFlow() |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createReadArrayFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("readBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("dst", ByteArray::class) |
||||||
|
|
||||||
|
builder.addStatement("%N(dst, 0, dst.size)", "readBytes${order.suffix}${transformation.suffix}") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createReadArrayIndexLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("readBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("dst", ByteArray::class) |
||||||
|
builder.addParameter("dstIndex", Int::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.addStatement("val index = readerIndex()") |
||||||
|
builder.addStatement("%N(index, dst, dstIndex, len)", "getBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("readerIndex(index + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createReadByteBufFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("readBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("dst", ByteBuf::class) |
||||||
|
|
||||||
|
builder.addStatement("val dstIndex = dst.writerIndex()") |
||||||
|
builder.addStatement("val len = dst.writableBytes()") |
||||||
|
builder.addStatement("dst.ensureWritable(len)") |
||||||
|
builder.addStatement("%N(dst, dstIndex, len)", "readBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("dst.writerIndex(dstIndex + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createReadByteBufLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("readBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("dst", ByteBuf::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.addStatement("val dstIndex = dst.writerIndex()") |
||||||
|
builder.addStatement("dst.ensureWritable(len)") |
||||||
|
builder.addStatement("%N(dst, dstIndex, len)", "readBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("dst.writerIndex(dstIndex + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createReadByteBufIndexLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("readBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("dst", ByteBuf::class) |
||||||
|
builder.addParameter("dstIndex", Int::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.addStatement("val index = readerIndex()") |
||||||
|
builder.addStatement("%N(index, dst, dstIndex, len)", "getBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("readerIndex(index + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createSetArrayFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("src", ByteArray::class) |
||||||
|
|
||||||
|
builder.addStatement("%N(index, src, 0, src.size)", "setBytes${order.suffix}${transformation.suffix}") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createSetArrayIndexLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("src", ByteArray::class) |
||||||
|
builder.addParameter("srcIndex", Int::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.beginControlFlow("%T.wrappedBuffer(src).use { buf ->", Unpooled::class) |
||||||
|
builder.addStatement("%N(index, buf, srcIndex, len)", "setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.endControlFlow() |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createSetByteBufFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("src", ByteBuf::class) |
||||||
|
|
||||||
|
builder.addStatement("val srcIndex = src.readerIndex()") |
||||||
|
builder.addStatement("val len = src.readableBytes()") |
||||||
|
builder.addStatement("%N(index, src, srcIndex, len)", "setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("src.readerIndex(srcIndex + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createSetByteBufLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("src", ByteBuf::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.addStatement("val srcIndex = src.readerIndex()") |
||||||
|
builder.addStatement("%N(index, src, srcIndex, len)", "setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("src.readerIndex(srcIndex + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createSetByteBufIndexLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("index", Int::class) |
||||||
|
builder.addParameter("src", ByteBuf::class) |
||||||
|
builder.addParameter("srcIndex", Int::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
val srcIndex = if (order == ArrayOrder.FORWARD) { |
||||||
|
"i" |
||||||
|
} else { |
||||||
|
"len - i - 1" |
||||||
|
} |
||||||
|
|
||||||
|
builder.beginControlFlow("for (i in 0 until len)") |
||||||
|
builder.addStatement( |
||||||
|
"%N(index + i, src.getByte(srcIndex + $srcIndex).toInt())", |
||||||
|
"setByte${transformation.suffix}" |
||||||
|
) |
||||||
|
builder.endControlFlow() |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createWriteArrayFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("writeBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("src", ByteArray::class) |
||||||
|
|
||||||
|
builder.addStatement("%N(src, 0, src.size)", "writeBytes${order.suffix}${transformation.suffix}") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createWriteArrayIndexLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("writeBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("src", ByteArray::class) |
||||||
|
builder.addParameter("srcIndex", Int::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.addStatement("val index = writerIndex()") |
||||||
|
builder.addStatement("ensureWritable(len)") |
||||||
|
builder.addStatement("%N(index, src, srcIndex, len)", "setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("writerIndex(index + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createWriteByteBufFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("writeBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("src", ByteBuf::class) |
||||||
|
|
||||||
|
builder.addStatement("val srcIndex = src.readerIndex()") |
||||||
|
builder.addStatement("val len = src.readableBytes()") |
||||||
|
builder.addStatement("%N(src, srcIndex, len)", "writeBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("src.readerIndex(srcIndex + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createWriteByteBufLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("writeBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("src", ByteBuf::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.addStatement("val srcIndex = src.readerIndex()") |
||||||
|
builder.addStatement("%N(src, srcIndex, len)", "writeBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("src.readerIndex(srcIndex + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
|
||||||
|
private fun createWriteByteBufIndexLenFunction(order: ArrayOrder, transformation: Transformation): FunSpec { |
||||||
|
val builder = FunSpec.builder("writeBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.receiver(ByteBuf::class) |
||||||
|
builder.addParameter("src", ByteBuf::class) |
||||||
|
builder.addParameter("srcIndex", Int::class) |
||||||
|
builder.addParameter("len", Int::class) |
||||||
|
|
||||||
|
builder.addStatement("val index = writerIndex()") |
||||||
|
builder.addStatement("ensureWritable(len)") |
||||||
|
builder.addStatement("%N(index, src, srcIndex, len)", "setBytes${order.suffix}${transformation.suffix}") |
||||||
|
builder.addStatement("writerIndex(index + len)") |
||||||
|
|
||||||
|
return builder.build() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package org.openrs2.buffer.generator |
||||||
|
|
||||||
|
public enum class ByteOrder(public val suffix: String) { |
||||||
|
BIG(""), |
||||||
|
LITTLE("LE"), |
||||||
|
ALT3("Alt3"), |
||||||
|
ALT3_REVERSE("Alt3Reverse"); |
||||||
|
|
||||||
|
public fun getShift(i: Int, width: Int): Int { |
||||||
|
return when (this) { |
||||||
|
BIG -> (width - i - 1) * 8 |
||||||
|
LITTLE -> i * 8 |
||||||
|
ALT3 -> { |
||||||
|
require(width == 4) |
||||||
|
when (i) { |
||||||
|
0 -> 16 |
||||||
|
1 -> 24 |
||||||
|
2 -> 0 |
||||||
|
else -> 8 |
||||||
|
} |
||||||
|
} |
||||||
|
ALT3_REVERSE -> { |
||||||
|
require(width == 4) |
||||||
|
when (i) { |
||||||
|
0 -> 8 |
||||||
|
1 -> 0 |
||||||
|
2 -> 24 |
||||||
|
else -> 16 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package org.openrs2.buffer.generator |
||||||
|
|
||||||
|
import com.github.ajalt.clikt.core.CliktCommand |
||||||
|
import java.nio.file.Files |
||||||
|
import java.nio.file.Path |
||||||
|
|
||||||
|
public fun main(args: Array<String>): Unit = GenerateBufferCommand().main(args) |
||||||
|
|
||||||
|
public class GenerateBufferCommand : CliktCommand(name = "generate-buffer") { |
||||||
|
override fun run() { |
||||||
|
Files.writeString(PATH, ByteBufExtensionGenerator().generate()) |
||||||
|
} |
||||||
|
|
||||||
|
private companion object { |
||||||
|
private val PATH = Path.of("buffer/src/main/kotlin/org/openrs2/buffer/GeneratedByteBufExtensions.kt") |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package org.openrs2.buffer.generator |
||||||
|
|
||||||
|
import kotlin.reflect.KClass |
||||||
|
|
||||||
|
public enum class IntType( |
||||||
|
public val width: Int, |
||||||
|
private val signedReadType: KClass<*>, |
||||||
|
private val unsignedReadType: KClass<*>, |
||||||
|
public val writeType: KClass<*> |
||||||
|
) { |
||||||
|
BYTE(1, Byte::class, Short::class, Int::class), |
||||||
|
SHORT(2, Short::class, Int::class, Int::class), |
||||||
|
INT(4, Int::class, Long::class, Int::class); |
||||||
|
|
||||||
|
public val prettyName: String = name.toLowerCase().capitalize() |
||||||
|
|
||||||
|
public fun getReadType(signedness: Signedness): KClass<*> { |
||||||
|
return if (signedness == Signedness.SIGNED) { |
||||||
|
signedReadType |
||||||
|
} else { |
||||||
|
unsignedReadType |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
package org.openrs2.buffer.generator |
||||||
|
|
||||||
|
public enum class Signedness(public val prefix: String) { |
||||||
|
SIGNED(""), |
||||||
|
UNSIGNED("Unsigned") |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
package org.openrs2.buffer.generator |
||||||
|
|
||||||
|
public enum class Transformation( |
||||||
|
public val suffix: String, |
||||||
|
public val preTransform: String, |
||||||
|
public val postReadTransform: String, |
||||||
|
public val postWriteTransform: String |
||||||
|
) { |
||||||
|
IDENTITY("", "", "", ""), |
||||||
|
A("A", "", " - 128", " + 128"), |
||||||
|
C("C", "-", "", ""), |
||||||
|
S("S", "128 - ", "", "") |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue