static S fastu_fromUtf8(byte[] data) { ret fastu_fromUtf8(data, 0, data.length); } static S fastu_fromUtf8(byte[] data, int i, int n) { char[] chars = new char[n]; int len = 0, offset = i; n += i; while (offset < n) { if (data[offset] >= 0) { // 0xxxxxxx - it is an ASCII char, so copy it exactly as it is chars[len] = (char) data[offset]; len++; offset++; } else { int uc = 0; if ((data[offset] & 0xE0) == 0xC0) { uc = (int) (data[offset] & 0x1F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; } else if ((data[offset] & 0xF0) == 0xE0) { uc = (int) (data[offset] & 0x0F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; } else if ((data[offset] & 0xF8) == 0xF0) { uc = (int) (data[offset] & 0x07); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; } else if ((data[offset] & 0xFC) == 0xF8) { uc = (int) (data[offset] & 0x03); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; } else if ((data[offset] & 0xFE) == 0xFC) { uc = (int) (data[offset] & 0x01); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; uc <<= 6; uc |= (int) (data[offset] & 0x3F); offset++; } len = fastu_fromUtf8_toChars(uc, chars, len); } } ret new S(chars, 0, len); } static int fastu_fromUtf8_toChars(int codePoint, char[] dst, int index) { if (codePoint < 0 || codePoint > Character.MAX_CODE_POINT) throw new IllegalArgumentException; if (codePoint < Character.MIN_SUPPLEMENTARY_CODE_POINT) { dst[index] = (char) codePoint; ret ++index; } int offset = codePoint - Character.MIN_SUPPLEMENTARY_CODE_POINT; dst[index + 1] = (char) ((offset & 0x3ff) + Character.MIN_LOW_SURROGATE); dst[index] = (char) ((offset >>> 10) + Character.MIN_HIGH_SURROGATE); ret index + 2; }