Removed vinit, was a really dumb idea. Redid a lot of the API to match. Fixed some tree related memory leaks.
This commit is contained in:
parent
0dfbbb5a5c
commit
67208e38e0
188
include/rjp.h
188
include/rjp.h
@ -41,6 +41,9 @@ extern "C"{
|
||||
#include <stdint.h>
|
||||
#define RJP_float double
|
||||
#endif
|
||||
#ifndef RJP_bool
|
||||
#define RJP_bool _Bool
|
||||
#endif
|
||||
|
||||
//used with rjp_to_json
|
||||
#define RJP_FORMAT_NONE 0
|
||||
@ -58,6 +61,8 @@ typedef enum RJP_data_type{
|
||||
}RJP_data_type;
|
||||
|
||||
|
||||
typedef struct RJP_value RJP_value;
|
||||
|
||||
//Hold a C string and the length excluding NULL terminator
|
||||
typedef struct RJP_string{
|
||||
char* value;
|
||||
@ -70,64 +75,13 @@ typedef struct RJP_object_iterator{
|
||||
struct RJP_object_iterator_impl* it;
|
||||
}RJP_object_iterator;
|
||||
|
||||
struct RJP_array_iterator_impl;
|
||||
typedef struct RJP_array_iterator{
|
||||
struct RJP_array_iterator_impl* it;
|
||||
RJP_value* current;
|
||||
}RJP_array_iterator;
|
||||
|
||||
typedef struct RJP_value RJP_value;
|
||||
|
||||
typedef struct RJP_vinit{
|
||||
union{
|
||||
RJP_int integer;
|
||||
RJP_float dfloat;
|
||||
char boolean;
|
||||
struct RJP_string string;
|
||||
};
|
||||
enum RJP_data_type type;
|
||||
}RJP_vinit;
|
||||
|
||||
/*
|
||||
Generic operations
|
||||
*/
|
||||
//Convert C string consisting of json data into RJP's format
|
||||
RJP_value* rjp_parse(const char* str);
|
||||
//RJP_value* rjp_parse_chunked(const char* str, RJP_value* prev_chunk);
|
||||
|
||||
//Initialize a root RJP_value to NULL
|
||||
RJP_value* rjp_new_value(void);
|
||||
//Initialize a root RJP_value to copy of value
|
||||
RJP_value* rjp_new_value_as(RJP_vinit* val);
|
||||
//Free an RJP_value and all members/elements
|
||||
void rjp_free_value(RJP_value* root);
|
||||
//Deep copy RJP_value
|
||||
void rjp_copy_value(RJP_value* dest, const RJP_value* src);
|
||||
//set existing value
|
||||
void rjp_set_value(RJP_value* dest, RJP_vinit* val);
|
||||
//initialize a RJP_value to the requested type and value
|
||||
RJP_vinit rjp_integer(RJP_int i);
|
||||
RJP_vinit rjp_boolean(char b);
|
||||
RJP_vinit rjp_dfloat(RJP_float d);
|
||||
RJP_vinit rjp_string(char* c, RJP_index len);
|
||||
RJP_vinit rjp_null(void);
|
||||
RJP_vinit rjp_object(void);
|
||||
RJP_vinit rjp_array(void);
|
||||
//Return handle to parent of given value
|
||||
RJP_value* rjp_value_parent(const RJP_value* element);
|
||||
//Return type of value
|
||||
RJP_data_type rjp_value_type(const RJP_value* value);
|
||||
//value accessors
|
||||
RJP_float rjp_value_dfloat(const RJP_value* value);
|
||||
RJP_int rjp_value_integer(const RJP_value* value);
|
||||
char rjp_value_boolean(const RJP_value* value);
|
||||
char* rjp_value_string(RJP_value* value);
|
||||
const char* rjp_value_cstring(const RJP_value* value);
|
||||
RJP_index rjp_value_string_length(const RJP_value* value);
|
||||
//copy input string and add json escape sequences
|
||||
RJP_index rjp_escape_strcpy(char* dest, const char* src);
|
||||
//length of string including escape sequences
|
||||
RJP_index rjp_escape_strlen(const char* str);
|
||||
|
||||
/***************** NON OBJECT OPERATIONS *******************/
|
||||
//Allocate heap space for rjp to use. Use if the memory is to be freed by rjp
|
||||
void* rjp_alloc(RJP_index nbytes);
|
||||
//Allocate heap space for rjp and initialize to 0.
|
||||
@ -137,67 +91,105 @@ void* rjp_realloc(void* ptr, RJP_index nbytes);
|
||||
//Free memory allocated by rjp_alloc or rjp_calloc
|
||||
void rjp_free(void* dest);
|
||||
|
||||
//copy input string and add json escape sequences
|
||||
RJP_index rjp_escape_strcpy(char* dest, const char* src);
|
||||
//length of string including escape sequences
|
||||
RJP_index rjp_escape_strlen(const char* str);
|
||||
|
||||
/*
|
||||
Object operations
|
||||
*/
|
||||
/***************** GENERIC OPERATIONS *******************/
|
||||
//Convert C string consisting of json data into RJP's format
|
||||
RJP_value* rjp_parse(const char* str);
|
||||
//RJP_value* rjp_parse_chunked(const char* str, RJP_value* prev_chunk);
|
||||
char* rjp_to_json(const RJP_value* root, int pretty);
|
||||
|
||||
//Initialize a root RJP_value to copy of value
|
||||
RJP_value* rjp_new_null(void);
|
||||
RJP_value* rjp_new_int(RJP_int val);
|
||||
RJP_value* rjp_new_float(RJP_float val);
|
||||
RJP_value* rjp_new_bool(RJP_bool val);
|
||||
RJP_value* rjp_new_string_copy(const char* val, RJP_index length);
|
||||
RJP_value* rjp_new_string(char* val, RJP_index length);
|
||||
RJP_value* rjp_new_object(void);
|
||||
RJP_value* rjp_new_array(void);
|
||||
|
||||
//Deallocate RJP_value
|
||||
void rjp_free_value(RJP_value* root);
|
||||
|
||||
//Deep copy RJP_value
|
||||
//When dest is not null, cleanup and then fill the object pointed to by dest. Otherwise allocate a new value.
|
||||
RJP_value* rjp_copy_value(RJP_value* dest, const RJP_value* src);
|
||||
|
||||
//set existing value
|
||||
//initialize a RJP_value to the requested type and value
|
||||
RJP_value* rjp_set_null(RJP_value* v);
|
||||
RJP_value* rjp_set_int(RJP_value* v, RJP_int val);
|
||||
RJP_value* rjp_set_float(RJP_value* v, RJP_float val);
|
||||
RJP_value* rjp_set_bool(RJP_value* v, RJP_bool val);
|
||||
RJP_value* rjp_set_string_copy(RJP_value* v, const char* val, RJP_index length);
|
||||
RJP_value* rjp_set_string(RJP_value* v, char* val, RJP_index length);
|
||||
RJP_value* rjp_set_object(RJP_value* v);
|
||||
RJP_value* rjp_set_array(RJP_value* v);
|
||||
|
||||
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);
|
||||
RJP_string* rjp_get_string(RJP_value* value);
|
||||
const RJP_string* rjp_get_cstring(const RJP_value* value);
|
||||
|
||||
|
||||
/***************** OBJECT/ARRAY SHARED OPERATIONS *******************/
|
||||
RJP_value* rjp_value_parent(const RJP_value* element);
|
||||
//Return type of value
|
||||
RJP_data_type rjp_value_type(const RJP_value* value);
|
||||
|
||||
/***************** OBJECT OPERATIONS *******************/
|
||||
//add a member to a json object, allocating a copy of the key
|
||||
RJP_value* rjp_new_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_vinit* value);
|
||||
RJP_value* rjp_add_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_value* value);
|
||||
RJP_value* rjp_add_member_key_copy(RJP_value* dest, const char* key, RJP_index keylen);
|
||||
//add a member to a json object without allocation. key must be allocated using rjp_alloc/rjp_calloc
|
||||
RJP_value* rjp_new_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_vinit* value);
|
||||
RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_value* value);
|
||||
RJP_value* rjp_add_member(RJP_value* dest, char* key, RJP_index keylen);
|
||||
|
||||
//Remove member without freeing
|
||||
RJP_value* rjp_remove_member_by_key(RJP_value* obj, const char* key);
|
||||
RJP_value* rjp_remove_member(RJP_value* obj, RJP_value* member);
|
||||
//Remove and free member
|
||||
void rjp_free_member_by_key(RJP_value* obj, const char* key);
|
||||
void rjp_free_member(RJP_value* obj, RJP_value* member);
|
||||
//add an element to a json array
|
||||
RJP_value* rjp_add_element(RJP_value* dest, RJP_value* value);
|
||||
RJP_value* rjp_new_element(RJP_value* dest, RJP_vinit* value);
|
||||
//set existing object member's key
|
||||
void rjp_set_key(RJP_value* dest, const char* key, RJP_index keylen);
|
||||
|
||||
//set existing object member's key without allocation. key must be allocated using rjp_alloc/rjp_calloc
|
||||
void rjp_set_key_no_alloc(RJP_value* dest, char* key, RJP_index keylen);
|
||||
void rjp_set_key(RJP_value* dest, char* key, RJP_index keylen);
|
||||
//set existing object member's key
|
||||
void rjp_set_key_copy(RJP_value* dest, const char* key, RJP_index keylen);
|
||||
|
||||
//Return number of members in the object
|
||||
RJP_index rjp_num_members(const RJP_value* object);
|
||||
//Return the object member's key
|
||||
const RJP_string* rjp_member_name(const RJP_value* member);
|
||||
//Search for an object member with given key
|
||||
RJP_value* rjp_search_member(const RJP_value* object, const char* search);
|
||||
|
||||
/***************** OBJECT ITERATOR OPERATIONS *******************/
|
||||
//Access first member of a json object
|
||||
RJP_value* rjp_get_member(RJP_object_iterator* object);
|
||||
void rjp_init_object_iterator(RJP_object_iterator* it, const RJP_value* object);
|
||||
void rjp_init_object_iterator(RJP_object_iterator* iter, const RJP_value* object);
|
||||
void rjp_delete_object_iterator(RJP_object_iterator* it);
|
||||
RJP_value* rjp_object_iterator_current(RJP_object_iterator* it);
|
||||
RJP_value* rjp_object_iterator_next(RJP_object_iterator* it);
|
||||
RJP_value* rjp_object_iterator_peek(RJP_object_iterator* it);
|
||||
void rjp_delete_object_iterator(RJP_object_iterator* it);
|
||||
//Return number of members in the object
|
||||
RJP_index rjp_num_members(const RJP_value* object);
|
||||
//Return the object member's key name
|
||||
char* rjp_member_name(const RJP_value* member);
|
||||
//Return the object member's key name length excluding null terminator
|
||||
RJP_index rjp_member_name_length(const RJP_value* member);
|
||||
//Search for an object member with given key
|
||||
RJP_value* rjp_search_member(const RJP_value* object, const char* search);
|
||||
//Search for first occurance of multiple keys. Returns first occurance of each.
|
||||
//Assumes dest is large enough to hold maximum num items.
|
||||
RJP_index rjp_search_members(const RJP_value* object, RJP_index num, const char* const* searches, RJP_value** dest);
|
||||
|
||||
/***************** ARRAY OPERATIONS *******************/
|
||||
//add an element to a json array
|
||||
RJP_value* rjp_add_element(RJP_value* dest);
|
||||
RJP_value* rjp_remove_element(RJP_value* arr, RJP_value* elem);
|
||||
void rjp_free_element(RJP_value* arr, RJP_value* elem);
|
||||
|
||||
/*
|
||||
Array operations
|
||||
*/
|
||||
//Access first element of a json array
|
||||
RJP_value* rjp_get_element(const RJP_value* array);
|
||||
//Access next element of a json array given the previous element
|
||||
RJP_value* rjp_next_element(const RJP_value* element);
|
||||
//Return number of elements in the array
|
||||
RJP_index rjp_num_elements(const RJP_value* array);
|
||||
RJP_index rjp_num_elements(const RJP_value* arr);
|
||||
|
||||
/***************** ARRAY ITERATOR OPERATIONS *******************/
|
||||
void rjp_init_array_iterator(RJP_array_iterator* iter, const RJP_value* array);
|
||||
void rjp_delete_array_iterator(RJP_array_iterator* iter);
|
||||
RJP_value* rjp_array_iterator_current(RJP_array_iterator* it);
|
||||
RJP_value* rjp_array_iterator_next(RJP_array_iterator* it);
|
||||
RJP_value* rjp_array_iterator_peek(RJP_array_iterator* it);
|
||||
|
||||
/*
|
||||
Output operations
|
||||
*/
|
||||
//Convert RJP_object to json string
|
||||
RJP_index rjp_dump_object(const RJP_value* root, char* dest);
|
||||
//Convert RJP_array to json string
|
||||
RJP_index rjp_dump_array(const RJP_value* arr, char* dest);
|
||||
//Convert root rjp value into json string
|
||||
char* rjp_to_json(const RJP_value* root, int pretty);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#define RJP_INTERNAL_H
|
||||
|
||||
#include "rjp.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define MAYBE_UNUSED __attribute__((unused))
|
||||
@ -28,17 +29,21 @@
|
||||
#endif
|
||||
|
||||
#ifdef RJP_DIAGNOSTICS
|
||||
#include <stdio.h>
|
||||
#define DIAG_PRINT(...) fprintf(__VA_ARGS__)
|
||||
#else
|
||||
#define DIAG_PRINT(...)
|
||||
#define DIAG_PRINT(...) irjp_ignore_unused(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define UNUSED_VARIABLE(thing) (void)(thing)
|
||||
|
||||
static inline void irjp_ignore_unused(FILE* fp, ...){
|
||||
UNUSED_VARIABLE(fp);
|
||||
}
|
||||
//
|
||||
//Represents a json object
|
||||
typedef struct RJP_object{
|
||||
struct RJP_tree_node* root;
|
||||
int num_members;
|
||||
RJP_index num_members;
|
||||
}RJP_object;
|
||||
|
||||
//Represents a json array
|
||||
@ -54,7 +59,7 @@ typedef struct RJP_value{
|
||||
union{
|
||||
RJP_int integer;
|
||||
RJP_float dfloat;
|
||||
char boolean;
|
||||
RJP_bool boolean;
|
||||
struct RJP_object object;
|
||||
struct RJP_string string;
|
||||
struct RJP_array array;
|
||||
@ -65,15 +70,15 @@ typedef struct RJP_value{
|
||||
typedef struct RJP_array_element{
|
||||
struct RJP_value value;
|
||||
struct RJP_array_element* next;
|
||||
struct RJP_array_element* prev;
|
||||
}RJP_array_element;
|
||||
|
||||
void irjp_copy_vinit_to_value(RJP_value* dest, RJP_vinit* src);
|
||||
void irjp_copy_array(RJP_value* dest, const RJP_value* src);
|
||||
void irjp_add_element(RJP_array* j);
|
||||
void irjp_add_member_no_alloc(RJP_object* j, char* str, size_t len);
|
||||
void irjp_delete_value(RJP_value* root);
|
||||
|
||||
RJP_value irjp_integer(RJP_int i);
|
||||
RJP_value irjp_boolean(char b);
|
||||
RJP_value irjp_boolean(RJP_bool b);
|
||||
RJP_value irjp_dfloat(RJP_float d);
|
||||
RJP_value irjp_string(char* c, RJP_index len);
|
||||
RJP_value irjp_string_copy(const char* c);
|
||||
@ -81,4 +86,7 @@ RJP_value irjp_null(void);
|
||||
RJP_value irjp_object(void);
|
||||
RJP_value irjp_array(void);
|
||||
|
||||
RJP_index rjp_dump_array(const RJP_value* arr, char* dest);
|
||||
RJP_index rjp_dump_object(const RJP_value* root, char* dest);
|
||||
|
||||
#endif
|
||||
|
||||
@ -36,8 +36,8 @@ struct RJP_tree_node{
|
||||
unsigned color:1;
|
||||
};
|
||||
|
||||
RJP_tree_node* irjp_new_node(RJP_object_member* value);
|
||||
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, RJP_object_member* value, RJP_value** added, int* status);
|
||||
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_tree_remove_value(RJP_tree_node* root, const char* key, RJP_value** removed_node, int* status);
|
||||
RJP_tree_node* irjp_tree_search_value(RJP_tree_node* root, const char* key);
|
||||
RJP_tree_node* irjp_copy_tree(const RJP_tree_node* root);
|
||||
|
||||
177
makefile
Normal file
177
makefile
Normal file
@ -0,0 +1,177 @@
|
||||
#This program is free software: you can redistribute it and/or modify
|
||||
#it under the terms of the GNU General Public License as published by
|
||||
#the Free Software Foundation, either version 3 of the License, or
|
||||
#(at your option) any later version.
|
||||
|
||||
#This program is distributed in the hope that it will be useful,
|
||||
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#GNU General Public License for more details.
|
||||
|
||||
#You should have received a copy of the GNU General Public License
|
||||
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#Copyright 2018-2020 rexy712
|
||||
|
||||
#Makefile to generate a single executable from all sources in SOURCE_DIRS that end in EXT
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
WINDOWS::=1
|
||||
endif
|
||||
|
||||
SOURCE_DIRS::=
|
||||
SOURCES::=src/tree.c src/tester.c src/memory.c src/strings.c src/rjp.c src/output.c src/input.c src/object.c src/array.c
|
||||
OBJDIR::=obj
|
||||
DEPDIR::=$(OBJDIR)/dep
|
||||
LIBDIR::=lib
|
||||
INCLUDE_DIRS::=include
|
||||
CFLAGS::=-g -std=c18 -Wall -pedantic -Wextra
|
||||
CXXFLAGS::=-g -std=c++17 -Wall -pedantic -Wextra
|
||||
EXT::=c
|
||||
LANG::=$(EXT)
|
||||
MAIN_EXECUTABLE::=tester
|
||||
PRE_TARGETS::=
|
||||
POST_TARGETS::=
|
||||
CLEAN_TARGETS::=
|
||||
RELEASE?=0
|
||||
MEMCHK?=0
|
||||
|
||||
ifneq ($(WINDOWS),1)
|
||||
#*nix settings
|
||||
CC::=gcc
|
||||
CXX::=g++
|
||||
LDLIBS::=
|
||||
LDFLAGS::=
|
||||
STRIP::=strip
|
||||
RANLIB::=ranlib
|
||||
AR::=ar
|
||||
AS::=as
|
||||
else #windows
|
||||
#windows settings
|
||||
#windows is a fuckwit
|
||||
MINGW_PREFIX::=x86_64-w64-mingw32-
|
||||
CC::=$(MINGW_PREFIX)gcc
|
||||
CXX::=$(MINGW_PREFIX)g++
|
||||
LDLIBS::=
|
||||
LDFLAGS::=
|
||||
STRIP::=$(MINGW_PREFIX)strip
|
||||
RANLIB::=$(MINGW_PREFIX)ranlib
|
||||
AR::=$(MINGW_PREFIX)ar
|
||||
AS::=$(MINGW_PREFIX)as
|
||||
endif #windows
|
||||
|
||||
#Put your custom targets for PRE_TARGETS, POST_TARGETS, and CLEAN_TARGETS here:
|
||||
|
||||
|
||||
|
||||
###########################################################################################################
|
||||
#Everything past this point is internal BS, probably best not to touch it unless you know what you're doing
|
||||
|
||||
#set the all target as the default target, otherwise the topmost target will run
|
||||
.DEFAULT_GOAL::=all
|
||||
|
||||
#set the main target to match the output of mingw
|
||||
ifeq ($(WINDOWS),1)
|
||||
MAIN_EXECUTABLE::=$(MAIN_EXECUTABLE).exe
|
||||
endif
|
||||
|
||||
#system dependant bullshit
|
||||
ifeq ($(OS),Windows_NT)
|
||||
#windows' cmd commands
|
||||
mkdir=mkdir $(subst /,\,$(1)) > NUL 2>&1
|
||||
rm=del /F $(1) > NUL 2>&1
|
||||
rmdir=rd /S /Q $(1) > NUL 2>&1
|
||||
move=move /Y $(subst /,\,$(1)) $(subst /,\,$(2)) > NUL 2>&1
|
||||
copy=copy /Y /B $(subst /,\,$(1)) $(subst /,\,$(2)) > NUL 2>&1
|
||||
else
|
||||
#*nix terminal commands
|
||||
mkdir=mkdir -p $(1)
|
||||
rm=rm -f $(1)
|
||||
rmdir=rm -rf $(1)
|
||||
move=mv $(1) $(2)
|
||||
copy=cp $(1) $(2)
|
||||
endif
|
||||
|
||||
#setup compiler and flags based on language
|
||||
ifeq ($(LANG),cpp)
|
||||
COMPILER_FLAGS::=$(CXXFLAGS)
|
||||
COMPILER::=$(CXX)
|
||||
else ifeq ($(LANG),c)
|
||||
COMPILER_FLAGS::=$(CFLAGS)
|
||||
COMPILER::=$(CC)
|
||||
endif
|
||||
|
||||
ifeq ($(RELEASE),1)
|
||||
#a lot of false strict aliasing warnings from gcc 9
|
||||
COMPILER_FLAGS+=-O2 -Wno-strict-aliasing
|
||||
POST_TARGETS+= do_strip
|
||||
else ifeq ($(MEMCHK),1)
|
||||
#use asan to check memory leaks/invalid accesses
|
||||
LDFLAGS+=-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
||||
COMPILER_FLAGS+=-O0 -g3 -ggdb -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
||||
else
|
||||
#default target
|
||||
COMPILER_FLAGS+=-O0 -g3 -ggdb
|
||||
endif
|
||||
|
||||
#add dependency tracking and include directories
|
||||
INTERNAL_COMPILERFLAGS=-c $(foreach dir,$(INCLUDE_DIRS),-I"$(dir)") -MMD -MP -MF"$(DEPDIR)/$(notdir $(patsubst %.o,%.d,$@))"
|
||||
THIS_MAKEFILE_NAME::=$(lastword $(MAKEFILE_LIST))
|
||||
INTERNAL_SOURCES::=$(SOURCES) $(foreach source,$(SOURCE_DIRS),$(foreach ext,$(EXT),$(wildcard $(source)/*.$(ext))))
|
||||
OBJECTS::=$(addprefix $(OBJDIR)/,$(subst \,.,$(subst /,.,$(addsuffix .o,$(INTERNAL_SOURCES)))))
|
||||
|
||||
#Arguments to make submake use this makefile without "Entering directory" stuff
|
||||
SUBMAKE_ARGUMENTS::=--no-print-directory -f "$(THIS_MAKEFILE_NAME)"
|
||||
#just a variable for a newline
|
||||
define \n
|
||||
|
||||
|
||||
endef
|
||||
|
||||
#default target: run targets in PRE_TARGETS, then the main executable, then POST_TARGETS
|
||||
.PHONY: all
|
||||
all:
|
||||
$(foreach target,$(PRE_TARGETS),@$(MAKE) $(SUBMAKE_ARGUMENTS) "$(target)"$(\n))
|
||||
@$(MAKE) $(SUBMAKE_ARGUMENTS) "$(MAIN_EXECUTABLE)"
|
||||
$(foreach target,$(POST_TARGETS),@$(MAKE) $(SUBMAKE_ARGUMENTS) "$(target)"$(\n))
|
||||
|
||||
#Called in POST_TARGETS when RELEASE=1
|
||||
.PHONY: do_strip
|
||||
do_strip:
|
||||
$(STRIP) --strip-all "$(MAIN_EXECUTABLE)"
|
||||
|
||||
#Link executable
|
||||
$(MAIN_EXECUTABLE): $(OBJECTS)
|
||||
$(COMPILER) $(LDFLAGS) $^ -o "$(basename $@)" $(LDLIBS)
|
||||
|
||||
#Object target recipe
|
||||
define GENERATE_OBJECTS
|
||||
$$(OBJDIR)/$(subst \,.,$(subst /,.,$(1))).%.o: $(1)/%
|
||||
$$(COMPILER) $$(COMPILER_FLAGS) $$(INTERNAL_COMPILERFLAGS) "$$<" -o "$$@"
|
||||
endef
|
||||
define GENERATE_INDIVIDUAL_OBJECTS
|
||||
$$(OBJDIR)/$(subst \,.,$(subst /,.,$(1))).o: $(1)
|
||||
$$(COMPILER) $$(COMPILER_FLAGS) $$(INTERNAL_COMPILERFLAGS) "$$<" -o "$$@"
|
||||
endef
|
||||
|
||||
#Create targets for object files
|
||||
$(foreach dir,$(SOURCE_DIRS),$(eval $(call GENERATE_OBJECTS,$(dir))))
|
||||
$(foreach src,$(SOURCES),$(eval $(call GENERATE_INDIVIDUAL_OBJECTS,$(src))))
|
||||
$(OBJECTS): | $(OBJDIR) $(DEPDIR)
|
||||
|
||||
#Output directory creation
|
||||
$(OBJDIR):
|
||||
$(call mkdir,"$@")
|
||||
$(DEPDIR):
|
||||
$(call mkdir,"$@")
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(foreach target,$(CLEAN_TARGETS),@$(MAKE) $(SUBMAKE_ARGUMENTS) "$(target)"$(\n))
|
||||
$(call rmdir,"$(DEPDIR)")
|
||||
$(call rmdir,"$(OBJDIR)")
|
||||
$(call rm,"$(MAIN_EXECUTABLE)")
|
||||
$(call rm,"$(MAIN_EXECUTABLE).exe")
|
||||
|
||||
#header file dep tracking
|
||||
-include $(wildcard $(DEPDIR)/*.d)
|
||||
65
src/array.c
65
src/array.c
@ -18,6 +18,14 @@
|
||||
|
||||
#include "rjp_internal.h"
|
||||
|
||||
void irjp_copy_array(RJP_value* dest, const RJP_value* src){
|
||||
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_add_element(dest);
|
||||
rjp_copy_value(copy_mem, &curr->value);
|
||||
}
|
||||
}
|
||||
void irjp_add_element(RJP_array* j){
|
||||
++j->num_elements;
|
||||
if(!j->elements){
|
||||
@ -26,26 +34,59 @@ void irjp_add_element(RJP_array* j){
|
||||
}else{
|
||||
j->last->next = rjp_calloc(1, sizeof(RJP_array_element));
|
||||
j->last = j->last->next;
|
||||
j->last->prev = j->last;
|
||||
}
|
||||
}
|
||||
RJP_value* rjp_add_element(RJP_value* dest, RJP_value* value){
|
||||
RJP_value* rjp_add_element(RJP_value* dest){
|
||||
irjp_add_element(&dest->array);
|
||||
dest->array.last->value = *value;
|
||||
dest->array.last->value.parent = dest;
|
||||
return &dest->array.last->value;
|
||||
}
|
||||
RJP_value* rjp_new_element(RJP_value* dest, RJP_vinit* value){
|
||||
irjp_add_element(&dest->array);
|
||||
irjp_copy_vinit_to_value(&dest->array.last->value, value);
|
||||
dest->array.last->value.parent = dest;
|
||||
return &dest->array.last->value;
|
||||
RJP_value* rjp_remove_element(RJP_value* dest, RJP_value* value){
|
||||
RJP_array* j = &dest->array;
|
||||
if(!j->num_elements)
|
||||
return NULL;
|
||||
|
||||
--j->num_elements;
|
||||
RJP_array_element* elem = (RJP_array_element*)value;
|
||||
RJP_array_element* prev = elem->prev;
|
||||
RJP_array_element* next = elem->next;
|
||||
if(prev)
|
||||
prev->next = elem->next;
|
||||
if(next)
|
||||
next->prev = prev;
|
||||
if(elem == j->elements)
|
||||
j->elements = next;
|
||||
if(elem == j->last)
|
||||
j->last = prev;
|
||||
return value;
|
||||
}
|
||||
RJP_value* rjp_get_element(const RJP_value* array){
|
||||
return &array->array.elements->value;
|
||||
}
|
||||
RJP_value* rjp_next_element(const RJP_value* element){
|
||||
return (RJP_value*)(((RJP_array_element*)element)->next);
|
||||
void rjp_free_element(RJP_value* dest, RJP_value* value){
|
||||
rjp_remove_element(dest, value);
|
||||
rjp_free_value(value);
|
||||
}
|
||||
RJP_index rjp_num_elements(const RJP_value* array){
|
||||
return array->array.num_elements;
|
||||
}
|
||||
|
||||
void rjp_init_array_iterator(RJP_array_iterator* iter, const RJP_value* array){
|
||||
iter->current = &(array->array.elements->value);
|
||||
}
|
||||
void rjp_delete_array_iterator(RJP_array_iterator* it){
|
||||
it->current = NULL;
|
||||
}
|
||||
RJP_value* rjp_get_element(const RJP_value* array){
|
||||
return &array->array.elements->value;
|
||||
}
|
||||
RJP_value* rjp_array_iterator_current(RJP_array_iterator* it){
|
||||
return it->current;
|
||||
}
|
||||
RJP_value* rjp_array_iterator_next(RJP_array_iterator* it){
|
||||
RJP_array_element* curr = (RJP_array_element*)it->current;
|
||||
it->current = curr ? &(curr->next->value) : NULL;
|
||||
return it->current;
|
||||
}
|
||||
RJP_value* rjp_array_iterator_peek(RJP_array_iterator* it){
|
||||
RJP_array_element* curr = (RJP_array_element*)it->current;
|
||||
return curr ? &(curr->next->value) : NULL;
|
||||
}
|
||||
|
||||
@ -134,8 +134,8 @@ int irjp_handle_key(const char* str, RJP_parse_state* state){
|
||||
syntax_error("Cannot have empty key name!", state);
|
||||
return -1;
|
||||
}
|
||||
RJP_value nil = irjp_null();
|
||||
state->lastadded = rjp_add_member_no_alloc(state->curr, new_string, keylen, &nil);
|
||||
state->lastadded = rjp_add_member(state->curr, new_string, keylen);
|
||||
rjp_set_null(state->lastadded);
|
||||
*state->target = rjp_json_target_colon;
|
||||
return inclen+2;
|
||||
//end of this object (object is empty)
|
||||
|
||||
31
src/memory.c
31
src/memory.c
@ -36,40 +36,39 @@ void rjp_free(void* data){
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void irjp_copy_array(RJP_value* dest, const RJP_value* src){
|
||||
dest->array.elements = dest->array.last = 0;
|
||||
for(RJP_value* curr = rjp_get_element(src);curr;curr = rjp_next_element(curr)){
|
||||
RJP_value copy_mem;
|
||||
rjp_copy_value(©_mem, curr);
|
||||
rjp_add_element(dest, ©_mem);
|
||||
RJP_value* rjp_copy_value(RJP_value* dest, const RJP_value* src){
|
||||
RJP_value* ret;
|
||||
if(dest){
|
||||
irjp_delete_value(dest);
|
||||
ret = dest;
|
||||
}else{
|
||||
ret = rjp_new_null();
|
||||
}
|
||||
}
|
||||
|
||||
void rjp_copy_value(RJP_value* dest, const RJP_value* src){
|
||||
dest->type = src->type;
|
||||
ret->type = src->type;
|
||||
|
||||
switch(src->type){
|
||||
case rjp_json_object:
|
||||
irjp_copy_object(dest, src);
|
||||
irjp_copy_object(ret, src);
|
||||
break;
|
||||
case rjp_json_array:
|
||||
irjp_copy_array(dest, src);
|
||||
irjp_copy_array(ret, src);
|
||||
break;
|
||||
case rjp_json_string:
|
||||
irjp_strcpy(&dest->string, &src->string);
|
||||
irjp_strcpy(&ret->string, &src->string);
|
||||
break;
|
||||
case rjp_json_integer:
|
||||
dest->integer = src->integer;
|
||||
ret->integer = src->integer;
|
||||
break;
|
||||
case rjp_json_boolean:
|
||||
dest->boolean = src->boolean;
|
||||
ret->boolean = src->boolean;
|
||||
break;
|
||||
case rjp_json_dfloat:
|
||||
dest->dfloat = src->dfloat;
|
||||
ret->dfloat = src->dfloat;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void irjp_delete_array(RJP_value* root){
|
||||
|
||||
113
src/object.c
113
src/object.c
@ -125,51 +125,26 @@ void irjp_copy_object(RJP_value* dest, const RJP_value* src){
|
||||
void irjp_delete_object(RJP_value* obj){
|
||||
irjp_free_tree(obj->object.root);
|
||||
}
|
||||
static void irjp_copy_init_member_string(RJP_object_member* mem, const char* key, RJP_index keylen){
|
||||
if(!keylen)
|
||||
keylen = strlen(key);
|
||||
mem->name.value = rjp_alloc(keylen+1);
|
||||
strncpy(mem->name.value, key, keylen);
|
||||
mem->name.value[keylen] = 0;
|
||||
mem->name.length = keylen;
|
||||
}
|
||||
static void irjp_init_member_string(RJP_object_member* mem, char* key, RJP_index keylen){
|
||||
if(!keylen)
|
||||
keylen = strlen(key);
|
||||
mem->name.value = key;
|
||||
mem->name.length = keylen;
|
||||
}
|
||||
static RJP_value* irjp_add_member_impl(RJP_value* dest, RJP_object_member* mem){
|
||||
static RJP_value* irjp_add_member_impl(RJP_value* dest, char* key, RJP_index keylen){
|
||||
++dest->object.num_members;
|
||||
mem->value.parent = dest;
|
||||
int status;
|
||||
RJP_value* retval;
|
||||
dest->object.root = irjp_tree_insert_value(dest->object.root, mem, &retval, &status);
|
||||
dest->object.root = irjp_tree_insert_value(dest->object.root, key, keylen, &retval, &status);
|
||||
retval->parent = dest;
|
||||
return retval;
|
||||
}
|
||||
RJP_value* rjp_new_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_vinit* value){
|
||||
RJP_object_member mem;
|
||||
irjp_copy_vinit_to_value(&mem.value, value);
|
||||
irjp_copy_init_member_string(&mem, key, keylen);
|
||||
return irjp_add_member_impl(dest, &mem);
|
||||
RJP_value* rjp_add_member(RJP_value* dest, char* key, RJP_index keylen){
|
||||
if(!keylen)
|
||||
keylen = strlen(key);
|
||||
return irjp_add_member_impl(dest, key, keylen);
|
||||
}
|
||||
RJP_value* rjp_add_member(RJP_value* dest, const char* key, RJP_index keylen, RJP_value* value){
|
||||
RJP_object_member mem;
|
||||
mem.value = *value;
|
||||
irjp_copy_init_member_string(&mem, key, keylen);
|
||||
return irjp_add_member_impl(dest, &mem);
|
||||
}
|
||||
RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_value* value){
|
||||
RJP_object_member mem;
|
||||
mem.value = *value;
|
||||
irjp_init_member_string(&mem, key, keylen);
|
||||
return irjp_add_member_impl(dest, &mem);
|
||||
}
|
||||
RJP_value* rjp_new_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_vinit* value){
|
||||
RJP_object_member mem;
|
||||
irjp_copy_vinit_to_value(&mem.value, value);
|
||||
irjp_init_member_string(&mem, key, keylen);
|
||||
return irjp_add_member_impl(dest, &mem);
|
||||
RJP_value* rjp_add_member_key_copy(RJP_value* dest, const char* key, RJP_index keylen){
|
||||
if(!keylen)
|
||||
keylen = rjp_escape_strlen(key);
|
||||
char* newkey = rjp_alloc(keylen+1);
|
||||
rjp_escape_strcpy(newkey, key);
|
||||
newkey[keylen] = 0;
|
||||
return irjp_add_member_impl(dest, newkey, keylen);
|
||||
}
|
||||
RJP_value* rjp_remove_member_by_key(RJP_value* obj, const char* key){
|
||||
int status;
|
||||
@ -190,7 +165,7 @@ void rjp_free_member(RJP_value* obj, RJP_value* member){
|
||||
rjp_free_member_by_key(obj, ((RJP_object_member*)member)->name.value);
|
||||
}
|
||||
|
||||
void rjp_set_key(RJP_value* dest, const char* key, RJP_index keylen){
|
||||
void rjp_set_key_copy(RJP_value* dest, const char* key, RJP_index keylen){
|
||||
RJP_object_member* mem = (RJP_object_member*)dest;
|
||||
if(key){
|
||||
if(!keylen){
|
||||
@ -204,7 +179,7 @@ void rjp_set_key(RJP_value* dest, const char* key, RJP_index keylen){
|
||||
mem->name.value[keylen] = 0;
|
||||
mem->name.length = keylen;
|
||||
}
|
||||
void rjp_set_key_no_alloc(RJP_value* dest, char* key, RJP_index keylen){
|
||||
void rjp_set_key(RJP_value* dest, char* key, RJP_index keylen){
|
||||
RJP_object_member* mem = (RJP_object_member*)dest;
|
||||
if(key){
|
||||
if(!keylen){
|
||||
@ -216,13 +191,29 @@ void rjp_set_key_no_alloc(RJP_value* dest, char* key, RJP_index keylen){
|
||||
mem->name.value = key;
|
||||
mem->name.length = keylen;
|
||||
}
|
||||
RJP_value* rjp_get_member(RJP_object_iterator* it){
|
||||
return &irjp_object_iterator_current(it->it)->data.value;
|
||||
RJP_index rjp_num_members(const RJP_value* object){
|
||||
return object->object.num_members;
|
||||
}
|
||||
const RJP_string* rjp_member_name(const RJP_value* member){
|
||||
return &(((RJP_object_member*)member)->name);
|
||||
}
|
||||
|
||||
RJP_value* rjp_search_member(const RJP_value* object, const char* search){
|
||||
RJP_tree_node* n = irjp_tree_search_value(object->object.root, search);
|
||||
if(!n)
|
||||
return NULL;
|
||||
return &n->data.value;
|
||||
}
|
||||
|
||||
void rjp_init_object_iterator(RJP_object_iterator* it, const RJP_value* object){
|
||||
it->it = rjp_alloc(sizeof(RJP_object_iterator_impl));
|
||||
irjp_init_object_iterator(it->it, object->object.root);
|
||||
}
|
||||
void rjp_delete_object_iterator(RJP_object_iterator* it){
|
||||
irjp_delete_object_iterator(it->it);
|
||||
rjp_free(it->it);
|
||||
it->it = NULL;
|
||||
}
|
||||
RJP_value* rjp_object_iterator_current(RJP_object_iterator* it){
|
||||
RJP_tree_node* n = irjp_object_iterator_current(it->it);
|
||||
if(!n)
|
||||
@ -241,40 +232,4 @@ RJP_value* rjp_object_iterator_peek(RJP_object_iterator* it){
|
||||
return NULL;
|
||||
return &n->data.value;
|
||||
}
|
||||
void rjp_delete_object_iterator(RJP_object_iterator* it){
|
||||
irjp_delete_object_iterator(it->it);
|
||||
rjp_free(it->it);
|
||||
it->it = NULL;
|
||||
}
|
||||
RJP_index rjp_num_members(const RJP_value* object){
|
||||
return object->object.num_members;
|
||||
}
|
||||
char* rjp_member_name(const RJP_value* member){
|
||||
return ((RJP_object_member*)member)->name.value;
|
||||
}
|
||||
RJP_index rjp_member_name_length(const RJP_value* member){
|
||||
return ((RJP_object_member*)member)->name.length;
|
||||
}
|
||||
|
||||
RJP_value* rjp_search_member(const RJP_value* object, const char* search){
|
||||
RJP_tree_node* n = irjp_tree_search_value(object->object.root, search);
|
||||
if(!n)
|
||||
return NULL;
|
||||
return &n->data.value;
|
||||
}
|
||||
|
||||
RJP_index rjp_search_members(const RJP_value* object, RJP_index num, const char* const* searches, RJP_value** dest){
|
||||
RJP_index matches = 0;
|
||||
|
||||
for(RJP_index i = 0;i < num;++i){
|
||||
RJP_tree_node* n = irjp_tree_search_value(object->object.root, searches[i]);
|
||||
if(!n){
|
||||
dest[i] = NULL;
|
||||
}else{
|
||||
dest[i] = &n->data.value;
|
||||
++matches;
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
|
||||
110
src/output.c
110
src/output.c
@ -28,15 +28,113 @@
|
||||
#include <string.h> //strlen
|
||||
#include <stdio.h> //sprintf
|
||||
|
||||
RJP_value* rjp_new_value(void){
|
||||
RJP_value* rjp_new_null(void){
|
||||
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
|
||||
ret->type = rjp_json_null;
|
||||
return ret;
|
||||
}
|
||||
RJP_value* rjp_new_value_as(RJP_vinit* value){
|
||||
RJP_value* ret = rjp_alloc(sizeof(RJP_value));
|
||||
irjp_copy_vinit_to_value(ret, value);
|
||||
RJP_value* rjp_new_int(RJP_int val){
|
||||
RJP_value* ret = rjp_calloc(1, 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));
|
||||
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));
|
||||
ret->type = rjp_json_boolean;
|
||||
ret->boolean = val;
|
||||
return ret;
|
||||
}
|
||||
RJP_value* rjp_new_string(char* val, RJP_index length){
|
||||
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
|
||||
ret->type = rjp_json_string;
|
||||
ret->string.value = val;
|
||||
ret->string.length = length;
|
||||
return ret;
|
||||
}
|
||||
RJP_value* rjp_new_string_copy(const char* value, RJP_index length){
|
||||
UNUSED_VARIABLE(length);
|
||||
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
|
||||
ret->type = rjp_json_string;
|
||||
RJP_index esclen = rjp_escape_strlen(value);
|
||||
ret->string.value = rjp_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));
|
||||
ret->type = rjp_json_object;
|
||||
return ret;
|
||||
}
|
||||
RJP_value* rjp_new_array(void){
|
||||
RJP_value* ret = rjp_calloc(1, sizeof(RJP_value));
|
||||
ret->type = rjp_json_array;
|
||||
return ret;
|
||||
}
|
||||
|
||||
RJP_value* rjp_set_null(RJP_value* v){
|
||||
irjp_delete_value(v);
|
||||
v->type = rjp_json_null;
|
||||
return v;
|
||||
}
|
||||
RJP_value* rjp_set_int(RJP_value* v, RJP_int val){
|
||||
irjp_delete_value(v);
|
||||
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);
|
||||
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);
|
||||
v->type = rjp_json_boolean;
|
||||
v->boolean = val;
|
||||
return v;
|
||||
}
|
||||
RJP_value* rjp_set_string(RJP_value* v, char* val, RJP_index len){
|
||||
irjp_delete_value(v);
|
||||
v->type = rjp_json_string;
|
||||
v->string.value = val;
|
||||
v->string.length = len;
|
||||
return v;
|
||||
}
|
||||
RJP_value* rjp_set_string_copy(RJP_value* v, const char* val, RJP_index length){
|
||||
UNUSED_VARIABLE(length);
|
||||
irjp_delete_value(v);
|
||||
v->type = rjp_json_string;
|
||||
RJP_index esclen = rjp_escape_strlen(val);
|
||||
v->string.value = rjp_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){
|
||||
if(v->type == rjp_json_object)
|
||||
return v;
|
||||
irjp_delete_value(v);
|
||||
v->type = rjp_json_object;
|
||||
return v;
|
||||
}
|
||||
RJP_value* rjp_set_array(RJP_value* v){
|
||||
if(v->type == rjp_json_array)
|
||||
return v;
|
||||
irjp_delete_value(v);
|
||||
v->type = rjp_json_array;
|
||||
return v;
|
||||
}
|
||||
|
||||
static size_t irjp_write_value(char* dest, const RJP_value* val){
|
||||
size_t ret;
|
||||
@ -142,7 +240,7 @@ static size_t irjp_write_value_pretty(char* dest, const RJP_value* val, int dept
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t rjp_dump_array(const RJP_value* arr, char* dest){
|
||||
RJP_index rjp_dump_array(const RJP_value* arr, char* dest){
|
||||
const RJP_array* array = &arr->array;
|
||||
const RJP_array_element* element_list = array->elements;
|
||||
size_t pos = 1;
|
||||
@ -159,7 +257,7 @@ size_t rjp_dump_array(const RJP_value* arr, char* dest){
|
||||
return pos;
|
||||
}
|
||||
|
||||
size_t rjp_dump_object(const RJP_value* root, char* dest){
|
||||
RJP_index rjp_dump_object(const RJP_value* root, char* dest){
|
||||
RJP_object_iterator it;
|
||||
rjp_init_object_iterator(&it, root);
|
||||
size_t pos = 1;
|
||||
|
||||
71
src/rjp.c
71
src/rjp.c
@ -19,58 +19,6 @@
|
||||
#include "rjp_internal.h"
|
||||
|
||||
/* VALUE SETTING */
|
||||
void irjp_copy_vinit_to_value(RJP_value* dest, RJP_vinit* src){
|
||||
switch(src->type){
|
||||
case rjp_json_integer:
|
||||
dest->integer = src->integer;
|
||||
break;
|
||||
case rjp_json_dfloat:
|
||||
dest->dfloat = src->dfloat;
|
||||
break;
|
||||
case rjp_json_boolean:
|
||||
dest->boolean = src->boolean;
|
||||
break;
|
||||
case rjp_json_string:
|
||||
dest->string = src->string;
|
||||
src->string.value = NULL;
|
||||
break;
|
||||
case rjp_json_null:
|
||||
dest->integer = 0;
|
||||
break;
|
||||
case rjp_json_object:
|
||||
*dest = irjp_object();
|
||||
break;
|
||||
case rjp_json_array:
|
||||
*dest = irjp_array();
|
||||
break;
|
||||
};
|
||||
dest->type = src->type;
|
||||
}
|
||||
void rjp_set_value(RJP_value* dest, RJP_vinit* value){
|
||||
irjp_copy_vinit_to_value(dest, value);
|
||||
}
|
||||
RJP_vinit rjp_integer(RJP_int i){
|
||||
return (RJP_vinit){.integer = i, .type = rjp_json_integer};
|
||||
}
|
||||
RJP_vinit rjp_boolean(char b){
|
||||
return (RJP_vinit){.boolean = b, .type = rjp_json_boolean};
|
||||
}
|
||||
RJP_vinit rjp_dfloat(double d){
|
||||
return (RJP_vinit){.dfloat = d, .type = rjp_json_dfloat};
|
||||
}
|
||||
RJP_vinit rjp_string(char* c, RJP_index len){
|
||||
return (RJP_vinit){.string = {.value = c, .length = len}, .type = rjp_json_string};
|
||||
}
|
||||
RJP_vinit rjp_null(void){
|
||||
return (RJP_vinit){.integer = 0, .type = rjp_json_null};
|
||||
}
|
||||
RJP_vinit rjp_object(void){
|
||||
return (RJP_vinit){.integer = 0, .type = rjp_json_object};
|
||||
}
|
||||
RJP_vinit rjp_array(void){
|
||||
return (RJP_vinit){.integer = 0, .type = rjp_json_array};
|
||||
}
|
||||
|
||||
/* GETTERS */
|
||||
RJP_value* rjp_value_parent(const RJP_value* value){
|
||||
return value->parent;
|
||||
@ -78,30 +26,27 @@ RJP_value* rjp_value_parent(const RJP_value* value){
|
||||
RJP_data_type rjp_value_type(const RJP_value* value){
|
||||
return value->type;
|
||||
}
|
||||
RJP_float rjp_value_dfloat(const RJP_value* value){
|
||||
RJP_float rjp_get_float(const RJP_value* value){
|
||||
return value->dfloat;
|
||||
}
|
||||
RJP_int rjp_value_integer(const RJP_value* value){
|
||||
RJP_int rjp_get_int(const RJP_value* value){
|
||||
return value->integer;
|
||||
}
|
||||
char rjp_value_boolean(const RJP_value* value){
|
||||
RJP_bool rjp_get_bool(const RJP_value* value){
|
||||
return value->boolean;
|
||||
}
|
||||
char* rjp_value_string(RJP_value* value){
|
||||
return value->string.value;
|
||||
RJP_string* rjp_get_string(RJP_value* value){
|
||||
return &(value->string);
|
||||
}
|
||||
const char* rjp_value_cstring(const RJP_value* value){
|
||||
return value->string.value;
|
||||
}
|
||||
RJP_index rjp_value_string_length(const RJP_value* value){
|
||||
return value->string.length;
|
||||
const RJP_string* rjp_get_cstring(const RJP_value* value){
|
||||
return &(value->string);
|
||||
}
|
||||
|
||||
|
||||
RJP_value irjp_integer(RJP_int i){
|
||||
return (RJP_value){.integer = i, .type = rjp_json_integer};
|
||||
}
|
||||
RJP_value irjp_boolean(char b){
|
||||
RJP_value irjp_boolean(RJP_bool b){
|
||||
return (RJP_value){.boolean = b, .type = rjp_json_boolean};
|
||||
}
|
||||
RJP_value irjp_dfloat(RJP_float d){
|
||||
|
||||
@ -120,7 +120,7 @@ static int codepoint_to_u8(char* dest, uint32_t codepoint){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static uint32_t u8_to_codepoint(char* u){
|
||||
/*static uint32_t u8_to_codepoint(char* u){
|
||||
if((u[0] & 0x80) == 0){
|
||||
//one byte
|
||||
return u[0];
|
||||
@ -149,7 +149,7 @@ static uint32_t u8_to_codepoint(char* u){
|
||||
//invalid
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//Convert escape sequences in strings
|
||||
char* irjp_parse_string(RJP_value* root, const char* str, int* inclen, int* len, int* row, int* column){
|
||||
|
||||
39
src/tester.c
Normal file
39
src/tester.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include "rjp.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(){
|
||||
RJP_value* test = rjp_parse("{\"test\":{\"key\":\"testvalue\",\"key2\": 7},\"test2\":[\"faggot\", 7, 8, 9]}");
|
||||
RJP_value* object = rjp_new_object();
|
||||
RJP_value* mem = rjp_add_member_key_copy(object, "1", 1);
|
||||
rjp_set_int(mem, 1);
|
||||
mem = rjp_add_member_key_copy(object, "2", 1);
|
||||
rjp_set_int(mem, 2);
|
||||
mem = rjp_add_member_key_copy(object, "3", 1);
|
||||
rjp_set_int(mem, 3);
|
||||
mem = rjp_add_member_key_copy(object, "4", 1);
|
||||
rjp_set_int(mem, 4);
|
||||
|
||||
|
||||
RJP_value* searchres = rjp_search_member(object, "3");
|
||||
rjp_set_int(searchres, 7);
|
||||
|
||||
RJP_object_iterator it;
|
||||
rjp_init_object_iterator(&it, object);
|
||||
for(RJP_value* v = rjp_object_iterator_current(&it);v;v = rjp_object_iterator_next(&it)){
|
||||
printf("%d\n", rjp_get_int(v));
|
||||
}
|
||||
rjp_delete_object_iterator(&it);
|
||||
|
||||
|
||||
char* buffer = rjp_to_json(object, RJP_FORMAT_PRETTY);
|
||||
printf("%s\n", buffer);
|
||||
rjp_free(buffer);
|
||||
buffer = rjp_to_json(test, RJP_FORMAT_PRETTY);
|
||||
printf("%s\n", buffer);
|
||||
rjp_free(buffer);
|
||||
|
||||
rjp_free_value(object);
|
||||
rjp_free_value(test);
|
||||
}
|
||||
15
src/tree.c
15
src/tree.c
@ -125,11 +125,12 @@ static void irjp_replace_node(RJP_tree_node *restrict node, RJP_tree_node *restr
|
||||
}
|
||||
|
||||
//Node construction / destruction
|
||||
RJP_tree_node* irjp_new_node(RJP_object_member* value){
|
||||
RJP_tree_node* node = rjp_alloc(sizeof(RJP_tree_node));
|
||||
node->data.name = value->name;
|
||||
node->data.value = value->value;
|
||||
RJP_tree_node* irjp_new_node(char* key, RJP_index keylen){
|
||||
RJP_tree_node* node = rjp_calloc(sizeof(RJP_tree_node), 1);
|
||||
node->data.name.value = key;
|
||||
node->data.name.length = keylen;
|
||||
node->parent = node->left = node->right = NULL;
|
||||
node->color = BLACK;
|
||||
return node;
|
||||
}
|
||||
static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src){
|
||||
@ -174,15 +175,15 @@ void irjp_free_tree(RJP_tree_node* root){
|
||||
irjp_free_node(root);
|
||||
}
|
||||
//Tree operations
|
||||
RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, RJP_object_member* value, 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){
|
||||
*status = RJP_TREE_SUCCESS;
|
||||
if(!root){
|
||||
root = irjp_new_node(value);
|
||||
root = irjp_new_node(key, keylen);
|
||||
if(added)
|
||||
*added = &root->data.value;
|
||||
return root;
|
||||
}
|
||||
RJP_tree_node* newnode = irjp_new_node(value);
|
||||
RJP_tree_node* newnode = irjp_new_node(key, keylen);
|
||||
if(added)
|
||||
*added = &newnode->data.value;
|
||||
return irjp_tree_insert_node(root, newnode);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user