All Downloads are FREE. Search and download functionalities are using the official Maven repository.

iosArm64Main.maryk.ByteBuffer.kt Maven / Gradle / Ivy

package maryk

import kotlinx.cinterop.ByteVar
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.allocArray
import kotlinx.cinterop.get
import kotlinx.cinterop.nativeHeap
import kotlinx.cinterop.readBytes
import kotlinx.cinterop.set

private val MAX_BYTE = 0b1111_1111.toUByte()

actual abstract class ByteBuffer(
    internal val nativePointer: CPointer,
    capacity: Int
) : Buffer(capacity, capacity) {
    actual final override fun array(): ByteArray {
        return nativePointer.readBytes(capacity)
    }

    actual fun put(src: ByteArray): ByteBuffer {
        for (byte in src) {
            nativePointer[position++] = byte
        }
        return this
    }

    actual operator fun get(dst: ByteArray): ByteBuffer {
        return this[dst, 0, dst.size]
    }

    actual operator fun get(dst: ByteArray, offset: Int, length: Int): ByteBuffer {
        if (length > capacity - position) {
            throw Exception("Not enough bytes left to fill destination byte array")
        }
        for (index in 0 until length) {
            dst[index + offset] = nativePointer[index + position]
        }
        position += dst.size
        return this
    }

    actual abstract fun put(index: Int, byte: Byte): ByteBuffer

    fun compareTo(other: ByteBuffer): Int {
        for (it in 0 until minOf(this.capacity, other.capacity)) {
            val a = nativePointer[it].toUByte() and MAX_BYTE
            val b = other.nativePointer[it].toUByte() and MAX_BYTE
            if (a != b) {
                return a.toInt() - b.toInt()
            }
        }
        return this.capacity - other.capacity
    }

    actual abstract operator fun get(index: Int): Byte

    actual abstract fun getInt(): Int

    internal fun readInt(): Int {
        if (position + 4 > capacity) {
            throw IllegalStateException("Not enough bytes left for int")
        }
        var int = 0 xor (this[position++].toInt() and 0xFF)
        for (it in 1 until 4) {
            int = int shl 8
            int = int xor (this[position++].toInt() and 0xFF)
        }
        return int
    }
}

class DirectByteBuffer internal constructor(
    nativePointer: CPointer,
    capacity: Int
) : ByteBuffer(nativePointer, capacity) {
    override fun get(index: Int) = nativePointer[index]

    override fun getInt() = readInt()

    override fun put(index: Int, byte: Byte): ByteBuffer {
        nativePointer[index] = byte
        return this
    }
}

class WrappedByteBuffer internal constructor(
    nativePointer: CPointer,
    capacity: Int
) : ByteBuffer(nativePointer, capacity) {
    override fun get(index: Int) = nativePointer[index]

    override fun put(index: Int, byte: Byte): ByteBuffer {
        nativePointer[index] = byte
        return this
    }

    override fun getInt() = readInt()
}

actual fun duplicateByteBuffer(byteBuffer: ByteBuffer): ByteBuffer {
    val newPointer = nativeHeap.allocArray(byteBuffer.capacity)
    for (i in 0..byteBuffer.capacity) {
        newPointer[i] = byteBuffer.nativePointer[i]
    }
    if (byteBuffer is WrappedByteBuffer) {
        return WrappedByteBuffer(newPointer, byteBuffer.capacity)
    } else {
        return DirectByteBuffer(newPointer, byteBuffer.capacity)
    }
}

actual fun allocateByteBuffer(capacity: Int): ByteBuffer {
    return WrappedByteBuffer(nativeHeap.allocArray(capacity), capacity)
}

actual fun allocateDirectByteBuffer(capacity: Int): ByteBuffer {
    return DirectByteBuffer(nativeHeap.allocArray(capacity), capacity)
}

actual fun wrapByteBuffer(bytes: ByteArray): ByteBuffer {
    return WrappedByteBuffer(bytes.toCPointer(), bytes.size)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy