From 94a0a311cb1b97faeb6e697aad045e75656c38ab Mon Sep 17 00:00:00 2001 From: tursom Date: Fri, 22 May 2020 16:06:03 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84Channel=E5=A2=9E=E5=BC=BA?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsyncSocket/build.gradle | 2 +- .../tursom/channel/enhance/EnhanceChannel.kt | 2 + .../enhance/impl/BufferedChannelReaderImpl.kt | 14 + .../channel/enhance/impl/EnhanceChannel.kt | 11 + .../enhance/impl/EnhanceChannelImpl.kt | 16 + .../impl/LengthFieldBasedFrameReader.kt | 41 +- .../enhance/impl/LengthFieldChannel.kt | 13 + .../channel/enhance/impl/StringChannel.kt | 19 + .../datagram/server/ServerNioDatagram.kt | 6 +- .../socket/security/SecurityEnhanceChannel.kt | 17 +- .../tursom/socket/server/BuffedNioServer.kt | 2 +- src/main/kotlin/cn/tursom/core/DataOperate.kt | 880 ++++++++++-------- .../tursom/core/buffer/ByteBufferExtension.kt | 75 +- .../tursom/core/buffer/MultipleByteBuffer.kt | 183 +++- .../core/buffer/impl/ArrayByteBuffer.kt | 4 +- .../core/buffer/impl/ArrayListByteBuffer.kt | 8 - .../tursom/core/buffer/impl/ListByteBuffer.kt | 57 +- 17 files changed, 911 insertions(+), 439 deletions(-) create mode 100644 AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/BufferedChannelReaderImpl.kt create mode 100644 AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/EnhanceChannel.kt create mode 100644 AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/EnhanceChannelImpl.kt create mode 100644 AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/LengthFieldChannel.kt create mode 100644 AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/StringChannel.kt delete mode 100644 src/main/kotlin/cn/tursom/core/buffer/impl/ArrayListByteBuffer.kt diff --git a/AsyncSocket/build.gradle b/AsyncSocket/build.gradle index a5cac03..16e2921 100644 --- a/AsyncSocket/build.gradle +++ b/AsyncSocket/build.gradle @@ -1,5 +1,5 @@ dependencies { - implementation project(":") + compile project(":") // kotlin 协程 compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1' diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/EnhanceChannel.kt b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/EnhanceChannel.kt index 9df8d22..fe9b7cc 100644 --- a/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/EnhanceChannel.kt +++ b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/EnhanceChannel.kt @@ -3,5 +3,7 @@ package cn.tursom.channel.enhance import java.io.Closeable interface EnhanceChannel : ChannelReader, ChannelWriter, Closeable { + val reader: ChannelReader + val writer: ChannelWriter override fun close() } \ No newline at end of file diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/BufferedChannelReaderImpl.kt b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/BufferedChannelReaderImpl.kt new file mode 100644 index 0000000..707d9a4 --- /dev/null +++ b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/BufferedChannelReaderImpl.kt @@ -0,0 +1,14 @@ +package cn.tursom.channel.enhance.impl + +import cn.tursom.channel.BufferedAsyncChannel +import cn.tursom.channel.enhance.ChannelReader +import cn.tursom.core.buffer.ByteBuffer +import cn.tursom.core.pool.MemoryPool + +class BufferedChannelReaderImpl( + private val socket: BufferedAsyncChannel +) : ChannelReader { + suspend fun read(timeout: Long) = socket.read(socket.pool, timeout) + override suspend fun read(pool: MemoryPool, timeout: Long) = socket.read(pool, timeout) + override fun close() = socket.close() +} \ No newline at end of file diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/EnhanceChannel.kt b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/EnhanceChannel.kt new file mode 100644 index 0000000..62654ed --- /dev/null +++ b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/EnhanceChannel.kt @@ -0,0 +1,11 @@ +package cn.tursom.channel.enhance.impl + +import cn.tursom.channel.AsyncChannel +import cn.tursom.core.buffer.ByteBuffer + +class EnhanceChannel( + val channel: Channel +) : EnhanceChannelImpl( + ChannelReaderImpl(channel), + ChannelWriterImpl(channel) +) \ No newline at end of file diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/EnhanceChannelImpl.kt b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/EnhanceChannelImpl.kt new file mode 100644 index 0000000..f3ee0e6 --- /dev/null +++ b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/EnhanceChannelImpl.kt @@ -0,0 +1,16 @@ +package cn.tursom.channel.enhance.impl + +import cn.tursom.channel.enhance.ChannelReader +import cn.tursom.channel.enhance.ChannelWriter +import cn.tursom.channel.enhance.EnhanceChannel +import cn.tursom.core.pool.MemoryPool + +open class EnhanceChannelImpl( + override val reader: ChannelReader, + override val writer: ChannelWriter +) : EnhanceChannel, ChannelReader by reader, ChannelWriter by writer { + override fun close() { + reader.close() + writer.close() + } +} \ No newline at end of file diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/LengthFieldBasedFrameReader.kt b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/LengthFieldBasedFrameReader.kt index ce9ce7e..944a62f 100644 --- a/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/LengthFieldBasedFrameReader.kt +++ b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/LengthFieldBasedFrameReader.kt @@ -6,13 +6,14 @@ import cn.tursom.core.pool.ExpandableMemoryPool import cn.tursom.core.pool.LongBitSetDirectMemoryPool import cn.tursom.core.pool.MemoryPool import cn.tursom.channel.enhance.ChannelReader +import cn.tursom.core.buffer.impl.ListByteBuffer class LengthFieldBasedFrameReader( private val prevReader: ChannelReader -) : ChannelReader> { +) : ChannelReader { private var lastRead: ByteBuffer? = null - override suspend fun read(pool: MemoryPool, timeout: Long): List { + override suspend fun read(pool: MemoryPool, timeout: Long): ByteBuffer { val startTime = CurrentTimeMillisClock.now val maxSize = prevReader.read(prevPool, timeout).let { val size = it.getInt() @@ -28,24 +29,26 @@ class LengthFieldBasedFrameReader( while (readSize < maxSize) { val buffer = prevReader.read(pool, timeout - (CurrentTimeMillisClock.now - startTime)) readSize += buffer.readable - bufList.add(if (readSize > maxSize) { - lastRead = buffer.slice( - buffer.readPosition + readSize - maxSize, - buffer.capacity - readSize - maxSize, - 0, - buffer.capacity - readSize - maxSize - ) - buffer.slice( - buffer.readPosition, - readSize - maxSize, - 0, - readSize - maxSize - ) - } else { - buffer - }) + bufList.add( + if (readSize > maxSize) { + lastRead = buffer.slice( + buffer.readPosition + readSize - maxSize, + buffer.capacity - readSize - maxSize, + 0, + buffer.capacity - readSize - maxSize + ) + buffer.slice( + buffer.readPosition, + readSize - maxSize, + 0, + readSize - maxSize + ) + } else { + buffer + } + ) } - return bufList + return ListByteBuffer(bufList) } override fun close() = prevReader.close() diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/LengthFieldChannel.kt b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/LengthFieldChannel.kt new file mode 100644 index 0000000..4b92d66 --- /dev/null +++ b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/LengthFieldChannel.kt @@ -0,0 +1,13 @@ +package cn.tursom.channel.enhance.impl + +import cn.tursom.channel.enhance.ChannelReader +import cn.tursom.channel.enhance.ChannelWriter +import cn.tursom.core.buffer.ByteBuffer + +class LengthFieldChannel( + reader: ChannelReader, + writer: ChannelWriter +) : EnhanceChannelImpl( + LengthFieldBasedFrameReader(reader), + LengthFieldPrependWriter(writer) +) \ No newline at end of file diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/StringChannel.kt b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/StringChannel.kt new file mode 100644 index 0000000..9177b77 --- /dev/null +++ b/AsyncSocket/src/main/kotlin/cn/tursom/channel/enhance/impl/StringChannel.kt @@ -0,0 +1,19 @@ +package cn.tursom.channel.enhance.impl + +import cn.tursom.channel.enhance.ChannelReader +import cn.tursom.channel.enhance.ChannelWriter +import cn.tursom.channel.enhance.EnhanceChannel +import cn.tursom.core.buffer.ByteBuffer + +class StringChannel( + prevReader: ChannelReader, + prevWriter: ChannelWriter +) : EnhanceChannelImpl( + StringReader(prevReader), + StringWriter(prevWriter) +) { + constructor(enhanceChannel: EnhanceChannel) : this( + enhanceChannel.reader, + enhanceChannel.writer + ) +} \ No newline at end of file diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/datagram/server/ServerNioDatagram.kt b/AsyncSocket/src/main/kotlin/cn/tursom/datagram/server/ServerNioDatagram.kt index af153ce..faa22f0 100644 --- a/AsyncSocket/src/main/kotlin/cn/tursom/datagram/server/ServerNioDatagram.kt +++ b/AsyncSocket/src/main/kotlin/cn/tursom/datagram/server/ServerNioDatagram.kt @@ -1,5 +1,6 @@ package cn.tursom.datagram.server +import cn.tursom.buffer.MultipleByteBuffer import cn.tursom.core.buffer.ByteBuffer import cn.tursom.core.buffer.read import cn.tursom.core.pool.MemoryPool @@ -39,7 +40,10 @@ class ServerNioDatagram( override suspend fun write(buffer: Array, timeout: Long): Long { var write = 0L buffer.forEach { buf -> - write += buf.read { channel.send(it, remoteAddress) } + if (buf is MultipleByteBuffer) { + } else { + write += buf.read { channel.send(it, remoteAddress) } + } } return write } diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/socket/security/SecurityEnhanceChannel.kt b/AsyncSocket/src/main/kotlin/cn/tursom/socket/security/SecurityEnhanceChannel.kt index 959521f..4459710 100644 --- a/AsyncSocket/src/main/kotlin/cn/tursom/socket/security/SecurityEnhanceChannel.kt +++ b/AsyncSocket/src/main/kotlin/cn/tursom/socket/security/SecurityEnhanceChannel.kt @@ -8,23 +8,26 @@ import cn.tursom.channel.enhance.ChannelReader import cn.tursom.channel.enhance.ChannelWriter class SecurityEnhanceChannel( - val reader: ChannelReader, - val writer: ChannelWriter, + val preReader: ChannelReader, + val preWriter: ChannelWriter, val aes: AES ) : EnhanceChannel { + override val reader: ChannelReader get() = this + override val writer: ChannelWriter get() = this + override fun close() { - reader.close() - writer.close() + preReader.close() + preWriter.close() } override suspend fun read(pool: MemoryPool, timeout: Long): ByteArray { - val buffer = reader.read(pool, timeout) + val buffer = preReader.read(pool, timeout) return aes.decrypt(buffer) } override suspend fun write(value: ByteArray) { - writer.write(aes.encrypt(value)) + preWriter.write(aes.encrypt(value)) } - override suspend fun flush(timeout: Long): Long = writer.flush() + override suspend fun flush(timeout: Long): Long = preWriter.flush() } \ No newline at end of file diff --git a/AsyncSocket/src/main/kotlin/cn/tursom/socket/server/BuffedNioServer.kt b/AsyncSocket/src/main/kotlin/cn/tursom/socket/server/BuffedNioServer.kt index 9872744..230743a 100644 --- a/AsyncSocket/src/main/kotlin/cn/tursom/socket/server/BuffedNioServer.kt +++ b/AsyncSocket/src/main/kotlin/cn/tursom/socket/server/BuffedNioServer.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.GlobalScope */ open class BuffedNioServer( port: Int, - private val memoryPool: MemoryPool, + val memoryPool: MemoryPool, backlog: Int = 50, coroutineScope: CoroutineScope = GlobalScope, handler: suspend BufferedAsyncSocket.() -> Unit diff --git a/src/main/kotlin/cn/tursom/core/DataOperate.kt b/src/main/kotlin/cn/tursom/core/DataOperate.kt index d25e943..656ca0b 100644 --- a/src/main/kotlin/cn/tursom/core/DataOperate.kt +++ b/src/main/kotlin/cn/tursom/core/DataOperate.kt @@ -9,421 +9,421 @@ import java.nio.ByteOrder class WrongPushTypeException : Exception() fun Char.toByteArray(): ByteArray { - val array = ByteArray(2) - array.put(this) - return array + val array = ByteArray(2) + array.put(this) + return array } fun Short.toByteArray(): ByteArray { - val array = ByteArray(2) - array.put(this) - return array + val array = ByteArray(2) + array.put(this) + return array } fun Int.toByteArray(): ByteArray { - val array = ByteArray(4) - array.put(this) - return array + val array = ByteArray(4) + array.put(this) + return array } fun Long.toByteArray(): ByteArray { - val array = ByteArray(8) - array.put(this) - return array + val array = ByteArray(8) + array.put(this) + return array } fun Float.toByteArray(): ByteArray { - val array = ByteArray(4) - array.put(this) - return array + val array = ByteArray(4) + array.put(this) + return array } fun Double.toByteArray(): ByteArray { - val array = ByteArray(8) - array.put(this) - return array + val array = ByteArray(8) + array.put(this) + return array } fun CharArray.toByteArray(): ByteArray { - val newArray = ByteArray(size * 2) - repeat(size) { - newArray.put(this[it], it * 2) - } - return newArray + val newArray = ByteArray(size * 2) + repeat(size) { + newArray.put(this[it], it * 2) + } + return newArray } fun ShortArray.toByteArray(): ByteArray { - val newArray = ByteArray(size * 2) - repeat(size) { - newArray.put(this[it], it * 2) - } - return newArray + val newArray = ByteArray(size * 2) + repeat(size) { + newArray.put(this[it], it * 2) + } + return newArray } fun IntArray.toByteArray(): ByteArray { - val newArray = ByteArray(size * 4) - repeat(size) { - newArray.put(this[it], it * 4) - } - return newArray + val newArray = ByteArray(size * 4) + repeat(size) { + newArray.put(this[it], it * 4) + } + return newArray } fun LongArray.toByteArray(): ByteArray { - val newArray = ByteArray(size * 8) - repeat(size) { - newArray.put(this[it], it * 8) - } - return newArray + val newArray = ByteArray(size * 8) + repeat(size) { + newArray.put(this[it], it * 8) + } + return newArray } fun FloatArray.toByteArray(): ByteArray { - val newArray = ByteArray(size * 4) - repeat(size) { - newArray.put(this[it], it * 4) - } - return newArray + val newArray = ByteArray(size * 4) + repeat(size) { + newArray.put(this[it], it * 4) + } + return newArray } fun DoubleArray.toByteArray(): ByteArray { - val newArray = ByteArray(size * 8) - repeat(size) { - newArray.put(this[it], it * 8) - } - return newArray + val newArray = ByteArray(size * 8) + repeat(size) { + newArray.put(this[it], it * 8) + } + return newArray } fun ByteArray.toChar(offset: Int = 0): Char { - return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { - (this[offset].toInt() or (this[offset + 1].toInt() shl 8)) - } else { - (this[offset + 1].toInt() or (this[offset].toInt() shl 8)) - }.toChar() + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + (this[offset].toInt() or (this[offset + 1].toInt() shl 8)) + } else { + (this[offset + 1].toInt() or (this[offset].toInt() shl 8)) + }.toChar() } fun ByteArray.toShort(offset: Int = 0): Short { - return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { - (this[offset].toInt() or (this[offset + 1].toInt() shl 8)) - } else { - (this[offset + 1].toInt() or (this[offset].toInt() shl 8)) - }.toShort() + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + (this[offset].toInt() or (this[offset + 1].toInt() shl 8)) + } else { + (this[offset + 1].toInt() or (this[offset].toInt() shl 8)) + }.toShort() } fun ByteArray.toInt(offset: Int = 0): Int { - return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { - this[offset].toInt() and 0xff or (this[offset + 1].toInt() shl 8 and 0xff00) or - (this[offset + 2].toInt() shl 16 and 0xff0000) or (this[offset + 3].toInt() shl 24 and 0xff000000.toInt()) - } else { - this[offset + 3].toInt() and 0xff or (this[offset + 2].toInt() shl 8 and 0xff00) or - (this[offset + 1].toInt() shl 16 and 0xff0000) or (this[offset].toInt() shl 24 and 0xff000000.toInt()) - } + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + this[offset].toInt() and 0xff or (this[offset + 1].toInt() shl 8 and 0xff00) or + (this[offset + 2].toInt() shl 16 and 0xff0000) or (this[offset + 3].toInt() shl 24 and 0xff000000.toInt()) + } else { + this[offset + 3].toInt() and 0xff or (this[offset + 2].toInt() shl 8 and 0xff00) or + (this[offset + 1].toInt() shl 16 and 0xff0000) or (this[offset].toInt() shl 24 and 0xff000000.toInt()) + } } fun ByteArray.toLong(offset: Int = 0): Long { - return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { - toInt(offset).toLong() or (toInt(offset + 4).toLong().shl(32) and 0xffff_ffffL.inv()) - } else { - toInt(offset + 4).toLong() or (toInt(offset).toLong().shl(32) and 0xffff_ffffL.inv()) - }.toLong() + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + toInt(offset).toLong() or (toInt(offset + 4).toLong().shl(32) and 0xffff_ffffL.inv()) + } else { + toInt(offset + 4).toLong() or (toInt(offset).toLong().shl(32) and 0xffff_ffffL.inv()) + }.toLong() } fun ByteArray.toFloat(offset: Int = 0): Float { - return Float.fromBits(toInt(offset)) + return Float.fromBits(toInt(offset)) } fun ByteArray.toDouble(offset: Int = 0): Double { - return Double.fromBits(toLong(offset)) + return Double.fromBits(toLong(offset)) } fun ByteArray.toCharArray(offset: Int, size: Int): CharArray { - if (offset + size * 2 > this.size) throw IndexOutOfBoundsException() - val newArray = CharArray(size) - repeat(newArray.size) { - newArray[it] = toChar(it * 2) - } - return newArray + if (offset + size * 2 > this.size) throw IndexOutOfBoundsException() + val newArray = CharArray(size) + repeat(newArray.size) { + newArray[it] = toChar(it * 2) + } + return newArray } fun ByteArray.toShortArray(offset: Int, size: Int): ShortArray { - if (offset + size * 2 > this.size) throw IndexOutOfBoundsException() - val newArray = ShortArray(size) - repeat(newArray.size) { - newArray[it] = toShort(it * 2) - } - return newArray + if (offset + size * 2 > this.size) throw IndexOutOfBoundsException() + val newArray = ShortArray(size) + repeat(newArray.size) { + newArray[it] = toShort(it * 2) + } + return newArray } fun ByteArray.toIntArray(offset: Int, size: Int): IntArray { - if (offset + size * 4 > this.size) throw IndexOutOfBoundsException() - val newArray = IntArray(size) - repeat(newArray.size) { - newArray[it] = toInt(it * 4) - } - return newArray + if (offset + size * 4 > this.size) throw IndexOutOfBoundsException() + val newArray = IntArray(size) + repeat(newArray.size) { + newArray[it] = toInt(it * 4) + } + return newArray } fun ByteArray.toLongArray(offset: Int, size: Int): LongArray { - if (offset + size * 8 > this.size) throw IndexOutOfBoundsException() - val newArray = LongArray(size) - repeat(newArray.size) { - newArray[it] = toLong(it * 8) - } - return newArray + if (offset + size * 8 > this.size) throw IndexOutOfBoundsException() + val newArray = LongArray(size) + repeat(newArray.size) { + newArray[it] = toLong(it * 8) + } + return newArray } fun ByteArray.toFloatArray(offset: Int, size: Int): FloatArray { - if (offset + size * 4 > this.size) throw IndexOutOfBoundsException() - val newArray = FloatArray(size) - repeat(newArray.size) { - newArray[it] = toFloat(it * 4) - } - return newArray + if (offset + size * 4 > this.size) throw IndexOutOfBoundsException() + val newArray = FloatArray(size) + repeat(newArray.size) { + newArray[it] = toFloat(it * 4) + } + return newArray } fun ByteArray.toDoubleArray(offset: Int, size: Int): DoubleArray { - if (offset + size * 8 > this.size) throw IndexOutOfBoundsException() - val newArray = DoubleArray(size) - repeat(newArray.size) { - newArray[it] = toDouble(it * 8) - } - return newArray + if (offset + size * 8 > this.size) throw IndexOutOfBoundsException() + val newArray = DoubleArray(size) + repeat(newArray.size) { + newArray[it] = toDouble(it * 8) + } + return newArray } fun Short.hton(): Short = ntoh() fun Short.ntoh(): Short { - return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { - this - } else { - val value = toInt() - (value shr 8 or (value shl 8)).toShort() - } + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + this + } else { + val value = toInt() + (value shr 8 or (value shl 8)).toShort() + } } fun Int.hton(): Int = ntoh() fun Int.ntoh(): Int { - return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { - this - } else { - shr(24) or (shr(16) and 0xff00) or (shr(8) and 0xff0000) or (this and 0xff) - } + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + this + } else { + shr(24) or (shr(16) and 0xff00) or (shr(8) and 0xff0000) or (this and 0xff) + } } fun Long.hton(): Long = ntoh() fun Long.ntoh(): Long { - return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { - this - } else { - shr(56) or (shr(48) and 0xff00) or (shr(40) and 0xff0000) - or(shr(32) and 0xff000000) or (shl(32) and (0xff shl 32)) - or(shl(40) and (0xff shl 40)) or (shl(48) and (0xff shl 48)) or shl(56) - } + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + this + } else { + shr(56) or (shr(48) and 0xff00) or (shr(40) and 0xff0000) + or(shr(32) and 0xff000000) or (shl(32) and (0xff shl 32)) + or(shl(40) and (0xff shl 40)) or (shl(48) and (0xff shl 48)) or shl(56) + } } fun ByteArray.put(char: Char, offset: Int = 0) { - val value = char.toInt() - when (ByteOrder.nativeOrder()) { - ByteOrder.BIG_ENDIAN -> { - this[offset] = value.toByte() - this[offset + 1] = (value shr 8).toByte() - } - ByteOrder.LITTLE_ENDIAN -> { - this[offset + 1] = value.toByte() - this[offset] = (value shr 8).toByte() - } - } + val value = char.toInt() + when (ByteOrder.nativeOrder()) { + ByteOrder.BIG_ENDIAN -> { + this[offset] = value.toByte() + this[offset + 1] = (value shr 8).toByte() + } + ByteOrder.LITTLE_ENDIAN -> { + this[offset + 1] = value.toByte() + this[offset] = (value shr 8).toByte() + } + } } fun ByteArray.put(short: Short, offset: Int = 0) { - val value = short.toInt() - when (ByteOrder.nativeOrder()) { - ByteOrder.BIG_ENDIAN -> { - this[offset] = value.toByte() - this[offset + 1] = (value shr 8).toByte() - } - ByteOrder.LITTLE_ENDIAN -> { - this[offset + 1] = value.toByte() - this[offset] = (value shr 8).toByte() - } - } + val value = short.toInt() + when (ByteOrder.nativeOrder()) { + ByteOrder.BIG_ENDIAN -> { + this[offset] = value.toByte() + this[offset + 1] = (value shr 8).toByte() + } + ByteOrder.LITTLE_ENDIAN -> { + this[offset + 1] = value.toByte() + this[offset] = (value shr 8).toByte() + } + } } fun ByteArray.put(int: Int, offset: Int = 0) { - when (ByteOrder.nativeOrder()) { - ByteOrder.BIG_ENDIAN -> { - this[offset] = int.toByte() - this[offset + 1] = (int shr 8).toByte() - this[offset + 2] = (int shr 16).toByte() - this[offset + 3] = (int shr 24).toByte() - } - ByteOrder.LITTLE_ENDIAN -> { - this[offset + 3] = int.toByte() - this[offset + 2] = (int shr 8).toByte() - this[offset + 1] = (int shr 16).toByte() - this[offset] = (int shr 24).toByte() - } - } + when (ByteOrder.nativeOrder()) { + ByteOrder.BIG_ENDIAN -> { + this[offset] = int.toByte() + this[offset + 1] = (int shr 8).toByte() + this[offset + 2] = (int shr 16).toByte() + this[offset + 3] = (int shr 24).toByte() + } + ByteOrder.LITTLE_ENDIAN -> { + this[offset + 3] = int.toByte() + this[offset + 2] = (int shr 8).toByte() + this[offset + 1] = (int shr 16).toByte() + this[offset] = (int shr 24).toByte() + } + } } fun ByteArray.put(long: Long, offset: Int = 0) { - when (ByteOrder.nativeOrder()) { - ByteOrder.BIG_ENDIAN -> { - this[offset] = long.toByte() - this[offset + 1] = (long shr 8).toByte() - this[offset + 2] = (long shr 16).toByte() - this[offset + 3] = (long shr 24).toByte() - this[offset + 4] = (long shr 32).toByte() - this[offset + 5] = (long shr 40).toByte() - this[offset + 6] = (long shr 48).toByte() - this[offset + 7] = (long shr 56).toByte() - } - ByteOrder.LITTLE_ENDIAN -> { - this[offset + 7] = long.toByte() - this[offset + 6] = (long shr 8).toByte() - this[offset + 5] = (long shr 16).toByte() - this[offset + 4] = (long shr 24).toByte() - this[offset + 3] = (long shr 32).toByte() - this[offset + 2] = (long shr 40).toByte() - this[offset + 1] = (long shr 48).toByte() - this[offset] = (long shr 56).toByte() - } - } + when (ByteOrder.nativeOrder()) { + ByteOrder.BIG_ENDIAN -> { + this[offset] = long.toByte() + this[offset + 1] = (long shr 8).toByte() + this[offset + 2] = (long shr 16).toByte() + this[offset + 3] = (long shr 24).toByte() + this[offset + 4] = (long shr 32).toByte() + this[offset + 5] = (long shr 40).toByte() + this[offset + 6] = (long shr 48).toByte() + this[offset + 7] = (long shr 56).toByte() + } + ByteOrder.LITTLE_ENDIAN -> { + this[offset + 7] = long.toByte() + this[offset + 6] = (long shr 8).toByte() + this[offset + 5] = (long shr 16).toByte() + this[offset + 4] = (long shr 24).toByte() + this[offset + 3] = (long shr 32).toByte() + this[offset + 2] = (long shr 40).toByte() + this[offset + 1] = (long shr 48).toByte() + this[offset] = (long shr 56).toByte() + } + } } fun ByteArray.put(float: Float, offset: Int = 0) { - put(float.toBits(), offset) + put(float.toBits(), offset) } fun ByteArray.put(double: Double, offset: Int = 0) { - put(double.toBits(), offset) + put(double.toBits(), offset) } fun ByteArray.put(charArray: CharArray, offset: Int = 0, addLength: Boolean = true) { - var index = offset - if (addLength) { - put(charArray.size, index) - index += 4 - } - charArray.forEach { - put(it) - index += 2 - } + var index = offset + if (addLength) { + put(charArray.size, index) + index += 4 + } + charArray.forEach { + put(it) + index += 2 + } } fun ByteArray.put(shortArray: ShortArray, offset: Int = 0, addLength: Boolean = true) { - var index = offset - if (addLength) { - put(shortArray.size, index) - index += 4 - } - shortArray.forEach { - put(it) - index += 2 - } + var index = offset + if (addLength) { + put(shortArray.size, index) + index += 4 + } + shortArray.forEach { + put(it) + index += 2 + } } fun ByteArray.put(intArray: IntArray, offset: Int = 0, addLength: Boolean = true) { - var index = offset - if (addLength) { - put(intArray.size, index) - index += 4 - } - intArray.forEach { - put(it) - index += 4 - } + var index = offset + if (addLength) { + put(intArray.size, index) + index += 4 + } + intArray.forEach { + put(it) + index += 4 + } } fun ByteArray.put(longArray: LongArray, offset: Int = 0, addLength: Boolean = true) { - var index = offset - if (addLength) { - put(longArray.size, index) - index += 4 - } - longArray.forEach { - put(it) - index += 8 - } + var index = offset + if (addLength) { + put(longArray.size, index) + index += 4 + } + longArray.forEach { + put(it) + index += 8 + } } fun ByteArray.put(floatArray: FloatArray, offset: Int = 0, addLength: Boolean = true) { - var index = offset - if (addLength) { - put(floatArray.size, index) - index += 4 - } - floatArray.forEach { - put(it) - index += 4 - } + var index = offset + if (addLength) { + put(floatArray.size, index) + index += 4 + } + floatArray.forEach { + put(it) + index += 4 + } } fun ByteArray.put(doubleArray: DoubleArray, offset: Int = 0, addLength: Boolean = true) { - var index = offset - if (addLength) { - put(doubleArray.size, index) - index += 4 - } - doubleArray.forEach { - put(it) - index += 8 - } + var index = offset + if (addLength) { + put(doubleArray.size, index) + index += 4 + } + doubleArray.forEach { + put(it) + index += 8 + } } fun ByteArray.put(str: String, offset: Int = 0, addLength: Boolean = false): Int { - val utf8Array = str.toByteArray() - return if (addLength) { - put(utf8Array.size) - utf8Array.copyInto(this, offset + 4) - utf8Array.size + 4 - } else { - utf8Array.copyInto(this, offset) - this[offset + utf8Array.size] = 0 - utf8Array.size - } + val utf8Array = str.toByteArray() + return if (addLength) { + put(utf8Array.size) + utf8Array.copyInto(this, offset + 4) + utf8Array.size + 4 + } else { + utf8Array.copyInto(this, offset) + this[offset + utf8Array.size] = 0 + utf8Array.size + } } fun ByteArray.pop(array: CharArray, offset: Int = 0, fromIndex: Int = 0, size: Int = (this.size - fromIndex) / 2) { - repeat(size) { - array[offset + it] = toChar(fromIndex + it * 2) - } + repeat(size) { + array[offset + it] = toChar(fromIndex + it * 2) + } } fun ByteArray.pop(array: ShortArray, offset: Int = 0, fromIndex: Int = 0, size: Int = (this.size - fromIndex) / 2) { - repeat(size) { - array[offset + it] = toShort(fromIndex + it * 2) - } + repeat(size) { + array[offset + it] = toShort(fromIndex + it * 2) + } } fun ByteArray.pop(array: IntArray, offset: Int = 0, fromIndex: Int = 0, size: Int = (this.size - fromIndex) / 4) { - repeat(size) { - array[offset + it] = toInt(fromIndex + it * 4) - } + repeat(size) { + array[offset + it] = toInt(fromIndex + it * 4) + } } fun ByteArray.pop(array: LongArray, offset: Int = 0, fromIndex: Int = 0, size: Int = (this.size - fromIndex) / 8) { - repeat(size) { - array[offset + it] = toLong(fromIndex + it * 8) - } + repeat(size) { + array[offset + it] = toLong(fromIndex + it * 8) + } } fun ByteArray.pop(array: FloatArray, offset: Int = 0, fromIndex: Int = 0, size: Int = (this.size - fromIndex) / 4) { - repeat(size) { - array[offset + it] = toFloat(fromIndex + it * 4) - } + repeat(size) { + array[offset + it] = toFloat(fromIndex + it * 4) + } } fun ByteArray.pop(array: DoubleArray, offset: Int = 0, fromIndex: Int = 0, size: Int = (this.size - fromIndex) / 8) { - repeat(size) { - array[offset + it] = toDouble(fromIndex + it * 8) - } + repeat(size) { + array[offset + it] = toDouble(fromIndex + it * 8) + } } fun ByteArray.strlen(offset: Int = 0): Int { - for (index in offset until size) { - if (get(index).toInt() == 0) return index - } - return size + for (index in offset until size) { + if (get(index).toInt() == 0) return index + } + return size } fun Float.asInt(): Int = toRawBits() @@ -433,113 +433,115 @@ fun Long.asDouble(): Double = Double.fromBits(this) fun ByteArray.put(obj: Any, offset: Int = 0): Int { - return when (obj) { - is Byte -> if (offset < size) { - this[offset] = obj - 1 - } else { - throw IndexOutOfBoundsException() - } - is Char -> { - put(obj, offset) - 2 - } - is Short -> { - put(obj, offset) - 2 - } - is Int -> { - put(obj, offset) - 4 - } - is Long -> { - put(obj, offset) - 8 - } - is Float -> { - put(obj, offset) - 4 - } - is Double -> { - put(obj, offset) - 8 - } + return when (obj) { + is Byte -> if (offset < size) { + this[offset] = obj + 1 + } else { + throw IndexOutOfBoundsException() + } + is Char -> { + put(obj, offset) + 2 + } + is Short -> { + put(obj, offset) + 2 + } + is Int -> { + put(obj, offset) + 4 + } + is Long -> { + put(obj, offset) + 8 + } + is Float -> { + put(obj, offset) + 4 + } + is Double -> { + put(obj, offset) + 8 + } - is ByteArray -> if (size < offset + obj.size) { - put(obj.size, offset) - obj.copyInto(this, offset + 4) - obj.size + 4 - } else { - throw IndexOutOfBoundsException() - } - is CharArray -> { - put(obj, offset) - obj.size * 2 + 4 - } - is ShortArray -> { - put(obj, offset) - obj.size * 2 + 4 - } - is IntArray -> { - put(obj, offset) - obj.size * 4 + 4 - } - is LongArray -> { - put(obj, offset) - obj.size * 8 + 4 - } - is FloatArray -> { - put(obj, offset) - obj.size * 4 + 4 - } - is DoubleArray -> { - put(obj, offset) - obj.size * 8 + 4 - } + is ByteArray -> if (size < offset + obj.size) { + put(obj.size, offset) + obj.copyInto(this, offset + 4) + obj.size + 4 + } else { + throw IndexOutOfBoundsException() + } + is CharArray -> { + put(obj, offset) + obj.size * 2 + 4 + } + is ShortArray -> { + put(obj, offset) + obj.size * 2 + 4 + } + is IntArray -> { + put(obj, offset) + obj.size * 4 + 4 + } + is LongArray -> { + put(obj, offset) + obj.size * 8 + 4 + } + is FloatArray -> { + put(obj, offset) + obj.size * 4 + 4 + } + is DoubleArray -> { + put(obj, offset) + obj.size * 8 + 4 + } - is String -> { - put(obj, offset, true) - } + is String -> { + put(obj, offset, true) + } - else -> throw WrongPushTypeException() - } + else -> throw WrongPushTypeException() + } } val Int.ipStr - get() = formatIpAddress(this) + get() = formatIpAddress(this) fun formatIpAddress(ip: Int) = - "${ip and 0xff}.${(ip shr 8) and 0xff}.${(ip shr 16) and 0xff}.${(ip shr 24) and 0xff}" + "${ip and 0xff}.${(ip shr 8) and 0xff}.${(ip shr 16) and 0xff}.${(ip shr 24) and 0xff}" /** * 序列化 */ fun serialize(outputStream: T, obj: Any): T { - val oos = ObjectOutputStream(outputStream) - oos.writeObject(obj) - return outputStream + val oos = ObjectOutputStream(outputStream) + oos.writeObject(obj) + return outputStream } fun serialize(obj: Any): ByteArray? = try { - val baos = ByteArrayOutputStream() - serialize(baos, obj) - baos.toByteArray() + val baos = ByteArrayOutputStream() + serialize(baos, obj) + baos.toByteArray() } catch (e: Exception) { - null + null } /** * 反序列化 */ fun unSerialize(bytes: ByteArray, offset: Int = 0, size: Int = bytes.size): Any? = try { - ObjectInputStream(ByteArrayInputStream(bytes, offset, size)).readObject() + ObjectInputStream(ByteArrayInputStream(bytes, offset, size)).readObject() } catch (e: Exception) { - null + null } -private val ByteArrayOutputStream_buf = ByteArrayOutputStream::class.java.getDeclaredField("buf").apply { isAccessible = true } -private val ByteArrayOutputStream_count = ByteArrayOutputStream::class.java.getDeclaredField("count").apply { isAccessible = true } +private val ByteArrayOutputStream_buf = + ByteArrayOutputStream::class.java.getDeclaredField("buf").apply { isAccessible = true } +private val ByteArrayOutputStream_count = + ByteArrayOutputStream::class.java.getDeclaredField("count").apply { isAccessible = true } val ByteArrayOutputStream.buf get() = ByteArrayOutputStream_buf.get(this) as ByteArray val ByteArrayOutputStream.count get() = ByteArrayOutputStream_count.get(this) as Int @@ -547,49 +549,175 @@ val ByteArrayOutputStream.count get() = ByteArrayOutputStream_count.get(this) as fun ByteArray.toByteBuffer() = HeapByteBuffer(this, 0, size) inline fun Array.forEachIndex(fromIndex: Int, toIndex: Int, action: (T) -> Unit) { - for (i in fromIndex..toIndex) { - action(this[i]) - } + for (i in fromIndex..toIndex) { + action(this[i]) + } } inline fun ByteArray.forEachIndex(fromIndex: Int, toIndex: Int, action: (Byte) -> Unit) { - for (i in fromIndex..toIndex) { - action(this[i]) - } + for (i in fromIndex..toIndex) { + action(this[i]) + } } inline fun CharArray.forEachIndex(fromIndex: Int, toIndex: Int, action: (Char) -> Unit) { - for (i in fromIndex..toIndex) { - action(this[i]) - } + for (i in fromIndex..toIndex) { + action(this[i]) + } } inline fun ShortArray.forEachIndex(fromIndex: Int, toIndex: Int, action: (Short) -> Unit) { - for (i in fromIndex..toIndex) { - action(this[i]) - } + for (i in fromIndex..toIndex) { + action(this[i]) + } } inline fun IntArray.forEachIndex(fromIndex: Int, toIndex: Int, action: (Int) -> Unit) { - for (i in fromIndex..toIndex) { - action(this[i]) - } + for (i in fromIndex..toIndex) { + action(this[i]) + } } inline fun LongArray.forEachIndex(fromIndex: Int, toIndex: Int, action: (Long) -> Unit) { - for (i in fromIndex..toIndex) { - action(this[i]) - } + for (i in fromIndex..toIndex) { + action(this[i]) + } } inline fun FloatArray.forEachIndex(fromIndex: Int, toIndex: Int, action: (Float) -> Unit) { - for (i in fromIndex..toIndex) { - action(this[i]) - } + for (i in fromIndex..toIndex) { + action(this[i]) + } } inline fun DoubleArray.forEachIndex(fromIndex: Int, toIndex: Int, action: (Double) -> Unit) { - for (i in fromIndex..toIndex) { - action(this[i]) - } + for (i in fromIndex..toIndex) { + action(this[i]) + } +} + +inline fun Char.toBytes(action: (Byte) -> Unit) { + val value = toInt() + when (ByteOrder.nativeOrder()) { + ByteOrder.BIG_ENDIAN -> { + action(value.toByte()) + action((value shr 8).toByte()) + } + ByteOrder.LITTLE_ENDIAN -> { + action((value shr 8).toByte()) + action(value.toByte()) + } + } +} + +inline fun Short.toBytes(action: (Byte) -> Unit) { + val value = toInt() + when (ByteOrder.nativeOrder()) { + ByteOrder.BIG_ENDIAN -> { + action(value.toByte()) + action((value shr 8).toByte()) + } + ByteOrder.LITTLE_ENDIAN -> { + action((value shr 8).toByte()) + action(value.toByte()) + } + } +} + +inline fun Int.toBytes(action: (Byte) -> Unit) { + when (ByteOrder.nativeOrder()) { + ByteOrder.BIG_ENDIAN -> { + action(this.toByte()) + action((this shr 8).toByte()) + action((this shr 16).toByte()) + action((this shr 24).toByte()) + } + ByteOrder.LITTLE_ENDIAN -> { + action((this shr 24).toByte()) + action((this shr 16).toByte()) + action((this shr 8).toByte()) + action(this.toByte()) + } + } +} + +inline fun Long.toBytes(action: (Byte) -> Unit) { + when (ByteOrder.nativeOrder()) { + ByteOrder.BIG_ENDIAN -> { + action(this.toByte()) + action((this shr 8).toByte()) + action((this shr 16).toByte()) + action((this shr 24).toByte()) + action((this shr 32).toByte()) + action((this shr 40).toByte()) + action((this shr 48).toByte()) + action((this shr 56).toByte()) + } + ByteOrder.LITTLE_ENDIAN -> { + action((this shr 56).toByte()) + action((this shr 48).toByte()) + action((this shr 40).toByte()) + action((this shr 32).toByte()) + action((this shr 24).toByte()) + action((this shr 16).toByte()) + action((this shr 8).toByte()) + action(this.toByte()) + } + } +} + +inline fun Float.toBytes(action: (Byte) -> Unit) { + toBits().toBytes(action) +} + +inline fun Double.toBytes(action: (Byte) -> Unit) { + toBits().toBytes(action) +} + +inline fun toChar(get: () -> Byte): Char { + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + (get().toInt() or (get().toInt() shl 8)) + } else { + val late = get() + (get().toInt() or (late.toInt() shl 8)) + }.toChar() +} + +inline fun toShort(get: () -> Byte): Short { + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + (get().toInt() or (get().toInt() shl 8)) + } else { + val late = get() + (get().toInt() or (late.toInt() shl 8)) + }.toShort() +} + +inline fun toInt(get: () -> Byte): Int { + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + get().toInt() and 0xff or (get().toInt() shl 8 and 0xff00) or + (get().toInt() shl 16 and 0xff0000) or (get().toInt() shl 24 and 0xff000000.toInt()) + } else { + val i1 = get() + val i2 = get() + val i3 = get() + get().toInt() and 0xff or (i3.toInt() shl 8 and 0xff00) or + (i2.toInt() shl 16 and 0xff0000) or (i1.toInt() shl 24 and 0xff000000.toInt()) + } +} + +inline fun toLong(get: () -> Byte): Long { + return if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) { + toInt(get).toLong() or (toInt(get).toLong().shl(32) and 0xffff_ffffL.inv()) + } else { + val late = toInt(get) + get().toLong() or (late.toLong().shl(32) and 0xffff_ffffL.inv()) + }.toLong() +} + +inline fun toFloat(get: () -> Byte): Float { + return Float.fromBits(toInt(get)) +} + +inline fun toDouble(get: () -> Byte): Double { + return Double.fromBits(toLong(get)) } \ No newline at end of file diff --git a/src/main/kotlin/cn/tursom/core/buffer/ByteBufferExtension.kt b/src/main/kotlin/cn/tursom/core/buffer/ByteBufferExtension.kt index 370d041..0d43b81 100644 --- a/src/main/kotlin/cn/tursom/core/buffer/ByteBufferExtension.kt +++ b/src/main/kotlin/cn/tursom/core/buffer/ByteBufferExtension.kt @@ -34,9 +34,28 @@ inline fun ByteBuffer.write(block: (java.nio.ByteBuffer) -> T): T { } } +inline fun MultipleByteBuffer.reads(block: (List) -> T): T { + val bufferList = readBuffers() + try { + return block(bufferList) + } finally { + finishRead(bufferList) + } +} + + +inline fun MultipleByteBuffer.writes(block: (List) -> T): T { + val bufferList = writeBuffers() + try { + return block(bufferList) + } finally { + finishWrite(bufferList) + } +} + fun ReadableByteChannel.read(buffer: ByteBuffer): Int { return if (buffer is MultipleByteBuffer && this is ScatteringByteChannel) { - buffer.writeBuffers { read(it) }.toInt() + buffer.writeBuffers { read(it.toTypedArray()) }.toInt() } else { buffer.write { read(it) } } @@ -44,35 +63,75 @@ fun ReadableByteChannel.read(buffer: ByteBuffer): Int { fun WritableByteChannel.write(buffer: ByteBuffer): Int { return if (buffer is MultipleByteBuffer && this is GatheringByteChannel) { - buffer.readBuffers { write(it) }.toInt() + buffer.readBuffers { write(it.toTypedArray()) }.toInt() } else { buffer.read { write(it) } } } fun ScatteringByteChannel.read(buffer: MultipleByteBuffer): Long { - return buffer.writeBuffers { read(it) } + return buffer.writeBuffers { read(it.toTypedArray()) } } fun GatheringByteChannel.write(buffer: MultipleByteBuffer): Long { - return buffer.readBuffers { write(it) } + return buffer.readBuffers { write(it.toTypedArray()) } } fun ScatteringByteChannel.read(buffers: Array): Long { - val bufferArray = Array(buffers.size) { buffers[it].writeBuffer() } + val bufferList = ArrayList() + buffers.forEach { + if (it is MultipleByteBuffer) { + it.forEach { + bufferList.add(it.writeBuffer()) + } + } else { + bufferList.add(it.writeBuffer()) + } + } + val bufferArray = bufferList.toTypedArray() return try { read(bufferArray) } finally { - buffers.forEachIndexed { index, byteBuffer -> byteBuffer.finishWrite(bufferArray[index]) } + var index = 0 + buffers.forEach { + if (it is MultipleByteBuffer) { + it.forEach { + it.finishWrite(bufferArray[index]) + } + } else { + it.finishRead(bufferArray[index]) + } + } + index++ } } fun GatheringByteChannel.write(buffers: Array): Long { - val bufferArray = Array(buffers.size) { buffers[it].readBuffer() } + val bufferList = ArrayList() + buffers.forEach { + if (it is MultipleByteBuffer) { + it.forEach { + bufferList.add(it.readBuffer()) + } + } else { + bufferList.add(it.readBuffer()) + } + } + val bufferArray = bufferList.toTypedArray() return try { write(bufferArray) } finally { - buffers.forEachIndexed { index, byteBuffer -> byteBuffer.finishRead(bufferArray[index]) } + var index = 0 + buffers.forEach { + if (it is MultipleByteBuffer) { + it.forEach { + it.finishRead(bufferArray[index]) + } + } else { + it.finishRead(bufferArray[index]) + } + } + index++ } } diff --git a/src/main/kotlin/cn/tursom/core/buffer/MultipleByteBuffer.kt b/src/main/kotlin/cn/tursom/core/buffer/MultipleByteBuffer.kt index 2710a25..900f72e 100644 --- a/src/main/kotlin/cn/tursom/core/buffer/MultipleByteBuffer.kt +++ b/src/main/kotlin/cn/tursom/core/buffer/MultipleByteBuffer.kt @@ -2,16 +2,22 @@ package cn.tursom.buffer import cn.tursom.core.buffer.ByteBuffer import cn.tursom.core.buffer.impl.ListByteBuffer +import cn.tursom.core.forEachIndex +import cn.tursom.core.toBytes import java.io.Closeable +import java.io.IOException +import java.io.InputStream +import java.io.OutputStream +import kotlin.math.min @Suppress("unused") -interface MultipleByteBuffer : List, Closeable { +interface MultipleByteBuffer : List, Closeable, ByteBuffer { val buffers: Array get() = toTypedArray() /** * 使用读 buffer,ByteBuffer 实现类有义务维护指针正常推进 */ - fun readBuffers(block: (Array) -> T): T { + fun readBuffers(block: (List) -> T): T { val buffer = readBuffers() return try { block(buffer) @@ -23,7 +29,7 @@ interface MultipleByteBuffer : List, Closeable { /** * 使用写 buffer,ByteBuffer 实现类有义务维护指针正常推进 */ - fun writeBuffers(block: (Array) -> T): T { + fun writeBuffers(block: (List) -> T): T { val buffer = writeBuffers() return try { block(buffer) @@ -32,20 +38,169 @@ interface MultipleByteBuffer : List, Closeable { } } - fun readBuffers(): Array = Array(size) { this[it].readBuffer() } - fun writeBuffers(): Array = Array(size) { this[it].writeBuffer() } - - fun finishRead(buffers: Array) = buffers.forEachIndexed { index, byteBuffer -> - this[index].finishRead(byteBuffer) + fun readBuffers(): List { + val bufferList = ArrayList() + buffers.forEach { + if (it is MultipleByteBuffer) { + it.forEach { + bufferList.add(it.readBuffer()) + } + } else { + bufferList.add(it.readBuffer()) + } + } + return bufferList } - fun finishWrite(buffers: Array) = buffers.forEachIndexed { index, byteBuffer -> - this[index].finishWrite(byteBuffer) + fun writeBuffers(): List { + val bufferList = ArrayList() + buffers.forEach { + if (it is MultipleByteBuffer) { + it.forEach { + bufferList.add(it.writeBuffer()) + } + } else { + bufferList.add(it.writeBuffer()) + } + } + return bufferList + } + + fun finishRead(buffers: List) { + var index = 0 + forEach { + if (it is MultipleByteBuffer) { + it.forEach { + it.finishRead(buffers[index]) + index++ + } + } else { + it.finishRead(buffers[index]) + index++ + } + } + } + + fun finishWrite(buffers: List) { + var index = 0 + forEach { + if (it is MultipleByteBuffer) { + it.forEach { + it.finishWrite(buffers[index]) + index++ + } + } else { + it.finishWrite(buffers[index]) + index++ + } + } } override fun close() = forEach(ByteBuffer::close) - fun slice(offset: Int, size: Int): MultipleByteBuffer = ListByteBuffer(subList(offset, offset + size)) - fun fill(byte: Byte) = forEach { it.fill(byte) } - fun clear() = forEach(ByteBuffer::clear) - fun reset() = forEach(ByteBuffer::reset) + override fun slice(offset: Int, size: Int): MultipleByteBuffer = ListByteBuffer(subList(offset, offset + size)) + override fun fill(byte: Byte) = forEach { it.fill(byte) } + override fun clear() = forEach(ByteBuffer::clear) + override fun reset() = forEach(ByteBuffer::reset) + + + override val resized: Boolean get() = false + override val hasArray: Boolean get() = false + override val array: ByteArray + get() = throw UnsupportedOperationException() + override val arrayOffset: Int get() = 0 + override val capacity: Int + get() { + var capacity = 0 + forEach { + capacity += it.capacity + } + return capacity + } + + override fun readBuffer(): java.nio.ByteBuffer = throw UnsupportedOperationException() + override fun writeBuffer(): java.nio.ByteBuffer = throw UnsupportedOperationException() + override fun slice(position: Int, size: Int, readPosition: Int, writePosition: Int): ByteBuffer = + throw UnsupportedOperationException() + + override fun resize(newSize: Int): Boolean = false + + override fun get(): Byte + override fun getChar(): Char = cn.tursom.core.toChar(::get) + override fun getShort(): Short = cn.tursom.core.toShort(::get) + override fun getInt(): Int = cn.tursom.core.toInt(::get) + override fun getLong(): Long = cn.tursom.core.toLong(::get) + override fun getFloat(): Float = cn.tursom.core.toFloat(::get) + override fun getDouble(): Double = cn.tursom.core.toDouble(::get) + override fun getBytes(size: Int): ByteArray { + val buffer = ByteArray(size) + buffer.indices.forEach { + buffer[it] = get() + } + return buffer + } + + override fun writeTo(buffer: ByteArray, bufferOffset: Int, size: Int): Int { + var write = 0 + try { + repeat(size) { + buffer[bufferOffset + it] = get() + write++ + } + } catch (e: Exception) { + } + return write + } + + override fun writeTo(os: OutputStream): Int { + var write = 0 + try { + while (true) { + os.write(get().toInt()) + write++ + } + } catch (e: Exception) { + } + return write + } + + override fun writeTo(buffer: ByteBuffer): Int { + var write = 0 + try { + while (true) { + buffer.put(get().toInt()) + write++ + } + } catch (e: Exception) { + } + return write + } + + override fun put(byte: Byte): Unit + override fun put(char: Char) = char.toBytes { put(it) } + override fun put(short: Short) = short.toBytes { put(it) } + override fun put(int: Int) = int.toBytes { put(it) } + override fun put(long: Long) = long.toBytes { put(it) } + override fun put(float: Float) = float.toBytes { put(it) } + override fun put(double: Double) = double.toBytes { put(it) } + override fun put(byteArray: ByteArray, offset: Int, len: Int): Int { + var write = 0 + byteArray.forEachIndex(offset, offset + len) { + put(it) + write++ + } + return write + } + + override fun put(inputStream: InputStream, size: Int): Int { + var read = 0 + try { + put(inputStream.read().toByte()) + read++ + } catch (e: Exception) { + } + return read + } + + override fun split(maxSize: Int): Array = throw UnsupportedOperationException() + override fun readAllSize(): Int = throw UnsupportedOperationException() } \ No newline at end of file diff --git a/src/main/kotlin/cn/tursom/core/buffer/impl/ArrayByteBuffer.kt b/src/main/kotlin/cn/tursom/core/buffer/impl/ArrayByteBuffer.kt index 7397077..72d532c 100644 --- a/src/main/kotlin/cn/tursom/core/buffer/impl/ArrayByteBuffer.kt +++ b/src/main/kotlin/cn/tursom/core/buffer/impl/ArrayByteBuffer.kt @@ -4,5 +4,5 @@ import cn.tursom.core.buffer.ByteBuffer import cn.tursom.buffer.MultipleByteBuffer class ArrayByteBuffer( - override vararg val buffers: ByteBuffer -) : MultipleByteBuffer, List by buffers.asList() \ No newline at end of file + override vararg val buffers: ByteBuffer +) : ListByteBuffer(buffers.asList()) \ No newline at end of file diff --git a/src/main/kotlin/cn/tursom/core/buffer/impl/ArrayListByteBuffer.kt b/src/main/kotlin/cn/tursom/core/buffer/impl/ArrayListByteBuffer.kt deleted file mode 100644 index ceeecb8..0000000 --- a/src/main/kotlin/cn/tursom/core/buffer/impl/ArrayListByteBuffer.kt +++ /dev/null @@ -1,8 +0,0 @@ -package cn.tursom.core.buffer.impl - -import cn.tursom.core.buffer.ByteBuffer -import cn.tursom.buffer.MultipleByteBuffer - -class ArrayListByteBuffer : MultipleByteBuffer, MutableList by ArrayList() { - override fun clear() = super.clear() -} \ No newline at end of file diff --git a/src/main/kotlin/cn/tursom/core/buffer/impl/ListByteBuffer.kt b/src/main/kotlin/cn/tursom/core/buffer/impl/ListByteBuffer.kt index cf28407..2822c5a 100644 --- a/src/main/kotlin/cn/tursom/core/buffer/impl/ListByteBuffer.kt +++ b/src/main/kotlin/cn/tursom/core/buffer/impl/ListByteBuffer.kt @@ -1,6 +1,59 @@ package cn.tursom.core.buffer.impl -import cn.tursom.core.buffer.ByteBuffer import cn.tursom.buffer.MultipleByteBuffer +import cn.tursom.core.buffer.ByteBuffer -class ListByteBuffer(bufferList: List) : MultipleByteBuffer, List by bufferList \ No newline at end of file +open class ListByteBuffer(val bufferList: List) : MultipleByteBuffer, List by bufferList { + private var readOperator = bufferList.firstOrNull() + private var writeOperator = bufferList.firstOrNull() + override val hasArray: Boolean get() = false + override val array: ByteArray + get() = throw UnsupportedOperationException() + override val capacity: Int + get() { + var capacity = 0 + bufferList.forEach { + capacity += it.capacity + } + return capacity + } + override val arrayOffset: Int get() = 0 + override var writePosition: Int = 0 + override var readPosition: Int = 0 + override val resized: Boolean get() = false + + override fun readBuffer(): java.nio.ByteBuffer = throw UnsupportedOperationException() + override fun writeBuffer(): java.nio.ByteBuffer = throw UnsupportedOperationException() + override fun slice(position: Int, size: Int, readPosition: Int, writePosition: Int): ByteBuffer = + throw UnsupportedOperationException() + + override fun resize(newSize: Int): Boolean = throw UnsupportedOperationException() + + fun updateRead() { + if (readOperator == null || readOperator!!.readable == 0) { + readOperator = bufferList[readPosition++] + } + } + + fun updateWrite() { + if (writeOperator == null || writeOperator!!.readable == 0) { + writeOperator = bufferList[writePosition++] + } + } + + override fun get(): Byte { + updateRead() + return readOperator!!.get() + } + override fun put(byte: Byte) { + TODO("Not yet implemented") + } + + override fun split(maxSize: Int): Array { + TODO("Not yet implemented") + } + + override fun readAllSize(): Int { + TODO("Not yet implemented") + } +} \ No newline at end of file