Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1140,8 +1140,8 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<

protected abstract fun Int.decodeDiff(): Int

private val buf = IntArray(7)
private var iBuf = 0
private var _count = 0
private var _word = 0L

override fun consumeProtected(input: Char) {
val code = input.code
Expand All @@ -1150,21 +1150,15 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<
throw MalformedEncodingException("Char[$input] is not a valid ${name()} character")
}

if (iBuf < 7) {
buf[iBuf++] = code + diff
// Append each character's 5 bits to the word
val word = _word shl 5 or (code + diff).toLong()

if (_count++ < 7) {
_word = word
return // Await more input
}

// Append each character's 5 bits to the word
var word: Long = buf[0].toLong()
word = word shl 5 or buf[1].toLong()
word = word shl 5 or buf[2].toLong()
word = word shl 5 or buf[3].toLong()
word = word shl 5 or buf[4].toLong()
word = word shl 5 or buf[5].toLong()
word = word shl 5 or buf[6].toLong()
word = word shl 5 or (code + diff).toLong()
iBuf = 0
_count = 0
_word = 0L

// For every 8 characters of input, 40 bits of output are accumulated. Emit 5 bytes.
_out.output((word shr 32).toByte())
Expand All @@ -1175,47 +1169,29 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<
}

override fun doFinalProtected() {
if (iBuf == 0) return buf.fill(0)
val count = _count
if (count == 0) return
var word = _word
_count = 0
_word = 0L

if (iBuf == 1) {
if (count == 1) {
// 5*1 = 5 bits. Truncated, fail.
iBuf = 0
buf.fill(0)
throw FeedBuffer.truncatedInputEncodingException(1)
}
if (iBuf == 3) {
// 5*3 = 15 bits. Truncated, fail.
iBuf = 0
buf.fill(0)
throw FeedBuffer.truncatedInputEncodingException(3)
}
if (iBuf == 6) {
// 5*6 = 30 bits. Truncated, fail.
iBuf = 0
buf.fill(0)
throw FeedBuffer.truncatedInputEncodingException(6)
}

// iBuf == 2, 4, 5 or 7
// Append each character's 5 bits to the word
var word: Long = buf[0].toLong()
word = word shl 5 or buf[1].toLong()
if (iBuf == 2) {
iBuf = 0
buf.fill(0)
if (count == 2) {
// 5*2 = 10 bits. Drop 2
word = word shr 2

// 8/8 = 1 byte
_out.output((word ).toByte())
return
}

word = word shl 5 or buf[2].toLong()
word = word shl 5 or buf[3].toLong()
if (iBuf == 4) {
iBuf = 0
buf.fill(0)
if (count == 3) {
// 5*3 = 15 bits. Truncated, fail.
throw FeedBuffer.truncatedInputEncodingException(3)
}
if (count == 4) {
// 5*4 = 20 bits. Drop 4
word = word shr 4

Expand All @@ -1224,11 +1200,7 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<
_out.output((word ).toByte())
return
}

word = word shl 5 or buf[4].toLong()
if (iBuf == 5) {
iBuf = 0
buf.fill(0)
if (count == 5) {
// 5*5 = 25 bits. Drop 1
word = word shr 1

Expand All @@ -1238,12 +1210,11 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<
_out.output((word ).toByte())
return
}

word = word shl 5 or buf[5].toLong()
word = word shl 5 or buf[6].toLong()
if (iBuf == 7) {
iBuf = 0
buf.fill(0)
if (count == 6) {
// 5*6 = 30 bits. Truncated, fail.
throw FeedBuffer.truncatedInputEncodingException(6)
}
if (count == 7) {
// 5*7 = 35 bits. Drop 3
word = word shr 3

Expand All @@ -1256,7 +1227,7 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<
}

// "Should" never make it here
error("Illegal configuration >> iBuf[$iBuf] - buf[${buf[0]}, ${buf[1]}, ${buf[2]}, ${buf[3]}, ${buf[4]}, ${buf[5]}, ${buf[6]}]")
error("Illegal configuration >> count[$count]")
}
}

Expand All @@ -1265,22 +1236,19 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<
protected abstract fun Encoder.OutFeed.output1(i: Int)
protected abstract fun Encoder.OutFeed.outputPadding(n: Int)

private val buf = ByteArray(4)
private var iBuf = 0
private var _count = 0
private var _word = 0L

final override fun consumeProtected(input: Byte) {
if (iBuf < 4) {
buf[iBuf++] = input
// Append each character's 8 bits to the word
val word = (_word shl 8) + input.toBits()

if (_count++ < 4) {
_word = word
return // Await more input
}

// Append each character's 8 bits to the word
var word: Long = buf[0].toBits()
word = (word shl 8) + buf[1].toBits()
word = (word shl 8) + buf[2].toBits()
word = (word shl 8) + buf[3].toBits()
word = (word shl 8) + input.toBits()
iBuf = 0
_count = 0
_word = 0L

// For every 5 bytes of input, 40 bits of output are accumulated. Emit 8 characters.
_out.output1(i = (word shr 35 and 0x1fL).toInt()) // 40-1*5 = 35
Expand All @@ -1294,38 +1262,30 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<
}

final override fun doFinalProtected() {
if (iBuf == 0) {
buf.fill(0)
val count = _count
if (count == 0) {
// Still call with 0 b/c Crockford uses to append its check symbol
return _out.outputPadding(n = 0)
}
val word = _word
_count = 0
_word = 0L

var word: Long = buf[0].toBits()
if (iBuf == 1) {
iBuf = 0
buf.fill(0)
if (count == 1) {
// 8*1 = 8 bits
_out.output1(i = (word shr 3 and 0x1fL).toInt()) // 8-1*5 = 3
_out.output1(i = (word shl 2 and 0x1fL).toInt()) // 5-3 = 2
return _out.outputPadding(n = 6)
}

word = (word shl 8) + buf[1].toBits()
if (iBuf == 2) {
iBuf = 0
buf.fill(0)
if (count == 2) {
// 8*2 = 16 bits
_out.output1(i = (word shr 11 and 0x1fL).toInt()) // 16-1*5 = 11
_out.output1(i = (word shr 6 and 0x1fL).toInt()) // 16-2*5 = 6
_out.output1(i = (word shr 1 and 0x1fL).toInt()) // 16-3*5 = 1
_out.output1(i = (word shl 4 and 0x1fL).toInt()) // 5-1 = 4
return _out.outputPadding(n = 4)
}

word = (word shl 8) + buf[2].toBits()
if (iBuf == 3) {
iBuf = 0
buf.fill(0)
if (count == 3) {
// 8*3 = 24 bits
_out.output1(i = (word shr 19 and 0x1fL).toInt()) // 24-1*5 = 19
_out.output1(i = (word shr 14 and 0x1fL).toInt()) // 24-2*5 = 14
Expand All @@ -1334,11 +1294,7 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<
_out.output1(i = (word shl 1 and 0x1fL).toInt()) // 5-4 = 1
return _out.outputPadding(n = 3)
}

word = (word shl 8) + buf[3].toBits()
if (iBuf == 4) {
iBuf = 0
buf.fill(0)
if (count == 4) {
// 8*4 = 32 bits
_out.output1(i = (word shr 27 and 0x1fL).toInt()) // 32-1*5 = 27
_out.output1(i = (word shr 22 and 0x1fL).toInt()) // 32-2*5 = 22
Expand All @@ -1351,7 +1307,7 @@ public sealed class Base32<C: EncoderDecoder.Config>(config: C): EncoderDecoder<
}

// "Should" never make it here
error("Illegal configuration >> iBuf[$iBuf] - buf[${buf[0]}, ${buf[1]}, ${buf[2]}, ${buf[3]}]")
error("Illegal configuration >> count[$count]")
}

private inline fun Byte.toBits(): Long = if (this < 0) this + 256L else toLong()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,8 @@ public class Base64: EncoderDecoder<Base64.Config> {

private inner class DecoderFeed(out: Decoder.OutFeed): Decoder<Config>.Feed(_out = out) {

private val buf = IntArray(3)
private var iBuf = 0
private var _count = 0
private var _word = 0

override fun consumeProtected(input: Char) {
val code = input.code
Expand Down Expand Up @@ -460,17 +460,15 @@ public class Base64: EncoderDecoder<Base64.Config> {
throw MalformedEncodingException("Char[$input] is not a valid $NAME character")
}

if (iBuf < 3) {
buf[iBuf++] = code + diff
// Append each character's 6 bits to the word
val word = _word shl 6 or (code + diff)

if (_count++ < 3) {
_word = word
return // Await more input
}

// Append each character's 6 bits to the word
var word = buf[0]
word = word shl 6 or buf[1]
word = word shl 6 or buf[2]
word = word shl 6 or (code + diff)
iBuf = 0
_count = 0
_word = 0

// For every 4 characters of input, 24 bits of output are accumulated. Emit 3 bytes.
_out.output((word shr 16).toByte())
Expand All @@ -479,32 +477,23 @@ public class Base64: EncoderDecoder<Base64.Config> {
}

override fun doFinalProtected() {
if (iBuf == 0) return buf.fill(0)
val count = _count
if (count == 0) return
var word = _word
_count = 0
_word = 0

if (iBuf == 1) {
iBuf = 0
buf.fill(0)
if (count == 1) {
// 1 character followed by "===". But 6 bits is a truncated byte, fail.
throw FeedBuffer.truncatedInputEncodingException(1)
}

// Append each character's 6 bits to the word
var word = buf[0]
word = word shl 6 or buf[1]

if (iBuf == 2) {
iBuf = 0
buf.fill(0)
if (count == 2) {
// 2 characters followed by "==". Emit 1 byte for 8 of those 12 bits.
word = word shl 12
_out.output((word shr 16).toByte())
return
}

word = word shl 6 or buf[2]
if (iBuf == 3) {
iBuf = 0
buf.fill(0)
if (count == 3) {
// 3 characters followed by "=". Emit 2 byte for 16 of those 18 bits.
word = word shl 6
_out.output((word shr 16).toByte())
Expand All @@ -513,7 +502,7 @@ public class Base64: EncoderDecoder<Base64.Config> {
}

// "Should" never make it here
error("Illegal configuration >> iBuf[$iBuf] - buf[${buf[0]}, ${buf[1]}, ${buf[2]}]")
error("Illegal configuration >> count[$count]")
}
}

Expand Down