decodeLastUtf8 function

_Tuple2<String?, int> decodeLastUtf8(
  1. List<int> slice
)

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);
}