int (CharSequence input, int start, int end) { int h1 = seed; int i = start; int len = 0; // This loop optimizes for pure ASCII. while (i + 4 <= end) { char c0 = input.charAt(i); char c1 = input.charAt(i + 1); char c2 = input.charAt(i + 2); char c3 = input.charAt(i + 3); if (c0 < 0x80 && c1 < 0x80 && c2 < 0x80 && c3 < 0x80) { int k1 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24); k1 = mixK1(k1); h1 = mixH1(h1, k1); i += 4; len += 4; } else { break; } } long buffer = 0; int shift = 0; for (; i < end; i++) { char c = input.charAt(i); if (c < 0x80) { buffer |= (long)c << shift; shift += 8; len++; } else if (c < 0x800) { buffer |= charToTwoUtf8Bytes(c) << shift; shift += 16; len += 2; } else if (c < Character.MIN_SURROGATE || c > Character.MAX_SURROGATE) { buffer |= charToThreeUtf8Bytes(c) << shift; shift += 24; len += 3; } else { int codePoint = Character.codePointAt(input, i); if (codePoint == c) { // not a valid code point; let the JDK handle invalid Unicode byte[] bytes = input.toString().getBytes(StandardCharsets.UTF_8); return hashBytes(bytes, 0, bytes.length); } i++; buffer |= codePointToFourUtf8Bytes(codePoint) << shift; len += 4; } if (shift >= 32) { int k1 = mixK1((int)buffer); h1 = mixH1(h1, k1); buffer >>>= 32; shift -= 32; } } int k1 = mixK1((int)buffer); h1 ^= k1; return fMix(h1, len); }