Add _c API functions to allow custom allocation/deallocation functions

This commit is contained in:
rexy712 2020-07-20 03:16:21 -07:00
parent bf098ac96a
commit e77d20cae4
18 changed files with 396 additions and 208 deletions

View File

@ -113,6 +113,10 @@ typedef struct RJP_parse_error{
int errcode;
int row, column;
}RJP_parse_error;
typedef struct RJP_memory_fns{
void (*free)(void*);
void* (*alloc)(RJP_index);
}RJP_memory_fns;
/***************** NON OBJECT OPERATIONS *******************/
void* rjp_alloc(RJP_index nbytes);
@ -127,10 +131,15 @@ RJP_string rjp_escape(const char* src);
RJP_value* rjp_simple_parse(const char* str);
RJP_value* rjp_parse(const char* str, int flags, RJP_parse_error* err);
RJP_value* rjp_parse_cback(int flags, RJP_parse_callback* cbacks, RJP_parse_error* err);
RJP_value* rjp_parse_c(const char* str, int flags, RJP_parse_error* err, const RJP_memory_fns* fns);
RJP_value* rjp_parse_cback_c(int flags, RJP_parse_callback* cbacks, RJP_parse_error* err, const RJP_memory_fns* fns);
char* rjp_to_json(const RJP_value* root, int pretty);
char* rjp_to_json_c(const RJP_value* root, int pretty, const RJP_memory_fns* fns);
char* rjp_parse_error_to_string(const RJP_parse_error* err);
char* rjp_parse_error_to_string_c(const RJP_parse_error* err, const RJP_memory_fns* fns);
void rjp_delete_parse_error(RJP_parse_error* err);
void rjp_delete_parse_error_c(RJP_parse_error* err, const RJP_memory_fns* fns);
RJP_value* rjp_new_null(void);
RJP_value* rjp_new_int(RJP_int val);
@ -142,9 +151,21 @@ RJP_value* rjp_new_object(void);
RJP_value* rjp_new_ordered_object(void);
RJP_value* rjp_new_array(void);
RJP_value* rjp_new_null_c(const RJP_memory_fns* fns);
RJP_value* rjp_new_int_c(RJP_int val, const RJP_memory_fns* fns);
RJP_value* rjp_new_float_c(RJP_float val, const RJP_memory_fns* fns);
RJP_value* rjp_new_bool_c(RJP_bool val, const RJP_memory_fns* fns);
RJP_value* rjp_new_string_c(const char* val, RJP_index length, const RJP_memory_fns* fns);
RJP_value* rjp_new_string_steal_c(char* val, RJP_index length, const RJP_memory_fns* fns);
RJP_value* rjp_new_object_c(const RJP_memory_fns* fns);
RJP_value* rjp_new_ordered_object_c(const RJP_memory_fns* fns);
RJP_value* rjp_new_array_c(const RJP_memory_fns* fns);
void rjp_free_value(RJP_value* root);
void rjp_free_value_c(RJP_value* root, const RJP_memory_fns* fns);
RJP_value* rjp_copy_value(RJP_value* dest, const RJP_value* src);
RJP_value* rjp_copy_value_c(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns);
RJP_value* rjp_move_value(RJP_value* dest, RJP_value* src);
RJP_value* rjp_set_null(RJP_value* v);
@ -157,6 +178,16 @@ RJP_value* rjp_set_object(RJP_value* v);
RJP_value* rjp_set_ordered_object(RJP_value* v);
RJP_value* rjp_set_array(RJP_value* v);
RJP_value* rjp_set_null_c(RJP_value* v, const RJP_memory_fns* fns);
RJP_value* rjp_set_int_c(RJP_value* v, RJP_int val, const RJP_memory_fns* fns);
RJP_value* rjp_set_float_c(RJP_value* v, RJP_float val, const RJP_memory_fns* fns);
RJP_value* rjp_set_bool_c(RJP_value* v, RJP_bool val, const RJP_memory_fns* fns);
RJP_value* rjp_set_string_c(RJP_value* v, const char* val, RJP_index length, const RJP_memory_fns* fns);
RJP_value* rjp_set_string_steal_c(RJP_value* v, char* val, RJP_index length, const RJP_memory_fns* fns);
RJP_value* rjp_set_object_c(RJP_value* v, const RJP_memory_fns* fns);
RJP_value* rjp_set_ordered_object_c(RJP_value* v, const RJP_memory_fns* fns);
RJP_value* rjp_set_array_c(RJP_value* v, const RJP_memory_fns* fns);
RJP_float rjp_get_float(const RJP_value* value);
RJP_int rjp_get_int(const RJP_value* value);
RJP_bool rjp_get_bool(const RJP_value* value);
@ -174,13 +205,24 @@ RJP_value* rjp_new_member_steal_key(RJP_value* dest, char* key, RJP_index keylen
RJP_value* rjp_add_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_value* src);
RJP_value* rjp_add_member_steal_key(RJP_value* dest, char* key, RJP_index keylen, RJP_value* src);
RJP_value* rjp_new_member_c(RJP_value* dest, const char* key, RJP_index keylen, const RJP_memory_fns* fns);
RJP_value* rjp_new_member_steal_key_c(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns);
RJP_value* rjp_add_member_c(RJP_value* dest, const char* key, RJP_index keylen, RJP_value* src, const RJP_memory_fns* fns);
RJP_value* rjp_add_member_steal_key_c(RJP_value* dest, char* key, RJP_index keylen, RJP_value* src, const RJP_memory_fns* fns);
RJP_value* rjp_remove_member_by_key(RJP_value* obj, const char* key);
RJP_value* rjp_remove_member(RJP_value* obj, RJP_value* member);
void rjp_free_member_by_key(RJP_value* obj, const char* key);
void rjp_free_member(RJP_value* obj, RJP_value* member);
RJP_value* rjp_remove_member_by_key_c(RJP_value* obj, const char* key, const RJP_memory_fns* fns);
RJP_value* rjp_remove_member_c(RJP_value* obj, RJP_value* member, const RJP_memory_fns* fns);
void rjp_free_member_by_key_c(RJP_value* obj, const char* key, const RJP_memory_fns* fns);
void rjp_free_member_c(RJP_value* obj, RJP_value* member, const RJP_memory_fns* fns);
RJP_value* rjp_set_key_steal(RJP_value* dest, char* key, RJP_index keylen);
RJP_value* rjp_set_key(RJP_value* dest, const char* key, RJP_index keylen);
RJP_value* rjp_set_key_steal_c(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns);
RJP_value* rjp_set_key_c(RJP_value* dest, const char* key, RJP_index keylen, const RJP_memory_fns* fns);
RJP_index rjp_num_members(const RJP_value* object);
const RJP_string* rjp_member_key(const RJP_value* member);
@ -188,6 +230,8 @@ RJP_value* rjp_search_member(const RJP_value* object, const char* search);
RJP_value* rjp_object_to_ordered(RJP_value* object);
RJP_value* rjp_object_to_unordered(RJP_value* object);
RJP_value* rjp_object_to_ordered_c(RJP_value* object, const RJP_memory_fns* fns);
RJP_value* rjp_object_to_unordered_c(RJP_value* object, const RJP_memory_fns* fns);
/***************** OBJECT ITERATOR OPERATIONS *******************/
void rjp_init_object_iterator(RJP_object_iterator* iter, const RJP_value* object);
@ -199,8 +243,11 @@ RJP_value* rjp_object_iterator_peek(const RJP_object_iterator* it);
/***************** ARRAY OPERATIONS *******************/
RJP_value* rjp_new_element(RJP_value* dest);
RJP_value* rjp_add_element(RJP_value* dest, RJP_value* src);
RJP_value* rjp_new_element_c(RJP_value* dest, const RJP_memory_fns* fns);
RJP_value* rjp_add_element_c(RJP_value* dest, RJP_value* src, const RJP_memory_fns* fns);
RJP_value* rjp_remove_element(RJP_value* arr, RJP_value* elem);
void rjp_free_element(RJP_value* arr, RJP_value* elem);
void rjp_free_element_c(RJP_value* arr, RJP_value* elem, const RJP_memory_fns* fns);
RJP_index rjp_num_elements(const RJP_value* arr);

View File

@ -30,8 +30,8 @@ typedef struct RJP_array{
RJP_index num_elements;
}RJP_array;
void irjp_add_element(RJP_array* j);
void irjp_copy_array(RJP_value* dest, const RJP_value* src);
void irjp_add_element(RJP_array* j, const RJP_memory_fns* fns);
void irjp_copy_array(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns);
RJP_index irjp_dump_array(const RJP_value* arr, char* dest, const int flags, int depth);

View File

@ -41,4 +41,6 @@ static inline void irjp_ignore_unused(FILE* fp, ...){
}
#endif
extern const RJP_memory_fns irjp_default_memory_fns;
#endif

View File

@ -23,8 +23,8 @@
#include "rjp_ordered_object.h"
#include "rjp_internal.h"
void irjp_copy_object(RJP_value* dest, const RJP_value* src);
void irjp_delete_object(RJP_value* obj);
void irjp_copy_object(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns);
void irjp_delete_object(RJP_value* obj, const RJP_memory_fns* fns);
RJP_index irjp_dump_object(const RJP_value* root, char* dest, const int flags, int depth);

View File

@ -29,14 +29,12 @@ typedef struct RJP_ordered_object{
RJP_index num_members;
}RJP_ordered_object;
void irjp_copy_ordered_object(RJP_value* dest, const RJP_value* src);
void irjp_delete_ordered_object(RJP_value* obj);
void irjp_copy_ordered_object(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns);
void irjp_delete_ordered_object(RJP_value* obj, const RJP_memory_fns* fns);
void irjp_copy_ordered_object(RJP_value* dest, const RJP_value* src);
void irjp_delete_ordered_object(RJP_value* obj);
RJP_value* irjp_add_ordered_member(RJP_value* dest, char* key, RJP_index keylen);
RJP_value* irjp_remove_ordered_member(RJP_value* obj, RJP_value* member);
void irjp_ordered_set_key(RJP_value* dest, char* key, RJP_index keylen);
RJP_value* irjp_add_ordered_member(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns);
RJP_value* irjp_remove_ordered_member(RJP_value* obj, RJP_value* member, const RJP_memory_fns* fns);
void irjp_ordered_set_key(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns);
RJP_index irjp_ordered_num_members(const RJP_value* object);
RJP_value* irjp_ordered_search_member(const RJP_value* object, const char* search);
void irjp_init_ordered_object_iterator(RJP_object_iterator* it, const RJP_value* object);

View File

@ -20,15 +20,16 @@
#define RJP_STRINGS_H
#include "rjp.h"
#include "rjp_internal.h"
int irjp_is_whitespace(char c);
int irjp_copy_string_quoted(char* restrict dest, const char* restrict string, RJP_index length);
int irjp_copy_string_keyed(char* restrict dest, const char* restrict string, RJP_index length);
char* irjp_convert_string(const char* str, RJP_index length, RJP_index* newlen);
char* irjp_convert_string(const char* str, RJP_index length, RJP_index* newlen, const RJP_memory_fns* fns);
RJP_index irjp_array_strlen(const RJP_value* arr, const int flags, int depth);
RJP_index irjp_object_strlen(const RJP_value* root, const int flags, int depth);
RJP_index irjp_value_strlen(const RJP_value* root, const int flags, int depth);
void irjp_strcpy(RJP_string* dest, const RJP_string* src);
void irjp_strcpy(RJP_string* dest, const RJP_string* src, const RJP_memory_fns* fns);
#endif

View File

@ -29,11 +29,11 @@ typedef struct RJP_unordered_object{
RJP_index num_members;
}RJP_unordered_object;
void irjp_copy_unordered_object(RJP_value* dest, const RJP_value* src);
void irjp_delete_unordered_object(RJP_value* obj);
RJP_value* irjp_add_unordered_member(RJP_value* dest, char* key, RJP_index keylen);
RJP_value* irjp_remove_unordered_member(RJP_value* obj, RJP_value* member);
void irjp_unordered_set_key(RJP_value* dest, char* key, RJP_index keylen);
void irjp_copy_unordered_object(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns);
void irjp_delete_unordered_object(RJP_value* obj, const RJP_memory_fns* fns);
RJP_value* irjp_add_unordered_member(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns);
RJP_value* irjp_remove_unordered_member(RJP_value* obj, RJP_value* member, const RJP_memory_fns* fns);
void irjp_unordered_set_key(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns);
RJP_index irjp_unordered_num_members(const RJP_value* object);
RJP_value* irjp_unordered_search_member(const RJP_value* object, const char* search);
void irjp_init_unordered_object_iterator(RJP_object_iterator* it, const RJP_value* object);

View File

@ -40,6 +40,6 @@ typedef struct RJP_value{
enum RJP_data_type type; //flag to determine active member of union
}RJP_value;
void irjp_delete_value(RJP_value* root);
void irjp_delete_value(RJP_value* root, const RJP_memory_fns* fns);
#endif

View File

@ -37,12 +37,12 @@ struct RJP_tree_node{
unsigned color:1;
};
RJP_tree_node* irjp_new_node(char* key, RJP_index keylen);
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, char* key, RJP_index keylen, RJP_value** added, int* status);
RJP_tree_node* irjp_new_node(char* key, RJP_index keylen, const RJP_memory_fns* fns);
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, char* key, RJP_index keylen, RJP_value** added, int* status, const RJP_memory_fns* fns);
RJP_tree_node* irjp_tree_insert_node(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode);
RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* restrict root, RJP_tree_node* restrict member, RJP_tree_node** removed_node);
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);
RJP_tree_node* irjp_copy_tree(const RJP_tree_node* root, const RJP_memory_fns* fns);
void irjp_free_tree(RJP_tree_node* root, const RJP_memory_fns* fns);
#endif

View File

@ -30,123 +30,187 @@
#include <stdio.h> //sprintf
RJP_value* rjp_new_null(void){
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
return rjp_new_null_c(&irjp_default_memory_fns);
}
RJP_value* rjp_new_int(RJP_int val){
return rjp_new_int_c(val, &irjp_default_memory_fns);
}
RJP_value* rjp_new_float(RJP_float val){
return rjp_new_float_c(val, &irjp_default_memory_fns);
}
RJP_value* rjp_new_bool(RJP_bool val){
return rjp_new_bool_c(val, &irjp_default_memory_fns);
}
RJP_value* rjp_new_string_steal(char* val, RJP_index length){
return rjp_new_string_steal_c(val, length, &irjp_default_memory_fns);
}
RJP_value* rjp_new_string(const char* value, RJP_index length){
return rjp_new_string_c(value, length, &irjp_default_memory_fns);
}
RJP_value* rjp_new_object(void){
return rjp_new_object_c(&irjp_default_memory_fns);
}
RJP_value* rjp_new_ordered_object(void){
return rjp_new_ordered_object_c(&irjp_default_memory_fns);
}
RJP_value* rjp_new_array(void){
return rjp_new_array_c(&irjp_default_memory_fns);
}
RJP_value* rjp_new_null_c(const RJP_memory_fns* fns){
RJP_value* ret = fns->alloc(sizeof(RJP_value));
memset(ret, 0, sizeof(RJP_value));
ret->type = rjp_json_null;
return ret;
}
RJP_value* rjp_new_int(RJP_int val){
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
RJP_value* rjp_new_int_c(RJP_int val, const RJP_memory_fns* fns){
RJP_value* ret = fns->alloc(sizeof(RJP_value));
memset(ret, 0, sizeof(RJP_value));
ret->type = rjp_json_integer;
ret->integer = val;
return ret;
}
RJP_value* rjp_new_float(RJP_float val){
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
RJP_value* rjp_new_float_c(RJP_float val, const RJP_memory_fns* fns){
RJP_value* ret = fns->alloc(sizeof(RJP_value));
memset(ret, 0, sizeof(RJP_value));
ret->type = rjp_json_dfloat;
ret->dfloat = val;
return ret;
}
RJP_value* rjp_new_bool(RJP_bool val){
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
RJP_value* rjp_new_bool_c(RJP_bool val, const RJP_memory_fns* fns){
RJP_value* ret = fns->alloc(sizeof(RJP_value));
memset(ret, 0, sizeof(RJP_value));
ret->type = rjp_json_boolean;
ret->boolean = val;
return ret;
}
RJP_value* rjp_new_string_steal(char* val, RJP_index length){
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
RJP_value* rjp_new_string_steal_c(char* val, RJP_index length, const RJP_memory_fns* fns){
RJP_value* ret = fns->alloc(sizeof(RJP_value));
memset(ret, 0, sizeof(RJP_value));
ret->type = rjp_json_string;
ret->string.value = val;
ret->string.length = length;
return ret;
}
RJP_value* rjp_new_string(const char* value, RJP_index length){
RJP_value* rjp_new_string_c(const char* value, RJP_index length, const RJP_memory_fns* fns){
UNUSED_VARIABLE(length);
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
RJP_value* ret = fns->alloc(sizeof(RJP_value));
memset(ret, 0, sizeof(RJP_value));
ret->type = rjp_json_string;
RJP_index esclen = rjp_escape_strlen(value);
ret->string.value = rjp_alloc(esclen+1);
ret->string.value = fns->alloc(esclen+1);
rjp_escape_strcpy(ret->string.value, value);
ret->string.value[esclen] = 0;
ret->string.length = esclen;
return ret;
}
RJP_value* rjp_new_object(void){
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
RJP_value* rjp_new_object_c(const RJP_memory_fns* fns){
RJP_value* ret = fns->alloc(sizeof(RJP_value));
memset(ret, 0, sizeof(RJP_value));
ret->type = rjp_json_object;
return ret;
}
RJP_value* rjp_new_ordered_object(void){
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
RJP_value* rjp_new_ordered_object_c(const RJP_memory_fns* fns){
RJP_value* ret = fns->alloc(sizeof(RJP_value));
memset(ret, 0, sizeof(RJP_value));
ret->type = rjp_json_ordered_object;
return ret;
}
RJP_value* rjp_new_array(void){
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
RJP_value* rjp_new_array_c(const RJP_memory_fns* fns){
RJP_value* ret = fns->alloc(sizeof(RJP_value));
memset(ret, 0, sizeof(RJP_value));
ret->type = rjp_json_array;
return ret;
}
RJP_value* rjp_set_null(RJP_value* v){
irjp_delete_value(v);
return rjp_set_null_c(v, &irjp_default_memory_fns);
}
RJP_value* rjp_set_int(RJP_value* v, RJP_int val){
return rjp_set_int_c(v, val, &irjp_default_memory_fns);
}
RJP_value* rjp_set_float(RJP_value* v, RJP_float val){
return rjp_set_float_c(v, val, &irjp_default_memory_fns);
}
RJP_value* rjp_set_bool(RJP_value* v, RJP_bool val){
return rjp_set_bool_c(v, val, &irjp_default_memory_fns);
}
RJP_value* rjp_set_string_steal(RJP_value* v, char* val, RJP_index len){
return rjp_set_string_steal_c(v, val, len, &irjp_default_memory_fns);
}
RJP_value* rjp_set_string(RJP_value* v, const char* val, RJP_index length){
return rjp_set_string_c(v, val, length, &irjp_default_memory_fns);
}
RJP_value* rjp_set_object(RJP_value* v){
return rjp_set_object_c(v, &irjp_default_memory_fns);
}
RJP_value* rjp_set_ordered_object(RJP_value* v){
return rjp_set_ordered_object_c(v, &irjp_default_memory_fns);
}
RJP_value* rjp_set_array(RJP_value* v){
return rjp_set_array_c(v, &irjp_default_memory_fns);
}
RJP_value* rjp_set_null_c(RJP_value* v, const RJP_memory_fns* fns){
irjp_delete_value(v, fns);
v->type = rjp_json_null;
return v;
}
RJP_value* rjp_set_int(RJP_value* v, RJP_int val){
irjp_delete_value(v);
RJP_value* rjp_set_int_c(RJP_value* v, RJP_int val, const RJP_memory_fns* fns){
irjp_delete_value(v, fns);
v->type = rjp_json_integer;
v->integer = val;
return v;
}
RJP_value* rjp_set_float(RJP_value* v, RJP_float val){
irjp_delete_value(v);
RJP_value* rjp_set_float_c(RJP_value* v, RJP_float val, const RJP_memory_fns* fns){
irjp_delete_value(v, fns);
v->type = rjp_json_dfloat;
v->dfloat = val;
return v;
}
RJP_value* rjp_set_bool(RJP_value* v, RJP_bool val){
irjp_delete_value(v);
RJP_value* rjp_set_bool_c(RJP_value* v, RJP_bool val, const RJP_memory_fns* fns){
irjp_delete_value(v, fns);
v->type = rjp_json_boolean;
v->boolean = val;
return v;
}
RJP_value* rjp_set_string_steal(RJP_value* v, char* val, RJP_index len){
irjp_delete_value(v);
RJP_value* rjp_set_string_steal_c(RJP_value* v, char* val, RJP_index len, const RJP_memory_fns* fns){
irjp_delete_value(v, fns);
v->type = rjp_json_string;
v->string.value = val;
v->string.length = len;
return v;
}
RJP_value* rjp_set_string(RJP_value* v, const char* val, RJP_index length){
RJP_value* rjp_set_string_c(RJP_value* v, const char* val, RJP_index length, const RJP_memory_fns* fns){
UNUSED_VARIABLE(length);
irjp_delete_value(v);
irjp_delete_value(v, fns);
v->type = rjp_json_string;
RJP_index esclen = rjp_escape_strlen(val);
v->string.value = rjp_alloc(esclen+1);
v->string.value = fns->alloc(esclen+1);
rjp_escape_strcpy(v->string.value, val);
v->string.value[esclen] = 0;
v->string.length = esclen;
return v;
}
RJP_value* rjp_set_object(RJP_value* v){
RJP_value* rjp_set_object_c(RJP_value* v, const RJP_memory_fns* fns){
if(v->type == rjp_json_object)
return v;
irjp_delete_value(v);
irjp_delete_value(v, fns);
memset(&v->object, 0, sizeof(RJP_unordered_object));
v->type = rjp_json_object;
return v;
}
RJP_value* rjp_set_ordered_object(RJP_value* v){
RJP_value* rjp_set_ordered_object_c(RJP_value* v, const RJP_memory_fns* fns){
if(v->type == rjp_json_ordered_object)
return v;
irjp_delete_value(v);
irjp_delete_value(v, fns);
memset(&v->orobject, 0, sizeof(RJP_ordered_object));
v->type = rjp_json_ordered_object;
return v;
}
RJP_value* rjp_set_array(RJP_value* v){
RJP_value* rjp_set_array_c(RJP_value* v, const RJP_memory_fns* fns){
if(v->type == rjp_json_array)
return v;
irjp_delete_value(v);
irjp_delete_value(v, fns);
memset(&v->array, 0, sizeof(RJP_array));
v->type = rjp_json_array;
return v;
@ -279,12 +343,15 @@ RJP_index irjp_dump_object(const RJP_value* root, char* dest, const int flags, i
}
char* rjp_to_json(const RJP_value* root, const int flags){
return rjp_to_json_c(root, flags, &irjp_default_memory_fns);
}
char* rjp_to_json_c(const RJP_value* root, const int flags, const RJP_memory_fns* fns){
if(!root)
return NULL;
RJP_index len = irjp_value_strlen(root, flags, 0);
if(!len)
return NULL;
char* tmp = rjp_alloc(len + 1);
char* tmp = fns->alloc(len + 1);
tmp[len] = 0;
irjp_write_value(tmp, root, flags, 0);

View File

@ -34,28 +34,33 @@ void rjp_free(void* data){
free(data);
}
const RJP_memory_fns irjp_default_memory_fns = {rjp_free, rjp_alloc};
RJP_value* rjp_copy_value(RJP_value* dest, const RJP_value* src){
return rjp_copy_value_c(dest, src, &irjp_default_memory_fns);
}
RJP_value* rjp_copy_value_c(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns){
RJP_value* ret;
if(dest){
irjp_delete_value(dest);
irjp_delete_value(dest, fns);
ret = dest;
}else{
ret = rjp_new_null();
ret = rjp_new_null_c(fns);
}
ret->type = src->type;
switch(src->type){
case rjp_json_object:
irjp_copy_object(ret, src);
irjp_copy_object(ret, src, fns);
break;
case rjp_json_ordered_object:
irjp_copy_ordered_object(ret, src);
irjp_copy_ordered_object(ret, src, fns);
break;
case rjp_json_array:
irjp_copy_array(ret, src);
irjp_copy_array(ret, src, fns);
break;
case rjp_json_string:
irjp_strcpy(&ret->string, &src->string);
irjp_strcpy(&ret->string, &src->string, fns);
break;
case rjp_json_integer:
ret->integer = src->integer;
@ -77,37 +82,40 @@ RJP_value* rjp_move_value(RJP_value* dest, RJP_value* src){
return dest;
}
static void irjp_delete_array(RJP_value* root){
static void irjp_delete_array(RJP_value* root, const RJP_memory_fns* fns){
RJP_array_iterator it;
rjp_init_array_iterator(&it, root);
RJP_value* next = rjp_array_iterator_current(&it);
for(RJP_value* current = next;current;current = next){
next = rjp_array_iterator_next(&it);
rjp_free_value(current);
rjp_free_value_c(current, fns);
}
}
void irjp_delete_value(RJP_value* root){
void irjp_delete_value(RJP_value* root, const RJP_memory_fns* fns){
switch(root->type){
case rjp_json_object:
case rjp_json_ordered_object:
irjp_delete_object(root);
irjp_delete_object(root, fns);
break;
case rjp_json_array:
irjp_delete_array(root);
irjp_delete_array(root, fns);
break;
case rjp_json_string:
rjp_free(root->string.value);
fns->free(root->string.value);
break;
default: break;
};
}
void rjp_free_value(RJP_value* root){
rjp_free_value_c(root, &irjp_default_memory_fns);
}
void rjp_free_value_c(RJP_value* root, const RJP_memory_fns* fns){
if(!root)
return;
irjp_delete_value(root);
rjp_free(root);
irjp_delete_value(root, fns);
fns->free(root);
}
/* VALUE SETTING */

View File

@ -17,42 +17,51 @@
*/
#include <stddef.h>
#include <string.h> //memset
#include "rjp_internal.h"
#include "rjp_array.h"
#include "rjp_value.h"
#include "rjp_array_element.h"
void irjp_copy_array(RJP_value* dest, const RJP_value* src){
void irjp_copy_array(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns){
dest->array.elements = dest->array.last = NULL;
for(RJP_array_element* curr = src->array.elements;curr;curr = curr->next){
RJP_value* copy_mem;
copy_mem = rjp_new_element(dest);
rjp_copy_value(copy_mem, &curr->value);
copy_mem = rjp_new_element_c(dest, fns);
rjp_copy_value_c(copy_mem, &curr->value, fns);
}
}
void irjp_add_element(RJP_array* j){
void irjp_add_element(RJP_array* j, const RJP_memory_fns* fns){
++j->num_elements;
if(!j->elements){
j->elements = rjp_calloc(1, sizeof(RJP_array_element));
j->elements = fns->alloc(sizeof(RJP_array_element));
memset(j->elements, 0, sizeof(RJP_array_element));
j->last = j->elements;
}else{
j->last->next = rjp_calloc(1, sizeof(RJP_array_element));
j->last->next = fns->alloc(sizeof(RJP_array_element));
memset(j->last->next, 0, sizeof(RJP_array_element));
j->last = j->last->next;
j->last->prev = j->last;
}
}
RJP_value* rjp_new_element(RJP_value* dest){
irjp_add_element(&dest->array);
return rjp_new_element_c(dest, &irjp_default_memory_fns);
}
RJP_value* rjp_new_element_c(RJP_value* dest, const RJP_memory_fns* fns){
irjp_add_element(&dest->array, fns);
dest->array.last->value.parent = dest;
return &dest->array.last->value;
}
RJP_value* rjp_add_element(RJP_value* dest, RJP_value* src){
RJP_value* newelm = rjp_new_element(dest);
return rjp_add_element_c(dest, src, &irjp_default_memory_fns);
}
RJP_value* rjp_add_element_c(RJP_value* dest, RJP_value* src, const RJP_memory_fns* fns){
RJP_value* newelm = rjp_new_element_c(dest, fns);
if(!newelm)
return NULL;
rjp_move_value(newelm, src);
rjp_free(src);
fns->free(src);
return newelm;
}
RJP_value* rjp_remove_element(RJP_value* dest, RJP_value* value){
@ -75,8 +84,11 @@ RJP_value* rjp_remove_element(RJP_value* dest, RJP_value* value){
return value;
}
void rjp_free_element(RJP_value* dest, RJP_value* value){
rjp_free_element_c(dest, value, &irjp_default_memory_fns);
}
void rjp_free_element_c(RJP_value* dest, RJP_value* value, const RJP_memory_fns* fns){
rjp_remove_element(dest, value);
rjp_free_value(value);
rjp_free_value_c(value, fns);
}
RJP_index rjp_num_elements(const RJP_value* array){
return array->array.num_elements;

View File

@ -25,29 +25,32 @@
#include <string.h> //strlen, strncpy
void irjp_copy_object(RJP_value* dest, const RJP_value* src){
void irjp_copy_object(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns){
switch(src->type){
case rjp_json_object:
irjp_copy_unordered_object(dest, src);
irjp_copy_unordered_object(dest, src, fns);
break;
case rjp_json_ordered_object:
irjp_copy_ordered_object(dest, src);
irjp_copy_ordered_object(dest, src, fns);
break;
default: break;
};
}
void irjp_delete_object(RJP_value* obj){
void irjp_delete_object(RJP_value* obj, const RJP_memory_fns* fns){
switch(obj->type){
case rjp_json_object:
irjp_delete_unordered_object(obj);
irjp_delete_unordered_object(obj, fns);
break;
case rjp_json_ordered_object:
irjp_delete_ordered_object(obj);
irjp_delete_ordered_object(obj, fns);
break;
default: break;
};
}
RJP_value* rjp_new_member_steal_key(RJP_value* dest, char* key, RJP_index keylen){
return rjp_new_member_steal_key_c(dest, key, keylen, &irjp_default_memory_fns);
}
RJP_value* rjp_new_member_steal_key_c(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns){
if(!key)
return NULL;
if(!keylen)
@ -55,78 +58,105 @@ RJP_value* rjp_new_member_steal_key(RJP_value* dest, char* key, RJP_index keylen
return NULL;
switch(dest->type){
case rjp_json_object:
return irjp_add_unordered_member(dest, key, keylen);
return irjp_add_unordered_member(dest, key, keylen, fns);
case rjp_json_ordered_object:
return irjp_add_ordered_member(dest, key, keylen);
return irjp_add_ordered_member(dest, key, keylen, fns);
default: break;
};
return NULL;
}
RJP_value* rjp_new_member(RJP_value* dest, const char* key, RJP_index keylen){
return rjp_new_member_c(dest, key, keylen, &irjp_default_memory_fns);
}
RJP_value* rjp_new_member_c(RJP_value* dest, const char* key, RJP_index keylen, const RJP_memory_fns* fns){
if(!key)
return NULL;
if(!keylen)
if(!(keylen = rjp_escape_strlen(key)))
return NULL;
char* newkey = rjp_alloc(keylen+1);
char* newkey = fns->alloc(keylen+1);
rjp_escape_strcpy(newkey, key);
newkey[keylen] = 0;
return rjp_new_member_steal_key(dest, newkey, keylen);
return rjp_new_member_steal_key_c(dest, newkey, keylen, fns);
}
RJP_value* rjp_add_member_steal_key(RJP_value* dest, char* key, RJP_index keylen, RJP_value* src){
RJP_value* newval = rjp_new_member_steal_key(dest, key, keylen);
return rjp_add_member_steal_key_c(dest, key, keylen, src, &irjp_default_memory_fns);
}
RJP_value* rjp_add_member_steal_key_c(RJP_value* dest, char* key, RJP_index keylen, RJP_value* src, const RJP_memory_fns* fns){
RJP_value* newval = rjp_new_member_steal_key_c(dest, key, keylen, fns);
if(!newval)
return NULL;
rjp_move_value(newval, src);
rjp_free(src);
fns->free(src);
return newval;
}
RJP_value* rjp_add_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_value* src){
RJP_value* newval = rjp_new_member(dest, key, keylen);
return rjp_add_member_c(dest, key, keylen, src, &irjp_default_memory_fns);
}
RJP_value* rjp_add_member_c(RJP_value* dest, const char* key, RJP_index keylen, RJP_value* src, const RJP_memory_fns* fns){
RJP_value* newval = rjp_new_member_c(dest, key, keylen, fns);
if(!newval)
return NULL;
rjp_move_value(newval, src);
rjp_free(src);
fns->free(src);
return newval;
}
RJP_value* rjp_remove_member_by_key(RJP_value* obj, const char* key){
return rjp_remove_member_by_key_c(obj, key, &irjp_default_memory_fns);
}
RJP_value* rjp_remove_member_by_key_c(RJP_value* obj, const char* key, const RJP_memory_fns* fns){
RJP_value* member = rjp_search_member(obj, key);
if(!member)
return NULL;
return rjp_remove_member(obj, member);
return rjp_remove_member_c(obj, member, fns);
}
RJP_value* rjp_remove_member(RJP_value* obj, RJP_value* member){
return rjp_remove_member_c(obj, member, &irjp_default_memory_fns);
}
RJP_value* rjp_remove_member_c(RJP_value* obj, RJP_value* member, const RJP_memory_fns* fns){
if(member->parent != obj)
return NULL;
switch(obj->type){
case rjp_json_object:
return irjp_remove_unordered_member(obj, member);
return irjp_remove_unordered_member(obj, member, fns);
case rjp_json_ordered_object:
return irjp_remove_ordered_member(obj, member);
return irjp_remove_ordered_member(obj, member, fns);
default: break;
};
return NULL;
}
void rjp_free_member_by_key(RJP_value* obj, const char* key){
rjp_free_member_by_key_c(obj, key, &irjp_default_memory_fns);
}
void rjp_free_member_by_key_c(RJP_value* obj, const char* key, const RJP_memory_fns* fns){
RJP_value* removed = rjp_remove_member_by_key(obj, key);
rjp_free_value(removed);
rjp_free_value_c(removed, fns);
}
void rjp_free_member(RJP_value* obj, RJP_value* member){
rjp_free_member_by_key(obj, ((RJP_object_member*)member)->name.value);
rjp_free_member_c(obj, member, &irjp_default_memory_fns);
}
void rjp_free_member_c(RJP_value* obj, RJP_value* member, const RJP_memory_fns* fns){
rjp_free_member_by_key_c(obj, ((RJP_object_member*)member)->name.value, fns);
}
RJP_value* rjp_set_key(RJP_value* dest, const char* key, RJP_index keylen){
return rjp_set_key_c(dest, key, keylen, &irjp_default_memory_fns);
}
RJP_value* rjp_set_key_c(RJP_value* dest, const char* key, RJP_index keylen, const RJP_memory_fns* fns){
if(!key)
return NULL;
if(!keylen){
if(!(keylen = strlen(key)))
return NULL;
}
char* newkey = rjp_alloc(keylen + 1);
char* newkey = fns->alloc(keylen + 1);
strncpy(newkey, key, keylen+1);
return rjp_set_key_steal(dest, newkey, keylen);
}
RJP_value* rjp_set_key_steal(RJP_value* dest, char* key, RJP_index keylen){
return rjp_set_key_steal_c(dest, key, keylen, &irjp_default_memory_fns);
}
RJP_value* rjp_set_key_steal_c(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns){
if(!key)
return NULL;
if(!keylen){
@ -135,10 +165,10 @@ RJP_value* rjp_set_key_steal(RJP_value* dest, char* key, RJP_index keylen){
}
switch(dest->parent->type){
case rjp_json_object:
irjp_unordered_set_key(dest, key, keylen);
irjp_unordered_set_key(dest, key, keylen, fns);
break;
case rjp_json_ordered_object:
irjp_ordered_set_key(dest, key, keylen);
irjp_ordered_set_key(dest, key, keylen, fns);
break;
default: break;
};
@ -233,6 +263,9 @@ RJP_value* rjp_object_iterator_peek(const RJP_object_iterator* it){
}
RJP_value* rjp_object_to_ordered(RJP_value* object){
return rjp_object_to_ordered_c(object, &irjp_default_memory_fns);
}
RJP_value* rjp_object_to_ordered_c(RJP_value* object, const RJP_memory_fns* fns){
if(object->type == rjp_json_ordered_object)
return object;
RJP_value newobj = {0};
@ -242,11 +275,11 @@ RJP_value* rjp_object_to_ordered(RJP_value* object){
irjp_init_unordered_object_iterator(&it, object);
RJP_value* next = irjp_unordered_object_iterator_current(&it);
for(RJP_value* current = next;current;current = next){
RJP_value* newcur = irjp_add_ordered_member(&newobj, rjp_member_key(current)->value, rjp_member_key(current)->length);
RJP_value* newcur = irjp_add_ordered_member(&newobj, rjp_member_key(current)->value, rjp_member_key(current)->length, fns);
((RJP_object_member*)current)->name.value = NULL;
rjp_move_value(newcur, current);
next = irjp_unordered_object_iterator_next(&it);
rjp_free(current);
fns->free(current);
}
irjp_delete_unordered_object_iterator(&it);
@ -256,6 +289,9 @@ RJP_value* rjp_object_to_ordered(RJP_value* object){
return object;
}
RJP_value* rjp_object_to_unordered(RJP_value* object){
return rjp_object_to_unordered_c(object, &irjp_default_memory_fns);
}
RJP_value* rjp_object_to_unordered_c(RJP_value* object, const RJP_memory_fns* fns){
if(object->type == rjp_json_object)
return object;
RJP_value newobj = {0};
@ -265,11 +301,11 @@ RJP_value* rjp_object_to_unordered(RJP_value* object){
irjp_init_ordered_object_iterator(&it, object);
RJP_value* next = irjp_ordered_object_iterator_current(&it);
for(RJP_value* current = next;current;current = next){
RJP_value* newcur = irjp_add_unordered_member(&newobj, rjp_member_key(current)->value, rjp_member_key(current)->length);
RJP_value* newcur = irjp_add_unordered_member(&newobj, rjp_member_key(current)->value, rjp_member_key(current)->length, fns);
((RJP_object_member*)current)->name.value = NULL;
rjp_move_value(newcur, current);
next = irjp_ordered_object_iterator_next(&it);
rjp_free(current);
fns->free(current);
}
irjp_delete_ordered_object_iterator(&it);

View File

@ -30,33 +30,33 @@ typedef struct RJP_ordered_member{
struct RJP_ordered_member* next;
}RJP_ordered_member;
static void irjp_copy_ordered_member(RJP_ordered_member* dest, const RJP_ordered_member* src){
irjp_strcpy(&dest->member.name, &src->member.name);
rjp_copy_value(&dest->member.value, &src->member.value);
static void irjp_copy_ordered_member(RJP_ordered_member* dest, const RJP_ordered_member* src, const RJP_memory_fns* fns){
irjp_strcpy(&dest->member.name, &src->member.name, fns);
rjp_copy_value_c(&dest->member.value, &src->member.value, fns);
}
void irjp_copy_ordered_object(RJP_value* dest, const RJP_value* src){
irjp_delete_ordered_object(dest);
void irjp_copy_ordered_object(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns){
irjp_delete_ordered_object(dest, fns);
dest->orobject.num_members = 0;
RJP_object_iterator it;
irjp_init_ordered_object_iterator(&it, src);
for(const RJP_value* current = irjp_ordered_object_iterator_current(&it);current;current = irjp_ordered_object_iterator_next(&it)){
RJP_string keycopy;
irjp_strcpy(&keycopy, &((RJP_object_member*)current)->name);
RJP_ordered_member* newmemb = (RJP_ordered_member*)irjp_add_ordered_member(dest, keycopy.value, keycopy.length);
irjp_copy_ordered_member(newmemb, (RJP_ordered_member*)current);
irjp_strcpy(&keycopy, &((RJP_object_member*)current)->name, fns);
RJP_ordered_member* newmemb = (RJP_ordered_member*)irjp_add_ordered_member(dest, keycopy.value, keycopy.length, fns);
irjp_copy_ordered_member(newmemb, (RJP_ordered_member*)current, fns);
}
irjp_delete_ordered_object_iterator(&it);
}
void irjp_delete_ordered_object(RJP_value* obj){
void irjp_delete_ordered_object(RJP_value* obj, const RJP_memory_fns* fns){
RJP_object_iterator it;
irjp_init_ordered_object_iterator(&it, obj);
RJP_value* next = irjp_ordered_object_iterator_current(&it);
for(RJP_value* current = next;current;current = next){
next = irjp_ordered_object_iterator_next(&it);
rjp_free(((RJP_object_member*)current)->name.value);
rjp_free_value(current);
fns->free(((RJP_object_member*)current)->name.value);
rjp_free_value_c(current, fns);
}
irjp_delete_ordered_object_iterator(&it);
}
@ -73,15 +73,16 @@ static RJP_ordered_member* irjp_append_ordered_member(RJP_ordered_object* dest,
dest->last = newmemb;
return newmemb;
}
RJP_value* irjp_add_ordered_member(RJP_value* dest, char* key, RJP_index keylen){
RJP_ordered_member* newmemb = rjp_calloc(1, sizeof(RJP_ordered_member));
RJP_value* irjp_add_ordered_member(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns){
RJP_ordered_member* newmemb = fns->alloc(sizeof(RJP_ordered_member));
memset(newmemb, 0, sizeof(RJP_ordered_member));
irjp_append_ordered_member((RJP_ordered_object*)dest, newmemb);
irjp_ordered_set_key((RJP_value*)newmemb, key, keylen);
irjp_ordered_set_key((RJP_value*)newmemb, key, keylen, fns);
((RJP_value*)newmemb)->parent = dest;
((RJP_value*)newmemb)->type = rjp_json_null;
return (RJP_value*)newmemb;
}
RJP_value* irjp_remove_ordered_member(RJP_value* obj, RJP_value* member){
RJP_value* irjp_remove_ordered_member(RJP_value* obj, RJP_value* member, const RJP_memory_fns* fns){
RJP_ordered_member* current = (RJP_ordered_member*)member;
RJP_ordered_member* prev = current->prev;
RJP_ordered_member* next = current->next;
@ -97,11 +98,12 @@ RJP_value* irjp_remove_ordered_member(RJP_value* obj, RJP_value* member){
obj->orobject.last = prev;
member->parent = NULL;
fns->free(((RJP_object_member*)member)->name.value);
return member;
}
void irjp_ordered_set_key(RJP_value* dest, char* key, RJP_index keylen){
void irjp_ordered_set_key(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns){
RJP_object_member* mem = (RJP_object_member*)dest;
rjp_free(mem->name.value);
fns->free(mem->name.value);
mem->name.value = key;
mem->name.length = keylen;
}

View File

@ -104,7 +104,7 @@ static void irjp_parse_stack_set(RJP_parse_stack* s, RJP_parse_target target){
s->stack[s->position] = target;
}
static int irjp_init_value(RJP_value* newval, RJP_lex_category cat, RJP_parse_state* state){
static int irjp_init_value(RJP_value* newval, RJP_lex_category cat, RJP_parse_state* state, const RJP_memory_fns* fns){
RJP_index length = state->lexstate.length;
RJP_index offset = state->lexstate.offset;
const char* str = state->lexstate.str + offset;
@ -112,7 +112,7 @@ static int irjp_init_value(RJP_value* newval, RJP_lex_category cat, RJP_parse_st
case rjp_lex_string:;
RJP_index newlength;
newval->type = rjp_json_string;
newval->string.value = irjp_convert_string(str, length, &newlength);
newval->string.value = irjp_convert_string(str, length, &newlength, fns);
if(!newval->string.value)
return 1;
newval->string.length = newlength;
@ -152,20 +152,20 @@ static int irjp_init_value(RJP_value* newval, RJP_lex_category cat, RJP_parse_st
};
return 0;
}
static RJP_value* irjp_add_value_to_array(RJP_lex_category cat, RJP_parse_state* state){
state->lastadded = rjp_new_element(state->curr);
if(irjp_init_value(state->lastadded, cat, state))
static RJP_value* irjp_add_value_to_array(RJP_lex_category cat, RJP_parse_state* state, const RJP_memory_fns* fns){
state->lastadded = rjp_new_element_c(state->curr, fns);
if(irjp_init_value(state->lastadded, cat, state, fns))
return NULL;
return state->lastadded;
}
static RJP_value* irjp_add_value_to_object(RJP_parse_state* state, const char* key, RJP_index keylen){
static RJP_value* irjp_add_value_to_object(RJP_parse_state* state, const char* key, RJP_index keylen, const RJP_memory_fns* fns){
RJP_index newlen;
char* newkey = irjp_convert_string(key, keylen, &newlen);
char* newkey = irjp_convert_string(key, keylen, &newlen, fns);
if(!newlen){ //cannot have empty key
rjp_free(newkey);
fns->free(newkey);
return NULL;
}
return (state->lastadded = rjp_new_member_steal_key(state->curr, newkey, newlen));
return (state->lastadded = rjp_new_member_steal_key_c(state->curr, newkey, newlen, fns));
}
@ -176,25 +176,26 @@ static RJP_lex_category irjp_convert_comment(_Bool allow_comments){
return rjp_lex_invalid;
}
static void irjp_init_parse_state(RJP_parse_state* state, const char* str){
static void irjp_init_parse_state(RJP_parse_state* state, const char* str, const RJP_memory_fns* fns){
state->column = 1;
state->row = 1;
irjp_init_parse_stack(&state->target_stack);
state->lexstate.str = (char*)str;
state->root = state->curr = state->lastadded = rjp_calloc(1, sizeof(RJP_value));
state->root = state->curr = state->lastadded = fns->alloc(sizeof(RJP_value));
memset(state->root, 0, sizeof(RJP_value));
}
static void irjp_delete_parse_state(RJP_parse_state* state){
irjp_delete_parse_stack(&state->target_stack);
irjp_delete_lex_state(&state->lexstate);
}
static void irjp_delete_parse_state_no_preserve_root(RJP_parse_state* state){
static void irjp_delete_parse_state_no_preserve_root(RJP_parse_state* state, const RJP_memory_fns* fns){
irjp_delete_parse_state(state);
rjp_free_value(state->root);
rjp_free_value_c(state->root, fns);
state->root = NULL;
}
static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_parse_state* state){
static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_parse_state* state, const RJP_memory_fns* fns){
if(cat == rjp_lex_line_comment || cat == rjp_lex_block_comment)
cat = irjp_convert_comment(state->allow_comments);
@ -212,7 +213,7 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_parse_state* state
case rjp_parse_start:
irjp_parse_stack_set(&state->target_stack, rjp_parse_end);
if(irjp_init_value(state->root, cat, state)){
if(irjp_init_value(state->root, cat, state, fns)){
return RJP_PARSE_STATUS_NO_ROOT_VALUE;
}
break;
@ -225,7 +226,7 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_parse_state* state
case rjp_parse_mem_key:
if(cat == rjp_lex_string){
irjp_parse_stack_set(&state->target_stack, rjp_parse_key_colon);
if(!irjp_add_value_to_object(state, state->lexstate.str+state->lexstate.offset, state->lexstate.length)){
if(!irjp_add_value_to_object(state, state->lexstate.str+state->lexstate.offset, state->lexstate.length, fns)){
return RJP_PARSE_STATUS_MISSING_KEY;
}
}else{
@ -241,7 +242,7 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_parse_state* state
//fallthrough
case rjp_parse_arr_value:
irjp_parse_stack_set(&state->target_stack, rjp_parse_arr_comma);
if(!irjp_add_value_to_array(cat, state))
if(!irjp_add_value_to_array(cat, state, fns))
return RJP_PARSE_STATUS_MISSING_VALUE;
}
break;
@ -253,7 +254,7 @@ static int irjp_parse_handle_lexcat(RJP_lex_category cat, RJP_parse_state* state
break;
case rjp_parse_obj_value:
irjp_parse_stack_set(&state->target_stack, rjp_parse_obj_comma);
if(irjp_init_value(state->lastadded, cat, state)){
if(irjp_init_value(state->lastadded, cat, state, fns)){
return RJP_PARSE_STATUS_MISSING_VALUE;
}
break;
@ -296,28 +297,31 @@ static int irjp_handle_final_parse_token(RJP_parse_state* state, RJP_lex_categor
}
//Basic parse loop
static int irjp_parse(RJP_parse_state* state){
static int irjp_parse(RJP_parse_state* state, const RJP_memory_fns* fns){
RJP_lex_category cat;
RJP_parse_status status;
for(cat = irjp_lex(&state->lexstate);cat & rjp_lex_accept;cat = irjp_lex(&state->lexstate),state->row += state->lexstate.length){
if((status = irjp_parse_handle_lexcat(cat, state)) != RJP_PARSE_STATUS_SUC)
if((status = irjp_parse_handle_lexcat(cat, state, fns)) != RJP_PARSE_STATUS_SUC)
return status;
}
return irjp_handle_final_parse_token(state, cat);
}
//Callback parse loop
static int irjp_parse_cback(RJP_parse_state* state, RJP_parse_callback* cback){
static int irjp_parse_cback(RJP_parse_state* state, RJP_parse_callback* cback, const RJP_memory_fns* fns){
RJP_lex_category cat;
RJP_parse_status status;
for(cat = irjp_lex_cback(&state->lexstate, cback);cat & rjp_lex_accept;cat = irjp_lex_cback(&state->lexstate, cback),state->row += state->lexstate.length){
if((status = irjp_parse_handle_lexcat(cat, state)) != RJP_PARSE_STATUS_SUC)
if((status = irjp_parse_handle_lexcat(cat, state, fns)) != RJP_PARSE_STATUS_SUC)
return status;
}
return irjp_handle_final_parse_token(state, cat);
}
char* rjp_parse_error_to_string(const RJP_parse_error* err){
return rjp_parse_error_to_string_c(err, &irjp_default_memory_fns);
}
char* rjp_parse_error_to_string_c(const RJP_parse_error* err, const RJP_memory_fns* fns){
const RJP_parse_state* state = (const RJP_parse_state*)err->parsestate;
RJP_parse_status status = err->errcode;
char* buffer = NULL;
@ -325,42 +329,42 @@ char* rjp_parse_error_to_string(const RJP_parse_error* err){
switch(status){
case RJP_PARSE_STATUS_MISSING_VALUE:
format = "Expected value before '%.*s'";
buffer = rjp_alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
buffer = fns->alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
sprintf(buffer, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset));
break;
case RJP_PARSE_STATUS_MISSING_COMMA:
format = "Expected comma before '%.*s'";
buffer = rjp_alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
buffer = fns->alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
sprintf(buffer, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset));
break;
case RJP_PARSE_STATUS_INVALID:
format = "Invalid lex token '%.*s'";
buffer = rjp_alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
buffer = fns->alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
sprintf(buffer, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset));
break;
case RJP_PARSE_STATUS_NO_ROOT_VALUE:
format = "Missing root JSON value";
buffer = rjp_alloc(snprintf(NULL, 0, "%s", format) + 1);
buffer = fns->alloc(snprintf(NULL, 0, "%s", format) + 1);
sprintf(buffer, "%s", format);
break;
case RJP_PARSE_STATUS_MISSING_KEY:
format = "Expected key before '%.*s'";
buffer = rjp_alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
buffer = fns->alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
sprintf(buffer, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset));
break;
case RJP_PARSE_STATUS_MISSING_COLON:
format = "Expected colon before '%.*s'";
buffer = rjp_alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
buffer = fns->alloc(snprintf(NULL, 0, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset)) + 1);
sprintf(buffer, format, (int)state->lexstate.length, (state->lexstate.str + state->lexstate.offset));
break;
case RJP_PARSE_STATUS_EXCESS_DATA:
format = "Excess data after JSON";
buffer = rjp_alloc(snprintf(NULL, 0, "%s", format) + 1);
buffer = fns->alloc(snprintf(NULL, 0, "%s", format) + 1);
sprintf(buffer, "%s", format);
break;
case RJP_PARSE_STATUS_MISSING_CLOSE_BRACE:
format = "Missing closing brace";
buffer = rjp_alloc(snprintf(NULL, 0, "%s", format) + 1);
buffer = fns->alloc(snprintf(NULL, 0, "%s", format) + 1);
sprintf(buffer, "%s", format);
break;
default:
@ -369,22 +373,28 @@ char* rjp_parse_error_to_string(const RJP_parse_error* err){
return buffer;
}
void rjp_delete_parse_error(RJP_parse_error* err){
irjp_delete_parse_state_no_preserve_root((RJP_parse_state*)err->parsestate);
rjp_delete_parse_error_c(err, &irjp_default_memory_fns);
}
void rjp_delete_parse_error_c(RJP_parse_error* err, const RJP_memory_fns* fns){
irjp_delete_parse_state_no_preserve_root((RJP_parse_state*)err->parsestate, fns);
rjp_free(err->parsestate);
}
RJP_value* rjp_simple_parse(const char* str){
return rjp_parse(str, RJP_PARSE_NO_EXT, NULL);
return rjp_parse_c(str, RJP_PARSE_NO_EXT, NULL, &irjp_default_memory_fns);
}
RJP_value* rjp_parse(const char* str, int flags, RJP_parse_error* err){
return rjp_parse_c(str, flags, err, &irjp_default_memory_fns);
}
RJP_value* rjp_parse_c(const char* str, int flags, RJP_parse_error* err, const RJP_memory_fns* fns){
RJP_parse_state* state = rjp_calloc(sizeof(RJP_parse_state), 1);
state->allow_comments = (flags & RJP_PARSE_ALLOW_COMMENTS);
state->allow_trail_comma = (flags & RJP_PARSE_ALLOW_TRAILING_COMMA);
irjp_init_parse_state(state, str);
irjp_init_parse_state(state, str, fns);
irjp_init_lex_state(&state->lexstate);
int status = irjp_parse(state);
int status = irjp_parse(state, fns);
if(status == RJP_PARSE_STATUS_SUC){
irjp_delete_parse_state(state);
RJP_value* root = state->root;
@ -397,7 +407,7 @@ RJP_value* rjp_parse(const char* str, int flags, RJP_parse_error* err){
err->row = state->column;
err->column = state->row;
}else{
irjp_delete_parse_state_no_preserve_root(state);
irjp_delete_parse_state_no_preserve_root(state, fns);
rjp_free(state);
}
return NULL;
@ -407,13 +417,16 @@ RJP_value* rjp_parse(const char* str, int flags, RJP_parse_error* err){
//Callback based parse. Runs identical to normal parsing except sets up callback
//lex state and calls callback lex function
RJP_value* rjp_parse_cback(int flags, RJP_parse_callback* cback, RJP_parse_error* err){
return rjp_parse_cback_c(flags, cback, err, &irjp_default_memory_fns);
}
RJP_value* rjp_parse_cback_c(int flags, RJP_parse_callback* cback, RJP_parse_error* err, const RJP_memory_fns* fns){
RJP_parse_state* state = rjp_calloc(sizeof(RJP_parse_state), 1);
state->allow_comments = (flags & RJP_PARSE_ALLOW_COMMENTS);
state->allow_trail_comma = (flags & RJP_PARSE_ALLOW_TRAILING_COMMA);
irjp_init_parse_state(state, NULL);
irjp_init_parse_state(state, NULL, fns);
irjp_init_lex_cback_state(&state->lexstate);
int status = irjp_parse_cback(state, cback);
int status = irjp_parse_cback(state, cback, fns);
if(status == RJP_PARSE_STATUS_SUC){
irjp_delete_parse_state(state);
RJP_value* root = state->root;
@ -426,7 +439,7 @@ RJP_value* rjp_parse_cback(int flags, RJP_parse_callback* cback, RJP_parse_error
err->row = state->column;
err->column = state->row;
}else{
irjp_delete_parse_state_no_preserve_root(state);
irjp_delete_parse_state_no_preserve_root(state, fns);
rjp_free(state);
}
return NULL;

View File

@ -163,7 +163,7 @@ int irjp_copy_string_keyed(char* restrict dest, const char* restrict string, RJP
dest[offset] = ':';
return offset+1;
}
char* irjp_convert_string(const char* str, RJP_index length, RJP_index* newlen){
char* irjp_convert_string(const char* str, RJP_index length, RJP_index* newlen, const RJP_memory_fns* fns){
char* newstring;
RJP_index oldpos = 1; //ignore opening quote
--length; //ignore closing quote
@ -184,7 +184,7 @@ char* irjp_convert_string(const char* str, RJP_index length, RJP_index* newlen){
return NULL;
}
}
newstring = rjp_alloc(newlength + 1);
newstring = fns->alloc(newlength + 1);
newstring[newlength] = 0;
*newlen = newlength;
oldpos = 1;
@ -276,8 +276,8 @@ RJP_index rjp_escape_strcpy(char* dest, const char* src){
dest[j] = 0;
return j;
}
void irjp_strcpy(RJP_string* dest, const RJP_string* src){
dest->value = rjp_alloc(src->length + 1);
void irjp_strcpy(RJP_string* dest, const RJP_string* src, const RJP_memory_fns* fns){
dest->value = fns->alloc(src->length + 1);
strcpy(dest->value, src->value);
dest->value[src->length] = 0;
dest->length = src->length;

View File

@ -79,36 +79,36 @@ static RJP_tree_node* irjp_double_peek_tree_stack(RJP_tree_stack* stack){
}
/* RJP_OBJECT */
void irjp_copy_unordered_object(RJP_value* dest, const RJP_value* src){
dest->object.root = irjp_copy_tree(src->object.root);
void irjp_copy_unordered_object(RJP_value* dest, const RJP_value* src, const RJP_memory_fns* fns){
dest->object.root = irjp_copy_tree(src->object.root, fns);
}
void irjp_delete_unordered_object(RJP_value* obj){
irjp_free_tree(obj->object.root);
void irjp_delete_unordered_object(RJP_value* obj, const RJP_memory_fns* fns){
irjp_free_tree(obj->object.root, fns);
}
RJP_value* irjp_add_unordered_member(RJP_value* dest, char* key, RJP_index keylen){
RJP_value* irjp_add_unordered_member(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns){
++dest->object.num_members;
int status;
RJP_value* retval;
dest->object.root = irjp_tree_insert_value(dest->object.root, key, keylen, &retval, &status);
dest->object.root = irjp_tree_insert_value(dest->object.root, key, keylen, &retval, &status, fns);
retval->parent = dest;
retval->type = rjp_json_null;
return retval;
}
RJP_value* irjp_remove_unordered_member(RJP_value* obj, RJP_value* member){
RJP_value* irjp_remove_unordered_member(RJP_value* obj, RJP_value* member, const RJP_memory_fns* fns){
RJP_tree_node* removed_node = NULL;
obj->object.root = irjp_tree_remove_value(obj->object.root, (RJP_tree_node*)member, &removed_node);
rjp_free(((RJP_object_member*)removed_node)->name.value);
fns->free(((RJP_object_member*)removed_node)->name.value);
member->parent = NULL;
--obj->object.num_members;
return member;
}
void irjp_unordered_set_key(RJP_value* dest, char* key, RJP_index keylen){
void irjp_unordered_set_key(RJP_value* dest, char* key, RJP_index keylen, const RJP_memory_fns* fns){
RJP_value* parent = dest->parent;
RJP_tree_node* removed_node = NULL;
parent->object.root = irjp_tree_remove_value(parent->object.root, (RJP_tree_node*)dest, &removed_node);
rjp_free(((RJP_object_member*)removed_node)->name.value);
fns->free(((RJP_object_member*)removed_node)->name.value);
((RJP_object_member*)removed_node)->name.value = key;
((RJP_object_member*)removed_node)->name.length = keylen;

View File

@ -40,10 +40,10 @@ 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(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);
static RJP_tree_node* irjp_clone_node(const RJP_tree_node* src, RJP_tree_node* parent, const RJP_memory_fns* fns);
static RJP_tree_node* irjp_copy_node(const RJP_tree_node* root, RJP_tree_node* parent, const RJP_memory_fns* fns);
static void irjp_free_node(RJP_tree_node* node, const RJP_memory_fns* fns);
static void irjp_delete_node(RJP_tree_node* node, const RJP_memory_fns* fns);
static RJP_tree_node* irjp_tree_insert_impl(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode);
static RJP_tree_node* irjp_tree_repair(RJP_tree_node* node);
@ -123,8 +123,9 @@ static void irjp_replace_node(RJP_tree_node *restrict node, RJP_tree_node *restr
}
//Node construction / destruction
RJP_tree_node* irjp_new_node(char* key, RJP_index keylen){
RJP_tree_node* node = rjp_calloc(sizeof(RJP_tree_node), 1);
RJP_tree_node* irjp_new_node(char* key, RJP_index keylen, const RJP_memory_fns* fns){
RJP_tree_node* node = fns->alloc(sizeof(RJP_tree_node));
memset(node, 0, sizeof(RJP_tree_node));
node->data.name.value = key;
node->data.name.length = keylen;
node->parent = node->left = node->right = NULL;
@ -134,54 +135,55 @@ RJP_tree_node* irjp_new_node(char* key, RJP_index keylen){
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(const RJP_tree_node* src, RJP_tree_node* parent){
RJP_tree_node* dest = rjp_calloc(1, sizeof(RJP_tree_node));
rjp_copy_value(&dest->data.value, &src->data.value);
irjp_strcpy(&dest->data.name, &src->data.name);
static RJP_tree_node* irjp_clone_node(const RJP_tree_node* src, RJP_tree_node* parent, const RJP_memory_fns* fns){
RJP_tree_node* dest = fns->alloc(sizeof(RJP_tree_node));
memset(dest, 0, sizeof(RJP_tree_node));
rjp_copy_value_c(&dest->data.value, &src->data.value, fns);
irjp_strcpy(&dest->data.name, &src->data.name, fns);
dest->parent = parent;
return dest;
}
static RJP_tree_node* irjp_copy_node(const RJP_tree_node* root, RJP_tree_node* parent){
static RJP_tree_node* irjp_copy_node(const RJP_tree_node* root, RJP_tree_node* parent, const RJP_memory_fns* fns){
if(!root){
return NULL;
}
RJP_tree_node* newnode = irjp_clone_node(root, parent);
newnode->left = irjp_copy_node(root->left, newnode);
newnode->right = irjp_copy_node(root->right, newnode);
RJP_tree_node* newnode = irjp_clone_node(root, parent, fns);
newnode->left = irjp_copy_node(root->left, newnode, fns);
newnode->right = irjp_copy_node(root->right, newnode, fns);
return newnode;
}
static void irjp_free_node(RJP_tree_node* node){
irjp_delete_node(node);
rjp_free(node);
static void irjp_free_node(RJP_tree_node* node, const RJP_memory_fns* fns){
irjp_delete_node(node, fns);
fns->free(node);
}
static void irjp_delete_node(RJP_tree_node* node){
rjp_free(node->data.name.value);
irjp_delete_value(&node->data.value);
static void irjp_delete_node(RJP_tree_node* node, const RJP_memory_fns* fns){
fns->free(node->data.name.value);
irjp_delete_value(&node->data.value, fns);
}
/* TREE */
//Tree construction / destruction
RJP_tree_node* irjp_copy_tree(const RJP_tree_node* root){
return irjp_copy_node(root, NULL);
RJP_tree_node* irjp_copy_tree(const RJP_tree_node* root, const RJP_memory_fns* fns){
return irjp_copy_node(root, NULL, fns);
}
void irjp_free_tree(RJP_tree_node* root){
void irjp_free_tree(RJP_tree_node* root, const RJP_memory_fns* fns){
if(!root)
return;
irjp_free_tree(root->left);
irjp_free_tree(root->right);
irjp_free_node(root);
irjp_free_tree(root->left, fns);
irjp_free_tree(root->right, fns);
irjp_free_node(root, fns);
}
//Tree operations
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, char* key, RJP_index keylen, RJP_value** added, int* status){
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, char* key, RJP_index keylen, RJP_value** added, int* status, const RJP_memory_fns* fns){
*status = RJP_TREE_SUCCESS;
if(!root){
root = irjp_new_node(key, keylen);
root = irjp_new_node(key, keylen, fns);
if(added)
*added = &root->data.value;
return root;
}
RJP_tree_node* newnode = irjp_new_node(key, keylen);
RJP_tree_node* newnode = irjp_new_node(key, keylen, fns);
if(added)
*added = &newnode->data.value;
return irjp_tree_insert_node(root, newnode);