blob: 9ab368823bc42b8cc7665a7621c5790ae9aff7c0 [file] [log] [blame]
/*
* Copyright (C) 2018 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@file:JvmName("-Util")
package okio
import okio.internal.HEX_DIGIT_CHARS
import kotlin.jvm.JvmName
internal fun checkOffsetAndCount(size: Long, offset: Long, byteCount: Long) {
if (offset or byteCount < 0 || offset > size || size - offset < byteCount) {
throw ArrayIndexOutOfBoundsException("size=$size offset=$offset byteCount=$byteCount")
}
}
/* ktlint-disable no-multi-spaces indent */
internal fun Short.reverseBytes(): Short {
val i = toInt() and 0xffff
val reversed = (i and 0xff00 ushr 8) or
(i and 0x00ff shl 8)
return reversed.toShort()
}
internal fun Int.reverseBytes(): Int {
return (this and -0x1000000 ushr 24) or
(this and 0x00ff0000 ushr 8) or
(this and 0x0000ff00 shl 8) or
(this and 0x000000ff shl 24)
}
internal fun Long.reverseBytes(): Long {
return (this and -0x100000000000000L ushr 56) or
(this and 0x00ff000000000000L ushr 40) or
(this and 0x0000ff0000000000L ushr 24) or
(this and 0x000000ff00000000L ushr 8) or
(this and 0x00000000ff000000L shl 8) or
(this and 0x0000000000ff0000L shl 24) or
(this and 0x000000000000ff00L shl 40) or
(this and 0x00000000000000ffL shl 56)
}
/* ktlint-enable no-multi-spaces indent */
internal inline infix fun Int.leftRotate(bitCount: Int): Int {
return (this shl bitCount) or (this ushr (32 - bitCount))
}
internal inline infix fun Long.rightRotate(bitCount: Int): Long {
return (this ushr bitCount) or (this shl (64 - bitCount))
}
@Suppress("NOTHING_TO_INLINE") // Syntactic sugar.
internal inline infix fun Byte.shr(other: Int): Int = toInt() shr other
@Suppress("NOTHING_TO_INLINE") // Syntactic sugar.
internal inline infix fun Byte.shl(other: Int): Int = toInt() shl other
@Suppress("NOTHING_TO_INLINE") // Syntactic sugar.
internal inline infix fun Byte.and(other: Int): Int = toInt() and other
@Suppress("NOTHING_TO_INLINE") // Syntactic sugar.
internal inline infix fun Byte.and(other: Long): Long = toLong() and other
@Suppress("NOTHING_TO_INLINE") // Pending `kotlin.experimental.xor` becoming stable
internal inline infix fun Byte.xor(other: Byte): Byte = (toInt() xor other.toInt()).toByte()
@Suppress("NOTHING_TO_INLINE") // Syntactic sugar.
internal inline infix fun Int.and(other: Long): Long = toLong() and other
@Suppress("NOTHING_TO_INLINE") // Syntactic sugar.
internal inline fun minOf(a: Long, b: Int): Long = minOf(a, b.toLong())
@Suppress("NOTHING_TO_INLINE") // Syntactic sugar.
internal inline fun minOf(a: Int, b: Long): Long = minOf(a.toLong(), b)
internal fun arrayRangeEquals(
a: ByteArray,
aOffset: Int,
b: ByteArray,
bOffset: Int,
byteCount: Int
): Boolean {
for (i in 0 until byteCount) {
if (a[i + aOffset] != b[i + bOffset]) return false
}
return true
}
internal fun Byte.toHexString(): String {
val result = CharArray(2)
result[0] = HEX_DIGIT_CHARS[this shr 4 and 0xf]
result[1] = HEX_DIGIT_CHARS[this and 0xf] // ktlint-disable no-multi-spaces
return String(result)
}
internal fun Int.toHexString(): String {
if (this == 0) return "0" // Required as code below does not handle 0
val result = CharArray(8)
result[0] = HEX_DIGIT_CHARS[this shr 28 and 0xf]
result[1] = HEX_DIGIT_CHARS[this shr 24 and 0xf]
result[2] = HEX_DIGIT_CHARS[this shr 20 and 0xf]
result[3] = HEX_DIGIT_CHARS[this shr 16 and 0xf]
result[4] = HEX_DIGIT_CHARS[this shr 12 and 0xf]
result[5] = HEX_DIGIT_CHARS[this shr 8 and 0xf] // ktlint-disable no-multi-spaces
result[6] = HEX_DIGIT_CHARS[this shr 4 and 0xf] // ktlint-disable no-multi-spaces
result[7] = HEX_DIGIT_CHARS[this and 0xf] // ktlint-disable no-multi-spaces
// Find the first non-zero index
var i = 0
while (i < result.size) {
if (result[i] != '0') break
i++
}
return String(result, i, result.size - i)
}
internal fun Long.toHexString(): String {
if (this == 0L) return "0" // Required as code below does not handle 0
val result = CharArray(16)
result[ 0] = HEX_DIGIT_CHARS[(this shr 60 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[ 1] = HEX_DIGIT_CHARS[(this shr 56 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[ 2] = HEX_DIGIT_CHARS[(this shr 52 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[ 3] = HEX_DIGIT_CHARS[(this shr 48 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[ 4] = HEX_DIGIT_CHARS[(this shr 44 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[ 5] = HEX_DIGIT_CHARS[(this shr 40 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[ 6] = HEX_DIGIT_CHARS[(this shr 36 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[ 7] = HEX_DIGIT_CHARS[(this shr 32 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[ 8] = HEX_DIGIT_CHARS[(this shr 28 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[ 9] = HEX_DIGIT_CHARS[(this shr 24 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[10] = HEX_DIGIT_CHARS[(this shr 20 and 0xf).toInt()]
result[11] = HEX_DIGIT_CHARS[(this shr 16 and 0xf).toInt()]
result[12] = HEX_DIGIT_CHARS[(this shr 12 and 0xf).toInt()]
result[13] = HEX_DIGIT_CHARS[(this shr 8 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[14] = HEX_DIGIT_CHARS[(this shr 4 and 0xf).toInt()] // ktlint-disable no-multi-spaces
result[15] = HEX_DIGIT_CHARS[(this and 0xf).toInt()] // ktlint-disable no-multi-spaces
// Find the first non-zero index
var i = 0
while (i < result.size) {
if (result[i] != '0') break
i++
}
return String(result, i, result.size - i)
}