mirror of
https://github.com/DaveGamble/cJSON.git
synced 2023-08-10 21:13:26 +03:00
Return output length from cJSON_PrintPreallocated
Adjust cJSON_PrintPreallocated() to return a size_t that provides the length of the output string. On error, it will return 0; so legacy behavior of interpreting its return as a boolean will still work as expected. In addition, a NULL buffer and zero length can be passed in to get the length of what would be the resulting string, so the needed buffer size is this plus 5 (extra that cJSON needs for printing).
This commit is contained in:
parent
203a0dec6f
commit
ed411f00e0
@ -300,7 +300,7 @@ It will allocate a string and print a JSON representation of the tree into it. O
|
|||||||
|
|
||||||
If you have a rough idea of how big your resulting string will be, you can use `cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)`. `fmt` is a boolean to turn formatting with whitespace on and off. `prebuffer` specifies the first buffer size to use for printing. `cJSON_Print` currently uses 256 bytes for its first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued.
|
If you have a rough idea of how big your resulting string will be, you can use `cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)`. `fmt` is a boolean to turn formatting with whitespace on and off. `prebuffer` specifies the first buffer size to use for printing. `cJSON_Print` currently uses 256 bytes for its first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued.
|
||||||
|
|
||||||
These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and its length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough.
|
These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a pointer to a buffer to which to print and the length of that buffer. If the length is reached, printing will fail and it returns `0`. In case of success, the length of the resulting string is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough. In addition, a NULL buffer pointer and length of zero can be provided to calculate and return the length of the resulting string without actually outputing to a buffer.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
|
303
cJSON.c
303
cJSON.c
@ -521,19 +521,6 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
|
|||||||
return newbuffer + p->offset;
|
return newbuffer + p->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate the new length of the string in a printbuffer and update the offset */
|
|
||||||
static void update_offset(printbuffer * const buffer)
|
|
||||||
{
|
|
||||||
const unsigned char *buffer_pointer = NULL;
|
|
||||||
if ((buffer == NULL) || (buffer->buffer == NULL))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
buffer_pointer = buffer->buffer + buffer->offset;
|
|
||||||
|
|
||||||
buffer->offset += strlen((const char*)buffer_pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* securely comparison of floating-point variables */
|
/* securely comparison of floating-point variables */
|
||||||
static cJSON_bool compare_double(double a, double b)
|
static cJSON_bool compare_double(double a, double b)
|
||||||
{
|
{
|
||||||
@ -581,26 +568,29 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reserve appropriate space in the output */
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
|
|
||||||
if (output_pointer == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
/* reserve appropriate space in the output */
|
||||||
}
|
output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
|
||||||
|
if (output_pointer == NULL)
|
||||||
/* copy the printed number to the output and replace locale
|
|
||||||
* dependent decimal point with '.' */
|
|
||||||
for (i = 0; i < ((size_t)length); i++)
|
|
||||||
{
|
|
||||||
if (number_buffer[i] == decimal_point)
|
|
||||||
{
|
{
|
||||||
output_pointer[i] = '.';
|
return false;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output_pointer[i] = number_buffer[i];
|
/* copy the printed number to the output and replace locale
|
||||||
|
* dependent decimal point with '.' */
|
||||||
|
for (i = 0; i < ((size_t)length); i++)
|
||||||
|
{
|
||||||
|
if (number_buffer[i] == decimal_point)
|
||||||
|
{
|
||||||
|
output_pointer[i] = '.';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output_pointer[i] = number_buffer[i];
|
||||||
|
}
|
||||||
|
output_pointer[i] = '\0';
|
||||||
}
|
}
|
||||||
output_pointer[i] = '\0';
|
|
||||||
|
|
||||||
output_buffer->offset += (size_t)length;
|
output_buffer->offset += (size_t)length;
|
||||||
|
|
||||||
@ -912,12 +902,16 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe
|
|||||||
/* empty string */
|
/* empty string */
|
||||||
if (input == NULL)
|
if (input == NULL)
|
||||||
{
|
{
|
||||||
output = ensure(output_buffer, sizeof("\"\""));
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
if (output == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
output = ensure(output_buffer, sizeof("\"\""));
|
||||||
|
if (output == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
strcpy((char*)output, "\"\"");
|
||||||
}
|
}
|
||||||
strcpy((char*)output, "\"\"");
|
output_buffer->offset += strlen("\"\"");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -948,6 +942,13 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe
|
|||||||
}
|
}
|
||||||
output_length = (size_t)(input_pointer - input) + escape_characters;
|
output_length = (size_t)(input_pointer - input) + escape_characters;
|
||||||
|
|
||||||
|
/* if just counting length, then do not need to actually copy string */
|
||||||
|
if (!output_buffer->buffer && !output_buffer->length)
|
||||||
|
{
|
||||||
|
output_buffer->offset += output_length + strlen("\"\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
output = ensure(output_buffer, output_length + sizeof("\"\""));
|
output = ensure(output_buffer, output_length + sizeof("\"\""));
|
||||||
if (output == NULL)
|
if (output == NULL)
|
||||||
{
|
{
|
||||||
@ -961,6 +962,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe
|
|||||||
memcpy(output + 1, input, output_length);
|
memcpy(output + 1, input, output_length);
|
||||||
output[output_length + 1] = '\"';
|
output[output_length + 1] = '\"';
|
||||||
output[output_length + 2] = '\0';
|
output[output_length + 2] = '\0';
|
||||||
|
output_buffer->offset += output_length + strlen("\"\"");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1012,6 +1014,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe
|
|||||||
}
|
}
|
||||||
output[output_length + 1] = '\"';
|
output[output_length + 1] = '\"';
|
||||||
output[output_length + 2] = '\0';
|
output[output_length + 2] = '\0';
|
||||||
|
output_buffer->offset += output_length + strlen("\"\"");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1203,7 +1206,6 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
|
|||||||
{
|
{
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
update_offset(buffer);
|
|
||||||
|
|
||||||
/* check if reallocate is available */
|
/* check if reallocate is available */
|
||||||
if (hooks->reallocate != NULL)
|
if (hooks->reallocate != NULL)
|
||||||
@ -1285,13 +1287,13 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
|
|||||||
return (char*)p.buffer;
|
return (char*)p.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
|
CJSON_PUBLIC(size_t) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
|
||||||
{
|
{
|
||||||
printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||||
|
|
||||||
if ((length < 0) || (buffer == NULL))
|
if (length < 0)
|
||||||
{
|
{
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.buffer = (unsigned char*)buffer;
|
p.buffer = (unsigned char*)buffer;
|
||||||
@ -1301,7 +1303,12 @@ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, cons
|
|||||||
p.format = format;
|
p.format = format;
|
||||||
p.hooks = global_hooks;
|
p.hooks = global_hooks;
|
||||||
|
|
||||||
return print_value(item, &p);
|
if (!print_value(item, &p))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parser core - when encountering text, process appropriately. */
|
/* Parser core - when encountering text, process appropriately. */
|
||||||
@ -1363,6 +1370,7 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf
|
|||||||
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
|
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
|
||||||
{
|
{
|
||||||
unsigned char *output = NULL;
|
unsigned char *output = NULL;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
if ((item == NULL) || (output_buffer == NULL))
|
if ((item == NULL) || (output_buffer == NULL))
|
||||||
{
|
{
|
||||||
@ -1372,52 +1380,68 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp
|
|||||||
switch ((item->type) & 0xFF)
|
switch ((item->type) & 0xFF)
|
||||||
{
|
{
|
||||||
case cJSON_NULL:
|
case cJSON_NULL:
|
||||||
output = ensure(output_buffer, 5);
|
length = strlen("null");
|
||||||
if (output == NULL)
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
{
|
{
|
||||||
return false;
|
output = ensure(output_buffer, length + sizeof(""));
|
||||||
|
if (output == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
strcpy((char*)output, "null");
|
||||||
}
|
}
|
||||||
strcpy((char*)output, "null");
|
output_buffer->offset += length;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case cJSON_False:
|
case cJSON_False:
|
||||||
output = ensure(output_buffer, 6);
|
length = strlen("false");
|
||||||
if (output == NULL)
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
{
|
{
|
||||||
return false;
|
output = ensure(output_buffer, length + sizeof(""));
|
||||||
|
if (output == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
strcpy((char*)output, "false");
|
||||||
}
|
}
|
||||||
strcpy((char*)output, "false");
|
output_buffer->offset += length;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case cJSON_True:
|
case cJSON_True:
|
||||||
output = ensure(output_buffer, 5);
|
length = strlen("true");
|
||||||
if (output == NULL)
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
{
|
{
|
||||||
return false;
|
output = ensure(output_buffer, length + sizeof(""));
|
||||||
|
if (output == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
strcpy((char*)output, "true");
|
||||||
}
|
}
|
||||||
strcpy((char*)output, "true");
|
output_buffer->offset += length;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case cJSON_Number:
|
case cJSON_Number:
|
||||||
return print_number(item, output_buffer);
|
return print_number(item, output_buffer);
|
||||||
|
|
||||||
case cJSON_Raw:
|
case cJSON_Raw:
|
||||||
{
|
|
||||||
size_t raw_length = 0;
|
|
||||||
if (item->valuestring == NULL)
|
if (item->valuestring == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_length = strlen(item->valuestring) + sizeof("");
|
length = strlen(item->valuestring);
|
||||||
output = ensure(output_buffer, raw_length);
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
if (output == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
output = ensure(output_buffer, length + sizeof(""));
|
||||||
|
if (output == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(output, item->valuestring, length + sizeof(""));
|
||||||
}
|
}
|
||||||
memcpy(output, item->valuestring, raw_length);
|
output_buffer->offset += length;
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
case cJSON_String:
|
case cJSON_String:
|
||||||
return print_string(item, output_buffer);
|
return print_string(item, output_buffer);
|
||||||
@ -1545,13 +1569,16 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp
|
|||||||
|
|
||||||
/* Compose the output array. */
|
/* Compose the output array. */
|
||||||
/* opening square bracket */
|
/* opening square bracket */
|
||||||
output_pointer = ensure(output_buffer, 1);
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
if (output_pointer == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
output_pointer = ensure(output_buffer, 1);
|
||||||
}
|
if (output_pointer == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*output_pointer = '[';
|
*output_pointer = '[';
|
||||||
|
}
|
||||||
output_buffer->offset++;
|
output_buffer->offset++;
|
||||||
output_buffer->depth++;
|
output_buffer->depth++;
|
||||||
|
|
||||||
@ -1561,33 +1588,40 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
update_offset(output_buffer);
|
|
||||||
if (current_element->next)
|
if (current_element->next)
|
||||||
{
|
{
|
||||||
length = (size_t) (output_buffer->format ? 2 : 1);
|
length = (size_t) (output_buffer->format ? 2 : 1);
|
||||||
output_pointer = ensure(output_buffer, length + 1);
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
if (output_pointer == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
output_pointer = ensure(output_buffer, length + sizeof(""));
|
||||||
|
if (output_pointer == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*output_pointer++ = ',';
|
||||||
|
if(output_buffer->format)
|
||||||
|
{
|
||||||
|
*output_pointer++ = ' ';
|
||||||
|
}
|
||||||
|
*output_pointer = '\0';
|
||||||
}
|
}
|
||||||
*output_pointer++ = ',';
|
|
||||||
if(output_buffer->format)
|
|
||||||
{
|
|
||||||
*output_pointer++ = ' ';
|
|
||||||
}
|
|
||||||
*output_pointer = '\0';
|
|
||||||
output_buffer->offset += length;
|
output_buffer->offset += length;
|
||||||
}
|
}
|
||||||
current_element = current_element->next;
|
current_element = current_element->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
output_pointer = ensure(output_buffer, 2);
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
if (output_pointer == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
output_pointer = ensure(output_buffer, 2);
|
||||||
|
if (output_pointer == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*output_pointer++ = ']';
|
||||||
|
*output_pointer = '\0';
|
||||||
}
|
}
|
||||||
*output_pointer++ = ']';
|
output_buffer->offset++;
|
||||||
*output_pointer = '\0';
|
|
||||||
output_buffer->depth--;
|
output_buffer->depth--;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1720,33 +1754,39 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out
|
|||||||
|
|
||||||
/* Compose the output: */
|
/* Compose the output: */
|
||||||
length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
|
length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
|
||||||
output_pointer = ensure(output_buffer, length + 1);
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
if (output_pointer == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
output_pointer = ensure(output_buffer, length + 1);
|
||||||
}
|
if (output_pointer == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*output_pointer++ = '{';
|
*output_pointer++ = '{';
|
||||||
output_buffer->depth++;
|
if (output_buffer->format)
|
||||||
if (output_buffer->format)
|
{
|
||||||
{
|
*output_pointer++ = '\n';
|
||||||
*output_pointer++ = '\n';
|
}
|
||||||
}
|
}
|
||||||
output_buffer->offset += length;
|
output_buffer->offset += length;
|
||||||
|
output_buffer->depth++;
|
||||||
|
|
||||||
while (current_item)
|
while (current_item)
|
||||||
{
|
{
|
||||||
if (output_buffer->format)
|
if (output_buffer->format)
|
||||||
{
|
{
|
||||||
size_t i;
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
output_pointer = ensure(output_buffer, output_buffer->depth);
|
|
||||||
if (output_pointer == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
size_t i;
|
||||||
}
|
output_pointer = ensure(output_buffer, output_buffer->depth);
|
||||||
for (i = 0; i < output_buffer->depth; i++)
|
if (output_pointer == NULL)
|
||||||
{
|
{
|
||||||
*output_pointer++ = '\t';
|
return false;
|
||||||
|
}
|
||||||
|
for (i = 0; i < output_buffer->depth; i++)
|
||||||
|
{
|
||||||
|
*output_pointer++ = '\t';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output_buffer->offset += output_buffer->depth;
|
output_buffer->offset += output_buffer->depth;
|
||||||
}
|
}
|
||||||
@ -1756,18 +1796,20 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
update_offset(output_buffer);
|
|
||||||
|
|
||||||
length = (size_t) (output_buffer->format ? 2 : 1);
|
length = (size_t) (output_buffer->format ? 2 : 1);
|
||||||
output_pointer = ensure(output_buffer, length);
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
if (output_pointer == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
output_pointer = ensure(output_buffer, length);
|
||||||
}
|
if (output_pointer == NULL)
|
||||||
*output_pointer++ = ':';
|
{
|
||||||
if (output_buffer->format)
|
return false;
|
||||||
{
|
}
|
||||||
*output_pointer++ = '\t';
|
*output_pointer++ = ':';
|
||||||
|
if (output_buffer->format)
|
||||||
|
{
|
||||||
|
*output_pointer++ = '\t';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output_buffer->offset += length;
|
output_buffer->offset += length;
|
||||||
|
|
||||||
@ -1776,45 +1818,52 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
update_offset(output_buffer);
|
|
||||||
|
|
||||||
/* print comma if not last */
|
/* print comma if not last */
|
||||||
length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
|
length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
|
||||||
output_pointer = ensure(output_buffer, length + 1);
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
if (output_pointer == NULL)
|
|
||||||
{
|
{
|
||||||
return false;
|
output_pointer = ensure(output_buffer, length + 1);
|
||||||
}
|
if (output_pointer == NULL)
|
||||||
if (current_item->next)
|
{
|
||||||
{
|
return false;
|
||||||
*output_pointer++ = ',';
|
}
|
||||||
}
|
if (current_item->next)
|
||||||
|
{
|
||||||
|
*output_pointer++ = ',';
|
||||||
|
}
|
||||||
|
|
||||||
if (output_buffer->format)
|
if (output_buffer->format)
|
||||||
{
|
{
|
||||||
*output_pointer++ = '\n';
|
*output_pointer++ = '\n';
|
||||||
|
}
|
||||||
|
*output_pointer = '\0';
|
||||||
}
|
}
|
||||||
*output_pointer = '\0';
|
|
||||||
output_buffer->offset += length;
|
output_buffer->offset += length;
|
||||||
|
|
||||||
current_item = current_item->next;
|
current_item = current_item->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
|
length = output_buffer->format ? output_buffer->depth : 1;
|
||||||
if (output_pointer == NULL)
|
if (output_buffer->buffer || output_buffer->length)
|
||||||
{
|
{
|
||||||
return false;
|
output_pointer = ensure(output_buffer, length + sizeof(""));
|
||||||
}
|
if (output_pointer == NULL)
|
||||||
if (output_buffer->format)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < (output_buffer->depth - 1); i++)
|
|
||||||
{
|
{
|
||||||
*output_pointer++ = '\t';
|
return false;
|
||||||
}
|
}
|
||||||
|
if (output_buffer->format)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < (output_buffer->depth - 1); i++)
|
||||||
|
{
|
||||||
|
*output_pointer++ = '\t';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*output_pointer++ = '}';
|
||||||
|
*output_pointer = '\0';
|
||||||
}
|
}
|
||||||
*output_pointer++ = '}';
|
output_buffer->offset += length;
|
||||||
*output_pointer = '\0';
|
|
||||||
output_buffer->depth--;
|
output_buffer->depth--;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
5
cJSON.h
5
cJSON.h
@ -158,9 +158,10 @@ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
|
|||||||
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
|
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
|
||||||
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
|
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
|
||||||
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
|
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
|
||||||
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
|
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns length of resulting string on success and 0 on failure. */
|
||||||
|
/* A NULL buffer and zero length can also be pass in to this function to calculate the resulting string length (excluding null terminator), so the needed buffer size is this plus 5 (see next line). */
|
||||||
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
|
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
|
CJSON_PUBLIC(size_t) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
|
||||||
/* Delete a cJSON entity and all subentities. */
|
/* Delete a cJSON entity and all subentities. */
|
||||||
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
|
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
|
||||||
|
|
||||||
|
15
test.c
15
test.c
@ -48,14 +48,15 @@ static int print_preallocated(cJSON *root)
|
|||||||
char *buf_fail = NULL;
|
char *buf_fail = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
size_t len_fail = 0;
|
size_t len_fail = 0;
|
||||||
|
size_t len_ret = 0;
|
||||||
|
|
||||||
/* formatted print */
|
/* formatted print */
|
||||||
out = cJSON_Print(root);
|
out = cJSON_Print(root);
|
||||||
|
|
||||||
/* create buffer to succeed */
|
/* create buffer to succeed */
|
||||||
/* the extra 5 bytes are because of inaccuracies when reserving memory */
|
/* the extra 5 bytes are because of inaccuracies when reserving memory */
|
||||||
len = strlen(out) + 5;
|
len = strlen(out);
|
||||||
buf = (char*)malloc(len);
|
buf = (char*)malloc(len + 5);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
{
|
{
|
||||||
printf("Failed to allocate memory.\n");
|
printf("Failed to allocate memory.\n");
|
||||||
@ -71,8 +72,16 @@ static int print_preallocated(cJSON *root)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
len_ret = cJSON_PrintPreallocated(root, NULL, 0, 1);
|
||||||
|
if (len_ret != len) {
|
||||||
|
printf("cJSON_PrintPreallocated length calculation failed!\n");
|
||||||
|
printf("cJSON_Print result length:%d\n", (int)(len));
|
||||||
|
printf("cJSON_PrintPreallocated length:%d\n", (int)(len_ret));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Print to buffer */
|
/* Print to buffer */
|
||||||
if (!cJSON_PrintPreallocated(root, buf, (int)len, 1)) {
|
if (!cJSON_PrintPreallocated(root, buf, (int)(len + 5), 1)) {
|
||||||
printf("cJSON_PrintPreallocated failed!\n");
|
printf("cJSON_PrintPreallocated failed!\n");
|
||||||
if (strcmp(out, buf) != 0) {
|
if (strcmp(out, buf) != 0) {
|
||||||
printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n");
|
printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user