blob: 573d572d9e8691fd35e4f0ed7324ca5b1c1c1c68 [file] [log] [blame]
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines.experimental.io.internal
import java.nio.*
import java.util.concurrent.atomic.*
import kotlin.reflect.*
internal fun ByteBuffer.isEmpty() = !hasRemaining()
internal inline fun <reified Owner : Any> longUpdater(p: KProperty1<Owner, Long>): AtomicLongFieldUpdater<Owner> {
return AtomicLongFieldUpdater.newUpdater(Owner::class.java, p.name)
}
internal inline fun <reified Owner : Any> intUpdater(p: KProperty1<Owner, Int>): AtomicIntegerFieldUpdater<Owner> {
return AtomicIntegerFieldUpdater.newUpdater(Owner::class.java, p.name)
}
internal inline fun <reified Owner : Any, reified T> updater(p: KProperty1<Owner, T>): AtomicReferenceFieldUpdater<Owner, T> {
return AtomicReferenceFieldUpdater.newUpdater(Owner::class.java, T::class.java, p.name)
}
internal fun getIOIntProperty(name: String, default: Int): Int =
try { System.getProperty("kotlinx.coroutines.io.$name") }
catch (e: SecurityException) { null }
?.toIntOrNull() ?: default
@Suppress("LoopToCallChain")
internal fun ByteBuffer.indexOfPartial(sub: ByteBuffer): Int {
val subPosition = sub.position()
val subSize = sub.remaining()
val first = sub[subPosition]
val limit = limit()
outer@for (idx in position() until limit) {
if (get(idx) == first) {
for (j in 1 until subSize) {
if (idx + j == limit) break
if (get(idx + j) != sub.get(subPosition + j)) continue@outer
}
return idx - position()
}
}
return -1
}
@Suppress("LoopToCallChain")
internal fun ByteBuffer.startsWith(prefix: ByteBuffer, prefixSkip: Int = 0): Boolean {
val size = minOf(remaining(), prefix.remaining() - prefixSkip)
if (size <= 0) return false
val position = position()
val prefixPosition = prefix.position() + prefixSkip
for (i in 0 until size) {
if (get(position + i) != prefix.get(prefixPosition + i)) return false
}
return true
}
internal fun ByteBuffer.putAtMost(src: ByteBuffer, n: Int = src.remaining()): Int {
val rem = remaining()
val srcRem = src.remaining()
return when {
srcRem <= rem && srcRem <= n -> {
put(src)
srcRem
}
else -> {
val size = minOf(rem, srcRem, n)
for (idx in 1..size) {
put(src.get())
}
size
}
}
}
internal fun ByteBuffer.putLimited(src: ByteBuffer, limit: Int = limit()): Int {
return putAtMost(src, limit - src.position())
}
internal fun ByteArray.asByteBuffer(offset: Int = 0, length: Int = size): ByteBuffer = ByteBuffer.wrap(this, offset, length)