diff --git a/include/rjp.h b/include/rjp.h index e6e98f2..a23b928 100644 --- a/include/rjp.h +++ b/include/rjp.h @@ -34,6 +34,10 @@ extern "C"{ #define RJP_float double #endif +//used with rjp_to_json +#define RJP_FORMAT_NONE 0 +#define RJP_FORMAT_PRETTY 1 + //type of data typedef enum RJP_type{ json_object = 0, @@ -190,7 +194,7 @@ size_t rjp_dump_object(const RJP_value* root, char* dest); //Convert RJP_array to json string size_t rjp_dump_array(const RJP_value* arr, char* dest); //Convert root rjp value into json string -char* rjp_to_json(const RJP_value* root); +char* rjp_to_json(const RJP_value* root, int pretty); #ifdef __cplusplus } diff --git a/include/strings.h b/include/strings.h index 46178a2..bfe43b2 100644 --- a/include/strings.h +++ b/include/strings.h @@ -27,6 +27,7 @@ char* irjp_parse_string(RJP_value* root, const char* str, int* inclen, int* len, size_t irjp_array_strlen(const RJP_value* arr); size_t irjp_object_strlen(const RJP_value* root); size_t irjp_value_strlen(const RJP_value* root); +size_t irjp_value_strlen_pretty(const RJP_value* root, int depth); void irjp_strcpy(RJP_string* dest, const RJP_string* src); #endif diff --git a/src/output.c b/src/output.c index 16784f6..6c433bf 100644 --- a/src/output.c +++ b/src/output.c @@ -66,6 +66,77 @@ static size_t irjp_write_value(char* dest, const RJP_value* val){ }; return ret; } +static size_t irjp_write_value_pretty(char* dest, const RJP_value* val, int depth); +static size_t irjp_dump_array_pretty(const RJP_value* arr, char* dest, int depth){ + const RJP_array* array = &arr->array; + const RJP_array_element* element_list = array->elements; + size_t pos = 2; + sprintf(dest, "[\n"); + for(;element_list;element_list = element_list->next){ + for(int i = 0;i < (depth+1);++i) + pos += sprintf(dest+pos, "\t"); + pos += irjp_write_value_pretty(dest+pos, &element_list->value, depth+1); + + if(element_list->next) + pos += sprintf(dest+pos, ","); + pos += sprintf(dest+pos, "\n"); + } + for(int i = 0;i < depth;++i) + pos += sprintf(dest+pos, "\t"); + pos += sprintf(dest+pos, "]"); + return pos; +} +static size_t irjp_dump_object_pretty(const RJP_value* root, char* dest, int depth){ + const RJP_object* root_obj = &root->object; + const RJP_object_member* member_list = root_obj->members; + size_t pos = 2; + sprintf(dest, "{\n"); + + for(;member_list;member_list = member_list->next){ + for(int i = 0;i < (depth+1);++i) + pos += sprintf(dest+pos, "\t"); + pos += sprintf(dest+pos, "\"%s\": ", member_list->name.value); + pos += irjp_write_value_pretty(dest+pos, &member_list->value, depth+1); + + if(member_list->next) + pos += sprintf(dest+pos, ","); + pos += sprintf(dest+pos, "\n"); + } + for(int i = 0;i < depth;++i) + pos += sprintf(dest+pos, "\t"); + pos += sprintf(dest+pos, "}"); + return pos; +} +static size_t irjp_write_value_pretty(char* dest, const RJP_value* val, int depth){ + size_t ret; + switch(val->type){ + case json_integer: + ret = sprintf(dest, "%" PRId64, val->integer); + break; + case json_dfloat: + ret = sprintf(dest, "%lf", val->dfloat); + break; + case json_boolean: + ret = sprintf(dest, val->boolean ? "true" : "false"); + break; + case json_null: + ret = sprintf(dest, "null"); + break; + case json_string:; + ret = sprintf(dest, "\"%s\"", val->string.value); + break; + case json_array: + ret = irjp_dump_array_pretty(val, dest, depth); + break; + case json_object: + ret = irjp_dump_object_pretty(val, dest, depth); + break; + default: + ret = 0; + break; + }; + return ret; +} size_t rjp_dump_array(const RJP_value* arr, char* dest){ const RJP_array* array = &arr->array; @@ -103,16 +174,19 @@ size_t rjp_dump_object(const RJP_value* root, char* dest){ return pos; } -char* rjp_to_json(const RJP_value* root){ +char* rjp_to_json(const RJP_value* root, int pretty){ if(!root) return NULL; - size_t len = irjp_value_strlen(root); + size_t len = pretty ? irjp_value_strlen_pretty(root, 0) : irjp_value_strlen(root); if(!len) return NULL; char* tmp = rjp_alloc(len + 1); tmp[len] = 0; - irjp_write_value(tmp, root); + if(pretty) + irjp_write_value_pretty(tmp, root, 0); + else + irjp_write_value(tmp, root); return tmp; } diff --git a/src/strings.c b/src/strings.c index 4ec82e5..ed9b7a5 100644 --- a/src/strings.c +++ b/src/strings.c @@ -302,33 +302,23 @@ size_t irjp_array_strlen(const RJP_value* arr){ const RJP_array* array = &arr->array; const RJP_array_element* element_list = array->elements; for(;element_list;element_list = element_list->next){ - switch(element_list->value.type){ - case json_integer: - count += snprintf(NULL, 0, "%" PRId64, element_list->value.integer); - break; - case json_dfloat: - count += snprintf(NULL, 0, "%lf", element_list->value.dfloat); - break; - case json_boolean: - count += element_list->value.boolean ? 4 : 5; - break; - case json_null: - count += 4; - break; - case json_string: - count += element_list->value.string.length; - break; - case json_array: - count += irjp_array_strlen(&element_list->value); - break; - case json_object: - count += irjp_object_strlen(&element_list->value); - break; - }; + count += irjp_value_strlen(&element_list->value); if(element_list->next) - ++count; - else - break; + ++count; //, + } + return count; +} +size_t irjp_array_strlen_pretty(const RJP_value* arr, int depth){ + size_t count = 3 + depth; //[\n\t] + ++depth; + const RJP_array* array = &arr->array; + const RJP_array_element* element_list = array->elements; + for(;element_list;element_list = element_list->next){ + count += irjp_value_strlen_pretty(&element_list->value, depth); + count += depth; //tabs + ++count; //newline + if(element_list->next) + ++count; //, } return count; } @@ -344,8 +334,23 @@ size_t irjp_object_strlen(const RJP_value* root){ count += irjp_value_strlen(&member_list->value); if(member_list->next) ++count; //, - else - break; + } + return count; +} +size_t irjp_object_strlen_pretty(const RJP_value* root, int depth){ + size_t count = 3 + depth; //{\n\t} + ++depth; + const RJP_object* root_obj = &root->object; + const RJP_object_member* member_list = root_obj->members; + for(;member_list;member_list = member_list->next){ + if(member_list->name.length == 0 || member_list->name.value[0] == 0) + return 0; + count += member_list->name.length + 4; //"":space + count += irjp_value_strlen_pretty(&member_list->value, depth); + count += depth; //tabs + ++count; //newline + if(member_list->next) + ++count; //, } return count; } @@ -370,3 +375,23 @@ size_t irjp_value_strlen(const RJP_value* root){ return 0; }; } +size_t irjp_value_strlen_pretty(const RJP_value* root, int depth){ + switch(root->type){ + case json_integer: + return snprintf(NULL, 0, "%" PRId64, root->integer); + case json_dfloat: + return snprintf(NULL, 0, "%lf", root->dfloat); + case json_boolean: + return root->boolean ? 4 : 5; //true, false + case json_null: + return 4; + case json_string: + return rjp_escape_strlen(root->string.value) + 2; //""; + case json_array: + return irjp_array_strlen_pretty(root, depth); + case json_object: + return irjp_object_strlen_pretty(root, depth); + default: + return 0; + }; +}