diff --git a/include/rjp.h b/include/rjp.h index dc9198f..b0cf144 100644 --- a/include/rjp.h +++ b/include/rjp.h @@ -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); diff --git a/include/rjp_array.h b/include/rjp_array.h index 19e7485..07f8edc 100644 --- a/include/rjp_array.h +++ b/include/rjp_array.h @@ -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); diff --git a/include/rjp_internal.h b/include/rjp_internal.h index f0ea9ba..d0ba5bb 100644 --- a/include/rjp_internal.h +++ b/include/rjp_internal.h @@ -41,4 +41,6 @@ static inline void irjp_ignore_unused(FILE* fp, ...){ } #endif +extern const RJP_memory_fns irjp_default_memory_fns; + #endif diff --git a/include/rjp_object.h b/include/rjp_object.h index dd003ab..1eeabd5 100644 --- a/include/rjp_object.h +++ b/include/rjp_object.h @@ -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); diff --git a/include/rjp_ordered_object.h b/include/rjp_ordered_object.h index 2792233..d7bd854 100644 --- a/include/rjp_ordered_object.h +++ b/include/rjp_ordered_object.h @@ -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); diff --git a/include/rjp_string.h b/include/rjp_string.h index faae5e9..e5a2b71 100644 --- a/include/rjp_string.h +++ b/include/rjp_string.h @@ -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 diff --git a/include/rjp_unordered_object.h b/include/rjp_unordered_object.h index d6d99b0..5d1c403 100644 --- a/include/rjp_unordered_object.h +++ b/include/rjp_unordered_object.h @@ -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); diff --git a/include/rjp_value.h b/include/rjp_value.h index 5896947..5e69fff 100644 --- a/include/rjp_value.h +++ b/include/rjp_value.h @@ -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 diff --git a/include/tree.h b/include/tree.h index 38e2c88..b825b66 100644 --- a/include/tree.h +++ b/include/tree.h @@ -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 diff --git a/src/output.c b/src/output.c index a115f20..d817c27 100644 --- a/src/output.c +++ b/src/output.c @@ -30,123 +30,187 @@ #include //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); diff --git a/src/rjp.c b/src/rjp.c index 9cd4780..a73e048 100644 --- a/src/rjp.c +++ b/src/rjp.c @@ -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 */ diff --git a/src/rjp_array.c b/src/rjp_array.c index e9f39d0..f5d52fa 100644 --- a/src/rjp_array.c +++ b/src/rjp_array.c @@ -17,42 +17,51 @@ */ #include +#include //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; diff --git a/src/rjp_object.c b/src/rjp_object.c index 2d14259..4edc84f 100644 --- a/src/rjp_object.c +++ b/src/rjp_object.c @@ -25,29 +25,32 @@ #include //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); diff --git a/src/rjp_ordered_object.c b/src/rjp_ordered_object.c index 861db37..bc2754e 100644 --- a/src/rjp_ordered_object.c +++ b/src/rjp_ordered_object.c @@ -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; } diff --git a/src/rjp_parse.c b/src/rjp_parse.c index 3fe5a66..ca108ec 100644 --- a/src/rjp_parse.c +++ b/src/rjp_parse.c @@ -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; diff --git a/src/rjp_string.c b/src/rjp_string.c index d642946..6b3518c 100644 --- a/src/rjp_string.c +++ b/src/rjp_string.c @@ -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; diff --git a/src/rjp_unordered_object.c b/src/rjp_unordered_object.c index 0b4c8d3..5eede16 100644 --- a/src/rjp_unordered_object.c +++ b/src/rjp_unordered_object.c @@ -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; diff --git a/src/tree.c b/src/tree.c index c52a46e..4ac61a4 100644 --- a/src/tree.c +++ b/src/tree.c @@ -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);