Add size of length to buffer, cleanup

This commit is contained in:
2024-09-02 11:19:37 +02:00
parent 09d88dbb3f
commit 6567da1683
10 changed files with 167 additions and 106 deletions

View File

@@ -1,27 +1,34 @@
package nl.astraeus.tba
enum class DataType(val size: Int) {
enum class DataType(
val size: Int,
val bytesUsedInternally: Int = 0
) {
BYTE(1),
SHORT(2),
INT(4),
LONG(8),
FLOAT(4),
DOUBLE(8),
STRING(-1), // max length 65535
CLOB(-1), // max length 2^32-1
BLOB(-1), // max length 2^32-1
STRING(-1, 2), // max length 65535
CLOB(-1, 4), // max length 2^32-1
BLOB(-1, 4), // max length 2^32-1
;
}
class Type(
val name: String,
val type: DataType,
val size: Int = if (type.size == -1) {
size: Int = 0,
) {
val size: Int = if (size > 0) {
size + type.bytesUsedInternally
} else if (type.size == -1) {
throw IllegalArgumentException("Size must be defined for type ${type.name}")
} else {
type.size
},
)
type.size + type.bytesUsedInternally
}
}
open class ByteArrayDefinition(
vararg types: Type,
@@ -31,4 +38,4 @@ open class ByteArrayDefinition(
val size: Int by lazy {
this.types.sumOf { it.size }
}
}
}

View File

@@ -1,69 +0,0 @@
package nl.astraeus.tba
fun ByteArray.setShort(index: Int, value: Short) {
this[index] = (value.toInt() shr 8).toByte()
this[index + 1] = value.toByte()
}
fun ByteArray.getShort(index: Int): Short {
return ((this[index].toInt() shl 8) or (this[index + 1].toInt() and 0xff)).toShort()
}
fun ByteArray.setInt(index: Int, value: Int) {
this[index] = ((value shr 24) and 0xff).toByte()
this[index + 1] = ((value shr 16) and 0xff).toByte()
this[index + 2] = ((value shr 8) and 0xff).toByte()
this[index + 3] = (value and 0xff).toByte()
}
fun ByteArray.getInt(index: Int): Int {
return (
(this[index].toInt() shl 24) or
((this[index+1].toInt() shl 16) and 0xff0000) or
((this[index+2].toInt() shl 8) and 0xff00) or
(this[index+3].toInt() and 0xff)
)
}
fun ByteArray.setLong(index: Int, value: Long) {
this[index] = ((value shr 56) and 0xff).toByte()
this[index + 1] = ((value shr 48) and 0xff).toByte()
this[index + 2] = ((value shr 40) and 0xff).toByte()
this[index + 3] = ((value shr 32) and 0xff).toByte()
this[index + 4] = ((value shr 24) and 0xff).toByte()
this[index + 5] = ((value shr 16) and 0xff).toByte()
this[index + 6] = ((value shr 8) and 0xff).toByte()
this[index + 7] = (value and 0xff).toByte()
}
fun ByteArray.getLong(index: Int): Long {
return (
(this[index].toLong() shl 56) or
((this[index+1].toLong() and 0xff) shl 48) or
((this[index+2].toLong() and 0xff) shl 40) or
((this[index+3].toLong() and 0xff) shl 32) or
((this[index+4].toLong() and 0xff) shl 24) or
((this[index+5].toLong() and 0xff) shl 16) or
((this[index+6].toLong() and 0xff) shl 8) or
(this[index+7].toLong() and 0xff)
)
}
fun ByteArray.setDouble(index: Int, value: Double) = this.setLong(index, value.toRawBits())
fun ByteArray.getDouble(index: Int): Double = Double.fromBits(this.getLong(index))
fun ByteArray.setFloat(index: Int, value: Float) = this.setInt(index, value.toRawBits())
fun ByteArray.getFloat(index: Int): Float = Float.fromBits(this.getInt(index))
fun ByteArray.getString(index: Int): Pair<String, Int> {
val length = this.getInt(index)
val str = this.copyOfRange(index + 4, index + 4 + length).decodeToString()
return Pair(str, index + 4 + length)
}
fun ByteArray.setString(index: Int, value: String): Int {
val bytes = value.encodeToByteArray()
this.setInt(index, bytes.size)
bytes.copyInto(this, index + 4)
return index + bytes.size + 4
}

View File

@@ -2,9 +2,13 @@ package nl.astraeus.tba
class MutableByteArrayHandler(
initialSize: Int = 1024,
buffer: ByteArray = ByteArray(initialSize)
buffer: SlicedByteArray = SlicedByteArray.wrap(ByteArray(initialSize), 0, initialSize),
) : ByteArrayHandler(initialSize, buffer) {
constructor(buffer: ByteArray, range: IntRange = buffer.indices) : this(
buffer = SlicedByteArray.wrap(buffer, range.first, range.last - range.first)
)
operator fun set(index: Int, value: Byte) {
buffer[index] = value
}
@@ -32,8 +36,8 @@ class MutableByteArrayHandler(
buffer[index + 7] = (value and 0xff).toByte()
}
fun setFloat(index: Int, value: Float) = buffer.setInt(index, value.toRawBits())
fun setDouble(index: Int, value: Double) = buffer.setLong(index, value.toRawBits())
fun setFloat(index: Int, value: Float) = setInt(index, value.toRawBits())
fun setDouble(index: Int, value: Double) = setLong(index, value.toRawBits())
fun setString(index: Int, value: String, maxLength: Int): Int {
val bytes = value.encodeToByteArray()
@@ -41,7 +45,7 @@ class MutableByteArrayHandler(
throw IllegalArgumentException("String is too long")
}
this.setShort(index, bytes.size.toShort())
bytes.copyInto(buffer, index + 2)
bytes.copyInto(buffer.data, index + 2)
return index + bytes.size + 2
}
@@ -51,7 +55,7 @@ class MutableByteArrayHandler(
throw IllegalArgumentException("String is too long")
}
this.setInt(index, bytes.size)
bytes.copyInto(buffer, index + 4)
bytes.copyInto(buffer.data, index + 4)
return index + bytes.size + 4
}
@@ -60,7 +64,7 @@ class MutableByteArrayHandler(
throw IllegalArgumentException("String is too long")
}
this.setInt(index, bytes.size)
bytes.copyInto(buffer, index + 4)
bytes.copyInto(buffer.data, index + 4)
return index + bytes.size + 4
}
@@ -68,15 +72,11 @@ class MutableByteArrayHandler(
open class ByteArrayHandler(
size: Int = 1024,
var buffer: ByteArray = ByteArray(size),
val firstIndex: Int = 0,
val lastIndex: Int = buffer.size
var buffer: SlicedByteArray = SlicedByteArray.wrap(ByteArray(size), 0, size),
) {
constructor(buffer: ByteArray, range: IntRange) : this(
buffer = buffer,
firstIndex = range.first,
lastIndex = range.last
constructor(buffer: ByteArray, range: IntRange = buffer.indices) : this(
buffer = SlicedByteArray.wrap(buffer, range.first, range.last - range.first)
)
operator fun get(index: Int): Byte {
@@ -109,35 +109,34 @@ open class ByteArrayHandler(
)
}
fun getFloat(index: Int): Float = Float.fromBits(buffer.getInt(index))
fun getDouble(index: Int): Double = Double.fromBits(buffer.getLong(index))
fun getFloat(index: Int): Float = Float.fromBits(getInt(index))
fun getDouble(index: Int): Double = Double.fromBits(getLong(index))
fun getString(index: Int): String {
val length = getShort(index)
val str = buffer.copyOfRange(index + 2, index + 2 + length).decodeToString()
val str = buffer.data.copyOfRange(index + 2, index + 2 + length).decodeToString()
return str
}
fun getClob(index: Int): String {
val length = getInt(index)
val str = buffer.copyOfRange(index + 4, index + 4 + length).decodeToString()
val str = buffer.data.copyOfRange(index + 4, index + 4 + length).decodeToString()
return str
}
fun getBlob(index: Int): ByteArray {
val length = getInt(index)
val str = buffer.copyOfRange(index + 4, index + 4 + length)
val str = buffer.data.copyOfRange(index + 4, index + 4 + length)
return str
}
fun slice(range: IntRange): ByteArrayHandler {
return ByteArrayHandler(
buffer,
range
buffer = SlicedByteArray(this.buffer.data, range.first, range.last - range.first)
)
}
fun asMutable(): MutableByteArrayHandler {
return MutableByteArrayHandler(buffer = buffer.copyOfRange(firstIndex, lastIndex))
return MutableByteArrayHandler(buffer = SlicedByteArray(buffer.data, 0, buffer.data.size))
}
}

View File

@@ -23,7 +23,10 @@ abstract class ByteArrayPropertyWithLength<T>(
protected fun getMaxLength(thisRef: TypedByteArray): Int {
if (maxLength == null) {
maxLength = thisRef.typeMap[name]!!.size - 2
val type = thisRef.typeMap[name] ?: throw IllegalArgumentException(
"Type $name not found in typemap in $thisRef"
)
maxLength = type.size
}
return maxLength!!
}

View File

@@ -0,0 +1,32 @@
package nl.astraeus.tba
class SlicedByteArray(
val data: ByteArray,
val offset: Int,
val length: Int
) {
val size: Int
get() = length
operator fun get(index: Int): Byte {
return data[offset + index]
}
operator fun set(index: Int, value: Byte) {
data[offset + index] = value
}
fun copyInto(dest: ByteArray, destOffset: Int, length: Int) {
data.copyInto(dest, destOffset, offset, offset + length)
}
companion object {
fun wrap(
data: ByteArray,
offset: Int,
length: Int
): SlicedByteArray {
return SlicedByteArray(data, offset,length)
}
}
}

View File

@@ -19,6 +19,8 @@ open class TypedByteArray(
}
}
constructor(vararg types: Type): this(ByteArrayDefinition(*types))
constructor(data: ByteArray): this(ByteArrayDefinition()) {
this.data = MutableByteArrayHandler(buffer = data)
}

View File

@@ -9,12 +9,10 @@ class ExtendedByteArrayDefinition {
open class MessageByteArray(
vararg types: Type
) : TypedByteArray(
ByteArrayDefinition(
Type("messageType", DataType.BYTE),
Type("messageLength", DataType.SHORT),
Type("message", DataType.STRING, 1024),
*types,
)
) {
var messageType by byte("messageType")
var messageLength by short("messageLength")

View File

@@ -0,0 +1,36 @@
package nl.astraeus.tba
import kotlin.test.Test
import kotlin.test.assertEquals
class TypedByteArraySize {
class Person() : TypedByteArray(
Type("name", DataType.STRING, 100),
) {
var name by string("name")
constructor(name: String): this() {
this.name = name
}
constructor(data: ByteArray): this() {
this.data = MutableByteArrayHandler(buffer = data)
}
}
@Test
fun testPersonSize() {
val type = Type("name", DataType.STRING, 10)
assertEquals(12, type.size)
val person = Person("Test")
assertEquals(102, person.data.buffer.size)
val clobType = Type("long-name", DataType.CLOB, 100)
assertEquals(104, clobType.size)
}
}

View File

@@ -6,11 +6,9 @@ import kotlin.test.assertEquals
class TypedByteArrayTest {
class Person() : TypedByteArray(
ByteArrayDefinition(
Type("name", DataType.STRING, 102),
Type("name", DataType.STRING, 100),
Type("age", DataType.BYTE),
Type("length", DataType.SHORT),
)
) {
var name by string("name")
var age by byte("age")
@@ -33,6 +31,7 @@ class TypedByteArrayTest {
assertEquals(4, person.data.buffer[1])
assertEquals(42, person.data.buffer[102])
assertEquals(180.toByte(), person.data.buffer[104])
assertEquals("Test", person.name)
assertEquals(42.toByte(), person.age)
@@ -42,7 +41,7 @@ class TypedByteArrayTest {
@Test
fun testToByteArrayAndBack() {
val person = Person("Test", 42, 180)
val bytes: ByteArray = person.data.buffer
val bytes: ByteArray = person.data.buffer.data
val person2 = Person(bytes)

View File

@@ -0,0 +1,54 @@
package nl.astraeus.tba
import kotlin.test.Test
import kotlin.test.assertEquals
class TypedByteArrayWithByteArrayTest {
class Person1() : TypedByteArray(
Type("name", DataType.STRING, 10),
) {
var name by string("name")
constructor(name: String): this() {
this.name = name
}
constructor(data: ByteArray): this() {
this.data = MutableByteArrayHandler(buffer = data)
}
}
class Company() : TypedByteArray(
Type("name", DataType.STRING, 10),
Type("person", DataType.BLOB, 12)
) {
var name by string("name")
var personData by blob("person")
val person by lazy { Person1(personData) }
constructor(name: String, person: Person1): this() {
this.name = name
this.personData = person.data.buffer.data
}
constructor(data: ByteArray): this() {
this.data = MutableByteArrayHandler(buffer = data)
}
}
@Test
fun testPersonSize() {
val person = Person1("A Name")
assertEquals(12, person.data.buffer.size)
val company = Company("A Company", person)
assertEquals("A Name", company.person.name)
company.person.name = "2nd Name"
assertEquals("2nd Name", company.person.name)
}
}