Moved rjp.c, memory.c, and strings.c over to new tree-based objects. Unfortunately, the API did need modified because C lacks the 'mutable' keyword.

This commit is contained in:
rexy712 2020-01-13 15:19:27 -08:00
parent 6e53fe29e2
commit a646d1c4e8
7 changed files with 123 additions and 210 deletions

View File

@ -74,14 +74,23 @@ typedef struct RJP_string{
}RJP_string;
//Forward declarations
struct RJP_object_member;
struct RJP_array_element;
typedef struct RJP_tree_node RJP_tree_node;
typedef struct RJP_tree_stack{
RJP_tree_node** data;
int size;
int pos;
}RJP_tree_stack;
typedef struct RJP_object_iterator{
RJP_tree_stack stack;
RJP_tree_node* current;
}RJP_object_iterator;
//Represents a json object
typedef struct RJP_object{
struct RJP_object_member* members; //linked list of members
struct RJP_object_member* last; //final member of linked list
size_t num_members;
struct RJP_tree_node* root;
int num_members;
}RJP_object;
//Represents a json array
@ -162,7 +171,7 @@ RJP_value rjp_object(void);
RJP_value rjp_array(void);
//Access first member of a json object
RJP_value* rjp_get_member(const RJP_value* object);
RJP_value* rjp_get_member(RJP_object_iterator* object);
//Access next member of a json object given the previous member
RJP_value* rjp_next_member(const RJP_value* member);
//Return number of members in the object
@ -172,13 +181,10 @@ char* rjp_member_name(const RJP_value* member);
//Return the object member's key name length excluding null terminator
size_t rjp_member_name_length(const RJP_value* member);
//Search for an object member with given key
RJP_search_res rjp_search_member(const RJP_value* object, const char* search, size_t skip);
RJP_value* rjp_search_member(const RJP_value* object, const char* search);
//Search for first occurance of multiple keys. Returns first occurance of each.
//Assumes dest is large enough to hold maximum num items.
size_t rjp_search_members(const RJP_value* object, size_t num, const char* const* searches, RJP_search_res* dest, size_t skip);
//Search for multiple occurances of multiple keys. Returns pointer to list of matches.
//Returned pointer must be freed using rjp_free
RJP_search_res* rjp_search_members_multi(const RJP_value* object, size_t num, const char* const* searches, size_t* rsize, size_t skip);
size_t rjp_search_members(const RJP_value* object, size_t num, const char* const* searches, RJP_value** dest);
//Access first element of a json array
RJP_value* rjp_get_element(const RJP_value* array);
//Access next element of a json array given the previous element

View File

@ -39,15 +39,8 @@ typedef struct RJP_array_element{
struct RJP_value value;
struct RJP_array_element* next;
}RJP_array_element;
//A member of an object
typedef struct RJP_object_member{
struct RJP_value value;
struct RJP_string name;
struct RJP_object_member* next;
}RJP_object_member;
void irjp_add_element(RJP_array* j);
void irjp_add_member(RJP_object* j, const char* str, size_t len);
void irjp_add_member_no_alloc(RJP_object* j, char* str, size_t len);
void irjp_delete_value(RJP_value* root);
#endif

View File

@ -22,14 +22,15 @@ struct RJP_tree_node{
unsigned color:1;
};
RJP_tree_node* irjp_new_node(RJP_object_member value);
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, RJP_object_member value, int* status);
RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, RJP_object_member value, int* status);
RJP_tree_node* irjp_tree_search_value(RJP_tree_node* root, RJP_object_member value);
RJP_tree_node* irjp_copy_tree(RJP_tree_node* root);
RJP_tree_node* irjp_new_node(RJP_object_member* value);
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, RJP_object_member* value, int* status);
RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, const char* key, int* status);
RJP_tree_node* irjp_tree_search_value(RJP_tree_node* root, const char* key);
RJP_tree_node* irjp_copy_tree(const RJP_tree_node* root);
void irjp_free_tree(RJP_tree_node* root);
int irjp_init_object_iterator(RJP_object_iterator* it, RJP_tree_node* root);
int irjp_init_object_iterator(RJP_object_iterator* it, const RJP_tree_node* root);
void irjp_delete_object_iterator(RJP_object_iterator* it);
RJP_tree_node* irjp_object_iterator_next(RJP_object_iterator* it);
RJP_tree_node* irjp_object_iterator_current(RJP_object_iterator* it);

View File

@ -18,6 +18,7 @@
#include "rjp_internal.h"
#include "strings.h"
#include "tree.h"
#include <stdlib.h>
#include <string.h>
@ -35,14 +36,6 @@ void rjp_free(void* data){
free(data);
}
static void irjp_copy_object(RJP_value* dest, const RJP_value* src){
dest->object.members = dest->object.last = 0;
for(RJP_value* curr = rjp_get_member(src);curr;curr = rjp_next_member(curr)){
RJP_value copy_mem;
rjp_copy_value(&copy_mem, curr);
rjp_add_member(dest, rjp_member_name(curr), rjp_member_name_length(curr), copy_mem);
}
}
static void irjp_copy_array(RJP_value* dest, const RJP_value* src){
dest->array.elements = dest->array.last = 0;
for(RJP_value* curr = rjp_get_element(src);curr;curr = rjp_next_element(curr)){
@ -57,7 +50,8 @@ void rjp_copy_value(RJP_value* dest, const RJP_value* src){
switch(src->type){
case rjp_json_object:
irjp_copy_object(dest, src);
irjp_free_tree(dest->object.root);
dest->object.root = irjp_copy_tree(src->object.root);
break;
case rjp_json_array:
irjp_copy_array(dest, src);
@ -79,13 +73,12 @@ void rjp_copy_value(RJP_value* dest, const RJP_value* src){
};
}
static void irjp_free_object_recurse(RJP_value* root);
static void irjp_free_array(RJP_value* root){
RJP_array_element* arr = root->array.elements;
for(RJP_array_element* i = arr;i != NULL;i = arr){
arr = arr->next;
if(i->value.type == rjp_json_object){
irjp_free_object_recurse(&i->value);
irjp_free_tree(i->value.object.root);
}else if(i->value.type == rjp_json_array){
irjp_free_array(&i->value);
}else if(i->value.type == rjp_json_string){
@ -94,32 +87,18 @@ static void irjp_free_array(RJP_value* root){
free(i);
}
}
//Recursively free JSON objects
static void irjp_free_object_recurse(RJP_value* root){
RJP_object_member* next;
for(RJP_object_member* m = root->object.members;m;m = next){
next = m->next;
if(m->value.type == rjp_json_object)
irjp_free_object_recurse(&m->value);
else if(m->value.type == rjp_json_string)
free(m->value.string.value);
else if(m->value.type == rjp_json_array)
irjp_free_array(&m->value);
if(m->name.value)
free(m->name.value);
free(m);
}
}
//Same as recurse but also frees root node
void irjp_delete_value(RJP_value* root){
if((root->type) == rjp_json_object)
irjp_free_tree(root->object.root);
else if((root->type) == rjp_json_array)
irjp_free_array(root);
else if((root->type) == rjp_json_string)
rjp_free(root->string.value);
}
void rjp_free_value(RJP_value* root){
if(!root)
return;
if((root->type) == rjp_json_object)
irjp_free_object_recurse(root);
else if((root->type) == rjp_json_array)
irjp_free_array(root);
irjp_delete_value(root);
free(root);
}

141
src/rjp.c
View File

@ -17,6 +17,7 @@
*/
#include "rjp_internal.h"
#include "tree.h"
#include <string.h> //strncpy, strlen
@ -30,49 +31,31 @@ void irjp_add_element(RJP_array* j){
j->last = j->last->next;
}
}
//create member of the object as a linked list member and assign a name with name allocation
void irjp_add_member(RJP_object* j, const char* str, size_t len){
++j->num_members;
if(!j->members){
j->members = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->members;
}else{
j->last->next = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->last->next;
}
j->last->name.value = rjp_alloc(len + 1);
strncpy(j->last->name.value, str, len);
j->last->name.value[len] = 0;
j->last->name.length = len;
}
void irjp_add_member_no_alloc(RJP_object* j, char* str, size_t len){
++j->num_members;
if(!j->members){
j->members = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->members;
}else{
j->last->next = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->last->next;
}
j->last->name.value = str;
j->last->name.length = len;
}
RJP_value* rjp_add_member(RJP_value* dest, const char* key, size_t keylen, RJP_value value){
if(!keylen)
keylen = strlen(key);
irjp_add_member(&dest->object, key, keylen);
dest->object.last->value = value;
dest->object.last->value.parent = dest;
return &dest->object.last->value;
++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;
int status;
return &irjp_tree_insert_value(dest->object.root, &mem, &status)->data.value;
}
RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, size_t keylen, RJP_value value){
if(!keylen)
keylen = strlen(key);
irjp_add_member_no_alloc(&dest->object, key, keylen);
dest->object.last->value = value;
dest->object.last->value.parent = dest;
return &dest->object.last->value;
RJP_object_member mem;
mem.name.value = key;
mem.name.length = keylen;
mem.value = value;
int status;
return &irjp_tree_insert_value(dest->object.root, &mem, &status)->data.value;
}
RJP_value* rjp_add_element(RJP_value* dest, RJP_value value){
irjp_add_element(&dest->array);
@ -140,12 +123,16 @@ RJP_value rjp_array(void){
}
RJP_value* rjp_get_member(const RJP_value* object){
return &object->object.members->value;
RJP_value* rjp_get_member(RJP_object_iterator* it){
return &it->current->data.value;
}
RJP_value* rjp_next_member(const RJP_value* member){
//polymorphism
return (RJP_value*)(((RJP_object_member*)member)->next);
RJP_object_iterator rjp_get_object_iterator(const RJP_value* object){
RJP_object_iterator it;
irjp_init_object_iterator(&it, object->object.root);
return it;
}
void rjp_object_iterator_next(RJP_object_iterator* it){
irjp_object_iterator_next(it);
}
size_t rjp_num_members(const RJP_value* object){
return object->object.num_members;
@ -157,75 +144,27 @@ size_t rjp_member_name_length(const RJP_value* member){
return ((RJP_object_member*)member)->name.length;
}
RJP_search_res rjp_search_member(const RJP_value* object, const char* search, size_t skip){
RJP_value* member = rjp_get_member(object);
size_t i = 0;
for(;i < skip && member;member = rjp_next_member(member),++i);
for(;member;member = rjp_next_member(member),++i){
if(!strcmp(((RJP_object_member*)member)->name.value, search)){
return (RJP_search_res){member, 0, i};
}
}
return (RJP_search_res){0};
RJP_value* rjp_search_member(const RJP_value* object, const char* search){
RJP_tree_node* n = irjp_tree_search_value(object->object.root, search);
if(!n)
return NULL;
return &n->data.value;
}
size_t rjp_search_members(const RJP_value* object, size_t num, const char* const* searches, RJP_search_res* dest, size_t skip){
for(size_t i = 0;i < num;++i){
dest[i] = (RJP_search_res){0};
}
RJP_value* member = rjp_get_member(object);
size_t objindex = 0;
for(;objindex < skip && member;member = rjp_next_member(member),++objindex);
size_t rjp_search_members(const RJP_value* object, size_t num, const char* const* searches, RJP_value** dest){
size_t matches = 0;
for(;member;member = rjp_next_member(member),++objindex){
for(size_t i = 0;i < num;++i){
if(dest[i].value != NULL)
continue;
if(!strcmp(((RJP_object_member*)member)->name.value, searches[i])){
dest[i].value = member;
dest[i].searchindex = i;
dest[i].objindex = objindex;
++matches;
break;
}
for(size_t i = 0;i < num;++i){
RJP_tree_node* n = irjp_tree_search_value(object->object.root, searches[i]);
if(!n){
dest[i] = NULL;
}else{
dest[i] = &n->data.value;
++matches;
}
}
return matches;
}
RJP_search_res* rjp_search_members_multi(const RJP_value* object, size_t num, const char* const* searches, size_t* rsize, size_t skip){
RJP_search_res* ret = rjp_alloc(num*sizeof(RJP_search_res));
size_t ret_size = num;
size_t j = 0;
RJP_value* member = rjp_get_member(object);
size_t objindex = 0;
for(;objindex < skip && member;member = rjp_next_member(member),++objindex);
for(;member;member = rjp_next_member(member),++objindex){
for(size_t i = 0;i < num;++i){
if(!strcmp(((RJP_object_member*)member)->name.value, searches[i])){
ret[j].value = member;
ret[j].searchindex = i;
ret[j].objindex = objindex;
++j;
if(j == ret_size){
ret_size *= 2;
ret = rjp_realloc(ret, ret_size*sizeof(RJP_search_res));
}
break;
}
}
}
if(rsize)
*rsize = j;
if(j == 0){
rjp_free(ret);
return NULL;
}
return ret;
}
RJP_value* rjp_get_element(const RJP_value* array){
return &array->array.elements->value;

View File

@ -21,6 +21,7 @@
#include "strings.h"
#include "rjp_internal.h"
#include "tree.h"
#include <stdio.h> //fprintf
#include <stdlib.h> //malloc, free
@ -325,33 +326,43 @@ size_t irjp_array_strlen_pretty(const RJP_value* arr, int depth){
size_t irjp_object_strlen(const RJP_value* root){
size_t count = 2; //{}
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)
RJP_object_iterator it;
irjp_init_object_iterator(&it, root->object.root);
RJP_tree_node* current = irjp_object_iterator_current(&it);
while(current){
RJP_object_member* mem = &current->data;
if(mem->name.length == 0 || mem->name.value[0] == 0){
irjp_delete_object_iterator(&it);
return 0;
count += member_list->name.length + 3; //"":
count += irjp_value_strlen(&member_list->value);
if(member_list->next)
}
count += mem->name.length + 3; //"":
count += irjp_value_strlen(&mem->value);
if((current = irjp_object_iterator_next(&it)))
++count; //,
}
irjp_delete_object_iterator(&it);
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)
RJP_object_iterator it;
irjp_init_object_iterator(&it, root->object.root);
RJP_tree_node* current = irjp_object_iterator_current(&it);
while(current){
RJP_object_member* mem = &current->data;
if(mem->name.length == 0 || mem->name.value[0] == 0){
irjp_delete_object_iterator(&it);
return 0;
count += member_list->name.length + 4; //"":space
count += irjp_value_strlen_pretty(&member_list->value, depth);
}
count += mem->name.length + 4; //"":space
count += irjp_value_strlen_pretty(&mem->value, depth);
count += depth; //tabs
++count; //newline
if(member_list->next)
if((current = irjp_object_iterator_next(&it)))
++count; //,
}
irjp_delete_object_iterator(&it);
return count;
}

View File

@ -5,30 +5,14 @@
#include <stdio.h>
#include "strings.h"
#include "rjp_internal.h"
#define BLACK 0
#define RED 1
//TMP
#define rjp_malloc malloc
#define rjp_free free
#define rjp_free_value(x)
#define irjp_strcpy(dest, src) do{(dest)->value = rjp_malloc((src)->length + 1);strcpy((dest)->value, (src)->value);(dest)->value[(src)->length] = 0;(dest)->length = (src)->length;}while(0);
#define rjp_copy_value(dest, src) ((dest)->integer = (src)->integer)
#define RJP_TREE_ITERATOR_STACK_START_SIZE 32
//Internal use only structs
typedef struct RJP_tree_stack{
RJP_tree_node** data;
int size;
int pos;
}RJP_tree_stack;
typedef struct RJP_object_iterator{
RJP_tree_stack stack;
RJP_tree_node* current;
}RJP_object_iterator;
//Forward declare static functions
static inline RJP_tree_node* irjp_grandparent(RJP_tree_node* n);
static inline RJP_tree_node* irjp_sibling(RJP_tree_node* n);
@ -40,8 +24,8 @@ static inline int irjp_is_inside_right(RJP_tree_node* n);
static void irjp_replace_node(RJP_tree_node *restrict node, RJP_tree_node *restrict child);
static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src);
static RJP_tree_node* irjp_clone_node(RJP_tree_node* src, RJP_tree_node* parent);
static RJP_tree_node* irjp_copy_node(RJP_tree_node* root, RJP_tree_node* parent);
static RJP_tree_node* irjp_clone_node(const RJP_tree_node* src, RJP_tree_node* parent);
static RJP_tree_node* irjp_copy_node(const RJP_tree_node* root, RJP_tree_node* parent);
static void irjp_free_node(RJP_tree_node* node);
static void irjp_delete_node(RJP_tree_node* node);
@ -131,24 +115,24 @@ static void irjp_replace_node(RJP_tree_node *restrict node, RJP_tree_node *restr
}
//Node construction / destruction
RJP_tree_node* irjp_new_node(RJP_object_member value){
RJP_tree_node* node = rjp_malloc(sizeof(RJP_tree_node));
node->data.name = value.name;
node->data.value = value.value;
RJP_tree_node* irjp_new_node(RJP_object_member* value){
RJP_tree_node* node = rjp_alloc(sizeof(RJP_tree_node));
node->data.name = value->name;
node->data.value = value->value;
node->parent = node->left = node->right = NULL;
return node;
}
static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src){
dest->data = src->data;
}
static RJP_tree_node* irjp_clone_node(RJP_tree_node* src, RJP_tree_node* parent){
RJP_tree_node* dest = rjp_malloc(sizeof(RJP_tree_node));
static RJP_tree_node* irjp_clone_node(const RJP_tree_node* src, RJP_tree_node* parent){
RJP_tree_node* dest = rjp_alloc(sizeof(RJP_tree_node));
rjp_copy_value(&dest->data.value, &src->data.value);
irjp_strcpy(&dest->data.name, &src->data.name);
dest->parent = parent;
return dest;
}
static RJP_tree_node* irjp_copy_node(RJP_tree_node* root, RJP_tree_node* parent){
static RJP_tree_node* irjp_copy_node(const RJP_tree_node* root, RJP_tree_node* parent){
if(!root){
return NULL;
}
@ -163,14 +147,14 @@ static void irjp_free_node(RJP_tree_node* node){
}
static void irjp_delete_node(RJP_tree_node* node){
rjp_free(node->data.name.value);
rjp_free_value(&node->data.value);
irjp_delete_value(&node->data.value);
}
/* TREE STACK */
//Stack construction / destruction
static int irjp_init_tree_stack(RJP_tree_stack* stack){
stack->data = rjp_malloc(sizeof(RJP_tree_node*)*RJP_TREE_ITERATOR_STACK_START_SIZE);
stack->data = rjp_alloc(sizeof(RJP_tree_node*)*RJP_TREE_ITERATOR_STACK_START_SIZE);
stack->size = RJP_TREE_ITERATOR_STACK_START_SIZE;
stack->pos = 0;
return 0;
@ -180,7 +164,7 @@ static void irjp_delete_tree_stack(RJP_tree_stack* stack){
}
static void irjp_resize_tree_stack(RJP_tree_stack* stack){
int newsize = stack->size*2;
RJP_tree_node** newdata = rjp_malloc(sizeof(RJP_tree_node*)*newsize);
RJP_tree_node** newdata = rjp_alloc(sizeof(RJP_tree_node*)*newsize);
for(int i = 0;i < stack->size;++i){
newdata[i] = stack->data[i];
}
@ -203,9 +187,9 @@ static RJP_tree_node* irjp_peek_tree_stack(RJP_tree_stack* stack){
/* TREE ITERATOR */
//Iterator construction / destruction
int irjp_init_object_iterator(RJP_object_iterator* it, RJP_tree_node* root){
int irjp_init_object_iterator(RJP_object_iterator* it, const RJP_tree_node* root){
irjp_init_tree_stack(&it->stack);
it->current = root;
it->current = (RJP_tree_node*)root;
while(it->current){
irjp_push_tree_stack(&it->stack, it->current);
it->current = it->current->left;
@ -230,7 +214,7 @@ RJP_tree_node* irjp_object_iterator_current(RJP_object_iterator* it){
/* TREE */
//Tree construction / destruction
RJP_tree_node* irjp_copy_tree(RJP_tree_node* root){
RJP_tree_node* irjp_copy_tree(const RJP_tree_node* root){
return irjp_copy_node(root, NULL);
}
void irjp_free_tree(RJP_tree_node* root){
@ -241,7 +225,7 @@ void irjp_free_tree(RJP_tree_node* root){
irjp_free_node(root);
}
//Tree operations
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, RJP_object_member value, int* status){
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, RJP_object_member* value, int* status){
*status = RJP_TREE_SUCCESS;
if(!root){
root = irjp_new_node(value);
@ -318,9 +302,9 @@ static RJP_tree_node* irjp_tree_repair(RJP_tree_node* node){
}
}
RJP_tree_node* irjp_tree_search_value(RJP_tree_node* root, RJP_object_member value){
RJP_tree_node* irjp_tree_search_value(RJP_tree_node* root, const char* key){
while(root != NULL){
int cmpval = strcmp(value.name.value, root->data.name.value);
int cmpval = strcmp(key, root->data.name.value);
if(cmpval < 0){
root = root->left;
}else if(cmpval > 0){
@ -398,12 +382,12 @@ void irjp_dbg_print_tree_bfs(RJP_tree_node* root){
#undef pop
#undef push
RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, RJP_object_member value, int* status){
RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, const char* key, int* status){
if(!root){
*status = RJP_TREE_ERR_NULL_ROOT;
return root;
}
RJP_tree_node* n = irjp_tree_search_value(root, value);
RJP_tree_node* n = irjp_tree_search_value(root, key);
if(!n){
*status = RJP_TREE_ERR_NOT_FOUND;
return root;