print_string_ptr: simplify code

This commit is contained in:
Max Bruckner 2017-02-20 13:03:51 +01:00
parent 88e38d042f
commit 0ca8587acc

97
cJSON.c
View File

@ -668,9 +668,9 @@ static unsigned char *print_string_ptr(const unsigned char * const input, printb
const unsigned char *input_pointer = NULL; const unsigned char *input_pointer = NULL;
unsigned char *output = NULL; unsigned char *output = NULL;
unsigned char *output_pointer = NULL; unsigned char *output_pointer = NULL;
size_t length = 0; size_t output_length = 0;
cjbool contains_special_char = false; /* numbers of additional characters needed for escaping */
unsigned char token = '\0'; size_t escape_characters = 0;
if (output_buffer == NULL) if (output_buffer == NULL)
{ {
@ -680,7 +680,7 @@ static unsigned char *print_string_ptr(const unsigned char * const input, printb
/* empty string */ /* empty string */
if (input == NULL) if (input == NULL)
{ {
output = ensure(output_buffer, 3); output = ensure(output_buffer, sizeof("\"\""));
if (output == NULL) if (output == NULL)
{ {
return NULL; return NULL;
@ -693,102 +693,83 @@ static unsigned char *print_string_ptr(const unsigned char * const input, printb
/* set "flag" to 1 if something needs to be escaped */ /* set "flag" to 1 if something needs to be escaped */
for (input_pointer = input; *input_pointer; input_pointer++) for (input_pointer = input; *input_pointer; input_pointer++)
{ {
contains_special_char |= (((*input_pointer > 0) && (*input_pointer < 32)) /* unprintable characters */ if (strchr("\"\\\b\f\n\r\t", *input_pointer))
|| (*input_pointer == '\"') /* double quote */
|| (*input_pointer == '\\')) /* backslash */
? 1
: 0;
}
/* no characters have to be escaped */
if (!contains_special_char)
{ {
length = (size_t)(input_pointer - input); /* one character escape sequence */
escape_characters++;
}
else if (*input_pointer < 32)
{
/* UTF-16 escape sequence uXXXX */
escape_characters += 5;
}
}
output_length = (size_t)(input_pointer - input) + escape_characters;
output = ensure(output_buffer, length + 3); output = ensure(output_buffer, output_length + sizeof("\"\""));
if (output == NULL) if (output == NULL)
{ {
return NULL; return NULL;
} }
output_pointer = output; /* no characters have to be escaped */
*output_pointer++ = '\"'; if (escape_characters == 0)
strcpy((char*)output_pointer, (const char*)input); {
output_pointer[length] = '\"'; output[0] = '\"';
output_pointer[length + 1] = '\0'; memcpy(output + 1, input, output_length);
output[output_length + 1] = '\"';
output[output_length + 2] = '\0';
return output; return output;
} }
input_pointer = input; output[0] = '\"';
/* calculate additional space that is needed for escaping */ output_pointer = output + 1;
while ((token = *input_pointer))
{
++length;
if (strchr("\"\\\b\f\n\r\t", token))
{
length++; /* +1 for the backslash */
}
else if (token < 32)
{
length += 5; /* +5 for \uXXXX */
}
input_pointer++;
}
output = ensure(output_buffer, length + 3);
if (output == NULL)
{
return NULL;
}
output_pointer = output;
input_pointer = input;
*output_pointer++ = '\"';
/* copy the string */ /* copy the string */
while (*input_pointer) for (input_pointer = input; *input_pointer != '\0'; input_pointer++, output_pointer++)
{ {
if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
{ {
/* normal character, copy */ /* normal character, copy */
*output_pointer++ = *input_pointer++; *output_pointer = *input_pointer;
} }
else else
{ {
/* character needs to be escaped */ /* character needs to be escaped */
*output_pointer++ = '\\'; *output_pointer++ = '\\';
switch (token = *input_pointer++) switch (*input_pointer)
{ {
case '\\': case '\\':
*output_pointer++ = '\\'; *output_pointer = '\\';
break; break;
case '\"': case '\"':
*output_pointer++ = '\"'; *output_pointer = '\"';
break; break;
case '\b': case '\b':
*output_pointer++ = 'b'; *output_pointer = 'b';
break; break;
case '\f': case '\f':
*output_pointer++ = 'f'; *output_pointer = 'f';
break; break;
case '\n': case '\n':
*output_pointer++ = 'n'; *output_pointer = 'n';
break; break;
case '\r': case '\r':
*output_pointer++ = 'r'; *output_pointer = 'r';
break; break;
case '\t': case '\t':
*output_pointer++ = 't'; *output_pointer = 't';
break; break;
default: default:
/* escape and print as unicode codepoint */ /* escape and print as unicode codepoint */
sprintf((char*)output_pointer, "u%04x", token); sprintf((char*)output_pointer, "u%04x", *input_pointer);
output_pointer += 5; output_pointer += 4;
break; break;
} }
} }
} }
*output_pointer++ = '\"'; output[output_length + 1] = '\"';
*output_pointer++ = '\0'; output[output_length + 2] = '\0';
return output; return output;
} }