in daffodil-io/src/main/scala/org/apache/daffodil/io/processors/charset/UTF8.scala [31:106]
protected override def decodeOneUnicodeChar(
dis: InputSourceDataInputStream,
finfo: FormatInfo
): Char = {
val byte1 = getByte(dis, 0)
if ((byte1 & 0x80) == 0) {
// 1 byte
byte1.toChar
} else if ((byte1 & 0xe0) == 0xc0) {
// 2 bytes
val byte2 = getByte(dis, 8)
checkContinuationByte(dis, byte2, 16)
checkOverlong(byte1, 0x1f, 0, 0, 16)
val cp = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f)
cp.toChar
} else if ((byte1 & 0xf0) == 0xe0) {
// 3 bytes
val byte2 = getByte(dis, 8)
checkContinuationByte(dis, byte2, 16)
val byte3 = getByte(dis, 16)
checkContinuationByte(dis, byte3, 24)
checkOverlong(byte1, 0x0f, byte2, 0x20, 24)
val cp = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f)
if (cp >= 0xd800 && cp <= 0xdfff) {
// out of valid range of Unicode (reserved for surrogate)
throw new BitsCharsetDecoderMalformedException(24)
}
cp.toChar
} else if ((byte1 & 0xf8) == 0xf0) {
// 4 bytes
val byte2 = getByte(dis, 8)
checkContinuationByte(dis, byte2, 16)
val byte3 = getByte(dis, 16)
checkContinuationByte(dis, byte3, 24)
val byte4 = getByte(dis, 24)
checkContinuationByte(dis, byte4, 32)
checkOverlong(byte1, 0x07, byte2, 0x30, 32)
val cp =
((byte1 & 0x0f) << 18) | ((byte2 & 0x3f) << 12) | ((byte3 & 0x3f) << 6) | (byte4 & 0x3f)
if (cp > 0x10ffff) {
// out of valid range of Unicode
throw new BitsCharsetDecoderMalformedException(32)
}
val high = Character.highSurrogate(cp)
setLowSurrogate(Character.lowSurrogate(cp))
high
} else if ((byte1 & 0xfc) == 0xf8) {
// 5 bytes, invalid, but we still need to read any continuation bits and
// mark them as all malformed
val byte2 = getByte(dis, 8)
checkContinuationByte(dis, byte2, 16)
val byte3 = getByte(dis, 16)
checkContinuationByte(dis, byte3, 24)
val byte4 = getByte(dis, 24)
checkContinuationByte(dis, byte4, 32)
val byte5 = getByte(dis, 32)
checkContinuationByte(dis, byte5, 40)
throw new BitsCharsetDecoderMalformedException(40)
} else if ((byte1 & 0xfe) == 0xfc) {
// 6 bytes, invalid, but we still need to read any continuation bits and
// mark them as all malformed
val byte2 = getByte(dis, 8)
checkContinuationByte(dis, byte2, 16)
val byte3 = getByte(dis, 16)
checkContinuationByte(dis, byte3, 24)
val byte4 = getByte(dis, 24)
checkContinuationByte(dis, byte4, 32)
val byte5 = getByte(dis, 32)
checkContinuationByte(dis, byte5, 40)
val byte6 = getByte(dis, 40)
checkContinuationByte(dis, byte6, 48)
throw new BitsCharsetDecoderMalformedException(48)
} else {
throw new BitsCharsetDecoderMalformedException(8)
}
}