SQInteger JSON::escapeAndEncode()

in AzureSphereSquirrel/HLCore/json.cpp [962:1064]


SQInteger JSON::escapeAndEncode(HSQUIRRELVM vm, const SQChar *&data, SQInteger dataSize, SQChar *&jsonString, SQInteger &jsonStringStorageSize, SQInteger &jsonStringSize)
{
    // Pre-grow storage to account for '"dataAsString"' to reduce number of mallocs
    growStorage(jsonString, jsonStringStorageSize, jsonStringSize+2+dataSize);

    jsonString[jsonStringSize++] = '"';

    for(int i = 0; i < dataSize; ++i)
    {
        unsigned char character = data[i];

        // Determine if the character can be represented as 7-bit ASCII or is unicode
        if((character & 0x80) == 0x00)
        {
            // Character was 7-bit ASCII, search for escape sequences
            switch(character)
            {
                case '"': case '\\': case '/': case '\b': case '\f':
                case '\n': case '\r': case '\t': case '\0':
                    growStorage(jsonString, jsonStringStorageSize, jsonStringSize+2);
                    jsonString[jsonStringSize++] = '\\';
                    break;
                default:
                    growStorage(jsonString, jsonStringStorageSize, jsonStringSize+1);
                    jsonString[jsonStringSize++] = character;
                    continue;
            }

            switch(character)
            {
                case '"': jsonString[jsonStringSize++] = '"'; break;
                case '\\': jsonString[jsonStringSize++] = '\\'; break;
                case '/': jsonString[jsonStringSize++] = '/'; break;
                case '\b': jsonString[jsonStringSize++] = 'b'; break;
                case '\f': jsonString[jsonStringSize++] = 'f'; break;
                case '\n': jsonString[jsonStringSize++] = 'n'; break;
                case '\r': jsonString[jsonStringSize++] = 'r'; break;
                case '\t': jsonString[jsonStringSize++] = 't'; break;
                case '\0':
                    growStorage(jsonString, jsonStringStorageSize, jsonStringSize+5);
                    jsonString[jsonStringSize]   = 'u';
                    jsonString[jsonStringSize+1] = '0';
                    jsonString[jsonStringSize+2] = '0';
                    jsonString[jsonStringSize+3] = '0';
                    jsonString[jsonStringSize+4] = '0';
                    jsonStringSize += 5;
                    break;
                default: break;
            }                
        }
        else
        {
            // Character was unicode, determine which format and encode
            if((character & 0xE0) == 0xC0)
            {
                // 2-byte unicode
                if(i+1 >= dataSize)
                {
                    return sq_throwerror(vm, "Unable to escape data as unicode");
                }
                
                growStorage(jsonString, jsonStringStorageSize, jsonStringSize+2);
                jsonString[jsonStringSize] = character;
                jsonString[jsonStringSize+1] = data[++i];
                jsonStringSize += 2;
            }
            else if((character & 0xF0) == 0xE0)
            {
                // 3-byte unicode
                if(i+2 >= dataSize)
                {
                    return sq_throwerror(vm, "Unable to escape data as unicode");
                }
                
                growStorage(jsonString, jsonStringStorageSize, jsonStringSize+3);
                jsonString[jsonStringSize] = character;
                jsonString[jsonStringSize+1] = data[++i];
                jsonString[jsonStringSize+2] = data[++i];
                jsonStringSize += 3;
            }
            else if((character & 0xF8) == 0xF0)
            {
                // 4-byte unicode
                if(i+3 >= dataSize)
                {
                    return sq_throwerror(vm, "Unable to escape data as unicode");
                }
                
                growStorage(jsonString, jsonStringStorageSize, jsonStringSize+4);
                jsonString[jsonStringSize] = character;
                jsonString[jsonStringSize+1] = data[++i];
                jsonString[jsonStringSize+2] = data[++i];
                jsonString[jsonStringSize+3] = data[++i];
                jsonStringSize += 4;
            }
        }
    }

    growStorage(jsonString, jsonStringStorageSize, jsonStringSize+1);
    jsonString[jsonStringSize++] = '"';

    return SQ_OK;
}