in tajo-common/src/main/java/org/apache/tajo/datum/protobuf/ProtobufJsonFormat.java [1102:1195]
static ByteString unescapeBytes(CharSequence input) throws InvalidEscapeSequence {
byte[] result = new byte[input.length()];
int pos = 0;
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c == '\\') {
if (i + 1 < input.length()) {
++i;
c = input.charAt(i);
if (TextUtils.isOctal(c)) {
// Octal escape.
int code = TextUtils.digitValue(c);
if ((i + 1 < input.length()) && TextUtils.isOctal(input.charAt(i + 1))) {
++i;
code = code * 8 + TextUtils.digitValue(input.charAt(i));
}
if ((i + 1 < input.length()) && TextUtils.isOctal(input.charAt(i + 1))) {
++i;
code = code * 8 + TextUtils.digitValue(input.charAt(i));
}
result[pos++] = (byte) code;
} else {
switch (c) {
case 'a':
result[pos++] = 0x07;
break;
case 'b':
result[pos++] = '\b';
break;
case 'f':
result[pos++] = '\f';
break;
case 'n':
result[pos++] = '\n';
break;
case 'r':
result[pos++] = '\r';
break;
case 't':
result[pos++] = '\t';
break;
case 'v':
result[pos++] = 0x0b;
break;
case '\\':
result[pos++] = '\\';
break;
case '\'':
result[pos++] = '\'';
break;
case '"':
result[pos++] = '\"';
break;
case 'x':
// hex escape
int code = 0;
if ((i + 1 < input.length()) && TextUtils.isHex(input.charAt(i + 1))) {
++i;
code = TextUtils.digitValue(input.charAt(i));
} else {
throw new InvalidEscapeSequence("Invalid escape sequence: '\\x' with no digits");
}
if ((i + 1 < input.length()) && TextUtils.isHex(input.charAt(i + 1))) {
++i;
code = code * 16 + TextUtils.digitValue(input.charAt(i));
}
result[pos++] = (byte) code;
break;
case 'u':
// UTF8 escape
code = (16 * 3 * TextUtils.digitValue(input.charAt(i+1))) +
(16 * 2 * TextUtils.digitValue(input.charAt(i+2))) +
(16 * TextUtils.digitValue(input.charAt(i+3))) +
TextUtils.digitValue(input.charAt(i+4));
i = i+4;
result[pos++] = (byte) code;
break;
default:
throw new InvalidEscapeSequence("Invalid escape sequence: '\\" + c
+ "'");
}
}
} else {
throw new InvalidEscapeSequence("Invalid escape sequence: '\\' at end of string.");
}
} else {
result[pos++] = (byte) c;
}
}
return ByteString.copyFrom(result, 0, pos);
}