in core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java [493:789]
public long readFieldNameHashCodeUnquote() {
this.nameEscape = false;
int offset = this.offset, end = this.end;
final byte[] bytes = this.bytes;
int ch = this.ch;
this.nameBegin = offset - 1;
int first = ch;
long nameValue = 0;
_for:
for (int i = 0; offset <= end; ++i) {
switch (ch) {
case ' ':
case '\n':
case '\r':
case '\t':
case '\f':
case '\b':
case '.':
case '-':
case '+':
case '*':
case '/':
case '>':
case '<':
case '=':
case '!':
case '[':
case ']':
case '{':
case '}':
case '(':
case ')':
case ',':
case ':':
case '|':
case '&':
case EOI:
nameLength = i;
this.nameEnd = ch == EOI ? offset : offset - 1;
if (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
ch = offset == end ? EOI : (char) bytes[offset++];
}
break _for;
default:
break;
}
if (ch == '\\') {
nameEscape = true;
ch = (char) bytes[offset++];
switch (ch) {
case 'u': {
ch = hexDigit4(bytes, check3(offset, end));
offset += 4;
break;
}
case 'x': {
ch = char2(bytes[offset], bytes[offset + 1]);
offset += 2;
break;
}
case '\\':
case '"':
case '.':
case '-':
case '+':
case '*':
case '/':
case '>':
case '<':
case '=':
case '@':
case ':':
break;
default:
ch = char1(ch);
break;
}
}
if (ch < 0) {
switch ((ch & 0xFF) >> 4) {
case 12:
case 13: {
/* 110x xxxx 10xx xxxx*/
ch = char2_utf8(ch & 0xFF, bytes[offset++], offset);
break;
}
case 14: {
ch = char2_utf8(ch & 0xFF, bytes[offset], bytes[offset + 1], offset);
offset += 2;
break;
}
default:
if ((ch >> 3) == -2) {
int c2 = bytes[offset];
int c3 = bytes[offset + 1];
int c4 = bytes[offset + 2];
ch = ((ch << 18) ^
(c2 << 12) ^
(c3 << 6) ^
(c4 ^ (((byte) 0xF0 << 18) ^
((byte) 0x80 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
break;
}
/* 10xx xxxx, 1111 xxxx */
throw new JSONException("malformed input around byte " + offset);
}
}
if (ch > 0xFF || i >= 8 || (i == 0 && ch == 0)) {
nameValue = 0;
ch = first;
offset = this.nameBegin + 1;
break;
}
byte c = (byte) ch;
switch (i) {
case 0:
nameValue = c;
break;
case 1:
nameValue = (c << 8) + (nameValue & 0xFFL);
break;
case 2:
nameValue = (c << 16) + (nameValue & 0xFFFFL);
break;
case 3:
nameValue = (c << 24) + (nameValue & 0xFFFFFFL);
break;
case 4:
nameValue = (((long) c) << 32) + (nameValue & 0xFFFFFFFFL);
break;
case 5:
nameValue = (((long) c) << 40L) + (nameValue & 0xFFFFFFFFFFL);
break;
case 6:
nameValue = (((long) c) << 48L) + (nameValue & 0xFFFFFFFFFFFFL);
break;
case 7:
nameValue = (((long) c) << 56L) + (nameValue & 0xFFFFFFFFFFFFFFL);
break;
default:
break;
}
ch = offset == end ? EOI : bytes[offset++];
}
long hashCode;
if (nameValue != 0) {
hashCode = nameValue;
} else {
hashCode = Fnv.MAGIC_HASH_CODE;
_for:
for (int i = 0; ; ++i) {
if (ch == '\\') {
nameEscape = true;
ch = bytes[offset++];
switch (ch) {
case 'u': {
ch = hexDigit4(bytes, check3(offset, end));
offset += 4;
break;
}
case 'x': {
ch = char2(bytes[offset], bytes[offset + 1]);
offset += 2;
break;
}
case '\\':
case '"':
case '.':
case '-':
case '+':
case '*':
case '/':
case '>':
case '<':
case '=':
case '@':
case ':':
break;
default:
ch = char1(ch);
break;
}
hashCode ^= ch;
hashCode *= Fnv.MAGIC_PRIME;
ch = offset == end ? EOI : bytes[offset++];
continue;
}
switch (ch) {
case ' ':
case '\n':
case '\r':
case '\t':
case '\f':
case '\b':
case '.':
case '-':
case '+':
case '*':
case '/':
case '>':
case '<':
case '=':
case '!':
case '[':
case ']':
case '{':
case '}':
case '(':
case ')':
case ',':
case ':':
case EOI:
nameLength = i;
this.nameEnd = ch == EOI ? offset : offset - 1;
while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
ch = offset == end ? EOI : bytes[offset++];
}
break _for;
default:
break;
}
if (ch < 0) {
switch ((ch & 0xFF) >> 4) {
case 12:
case 13: {
/* 110x xxxx 10xx xxxx*/
ch = char2_utf8(ch & 0xFF, bytes[offset++], offset);
nameAscii = false;
break;
}
case 14: {
ch = char2_utf8(ch & 0xFF, bytes[offset], bytes[offset + 1], offset);
offset += 2;
nameAscii = false;
break;
}
default:
if ((ch >> 3) == -2) {
int c2 = bytes[offset];
int c3 = bytes[offset + 1];
int c4 = bytes[offset + 2];
ch = ((ch << 18) ^
(c2 << 12) ^
(c3 << 6) ^
(c4 ^ (((byte) 0xF0 << 18) ^
((byte) 0x80 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
offset += 3;
nameAscii = false;
break;
}
/* 10xx xxxx, 1111 xxxx */
throw new JSONException("malformed input around byte " + offset);
}
}
if (ch > 0xFFFF) {
int c0 = (ch >>> 10) + ('\uD800' - (0x010000 >>> 10)); // Character.highSurrogate(uc);
hashCode ^= c0;
hashCode *= Fnv.MAGIC_PRIME;
int c1 = (ch & 0x3ff) + '\uDC00'; // Character.lowSurrogate(uc);
hashCode ^= c1;
} else {
hashCode ^= ch;
}
hashCode *= Fnv.MAGIC_PRIME;
ch = offset == end ? EOI : bytes[offset++];
}
}
if (ch == ':') {
ch = offset == end ? EOI : (char) bytes[offset++];
while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
ch = offset == end ? EOI : bytes[offset++];
}
}
this.offset = offset;
this.ch = (char) ch;
return hashCode;
}