in HAP/HAPJSONUtils.c [511:646]
HAPError HAPJSONUtilsUnescapeStringData(char* bytes, size_t* numBytes) {
HAPPrecondition(bytes);
HAPPrecondition(numBytes);
HAPPrecondition(HAPUTF8IsValidData(bytes, *numBytes));
HAPError err;
// See RFC 7159, Section 7 "Strings" (http://www.rfc-editor.org/rfc/rfc7159.txt)
size_t i = 0;
size_t j = 0;
while (j < *numBytes) {
int x = bytes[j];
if (x != '\\') {
j++;
bytes[i] = (char) x;
i++;
} else {
j++;
if (*numBytes - j < 1) {
return kHAPError_InvalidData;
}
x = bytes[j];
if ((x == '"') || (x == '\\') || (x == '/')) {
j++;
bytes[i] = (char) x;
i++;
} else if (x == 'b') {
j++;
bytes[i] = '\b';
i++;
} else if (x == 'f') {
j++;
bytes[i] = '\f';
i++;
} else if (x == 'n') {
j++;
bytes[i] = '\n';
i++;
} else if (x == 'r') {
j++;
bytes[i] = '\r';
i++;
} else if (x == 't') {
j++;
bytes[i] = '\t';
i++;
} else if (x == 'u') {
j++;
if (*numBytes - j < 4) {
return kHAPError_InvalidData;
}
uint32_t codePoint = 0;
size_t n = 0;
do {
x = bytes[j];
if (('0' <= x) && (x <= '9')) {
j++;
x = x - '0';
} else if (('A' <= x) && (x <= 'F')) {
j++;
x = x - 'A' + 10;
} else if (('a' <= x) && (x <= 'f')) {
j++;
x = x - 'a' + 10;
} else {
return kHAPError_InvalidData;
}
HAPAssert((0 <= x) && (x <= 0xf));
codePoint = (codePoint << 4) | ((uint32_t) x);
n++;
} while (n < 4);
HAPAssert(UnicodeIsCodePoint(codePoint));
if (UnicodeIsLowSurrogateCodePoint(codePoint)) {
return kHAPError_InvalidData;
} else if (UnicodeIsHighSurrogateCodePoint(codePoint)) {
// surrogate pair
uint32_t highSurrogate = codePoint;
if (*numBytes - j < 6) {
return kHAPError_InvalidData;
}
x = bytes[j];
if (x != '\\') {
return kHAPError_InvalidData;
}
j++;
x = bytes[j];
if (x != 'u') {
return kHAPError_InvalidData;
}
j++;
codePoint = 0;
n = 0;
do {
x = bytes[j];
if (('0' <= x) && (x <= '9')) {
j++;
x = x - '0';
} else if (('A' <= x) && (x <= 'F')) {
j++;
x = x - 'A' + 10;
} else if (('a' <= x) && (x <= 'f')) {
j++;
x = x - 'a' + 10;
} else {
return kHAPError_InvalidData;
}
HAPAssert((0 <= x) && (x <= 0xf));
codePoint = (codePoint << 4) | ((uint32_t) x);
n++;
} while (n < 4);
HAPAssert(UnicodeIsCodePoint(codePoint));
if (!UnicodeIsLowSurrogateCodePoint(codePoint)) {
return kHAPError_InvalidData;
}
uint32_t lowSurrogate = codePoint;
codePoint = UnicodeGetScalarValueFromSurrogatePair(highSurrogate, lowSurrogate);
} else {
HAPAssert(UnicodeIsScalarValue(codePoint));
}
size_t numUTF8Bytes = 0;
err = UTF8EncodeCodePoint(codePoint, &bytes[i], j - i, &numUTF8Bytes);
HAPAssert(!err);
i += numUTF8Bytes;
} else {
return kHAPError_InvalidData;
}
}
HAPAssert(i <= j);
}
HAPAssert(j == *numBytes);
*numBytes = i;
return kHAPError_None;
}