Successfully hid RJP_value implementation from API

This commit is contained in:
rexy712 2020-01-19 09:19:20 -08:00
parent 30cc8008af
commit ff241e2a6f
8 changed files with 197 additions and 104 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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(&copy_mem, curr);
rjp_add_element(dest, copy_mem);
rjp_add_element(dest, &copy_mem);
}
}

View File

@ -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;

View File

@ -28,13 +28,13 @@
#include <string.h> //strlen
#include <stdio.h> //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;
}

View File

@ -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};
}