in src/strings.c [257:394]
STRING_HANDLE STRING_new_JSON(const char* source)
{
STRING* result;
if (source == NULL)
{
/*Codes_SRS_STRING_02_011: [If source is NULL then STRING_new_JSON shall return NULL.] */
result = NULL;
LogError("invalid arg (NULL)");
}
else
{
size_t i;
size_t nControlCharacters = 0; /*counts how many characters are to be expanded from 1 character to \uxxxx (6 characters)*/
size_t nEscapeCharacters = 0;
size_t vlen = strlen(source);
for (i = 0; i < vlen; i++)
{
/*Codes_SRS_STRING_02_014: [If any character has the value outside [1...127] then STRING_new_JSON shall fail and return NULL.] */
if ((unsigned char)source[i] >= 128) /*this be a UNICODE character begin*/
{
break;
}
else
{
if (source[i] <= 0x1F)
{
nControlCharacters++;
}
else if (
(source[i] == '"') ||
(source[i] == '\\') ||
(source[i] == '/')
)
{
nEscapeCharacters++;
}
}
}
if (i < vlen)
{
result = NULL;
LogError("invalid character in input string");
}
else
{
//size_t malloc_len = vlen + 5 * nControlCharacters + nEscapeCharacters + 3;
size_t malloc_len = safe_multiply_size_t(5, nControlCharacters);
malloc_len = safe_add_size_t(malloc_len, vlen);
malloc_len = safe_add_size_t(malloc_len, nEscapeCharacters);
malloc_len = safe_add_size_t(malloc_len, 3);
if (malloc_len == SIZE_MAX)
{
result = NULL;
LogError("malloc len overflow");
}
else if ((result = (STRING*)malloc(sizeof(STRING))) == NULL)
{
/*Codes_SRS_STRING_02_021: [If the complete JSON representation cannot be produced, then STRING_new_JSON shall fail and return NULL.] */
LogError("malloc json failure");
}
else if ((result->s = (char*)malloc(malloc_len)) == NULL)
{
/*Codes_SRS_STRING_02_021: [If the complete JSON representation cannot be produced, then STRING_new_JSON shall fail and return NULL.] */
free(result);
result = NULL;
LogError("malloc failed");
}
else
{
size_t pos = 0;
/*Codes_SRS_STRING_02_012: [The string shall begin with the quote character.] */
result->s[pos++] = '"';
for (i = 0; i < vlen; i++)
{
if ((source[i] <= 0x1F) && ((pos + 6) <= malloc_len))
{
/*Codes_SRS_STRING_02_019: [If the character code is less than 0x20 then it shall be represented as \u00xx, where xx is the hex representation of the character code.]*/
result->s[pos++] = '\\';
result->s[pos++] = 'u';
result->s[pos++] = '0';
result->s[pos++] = '0';
result->s[pos++] = hexToASCII[(source[i] & 0xF0) >> 4]; /*high nibble*/
result->s[pos++] = hexToASCII[source[i] & 0x0F]; /*low nibble*/
}
else if ((source[i] == '"') && ((pos + 2) <= malloc_len))
{
/*Codes_SRS_STRING_02_016: [If the character is " (quote) then it shall be repsented as \".] */
result->s[pos++] = '\\';
result->s[pos++] = '"';
}
else if ((source[i] == '\\') && ((pos + 2) <= malloc_len))
{
/*Codes_SRS_STRING_02_017: [If the character is \ (backslash) then it shall represented as \\.] */
result->s[pos++] = '\\';
result->s[pos++] = '\\';
}
else if ((source[i] == '/') && ((pos + 2) <= malloc_len))
{
/*Codes_SRS_STRING_02_018: [If the character is / (slash) then it shall be represented as \/.] */
result->s[pos++] = '\\';
result->s[pos++] = '/';
}
else if (pos < malloc_len)
{
/*Codes_SRS_STRING_02_013: [The string shall copy the characters of source "as they are" (until the '\0' character) with the following exceptions:] */
result->s[pos++] = source[i];
}
else
{
free(result->s);
free(result);
result = NULL;
break;
}
}
if ((pos + 1) < malloc_len)
{
/*Codes_SRS_STRING_02_020: [The string shall end with " (quote).] */
result->s[pos++] = '"';
/*zero terminating it*/
result->s[pos] = '\0';
}
else
{
free(result->s);
free(result);
result = NULL;
}
}
}
}
return (STRING_HANDLE)result;
}