From ff241e2a6f592c91f7a7c2f2f1e979dfff2e115f Mon Sep 17 00:00:00 2001 From: rexy712 Date: Sun, 19 Jan 2020 09:19:20 -0800 Subject: [PATCH] Successfully hid RJP_value implementation from API --- include/rjp.h | 61 +++++++++++----------------- include/rjp_internal.h | 38 +++++++++++++++++ src/array.c | 10 ++++- src/input.c | 33 +++++++-------- src/memory.c | 2 +- src/object.c | 59 +++++++++++++++++---------- src/output.c | 6 +-- src/rjp.c | 92 +++++++++++++++++++++++++++++++----------- 8 files changed, 197 insertions(+), 104 deletions(-) diff --git a/include/rjp.h b/include/rjp.h index 6c6b5f8..d362af1 100644 --- a/include/rjp.h +++ b/include/rjp.h @@ -65,42 +65,27 @@ typedef struct RJP_string{ }RJP_string; //Forward declarations -struct RJP_array_element; -typedef struct RJP_tree_node RJP_tree_node; - struct RJP_object_iterator_impl; typedef struct RJP_object_iterator{ struct RJP_object_iterator_impl* it; }RJP_object_iterator; -//Represents a json object -typedef struct RJP_object{ - struct RJP_tree_node* root; - int num_members; -}RJP_object; +struct RJP_array_iterator_impl; +typedef struct RJP_array_iterator{ + struct RJP_array_iterator_impl* it; +}RJP_array_iterator; -//Represents a json array -typedef struct RJP_array{ - struct RJP_array_element* elements; //linked list of elements - struct RJP_array_element* last; //final member of linked list - RJP_index num_elements; -}RJP_array; +typedef struct RJP_value RJP_value; -//Represents json data -//hold any json data type -typedef struct RJP_value{ +typedef struct RJP_vinit{ union{ RJP_int integer; RJP_float dfloat; char boolean; - struct RJP_object object; struct RJP_string string; - struct RJP_array array; }; - struct RJP_value* parent; //pointer to parent (either an array or object or NULL) - enum RJP_data_type type; //flag to determine active member of union -}RJP_value; - + enum RJP_data_type type; +}RJP_vinit; /* Generic operations @@ -110,24 +95,23 @@ RJP_value* rjp_parse(const char* str); //RJP_value* rjp_parse_chunked(const char* str, RJP_value* prev_chunk); //Initialize a root RJP_value to NULL -RJP_value* rjp_init_json(void); +RJP_value* rjp_new_value(void); //Initialize a root RJP_value to copy of value -RJP_value* rjp_init_json_as(RJP_value value); +RJP_value* rjp_new_value_as(RJP_vinit* val); //Free an RJP_value and all members/elements void rjp_free_value(RJP_value* root); //Deep copy RJP_value void rjp_copy_value(RJP_value* dest, const RJP_value* src); //set existing value -void rjp_set_value(RJP_value* dest, RJP_value value); +void rjp_set_value(RJP_value* dest, RJP_vinit* val); //initialize a RJP_value to the requested type and value -RJP_value rjp_integer(RJP_int i); -RJP_value rjp_boolean(char b); -RJP_value rjp_dfloat(RJP_float d); -RJP_value rjp_string(char* c, RJP_index len); -RJP_value rjp_string_copy(const char* c); -RJP_value rjp_null(void); -RJP_value rjp_object(void); -RJP_value rjp_array(void); +RJP_vinit rjp_integer(RJP_int i); +RJP_vinit rjp_boolean(char b); +RJP_vinit rjp_dfloat(RJP_float d); +RJP_vinit rjp_string(char* c, RJP_index len); +RJP_vinit rjp_null(void); +RJP_vinit rjp_object(void); +RJP_vinit rjp_array(void); //Return handle to parent of given value RJP_value* rjp_value_parent(const RJP_value* element); //Return type of value @@ -158,13 +142,16 @@ void rjp_free(void* dest); Object operations */ //add a member to a json object, allocating a copy of the key -RJP_value* rjp_add_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_value value); +RJP_value* rjp_new_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_vinit* value); +RJP_value* rjp_add_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_value* value); //add a member to a json object without allocation. key must be allocated using rjp_alloc/rjp_calloc -RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_value value); +RJP_value* rjp_new_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_vinit* value); +RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_value* value); RJP_value* rjp_remove_member_by_key(RJP_value* obj, const char* key); RJP_value* rjp_remove_member(RJP_value* obj, RJP_value* member); //add an element to a json array -RJP_value* rjp_add_element(RJP_value* dest, RJP_value value); +RJP_value* rjp_add_element(RJP_value* dest, RJP_value* value); +RJP_value* rjp_new_element(RJP_value* dest, RJP_vinit* value); //set existing object member's key void rjp_set_key(RJP_value* dest, const char* key, RJP_index keylen); //set existing object member's key without allocation. key must be allocated using rjp_alloc/rjp_calloc diff --git a/include/rjp_internal.h b/include/rjp_internal.h index 1b5bb18..34b5ad1 100644 --- a/include/rjp_internal.h +++ b/include/rjp_internal.h @@ -35,12 +35,50 @@ #endif // +//Represents a json object +typedef struct RJP_object{ + struct RJP_tree_node* root; + int num_members; +}RJP_object; + +//Represents a json array +typedef struct RJP_array{ + struct RJP_array_element* elements; //linked list of elements + struct RJP_array_element* last; //final member of linked list + RJP_index num_elements; +}RJP_array; + +//Represents json data +//hold any json data type +typedef struct RJP_value{ + union{ + RJP_int integer; + RJP_float dfloat; + char boolean; + struct RJP_object object; + struct RJP_string string; + struct RJP_array array; + }; + struct RJP_value* parent; //pointer to parent (either an array or object or NULL) + enum RJP_data_type type; //flag to determine active member of union +}RJP_value; typedef struct RJP_array_element{ struct RJP_value value; struct RJP_array_element* next; }RJP_array_element; +void irjp_copy_vinit_to_value(RJP_value* dest, RJP_vinit* src); void irjp_add_element(RJP_array* j); void irjp_add_member_no_alloc(RJP_object* j, char* str, size_t len); void irjp_delete_value(RJP_value* root); + +RJP_value irjp_integer(RJP_int i); +RJP_value irjp_boolean(char b); +RJP_value irjp_dfloat(RJP_float d); +RJP_value irjp_string(char* c, RJP_index len); +RJP_value irjp_string_copy(const char* c); +RJP_value irjp_null(void); +RJP_value irjp_object(void); +RJP_value irjp_array(void); + #endif diff --git a/src/array.c b/src/array.c index d4b8edb..17127ee 100644 --- a/src/array.c +++ b/src/array.c @@ -28,9 +28,15 @@ void irjp_add_element(RJP_array* j){ j->last = j->last->next; } } -RJP_value* rjp_add_element(RJP_value* dest, RJP_value value){ +RJP_value* rjp_add_element(RJP_value* dest, RJP_value* value){ irjp_add_element(&dest->array); - dest->array.last->value = value; + dest->array.last->value = *value; + dest->array.last->value.parent = dest; + return &dest->array.last->value; +} +RJP_value* rjp_new_element(RJP_value* dest, RJP_vinit* value){ + irjp_add_element(&dest->array); + irjp_copy_vinit_to_value(&dest->array.last->value, value); dest->array.last->value.parent = dest; return &dest->array.last->value; } diff --git a/src/input.c b/src/input.c index 3afd846..7682106 100644 --- a/src/input.c +++ b/src/input.c @@ -134,7 +134,8 @@ int irjp_handle_key(const char* str, RJP_parse_state* state){ syntax_error("Cannot have empty key name!", state); return -1; } - state->lastadded = rjp_add_member_no_alloc(state->curr, new_string, keylen, (RJP_value){0}); + RJP_value nil = irjp_null(); + state->lastadded = rjp_add_member_no_alloc(state->curr, new_string, keylen, &nil); *state->target = rjp_json_target_colon; return inclen+2; //end of this object (object is empty) @@ -195,11 +196,11 @@ int irjp_handle_value(const char* str, RJP_parse_state* state){ char c = *str; if(c == '{'){ if(!state->root){ - state->root = irjp_add_value(NULL, NULL, rjp_object()); + state->root = irjp_add_value(NULL, NULL, irjp_object()); state->curr = state->root; *state->target = rjp_json_target_key; }else{ - state->curr = irjp_add_value(state->curr, state->lastadded, rjp_object()); + state->curr = irjp_add_value(state->curr, state->lastadded, irjp_object()); *state->target = rjp_json_target_comma; ++state->target; *state->target = rjp_json_target_key; @@ -208,11 +209,11 @@ int irjp_handle_value(const char* str, RJP_parse_state* state){ } else if(c == '['){ if(!state->root){ - state->root = irjp_add_value(NULL, NULL, rjp_array()); + state->root = irjp_add_value(NULL, NULL, irjp_array()); state->curr = state->root; }else{ - state->curr = irjp_add_value(state->curr, state->lastadded, rjp_array()); + state->curr = irjp_add_value(state->curr, state->lastadded, irjp_array()); } return 1; } @@ -232,7 +233,7 @@ int irjp_handle_value(const char* str, RJP_parse_state* state){ return -1; } } - irjp_add_value(state->curr, state->lastadded, rjp_string(new_string, vallen)); + irjp_add_value(state->curr, state->lastadded, irjp_string(new_string, vallen)); *state->target = rjp_json_target_comma; return inclen+2; } @@ -264,15 +265,15 @@ int irjp_handle_value(const char* str, RJP_parse_state* state){ } if(floating){ if(!state->root){ - state->root = state->curr = irjp_add_value(NULL, NULL, rjp_dfloat(strtod(str, NULL))); + state->root = state->curr = irjp_add_value(NULL, NULL, irjp_dfloat(strtod(str, NULL))); }else{ - irjp_add_value(state->curr, state->lastadded, rjp_dfloat(strtod(str, NULL))); + irjp_add_value(state->curr, state->lastadded, irjp_dfloat(strtod(str, NULL))); } }else{ if(!state->root){ - state->root = state->curr = irjp_add_value(NULL, NULL, rjp_integer(strtoll(str, NULL, 10))); + state->root = state->curr = irjp_add_value(NULL, NULL, irjp_integer(strtoll(str, NULL, 10))); }else{ - irjp_add_value(state->curr, state->lastadded, rjp_integer(strtoll(str, NULL, 10))); + irjp_add_value(state->curr, state->lastadded, irjp_integer(strtoll(str, NULL, 10))); } } state->column += numlen; @@ -282,30 +283,30 @@ int irjp_handle_value(const char* str, RJP_parse_state* state){ else if(!strncmp(str, "true", 4)){ if(!state->curr){ *state->target = rjp_json_target_none; - state->root = state->curr = irjp_add_value(state->curr, NULL, rjp_boolean(1)); + state->root = state->curr = irjp_add_value(state->curr, NULL, irjp_boolean(1)); }else{ *state->target = rjp_json_target_comma; - irjp_add_value(state->curr, state->lastadded, rjp_boolean(1)); + irjp_add_value(state->curr, state->lastadded, irjp_boolean(1)); } state->column += 3; return 4; }else if(!strncmp(str, "false", 5)){ if(!state->curr){ *state->target = rjp_json_target_none; - state->root = state->curr = irjp_add_value(state->curr, NULL, rjp_boolean(0)); + state->root = state->curr = irjp_add_value(state->curr, NULL, irjp_boolean(0)); }else{ *state->target = rjp_json_target_comma; - irjp_add_value(state->curr, state->lastadded, rjp_boolean(0)); + irjp_add_value(state->curr, state->lastadded, irjp_boolean(0)); } state->column += 4; return 5; }else if(!strncmp(str, "null", 4)){ if(!state->curr){ *state->target = rjp_json_target_none; - state->root = state->curr = irjp_add_value(state->curr, NULL, rjp_null()); + state->root = state->curr = irjp_add_value(state->curr, NULL, irjp_null()); }else{ *state->target = rjp_json_target_comma; - irjp_add_value(state->curr, state->lastadded, rjp_null()); + irjp_add_value(state->curr, state->lastadded, irjp_null()); } state->column += 3; return 4; diff --git a/src/memory.c b/src/memory.c index e1505fe..23d7e21 100644 --- a/src/memory.c +++ b/src/memory.c @@ -41,7 +41,7 @@ static void irjp_copy_array(RJP_value* dest, const RJP_value* src){ for(RJP_value* curr = rjp_get_element(src);curr;curr = rjp_next_element(curr)){ RJP_value copy_mem; rjp_copy_value(©_mem, curr); - rjp_add_element(dest, copy_mem); + rjp_add_element(dest, ©_mem); } } diff --git a/src/object.c b/src/object.c index 3c2dfe6..967f3a9 100644 --- a/src/object.c +++ b/src/object.c @@ -125,36 +125,51 @@ void irjp_copy_object(RJP_value* dest, const RJP_value* src){ void irjp_delete_object(RJP_value* obj){ irjp_free_tree(obj->object.root); } -RJP_value* rjp_add_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_value value){ +static void irjp_copy_init_member_string(RJP_object_member* mem, const char* key, RJP_index keylen){ if(!keylen) keylen = strlen(key); + mem->name.value = rjp_alloc(keylen+1); + strncpy(mem->name.value, key, keylen); + mem->name.value[keylen] = 0; + mem->name.length = keylen; +} +static void irjp_init_member_string(RJP_object_member* mem, char* key, RJP_index keylen){ + if(!keylen) + keylen = strlen(key); + mem->name.value = key; + mem->name.length = keylen; +} +static RJP_value* irjp_add_member_impl(RJP_value* dest, RJP_object_member* mem){ ++dest->object.num_members; - RJP_object_member mem; - mem.name.value = rjp_alloc(keylen+1); - strncpy(mem.name.value, key, keylen); - mem.name.value[keylen] = 0; - mem.name.length = keylen; - mem.value = value; - mem.value.parent = dest; - + mem->value.parent = dest; int status; RJP_value* retval; - dest->object.root = irjp_tree_insert_value(dest->object.root, &mem, &retval, &status); + dest->object.root = irjp_tree_insert_value(dest->object.root, mem, &retval, &status); return retval; } -RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_value value){ - if(!keylen) - keylen = strlen(key); +RJP_value* rjp_new_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_vinit* value){ RJP_object_member mem; - mem.name.value = key; - mem.name.length = keylen; - mem.value = value; - mem.value.parent = dest; - - int status; - RJP_value* retval; - dest->object.root = irjp_tree_insert_value(dest->object.root, &mem, &retval, &status); - return retval; + irjp_copy_vinit_to_value(&mem.value, value); + irjp_copy_init_member_string(&mem, key, keylen); + return irjp_add_member_impl(dest, &mem); +} +RJP_value* rjp_add_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_value* value){ + RJP_object_member mem; + mem.value = *value; + irjp_copy_init_member_string(&mem, key, keylen); + return irjp_add_member_impl(dest, &mem); +} +RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_value* value){ + RJP_object_member mem; + mem.value = *value; + irjp_init_member_string(&mem, key, keylen); + return irjp_add_member_impl(dest, &mem); +} +RJP_value* rjp_new_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_vinit* value){ + RJP_object_member mem; + irjp_copy_vinit_to_value(&mem.value, value); + irjp_init_member_string(&mem, key, keylen); + return irjp_add_member_impl(dest, &mem); } RJP_value* rjp_remove_member_by_key(RJP_value* obj, const char* key){ int status; diff --git a/src/output.c b/src/output.c index 57ef628..47456f7 100644 --- a/src/output.c +++ b/src/output.c @@ -28,13 +28,13 @@ #include //strlen #include //sprintf -RJP_value* rjp_init_json(void){ +RJP_value* rjp_new_value(void){ RJP_value* ret = rjp_calloc(1, sizeof(RJP_value)); return ret; } -RJP_value* rjp_init_json_as(RJP_value value){ +RJP_value* rjp_new_value_as(RJP_vinit* value){ RJP_value* ret = rjp_alloc(sizeof(RJP_value)); - *ret = value; + irjp_copy_vinit_to_value(ret, value); return ret; } diff --git a/src/rjp.c b/src/rjp.c index 616f2fc..7ea396d 100644 --- a/src/rjp.c +++ b/src/rjp.c @@ -19,37 +19,56 @@ #include "rjp_internal.h" /* VALUE SETTING */ -void rjp_set_value(RJP_value* dest, RJP_value value){ - struct RJP_value* p = dest->parent; - *dest = value; - dest->parent = p; +void irjp_copy_vinit_to_value(RJP_value* dest, RJP_vinit* src){ + switch(src->type){ + case rjp_json_integer: + dest->integer = src->integer; + break; + case rjp_json_dfloat: + dest->dfloat = src->dfloat; + break; + case rjp_json_boolean: + dest->boolean = src->boolean; + break; + case rjp_json_string: + dest->string = src->string; + src->string.value = NULL; + break; + case rjp_json_null: + dest->integer = 0; + break; + case rjp_json_object: + *dest = irjp_object(); + break; + case rjp_json_array: + *dest = irjp_array(); + break; + }; + dest->type = src->type; } -RJP_value rjp_integer(RJP_int i){ - return (RJP_value){.integer = i, .type = rjp_json_integer}; +void rjp_set_value(RJP_value* dest, RJP_vinit* value){ + irjp_copy_vinit_to_value(dest, value); } -RJP_value rjp_boolean(char b){ - return (RJP_value){.boolean = b, .type = rjp_json_boolean}; +RJP_vinit rjp_integer(RJP_int i){ + return (RJP_vinit){.integer = i, .type = rjp_json_integer}; } -RJP_value rjp_dfloat(double d){ - return (RJP_value){.dfloat = d, .type = rjp_json_dfloat}; +RJP_vinit rjp_boolean(char b){ + return (RJP_vinit){.boolean = b, .type = rjp_json_boolean}; } -RJP_value rjp_string(char* c, RJP_index len){ - return (RJP_value){.string = {.value = c, .length = len}, .type = rjp_json_string}; +RJP_vinit rjp_dfloat(double d){ + return (RJP_vinit){.dfloat = d, .type = rjp_json_dfloat}; } -RJP_value rjp_string_copy(const char* c){ - RJP_index esclen = rjp_escape_strlen(c); - char* tmp = rjp_alloc(esclen+1); - rjp_escape_strcpy(tmp, c); - return (RJP_value){.string = {.value = tmp, .length = esclen}, .type = rjp_json_string}; +RJP_vinit rjp_string(char* c, RJP_index len){ + return (RJP_vinit){.string = {.value = c, .length = len}, .type = rjp_json_string}; } -RJP_value rjp_null(void){ - return (RJP_value){.integer = 0, .type = rjp_json_null}; +RJP_vinit rjp_null(void){ + return (RJP_vinit){.integer = 0, .type = rjp_json_null}; } -RJP_value rjp_object(void){ - return (RJP_value){.object = {0}, .type = rjp_json_object}; +RJP_vinit rjp_object(void){ + return (RJP_vinit){.integer = 0, .type = rjp_json_object}; } -RJP_value rjp_array(void){ - return (RJP_value){.array = {0}, .type = rjp_json_array}; +RJP_vinit rjp_array(void){ + return (RJP_vinit){.integer = 0, .type = rjp_json_array}; } /* GETTERS */ @@ -79,3 +98,30 @@ RJP_index rjp_value_string_length(const RJP_value* value){ } +RJP_value irjp_integer(RJP_int i){ + return (RJP_value){.integer = i, .type = rjp_json_integer}; +} +RJP_value irjp_boolean(char b){ + return (RJP_value){.boolean = b, .type = rjp_json_boolean}; +} +RJP_value irjp_dfloat(RJP_float d){ + return (RJP_value){.dfloat = d, .type = rjp_json_dfloat}; +} +RJP_value irjp_string(char* c, RJP_index len){ + return (RJP_value){.string = {.value = c, .length = len}, .type = rjp_json_string}; +} +RJP_value irjp_string_copy(const char* c){ + RJP_index esclen = rjp_escape_strlen(c); + char* tmp = rjp_alloc(esclen+1); + rjp_escape_strcpy(tmp, c); + return (RJP_value){.string = {.value = tmp, .length = esclen}, .type = rjp_json_string}; +} +RJP_value irjp_null(void){ + return (RJP_value){.integer = 0, .type = rjp_json_null}; +} +RJP_value irjp_object(void){ + return (RJP_value){.object = {0}, .type = rjp_json_object}; +} +RJP_value irjp_array(void){ + return (RJP_value){.array = {0}, .type = rjp_json_array}; +}