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:
parent
6e53fe29e2
commit
a646d1c4e8
@ -74,14 +74,23 @@ typedef struct RJP_string{
|
|||||||
}RJP_string;
|
}RJP_string;
|
||||||
|
|
||||||
//Forward declarations
|
//Forward declarations
|
||||||
struct RJP_object_member;
|
|
||||||
struct RJP_array_element;
|
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
|
//Represents a json object
|
||||||
typedef struct RJP_object{
|
typedef struct RJP_object{
|
||||||
struct RJP_object_member* members; //linked list of members
|
struct RJP_tree_node* root;
|
||||||
struct RJP_object_member* last; //final member of linked list
|
int num_members;
|
||||||
size_t num_members;
|
|
||||||
}RJP_object;
|
}RJP_object;
|
||||||
|
|
||||||
//Represents a json array
|
//Represents a json array
|
||||||
@ -162,7 +171,7 @@ RJP_value rjp_object(void);
|
|||||||
RJP_value rjp_array(void);
|
RJP_value rjp_array(void);
|
||||||
|
|
||||||
//Access first member of a json object
|
//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
|
//Access next member of a json object given the previous member
|
||||||
RJP_value* rjp_next_member(const RJP_value* member);
|
RJP_value* rjp_next_member(const RJP_value* member);
|
||||||
//Return number of members in the object
|
//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
|
//Return the object member's key name length excluding null terminator
|
||||||
size_t rjp_member_name_length(const RJP_value* member);
|
size_t rjp_member_name_length(const RJP_value* member);
|
||||||
//Search for an object member with given key
|
//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.
|
//Search for first occurance of multiple keys. Returns first occurance of each.
|
||||||
//Assumes dest is large enough to hold maximum num items.
|
//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);
|
size_t rjp_search_members(const RJP_value* object, size_t num, const char* const* searches, RJP_value** dest);
|
||||||
//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);
|
|
||||||
//Access first element of a json array
|
//Access first element of a json array
|
||||||
RJP_value* rjp_get_element(const RJP_value* array);
|
RJP_value* rjp_get_element(const RJP_value* array);
|
||||||
//Access next element of a json array given the previous element
|
//Access next element of a json array given the previous element
|
||||||
|
|||||||
@ -39,15 +39,8 @@ typedef struct RJP_array_element{
|
|||||||
struct RJP_value value;
|
struct RJP_value value;
|
||||||
struct RJP_array_element* next;
|
struct RJP_array_element* next;
|
||||||
}RJP_array_element;
|
}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_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_add_member_no_alloc(RJP_object* j, char* str, size_t len);
|
||||||
|
void irjp_delete_value(RJP_value* root);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -22,14 +22,15 @@ struct RJP_tree_node{
|
|||||||
unsigned color:1;
|
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_new_node(RJP_object_member* value);
|
||||||
RJP_tree_node* irjp_tree_remove_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);
|
||||||
RJP_tree_node* irjp_tree_search_value(RJP_tree_node* root, RJP_object_member value);
|
RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, const char* key, int* status);
|
||||||
RJP_tree_node* irjp_copy_tree(RJP_tree_node* root);
|
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);
|
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);
|
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_next(RJP_object_iterator* it);
|
||||||
RJP_tree_node* irjp_object_iterator_current(RJP_object_iterator* it);
|
RJP_tree_node* irjp_object_iterator_current(RJP_object_iterator* it);
|
||||||
|
|||||||
47
src/memory.c
47
src/memory.c
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "rjp_internal.h"
|
#include "rjp_internal.h"
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -35,14 +36,6 @@ void rjp_free(void* data){
|
|||||||
free(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(©_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){
|
static void irjp_copy_array(RJP_value* dest, const RJP_value* src){
|
||||||
dest->array.elements = dest->array.last = 0;
|
dest->array.elements = dest->array.last = 0;
|
||||||
for(RJP_value* curr = rjp_get_element(src);curr;curr = rjp_next_element(curr)){
|
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){
|
switch(src->type){
|
||||||
case rjp_json_object:
|
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;
|
break;
|
||||||
case rjp_json_array:
|
case rjp_json_array:
|
||||||
irjp_copy_array(dest, src);
|
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){
|
static void irjp_free_array(RJP_value* root){
|
||||||
RJP_array_element* arr = root->array.elements;
|
RJP_array_element* arr = root->array.elements;
|
||||||
for(RJP_array_element* i = arr;i != NULL;i = arr){
|
for(RJP_array_element* i = arr;i != NULL;i = arr){
|
||||||
arr = arr->next;
|
arr = arr->next;
|
||||||
if(i->value.type == rjp_json_object){
|
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){
|
}else if(i->value.type == rjp_json_array){
|
||||||
irjp_free_array(&i->value);
|
irjp_free_array(&i->value);
|
||||||
}else if(i->value.type == rjp_json_string){
|
}else if(i->value.type == rjp_json_string){
|
||||||
@ -94,32 +87,18 @@ static void irjp_free_array(RJP_value* root){
|
|||||||
free(i);
|
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){
|
void rjp_free_value(RJP_value* root){
|
||||||
if(!root)
|
if(!root)
|
||||||
return;
|
return;
|
||||||
|
irjp_delete_value(root);
|
||||||
if((root->type) == rjp_json_object)
|
|
||||||
irjp_free_object_recurse(root);
|
|
||||||
else if((root->type) == rjp_json_array)
|
|
||||||
irjp_free_array(root);
|
|
||||||
|
|
||||||
free(root);
|
free(root);
|
||||||
}
|
}
|
||||||
|
|||||||
141
src/rjp.c
141
src/rjp.c
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rjp_internal.h"
|
#include "rjp_internal.h"
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
#include <string.h> //strncpy, strlen
|
#include <string.h> //strncpy, strlen
|
||||||
|
|
||||||
@ -30,49 +31,31 @@ void irjp_add_element(RJP_array* j){
|
|||||||
j->last = j->last->next;
|
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){
|
RJP_value* rjp_add_member(RJP_value* dest, const char* key, size_t keylen, RJP_value value){
|
||||||
if(!keylen)
|
if(!keylen)
|
||||||
keylen = strlen(key);
|
keylen = strlen(key);
|
||||||
irjp_add_member(&dest->object, key, keylen);
|
++dest->object.num_members;
|
||||||
dest->object.last->value = value;
|
RJP_object_member mem;
|
||||||
dest->object.last->value.parent = dest;
|
mem.name.value = rjp_alloc(keylen+1);
|
||||||
return &dest->object.last->value;
|
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){
|
RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, size_t keylen, RJP_value value){
|
||||||
if(!keylen)
|
if(!keylen)
|
||||||
keylen = strlen(key);
|
keylen = strlen(key);
|
||||||
irjp_add_member_no_alloc(&dest->object, key, keylen);
|
RJP_object_member mem;
|
||||||
dest->object.last->value = value;
|
mem.name.value = key;
|
||||||
dest->object.last->value.parent = dest;
|
mem.name.length = keylen;
|
||||||
return &dest->object.last->value;
|
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){
|
RJP_value* rjp_add_element(RJP_value* dest, RJP_value value){
|
||||||
irjp_add_element(&dest->array);
|
irjp_add_element(&dest->array);
|
||||||
@ -140,12 +123,16 @@ RJP_value rjp_array(void){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RJP_value* rjp_get_member(const RJP_value* object){
|
RJP_value* rjp_get_member(RJP_object_iterator* it){
|
||||||
return &object->object.members->value;
|
return &it->current->data.value;
|
||||||
}
|
}
|
||||||
RJP_value* rjp_next_member(const RJP_value* member){
|
RJP_object_iterator rjp_get_object_iterator(const RJP_value* object){
|
||||||
//polymorphism
|
RJP_object_iterator it;
|
||||||
return (RJP_value*)(((RJP_object_member*)member)->next);
|
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){
|
size_t rjp_num_members(const RJP_value* object){
|
||||||
return object->object.num_members;
|
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;
|
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* rjp_search_member(const RJP_value* object, const char* search){
|
||||||
RJP_value* member = rjp_get_member(object);
|
RJP_tree_node* n = irjp_tree_search_value(object->object.root, search);
|
||||||
size_t i = 0;
|
if(!n)
|
||||||
for(;i < skip && member;member = rjp_next_member(member),++i);
|
return NULL;
|
||||||
|
return &n->data.value;
|
||||||
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};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t rjp_search_members(const RJP_value* object, size_t num, const char* const* searches, RJP_search_res* dest, size_t skip){
|
size_t rjp_search_members(const RJP_value* object, size_t num, const char* const* searches, RJP_value** dest){
|
||||||
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 matches = 0;
|
size_t matches = 0;
|
||||||
|
|
||||||
for(;member;member = rjp_next_member(member),++objindex){
|
for(size_t i = 0;i < num;++i){
|
||||||
for(size_t i = 0;i < num;++i){
|
RJP_tree_node* n = irjp_tree_search_value(object->object.root, searches[i]);
|
||||||
if(dest[i].value != NULL)
|
if(!n){
|
||||||
continue;
|
dest[i] = NULL;
|
||||||
if(!strcmp(((RJP_object_member*)member)->name.value, searches[i])){
|
}else{
|
||||||
dest[i].value = member;
|
dest[i] = &n->data.value;
|
||||||
dest[i].searchindex = i;
|
++matches;
|
||||||
dest[i].objindex = objindex;
|
|
||||||
++matches;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 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){
|
RJP_value* rjp_get_element(const RJP_value* array){
|
||||||
return &array->array.elements->value;
|
return &array->array.elements->value;
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
#include "rjp_internal.h"
|
#include "rjp_internal.h"
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
#include <stdio.h> //fprintf
|
#include <stdio.h> //fprintf
|
||||||
#include <stdlib.h> //malloc, free
|
#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 irjp_object_strlen(const RJP_value* root){
|
||||||
size_t count = 2; //{}
|
size_t count = 2; //{}
|
||||||
const RJP_object* root_obj = &root->object;
|
RJP_object_iterator it;
|
||||||
const RJP_object_member* member_list = root_obj->members;
|
irjp_init_object_iterator(&it, root->object.root);
|
||||||
for(;member_list;member_list = member_list->next){
|
RJP_tree_node* current = irjp_object_iterator_current(&it);
|
||||||
if(member_list->name.length == 0 || member_list->name.value[0] == 0)
|
while(current){
|
||||||
|
RJP_object_member* mem = ¤t->data;
|
||||||
|
if(mem->name.length == 0 || mem->name.value[0] == 0){
|
||||||
|
irjp_delete_object_iterator(&it);
|
||||||
return 0;
|
return 0;
|
||||||
count += member_list->name.length + 3; //"":
|
}
|
||||||
count += irjp_value_strlen(&member_list->value);
|
count += mem->name.length + 3; //"":
|
||||||
if(member_list->next)
|
count += irjp_value_strlen(&mem->value);
|
||||||
|
if((current = irjp_object_iterator_next(&it)))
|
||||||
++count; //,
|
++count; //,
|
||||||
}
|
}
|
||||||
|
irjp_delete_object_iterator(&it);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
size_t irjp_object_strlen_pretty(const RJP_value* root, int depth){
|
size_t irjp_object_strlen_pretty(const RJP_value* root, int depth){
|
||||||
size_t count = 3 + depth; //{\n\t}
|
size_t count = 3 + depth; //{\n\t}
|
||||||
++depth;
|
++depth;
|
||||||
const RJP_object* root_obj = &root->object;
|
RJP_object_iterator it;
|
||||||
const RJP_object_member* member_list = root_obj->members;
|
irjp_init_object_iterator(&it, root->object.root);
|
||||||
for(;member_list;member_list = member_list->next){
|
RJP_tree_node* current = irjp_object_iterator_current(&it);
|
||||||
if(member_list->name.length == 0 || member_list->name.value[0] == 0)
|
while(current){
|
||||||
|
RJP_object_member* mem = ¤t->data;
|
||||||
|
if(mem->name.length == 0 || mem->name.value[0] == 0){
|
||||||
|
irjp_delete_object_iterator(&it);
|
||||||
return 0;
|
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 += depth; //tabs
|
||||||
++count; //newline
|
++count; //newline
|
||||||
if(member_list->next)
|
if((current = irjp_object_iterator_next(&it)))
|
||||||
++count; //,
|
++count; //,
|
||||||
}
|
}
|
||||||
|
irjp_delete_object_iterator(&it);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
58
src/tree.c
58
src/tree.c
@ -5,30 +5,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
|
#include "rjp_internal.h"
|
||||||
|
|
||||||
#define BLACK 0
|
#define BLACK 0
|
||||||
#define RED 1
|
#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
|
#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
|
//Forward declare static functions
|
||||||
static inline RJP_tree_node* irjp_grandparent(RJP_tree_node* n);
|
static inline RJP_tree_node* irjp_grandparent(RJP_tree_node* n);
|
||||||
static inline RJP_tree_node* irjp_sibling(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_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 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_clone_node(const 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_copy_node(const RJP_tree_node* root, RJP_tree_node* parent);
|
||||||
static void irjp_free_node(RJP_tree_node* node);
|
static void irjp_free_node(RJP_tree_node* node);
|
||||||
static void irjp_delete_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
|
//Node construction / destruction
|
||||||
RJP_tree_node* irjp_new_node(RJP_object_member value){
|
RJP_tree_node* irjp_new_node(RJP_object_member* value){
|
||||||
RJP_tree_node* node = rjp_malloc(sizeof(RJP_tree_node));
|
RJP_tree_node* node = rjp_alloc(sizeof(RJP_tree_node));
|
||||||
node->data.name = value.name;
|
node->data.name = value->name;
|
||||||
node->data.value = value.value;
|
node->data.value = value->value;
|
||||||
node->parent = node->left = node->right = NULL;
|
node->parent = node->left = node->right = NULL;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src){
|
static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src){
|
||||||
dest->data = src->data;
|
dest->data = src->data;
|
||||||
}
|
}
|
||||||
static RJP_tree_node* irjp_clone_node(RJP_tree_node* src, RJP_tree_node* parent){
|
static RJP_tree_node* irjp_clone_node(const RJP_tree_node* src, RJP_tree_node* parent){
|
||||||
RJP_tree_node* dest = rjp_malloc(sizeof(RJP_tree_node));
|
RJP_tree_node* dest = rjp_alloc(sizeof(RJP_tree_node));
|
||||||
rjp_copy_value(&dest->data.value, &src->data.value);
|
rjp_copy_value(&dest->data.value, &src->data.value);
|
||||||
irjp_strcpy(&dest->data.name, &src->data.name);
|
irjp_strcpy(&dest->data.name, &src->data.name);
|
||||||
dest->parent = parent;
|
dest->parent = parent;
|
||||||
return dest;
|
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){
|
if(!root){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -163,14 +147,14 @@ static void irjp_free_node(RJP_tree_node* node){
|
|||||||
}
|
}
|
||||||
static void irjp_delete_node(RJP_tree_node* node){
|
static void irjp_delete_node(RJP_tree_node* node){
|
||||||
rjp_free(node->data.name.value);
|
rjp_free(node->data.name.value);
|
||||||
rjp_free_value(&node->data.value);
|
irjp_delete_value(&node->data.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TREE STACK */
|
/* TREE STACK */
|
||||||
//Stack construction / destruction
|
//Stack construction / destruction
|
||||||
static int irjp_init_tree_stack(RJP_tree_stack* stack){
|
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->size = RJP_TREE_ITERATOR_STACK_START_SIZE;
|
||||||
stack->pos = 0;
|
stack->pos = 0;
|
||||||
return 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){
|
static void irjp_resize_tree_stack(RJP_tree_stack* stack){
|
||||||
int newsize = stack->size*2;
|
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){
|
for(int i = 0;i < stack->size;++i){
|
||||||
newdata[i] = stack->data[i];
|
newdata[i] = stack->data[i];
|
||||||
}
|
}
|
||||||
@ -203,9 +187,9 @@ static RJP_tree_node* irjp_peek_tree_stack(RJP_tree_stack* stack){
|
|||||||
|
|
||||||
/* TREE ITERATOR */
|
/* TREE ITERATOR */
|
||||||
//Iterator construction / destruction
|
//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);
|
irjp_init_tree_stack(&it->stack);
|
||||||
it->current = root;
|
it->current = (RJP_tree_node*)root;
|
||||||
while(it->current){
|
while(it->current){
|
||||||
irjp_push_tree_stack(&it->stack, it->current);
|
irjp_push_tree_stack(&it->stack, it->current);
|
||||||
it->current = it->current->left;
|
it->current = it->current->left;
|
||||||
@ -230,7 +214,7 @@ RJP_tree_node* irjp_object_iterator_current(RJP_object_iterator* it){
|
|||||||
|
|
||||||
/* TREE */
|
/* TREE */
|
||||||
//Tree construction / destruction
|
//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);
|
return irjp_copy_node(root, NULL);
|
||||||
}
|
}
|
||||||
void irjp_free_tree(RJP_tree_node* root){
|
void irjp_free_tree(RJP_tree_node* root){
|
||||||
@ -241,7 +225,7 @@ void irjp_free_tree(RJP_tree_node* root){
|
|||||||
irjp_free_node(root);
|
irjp_free_node(root);
|
||||||
}
|
}
|
||||||
//Tree operations
|
//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;
|
*status = RJP_TREE_SUCCESS;
|
||||||
if(!root){
|
if(!root){
|
||||||
root = irjp_new_node(value);
|
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){
|
while(root != NULL){
|
||||||
int cmpval = strcmp(value.name.value, root->data.name.value);
|
int cmpval = strcmp(key, root->data.name.value);
|
||||||
if(cmpval < 0){
|
if(cmpval < 0){
|
||||||
root = root->left;
|
root = root->left;
|
||||||
}else if(cmpval > 0){
|
}else if(cmpval > 0){
|
||||||
@ -398,12 +382,12 @@ void irjp_dbg_print_tree_bfs(RJP_tree_node* root){
|
|||||||
#undef pop
|
#undef pop
|
||||||
#undef push
|
#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){
|
if(!root){
|
||||||
*status = RJP_TREE_ERR_NULL_ROOT;
|
*status = RJP_TREE_ERR_NULL_ROOT;
|
||||||
return 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){
|
if(!n){
|
||||||
*status = RJP_TREE_ERR_NOT_FOUND;
|
*status = RJP_TREE_ERR_NOT_FOUND;
|
||||||
return root;
|
return root;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user