decodeLastUtf8 function
UTF-8 decode a single Unicode scalar value from the end of a slice.
Implementation
_Tuple2<String?, int> decodeLastUtf8(List<int> slice) {
if (slice.isEmpty) return const _Tuple2(null, 0);
int i = slice.length - 1;
while (i >= 0 && (slice[i] & 0xC0) == 0x80) {
i--;
}
if (i < 0) return _Tuple2(null, slice.length);
int b = slice[i];
int n = slice.length - i;
if ((b & 0x80) == 0) {
// ASCII character.
return _Tuple2(String.fromCharCode(b), n);
} else if ((b & 0xE0) == 0xC0 && n >= 2) {
// 2-byte sequence.
int c = ((b & 0x1F) << 6) | (slice[i + 1] & 0x3F);
return _Tuple2(String.fromCharCode(c), n);
} else if ((b & 0xF0) == 0xE0 && n >= 3) {
// 3-byte sequence.
int c = ((b & 0x0F) << 12) | ((slice[i + 1] & 0x3F) << 6) | (slice[i + 2] & 0x3F);
if (c >= 0x0800 && c <= 0xD7FF || c >= 0xE000 && c <= 0xFFFF) {
return _Tuple2(String.fromCharCode(c), n);
}
} else if ((b & 0xF8) == 0xF0 && n >= 4) {
// 4-byte sequence.
int c = ((b & 0x07) << 18) |
((slice[i + 1] & 0x3F) << 12) |
((slice[i + 2] & 0x3F) << 6) |
(slice[i + 3] & 0x3F);
if (c >= 0x10000 && c <= 0x10FFFF) {
return _Tuple2(String.fromCharCode(c), n);
}
}
// Invalid sequence.
return _Tuple2(null, slice.length - i);
}