1 /*
2 * Copyright 2017 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package trebuchet.io
18
19 data class DataSlice(var buffer: ByteArray,
20 var startIndex: Int,
21 var endIndex: Int) {
22
23 companion object {
24 val EmptyBuffer = ByteArray(0)
25 }
26
27 constructor() : this(EmptyBuffer, 0, 0)
28 constructor(buffer: ByteArray) : this(buffer, 0, buffer.size)
29
30 @Suppress("NOTHING_TO_INLINE")
getnull31 inline operator fun get(i: Int): Byte = buffer[startIndex + i]
32
33 @Suppress("NOTHING_TO_INLINE")
34 inline fun slice(startIndex: Int, endIndex: Int = this.endIndex,
35 dest: DataSlice = DataSlice()): DataSlice {
36 dest.set(buffer, this.startIndex + startIndex, this.startIndex + endIndex)
37 return dest
38 }
39
40 inline val length: Int get() = endIndex - startIndex
41
setnull42 fun set(buffer: ByteArray, startIndex: Int, endIndex: Int) {
43 this.buffer = buffer
44 this.startIndex = startIndex
45 this.endIndex = endIndex
46 _hasCachedHashCode = false
47 }
48
equalsnull49 override fun equals(other: Any?): Boolean {
50 if (other === this) return true
51 if (other !is DataSlice) return false
52 if (length != other.length) return false
53 if (_hasCachedHashCode && other._hasCachedHashCode
54 && hashCode() != other.hashCode()) return false
55 var myIndex = startIndex
56 var otherIndex = other.startIndex
57 while (myIndex < endIndex) {
58 if (buffer[myIndex] != other.buffer[otherIndex]) {
59 return false
60 }
61 myIndex++
62 otherIndex++
63 }
64 return true
65 }
66
67 private var _cachedHashCode: Int = 1
68 private var _hasCachedHashCode: Boolean = false
hashCodenull69 override fun hashCode(): Int {
70 if (_hasCachedHashCode) return _cachedHashCode
71 var hash = 1
72 for (i in startIndex..endIndex-1) {
73 hash = 31 * hash + buffer[i].toInt()
74 }
75 _cachedHashCode = hash
76 _hasCachedHashCode = true
77 return hash
78 }
79
toStringnull80 override fun toString() = String(buffer, startIndex, length)
81
82 fun compact(): DataSlice {
83 if (length - buffer.size < 50) {
84 return this
85 }
86 return DataSlice(buffer.copyOfRange(startIndex, endIndex))
87 }
88 }
89
ByteArraynull90 fun ByteArray.asSlice(length: Int = this.size) = DataSlice(this, 0, length)
91 fun String.asSlice() = DataSlice(this.toByteArray())
92
93 fun DataSlice.asText(): CharSequence {
94 val data = this
95 return object : CharSequence {
96 override val length: Int get() = data.length
97
98 override fun get(index: Int): Char {
99 return data[index].toChar()
100 }
101
102 override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
103 return data.slice(startIndex, endIndex).asText()
104 }
105 }
106 }