|
|
@ -1,6 +1,6 @@ |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
Parson ( http://kgabis.github.com/parson/ )
|
|
|
|
Parson ( http://kgabis.github.com/parson/ )
|
|
|
|
Copyright (c) 2012 - 2014 Krzysztof Gabis |
|
|
|
Copyright (c) 2012 - 2015 Krzysztof Gabis |
|
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
|
|
of this software and associated documentation files (the "Software"), to deal |
|
|
|
of this software and associated documentation files (the "Software"), to deal |
|
|
@ -49,8 +49,6 @@ |
|
|
|
static JSON_Malloc_Function parson_malloc = malloc; |
|
|
|
static JSON_Malloc_Function parson_malloc = malloc; |
|
|
|
static JSON_Free_Function parson_free = free; |
|
|
|
static JSON_Free_Function parson_free = free; |
|
|
|
|
|
|
|
|
|
|
|
#define INDENT_STRLEN(level) ((level)*4) /* strlen(" ") */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */ |
|
|
|
#define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */ |
|
|
|
|
|
|
|
|
|
|
|
/* Type definitions */ |
|
|
|
/* Type definitions */ |
|
|
@ -91,9 +89,6 @@ static int num_bytes_in_utf8_sequence(unsigned char c); |
|
|
|
static int verify_utf8_sequence(const unsigned char *string, int *len); |
|
|
|
static int verify_utf8_sequence(const unsigned char *string, int *len); |
|
|
|
static int is_valid_utf8(const char *string, size_t string_len); |
|
|
|
static int is_valid_utf8(const char *string, size_t string_len); |
|
|
|
static int is_decimal(const char *string, size_t length); |
|
|
|
static int is_decimal(const char *string, size_t length); |
|
|
|
static size_t serialization_strlen(const char *string); |
|
|
|
|
|
|
|
static int print_indent(char *buf, int level); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* JSON Object */ |
|
|
|
/* JSON Object */ |
|
|
|
static JSON_Object * json_object_init(void); |
|
|
|
static JSON_Object * json_object_init(void); |
|
|
@ -125,9 +120,10 @@ static JSON_Value * parse_null_value(const char **string); |
|
|
|
static JSON_Value * parse_value(const char **string, size_t nesting); |
|
|
|
static JSON_Value * parse_value(const char **string, size_t nesting); |
|
|
|
|
|
|
|
|
|
|
|
/* Serialization */ |
|
|
|
/* Serialization */ |
|
|
|
static size_t json_serialization_size_r(const JSON_Value *value, char *buf, int level, int is_pretty); |
|
|
|
static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf); |
|
|
|
static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty); |
|
|
|
|
|
|
|
static int json_serialize_string(const char *string, char *buf); |
|
|
|
static int json_serialize_string(const char *string, char *buf); |
|
|
|
|
|
|
|
static int append_indent(char *buf, int level); |
|
|
|
|
|
|
|
static int append_string(char *buf, const char *string); |
|
|
|
|
|
|
|
|
|
|
|
/* Various */ |
|
|
|
/* Various */ |
|
|
|
static char * parson_strndup(const char *string, size_t n) { |
|
|
|
static char * parson_strndup(const char *string, size_t n) { |
|
|
@ -227,31 +223,6 @@ static int is_decimal(const char *string, size_t length) { |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static size_t serialization_strlen(const char *string) { |
|
|
|
|
|
|
|
size_t result = 0; |
|
|
|
|
|
|
|
size_t i = 0, len = strlen(string); |
|
|
|
|
|
|
|
for (i = 0; i < len; i++) { |
|
|
|
|
|
|
|
if (strchr("\"\\\b\f\n\r\t", string[i])) /* must be escaped */ |
|
|
|
|
|
|
|
result += 2; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
result += 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int print_indent(char *buf, int level) { |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
char *buf_start = buf; |
|
|
|
|
|
|
|
int written = -1; |
|
|
|
|
|
|
|
for (i = 0; i < level; i++) { |
|
|
|
|
|
|
|
written = sprintf(buf, " "); |
|
|
|
|
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return (int)(buf - buf_start); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char * read_file(const char * filename) { |
|
|
|
static char * read_file(const char * filename) { |
|
|
|
FILE *fp = fopen(filename, "r"); |
|
|
|
FILE *fp = fopen(filename, "r"); |
|
|
|
size_t file_size; |
|
|
|
size_t file_size; |
|
|
@ -741,77 +712,17 @@ static JSON_Value * parse_null_value(const char **string) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Serialization */ |
|
|
|
/* Serialization */ |
|
|
|
static size_t json_serialization_size_r(const JSON_Value *value, char *buf, int level, int is_pretty) { |
|
|
|
#define APPEND_STRING(str) do { written = append_string(buf, (str)); \ |
|
|
|
size_t result_size = 0; |
|
|
|
if (written < 0) { return -1; } \
|
|
|
|
const char *key = NULL; |
|
|
|
if (buf != NULL) { buf += written; } \
|
|
|
|
JSON_Value *temp_value = NULL; |
|
|
|
written_total += written; } while(0) |
|
|
|
JSON_Array *array = NULL; |
|
|
|
|
|
|
|
JSON_Object *object = NULL; |
|
|
|
|
|
|
|
size_t i = 0, count = 0; |
|
|
|
|
|
|
|
double num = 0.0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (json_value_get_type(value)) { |
|
|
|
|
|
|
|
case JSONArray: |
|
|
|
|
|
|
|
array = json_value_get_array(value); |
|
|
|
|
|
|
|
count = json_array_get_count(array); |
|
|
|
|
|
|
|
result_size += 2; /* [ and ] brackets */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (count > 0) { |
|
|
|
|
|
|
|
result_size += count - 1; /* , between items */ |
|
|
|
|
|
|
|
if (is_pretty) { |
|
|
|
|
|
|
|
result_size += count + 1; /* \n after every item and [ */ |
|
|
|
|
|
|
|
result_size += INDENT_STRLEN(level+1) * count; /* indent for every item */ |
|
|
|
|
|
|
|
result_size += INDENT_STRLEN(level); /* indent for closing ] */ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) { |
|
|
|
|
|
|
|
temp_value = json_array_get_value(array, i); |
|
|
|
|
|
|
|
result_size += json_serialization_size_r(temp_value, buf, level+1, is_pretty); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return result_size; |
|
|
|
|
|
|
|
case JSONObject: |
|
|
|
|
|
|
|
object = json_value_get_object(value); |
|
|
|
|
|
|
|
count = json_object_get_count(object); |
|
|
|
|
|
|
|
result_size += 2; /* { and } brackets */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (count > 0) { |
|
|
|
#define APPEND_INDENT(level) do { written = append_indent(buf, (level)); \ |
|
|
|
result_size += (2 * count) - 1; /* : between keys and values and , between items */ |
|
|
|
if (written < 0) { return -1; } \
|
|
|
|
if (is_pretty) { |
|
|
|
if (buf != NULL) { buf += written; } \
|
|
|
|
result_size += count + 1; /* \n after every item and after { */ |
|
|
|
written_total += written; } while(0) |
|
|
|
result_size += count; /* " " after every : */ |
|
|
|
|
|
|
|
result_size += INDENT_STRLEN(level+1) * count; /* indent for every kvp pair */ |
|
|
|
|
|
|
|
result_size += INDENT_STRLEN(level); /* indent for closing } */ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < count; i++) { |
|
|
|
|
|
|
|
key = json_object_get_name(object, i); |
|
|
|
|
|
|
|
result_size += serialization_strlen(key) + 2; /* string and quotes */ |
|
|
|
|
|
|
|
result_size += json_serialization_size_r(json_object_get_value(object, key), buf, level+1, is_pretty); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return result_size; |
|
|
|
|
|
|
|
case JSONString: |
|
|
|
|
|
|
|
return serialization_strlen(json_value_get_string(value)) + 2; /* string and quotes */ |
|
|
|
|
|
|
|
case JSONBoolean: |
|
|
|
|
|
|
|
if (json_value_get_boolean(value)) |
|
|
|
|
|
|
|
return 4; /* strlen("true"); */ |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
return 5; /* strlen("false"); */ |
|
|
|
|
|
|
|
case JSONNumber: |
|
|
|
|
|
|
|
num = json_value_get_number(value); |
|
|
|
|
|
|
|
if (num == ((double)(int)num) ) /* check if num is integer */ |
|
|
|
|
|
|
|
return (size_t)sprintf(buf, "%d", (int)num); |
|
|
|
|
|
|
|
return (size_t)sprintf(buf, DOUBLE_SERIALIZATION_FORMAT, num); |
|
|
|
|
|
|
|
case JSONNull: |
|
|
|
|
|
|
|
return 4; /* strlen("null"); */ |
|
|
|
|
|
|
|
case JSONError: |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty) |
|
|
|
static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf) |
|
|
|
{ |
|
|
|
{ |
|
|
|
const char *key = NULL, *string = NULL; |
|
|
|
const char *key = NULL, *string = NULL; |
|
|
|
JSON_Value *temp_value = NULL; |
|
|
|
JSON_Value *temp_value = NULL; |
|
|
@ -819,157 +730,101 @@ static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int le |
|
|
|
JSON_Object *object = NULL; |
|
|
|
JSON_Object *object = NULL; |
|
|
|
size_t i = 0, count = 0; |
|
|
|
size_t i = 0, count = 0; |
|
|
|
double num = 0.0; |
|
|
|
double num = 0.0; |
|
|
|
int written = -1; |
|
|
|
int written = -1, written_total = 0; |
|
|
|
char *buf_start = buf; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (json_value_get_type(value)) { |
|
|
|
switch (json_value_get_type(value)) { |
|
|
|
case JSONArray: |
|
|
|
case JSONArray: |
|
|
|
array = json_value_get_array(value); |
|
|
|
array = json_value_get_array(value); |
|
|
|
count = json_array_get_count(array); |
|
|
|
count = json_array_get_count(array); |
|
|
|
written = sprintf(buf, "["); |
|
|
|
APPEND_STRING("["); |
|
|
|
if (written < 0) |
|
|
|
if (count > 0 && is_pretty) |
|
|
|
return -1; |
|
|
|
APPEND_STRING("\n"); |
|
|
|
buf += written; |
|
|
|
|
|
|
|
if (count > 0 && is_pretty) { |
|
|
|
|
|
|
|
written = sprintf(buf, "\n"); |
|
|
|
|
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < count; i++) { |
|
|
|
for (i = 0; i < count; i++) { |
|
|
|
if (is_pretty) { |
|
|
|
if (is_pretty) |
|
|
|
written = print_indent(buf, level+1); |
|
|
|
APPEND_INDENT(level+1); |
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
temp_value = json_array_get_value(array, i); |
|
|
|
temp_value = json_array_get_value(array, i); |
|
|
|
written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty); |
|
|
|
written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); |
|
|
|
if (written < 0) |
|
|
|
if (written < 0) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
if (buf != NULL) |
|
|
|
buf += written; |
|
|
|
buf += written; |
|
|
|
if (i < (count - 1)) { |
|
|
|
written_total += written; |
|
|
|
written = sprintf(buf, ","); |
|
|
|
if (i < (count - 1)) |
|
|
|
if (written < 0) |
|
|
|
APPEND_STRING(","); |
|
|
|
return -1; |
|
|
|
if (is_pretty) |
|
|
|
buf += written; |
|
|
|
APPEND_STRING("\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
if (is_pretty) { |
|
|
|
if (count > 0 && is_pretty) |
|
|
|
written = sprintf(buf, "\n"); |
|
|
|
APPEND_INDENT(level); |
|
|
|
if (written < 0) |
|
|
|
APPEND_STRING("]"); |
|
|
|
return -1; |
|
|
|
return written_total; |
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (count > 0 && is_pretty) { |
|
|
|
|
|
|
|
written = print_indent(buf, level); |
|
|
|
|
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
written = sprintf(buf, "]"); |
|
|
|
|
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
return (int)(buf - buf_start); |
|
|
|
|
|
|
|
case JSONObject: |
|
|
|
case JSONObject: |
|
|
|
object = json_value_get_object(value); |
|
|
|
object = json_value_get_object(value); |
|
|
|
count = json_object_get_count(object); |
|
|
|
count = json_object_get_count(object); |
|
|
|
written = sprintf(buf, "{"); |
|
|
|
APPEND_STRING("{"); |
|
|
|
if (written < 0) |
|
|
|
if (count > 0 && is_pretty) |
|
|
|
return -1; |
|
|
|
APPEND_STRING("\n"); |
|
|
|
buf += written; |
|
|
|
|
|
|
|
if (count > 0 && is_pretty) { |
|
|
|
|
|
|
|
written = sprintf(buf, "\n"); |
|
|
|
|
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < count; i++) { |
|
|
|
for (i = 0; i < count; i++) { |
|
|
|
key = json_object_get_name(object, i); |
|
|
|
key = json_object_get_name(object, i); |
|
|
|
if (is_pretty) { |
|
|
|
if (is_pretty) |
|
|
|
written = print_indent(buf, level+1); |
|
|
|
APPEND_INDENT(level+1); |
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
written = json_serialize_string(key, buf); |
|
|
|
written = json_serialize_string(key, buf); |
|
|
|
if (written < 0) |
|
|
|
if (written < 0) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
if (buf != NULL) |
|
|
|
buf += written; |
|
|
|
buf += written; |
|
|
|
written = sprintf(buf, ":"); |
|
|
|
written_total += written; |
|
|
|
if (written < 0) |
|
|
|
APPEND_STRING(":"); |
|
|
|
return -1; |
|
|
|
if (is_pretty) |
|
|
|
buf += written; |
|
|
|
APPEND_STRING(" "); |
|
|
|
if (is_pretty) { |
|
|
|
|
|
|
|
written = sprintf(buf, " "); |
|
|
|
|
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
temp_value = json_object_get_value(object, key); |
|
|
|
temp_value = json_object_get_value(object, key); |
|
|
|
written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty); |
|
|
|
written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf); |
|
|
|
if (written < 0) |
|
|
|
if (written < 0) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
if (buf != NULL) |
|
|
|
buf += written; |
|
|
|
buf += written; |
|
|
|
if (i < (count - 1)) { |
|
|
|
written_total += written; |
|
|
|
written = sprintf(buf, ","); |
|
|
|
if (i < (count - 1)) |
|
|
|
if (written < 0) |
|
|
|
APPEND_STRING(","); |
|
|
|
return -1; |
|
|
|
if (is_pretty) |
|
|
|
buf += written; |
|
|
|
APPEND_STRING("\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
if (is_pretty) { |
|
|
|
if (count > 0 && is_pretty) |
|
|
|
written = sprintf(buf, "\n"); |
|
|
|
APPEND_INDENT(level); |
|
|
|
if (written < 0) |
|
|
|
APPEND_STRING("}"); |
|
|
|
return -1; |
|
|
|
return written_total; |
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (count > 0 && is_pretty) { |
|
|
|
|
|
|
|
written = print_indent(buf, level); |
|
|
|
|
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
written = sprintf(buf, "}"); |
|
|
|
|
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
return (int)(buf - buf_start); |
|
|
|
|
|
|
|
case JSONString: |
|
|
|
case JSONString: |
|
|
|
string = json_value_get_string(value); |
|
|
|
string = json_value_get_string(value); |
|
|
|
written = json_serialize_string(string, buf); |
|
|
|
written = json_serialize_string(string, buf); |
|
|
|
if (written < 0) |
|
|
|
if (written < 0) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
if (buf != NULL) |
|
|
|
buf += written; |
|
|
|
buf += written; |
|
|
|
return (int)(buf - buf_start); |
|
|
|
written_total += written; |
|
|
|
|
|
|
|
return written_total; |
|
|
|
case JSONBoolean: |
|
|
|
case JSONBoolean: |
|
|
|
if (json_value_get_boolean(value)) { |
|
|
|
if (json_value_get_boolean(value)) |
|
|
|
written = sprintf(buf, "true"); |
|
|
|
APPEND_STRING("true"); |
|
|
|
} else { |
|
|
|
else |
|
|
|
written = sprintf(buf, "false"); |
|
|
|
APPEND_STRING("false"); |
|
|
|
} |
|
|
|
return written_total; |
|
|
|
if (written < 0) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
return (int)(buf - buf_start); |
|
|
|
|
|
|
|
case JSONNumber: |
|
|
|
case JSONNumber: |
|
|
|
num = json_value_get_number(value); |
|
|
|
num = json_value_get_number(value); |
|
|
|
if (num == ((double)(int)num)) { /* check if num is integer */ |
|
|
|
if (buf != NULL) |
|
|
|
written = sprintf(buf, "%d", (int)num); |
|
|
|
num_buf = buf; |
|
|
|
} else { |
|
|
|
if (num == ((double)(int)num)) /* check if num is integer */ |
|
|
|
written = sprintf(buf, DOUBLE_SERIALIZATION_FORMAT, num); |
|
|
|
written = sprintf(num_buf, "%d", (int)num); |
|
|
|
} |
|
|
|
else |
|
|
|
|
|
|
|
written = sprintf(num_buf, DOUBLE_SERIALIZATION_FORMAT, num); |
|
|
|
if (written < 0) |
|
|
|
if (written < 0) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
if (buf != NULL) |
|
|
|
buf += written; |
|
|
|
buf += written; |
|
|
|
return (int)(buf - buf_start); |
|
|
|
written_total += written; |
|
|
|
|
|
|
|
return written_total; |
|
|
|
case JSONNull: |
|
|
|
case JSONNull: |
|
|
|
written = sprintf(buf, "null"); |
|
|
|
APPEND_STRING("null"); |
|
|
|
if (written < 0) |
|
|
|
return written_total; |
|
|
|
return -1; |
|
|
|
|
|
|
|
buf += written; |
|
|
|
|
|
|
|
return (int)(buf - buf_start); |
|
|
|
|
|
|
|
case JSONError: |
|
|
|
case JSONError: |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
default: |
|
|
|
default: |
|
|
@ -980,27 +835,50 @@ static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int le |
|
|
|
static int json_serialize_string(const char *string, char *buf) { |
|
|
|
static int json_serialize_string(const char *string, char *buf) { |
|
|
|
size_t i = 0, len = strlen(string); |
|
|
|
size_t i = 0, len = strlen(string); |
|
|
|
char c = '\0'; |
|
|
|
char c = '\0'; |
|
|
|
char *buf_start = buf; |
|
|
|
int written = -1, written_total = 0; |
|
|
|
buf[0] = '\"'; |
|
|
|
APPEND_STRING("\""); |
|
|
|
buf++; |
|
|
|
|
|
|
|
for (i = 0; i < len; i++) { |
|
|
|
for (i = 0; i < len; i++) { |
|
|
|
c = string[i]; |
|
|
|
c = string[i]; |
|
|
|
switch (c) { |
|
|
|
switch (c) { |
|
|
|
case '\"': buf[0] = '\\'; buf[1] = '\"'; buf += 2; break; |
|
|
|
case '\"': APPEND_STRING("\\\""); break; |
|
|
|
case '\\': buf[0] = '\\'; buf[1] = '\\'; buf += 2; break; |
|
|
|
case '\\': APPEND_STRING("\\\\"); break; |
|
|
|
case '\b': buf[0] = '\\'; buf[1] = 'b'; buf += 2; break; |
|
|
|
case '\b': APPEND_STRING("\\b"); break; |
|
|
|
case '\f': buf[0] = '\\'; buf[1] = 'f'; buf += 2; break; |
|
|
|
case '\f': APPEND_STRING("\\f"); break; |
|
|
|
case '\n': buf[0] = '\\'; buf[1] = 'n'; buf += 2; break; |
|
|
|
case '\n': APPEND_STRING("\\n"); break; |
|
|
|
case '\r': buf[0] = '\\'; buf[1] = 'r'; buf += 2; break; |
|
|
|
case '\r': APPEND_STRING("\\r"); break; |
|
|
|
case '\t': buf[0] = '\\'; buf[1] = 't'; buf += 2; break; |
|
|
|
case '\t': APPEND_STRING("\\t"); break; |
|
|
|
default: buf[0] = c; buf+= 1; break; |
|
|
|
default: |
|
|
|
|
|
|
|
if (buf != NULL) { |
|
|
|
|
|
|
|
buf[0] = c; |
|
|
|
|
|
|
|
buf += 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
written_total += 1; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
APPEND_STRING("\""); |
|
|
|
|
|
|
|
return written_total; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int append_indent(char *buf, int level) { |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
int written = -1, written_total = 0; |
|
|
|
|
|
|
|
for (i = 0; i < level; i++) { |
|
|
|
|
|
|
|
APPEND_STRING(" "); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return written_total; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int append_string(char *buf, const char *string) { |
|
|
|
|
|
|
|
if (buf == NULL) { |
|
|
|
|
|
|
|
return (int)strlen(string); |
|
|
|
} |
|
|
|
} |
|
|
|
buf[0] = '\"'; |
|
|
|
return sprintf(buf, "%s", string); |
|
|
|
buf++; |
|
|
|
|
|
|
|
return (int)(buf - buf_start); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef APPEND_STRING |
|
|
|
|
|
|
|
#undef APPEND_INDENT |
|
|
|
|
|
|
|
|
|
|
|
/* Parser API */ |
|
|
|
/* Parser API */ |
|
|
|
JSON_Value * json_parse_file(const char *filename) { |
|
|
|
JSON_Value * json_parse_file(const char *filename) { |
|
|
|
char *file_contents = read_file(filename); |
|
|
|
char *file_contents = read_file(filename); |
|
|
@ -1333,8 +1211,8 @@ JSON_Value * json_value_deep_copy(const JSON_Value *value) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
size_t json_serialization_size(const JSON_Value *value) { |
|
|
|
size_t json_serialization_size(const JSON_Value *value) { |
|
|
|
char buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ |
|
|
|
char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ |
|
|
|
return json_serialization_size_r(value, buf, 0, 0) + 1; |
|
|
|
return (size_t)(json_serialize_to_buffer_r(value, NULL, 0, 0, num_buf) + 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { |
|
|
|
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { |
|
|
@ -1343,7 +1221,7 @@ JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t |
|
|
|
if (buf_size_in_bytes < needed_size_in_bytes) { |
|
|
|
if (buf_size_in_bytes < needed_size_in_bytes) { |
|
|
|
return JSONFailure; |
|
|
|
return JSONFailure; |
|
|
|
} |
|
|
|
} |
|
|
|
written = json_serialize_to_buffer_r(value, buf, 0, 0); |
|
|
|
written = json_serialize_to_buffer_r(value, buf, 0, 0, NULL); |
|
|
|
if (written < 0) |
|
|
|
if (written < 0) |
|
|
|
return JSONFailure; |
|
|
|
return JSONFailure; |
|
|
|
return JSONSuccess; |
|
|
|
return JSONSuccess; |
|
|
@ -1384,17 +1262,16 @@ char * json_serialize_to_string(const JSON_Value *value) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
size_t json_serialization_size_pretty(const JSON_Value *value) { |
|
|
|
size_t json_serialization_size_pretty(const JSON_Value *value) { |
|
|
|
char buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ |
|
|
|
char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */ |
|
|
|
return json_serialization_size_r(value, buf, 0, 1) + 1; |
|
|
|
return (size_t)(json_serialize_to_buffer_r(value, NULL, 0, 1, num_buf) + 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { |
|
|
|
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) { |
|
|
|
int written = -1; |
|
|
|
int written = -1; |
|
|
|
size_t needed_size_in_bytes = json_serialization_size_pretty(value); |
|
|
|
size_t needed_size_in_bytes = json_serialization_size_pretty(value); |
|
|
|
if (buf_size_in_bytes < needed_size_in_bytes) { |
|
|
|
if (buf_size_in_bytes < needed_size_in_bytes) |
|
|
|
return JSONFailure; |
|
|
|
return JSONFailure; |
|
|
|
} |
|
|
|
written = json_serialize_to_buffer_r(value, buf, 0, 1, NULL); |
|
|
|
written = json_serialize_to_buffer_r(value, buf, 0, 1); |
|
|
|
|
|
|
|
if (written < 0) |
|
|
|
if (written < 0) |
|
|
|
return JSONFailure; |
|
|
|
return JSONFailure; |
|
|
|
return JSONSuccess; |
|
|
|
return JSONSuccess; |
|
|
@ -1866,8 +1743,7 @@ int json_boolean(const JSON_Value *value) { |
|
|
|
return json_value_get_boolean(value); |
|
|
|
return json_value_get_boolean(value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) |
|
|
|
void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) { |
|
|
|
{ |
|
|
|
|
|
|
|
parson_malloc = malloc_fun; |
|
|
|
parson_malloc = malloc_fun; |
|
|
|
parson_free = free_fun; |
|
|
|
parson_free = free_fun; |
|
|
|
} |
|
|
|
} |
|
|
|