@@ -22,6 +22,10 @@ public open class ByteBackedBitString protected constructor(
2222 override fun getOrNull (index : Int ): Boolean? =
2323 if (index in 0 .. size) get(bytes, index) else null
2424
25+ override fun countLeadingBits (fromIndex : Int , toIndex : Int , bit : Boolean ): Int {
26+ return countLeadingBits(bytes, fromIndex, toIndex - fromIndex, bit)
27+ }
28+
2529 override fun plus (bits : BitString ): BitString = toMutableBitString().plus(bits)
2630 override fun plus (bytes : ByteArray ): BitString = toMutableBitString().plus(bytes)
2731 override fun plus (bytes : ByteArray , bits : Int ): BitString = toMutableBitString().plus(bytes, bits)
@@ -84,6 +88,13 @@ public open class ByteBackedBitString protected constructor(
8488 }
8589 }
8690
91+ override fun copyInto (destination : MutableBitString , destinationOffset : Int , startIndex : Int , endIndex : Int ) {
92+ if (destination !is ByteBackedBitString ) {
93+ return super .copyInto(destination, destinationOffset, startIndex, endIndex)
94+ }
95+ bitsCopy(destination.bytes, destinationOffset, bytes, startIndex, endIndex - startIndex)
96+ }
97+
8798 override fun toString (): String = " x{${toHexString()} }"
8899
89100 override fun toHexString (): String {
@@ -218,3 +229,117 @@ private fun appendAugmentTag(data: ByteArray, bits: Int): ByteArray {
218229 return newData
219230 }
220231}
232+
233+ internal fun bitsCopy (dest : ByteArray , toIndex : Int , src : ByteArray , fromIndex : Int , bitCount : Int ) {
234+ if (bitCount <= 0 ) return
235+
236+ var srcOffset = fromIndex shr 3
237+ var destOffset = toIndex shr 3
238+ val fromOffset = fromIndex and 7
239+ val toOffset = toIndex and 7
240+
241+ var remainingBits = bitCount
242+ val bitCountTotal = bitCount + fromOffset
243+
244+ if (fromOffset == toOffset) {
245+ if (bitCountTotal < 8 ) {
246+ val mask = ((- 0x100 ushr bitCountTotal) and (0xff ushr toOffset))
247+ dest[destOffset] = ((dest[destOffset].toInt() and mask.inv ()) or (src[srcOffset].toInt() and mask)).toByte()
248+ return
249+ }
250+
251+ val bytesToCopy = bitCountTotal shr 3
252+ if (toOffset == 0 ) {
253+ src.copyInto(dest, destOffset, srcOffset, srcOffset + bytesToCopy)
254+ } else {
255+ val mask = (0xff ushr toOffset)
256+ dest[destOffset] = ((dest[destOffset].toInt() and mask.inv ()) or (src[srcOffset].toInt() and mask)).toByte()
257+ src.copyInto(dest, destOffset + 1 , srcOffset + 1 , srcOffset + bytesToCopy)
258+ }
259+
260+ if (bitCountTotal and 7 != 0 ) {
261+ val mask = (- 0x100 ushr (bitCountTotal and 7 ))
262+ dest[destOffset + bytesToCopy] =
263+ ((dest[destOffset + bytesToCopy].toInt() and mask.inv ()) or (src[srcOffset + bytesToCopy].toInt() and mask)).toByte()
264+ }
265+ } else {
266+ var bitsInAcc = toOffset
267+ var accumulator = if (bitsInAcc != 0 ) dest[destOffset].toLong() ushr (8 - bitsInAcc) else 0L
268+
269+ if (bitCountTotal < 8 ) {
270+ accumulator = accumulator shl remainingBits
271+ accumulator =
272+ accumulator or ((src[srcOffset].toLong() and (0xffL ushr fromOffset)) ushr (8 - bitCountTotal))
273+ bitsInAcc + = remainingBits
274+ } else {
275+ val leadingBits = 8 - fromOffset
276+ accumulator = (accumulator shl leadingBits)
277+ accumulator = accumulator or (src[srcOffset++ ].toLong() and (0xffL ushr fromOffset))
278+ bitsInAcc + = leadingBits
279+ remainingBits - = leadingBits
280+
281+ while (remainingBits >= 8 ) {
282+ accumulator = accumulator shl 8
283+ accumulator = accumulator or (src[srcOffset++ ].toLong() and 0xffL )
284+ dest[destOffset++ ] = (accumulator ushr bitsInAcc).toByte()
285+ remainingBits - = 8
286+ }
287+
288+ if (remainingBits > 0 ) {
289+ accumulator =
290+ (accumulator shl remainingBits) or ((src[srcOffset].toLong() and 0xff ) ushr (8 - remainingBits))
291+ bitsInAcc + = remainingBits
292+ }
293+ }
294+
295+ while (bitsInAcc >= 8 ) {
296+ bitsInAcc - = 8
297+ dest[destOffset++ ] = (accumulator ushr bitsInAcc).toByte()
298+ }
299+
300+ if (bitsInAcc > 0 ) {
301+ dest[destOffset] =
302+ ((dest[destOffset].toInt() and (0xff ushr bitsInAcc)) or (accumulator.toInt() shl (8 - bitsInAcc))).toByte()
303+ }
304+ }
305+ }
306+
307+ internal fun countLeadingBits (
308+ array : ByteArray ,
309+ offset : Int ,
310+ bitCount : Int ,
311+ bit : Boolean
312+ ): Int {
313+ if (bitCount == 0 ) return 0
314+
315+ val xorVal = if (bit) - 1 else 0
316+ var index = offset ushr 3
317+ val bitOffset = offset and 7
318+ var reminder = bitCount
319+
320+ if (bitOffset != 0 ) {
321+ val v = ((array[index++ ].toInt() and 0xFF ) xor xorVal) shl (24 + bitOffset)
322+ val c = v.countLeadingZeroBits()
323+ val remainingBits = 8 - bitOffset
324+ if (c < remainingBits || bitCount <= remainingBits) {
325+ return min(c, bitCount)
326+ }
327+ reminder - = remainingBits
328+ }
329+
330+ while (reminder >= 8 ) {
331+ val v = ((array[index++ ].toInt() xor xorVal) and 0xFF ) shl 24
332+ if (v != 0 ) {
333+ return bitCount - reminder + v.countLeadingZeroBits()
334+ }
335+ reminder - = 8
336+ }
337+
338+ if (reminder > 0 ) {
339+ val v = (((array[index].toInt() xor xorVal) and 0xFF ) shl 24 ).countLeadingZeroBits()
340+ if (v < reminder) {
341+ return bitCount - reminder + v
342+ }
343+ }
344+ return bitCount
345+ }
0 commit comments