HAPError HAPJSONUtilsUnescapeStringData()

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;
}