Add _c API functions to allow custom allocation/deallocation functions
This commit is contained in:
parent
bf098ac96a
commit
e77d20cae4
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -41,4 +41,6 @@ static inline void irjp_ignore_unused(FILE* fp, ...){
|
||||
}
|
||||
#endif
|
||||
|
||||
extern const RJP_memory_fns irjp_default_memory_fns;
|
||||
|
||||
#endif
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
141
src/output.c
141
src/output.c
@ -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);
|
||||
|
||||
36
src/rjp.c
36
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 */
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
60
src/tree.c
60
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user