Reorganized file structure

This commit is contained in:
rexy712 2018-12-21 12:44:47 -08:00
parent 6d89e4dc5a
commit 4b5586ffed
9 changed files with 309 additions and 281 deletions

View File

@ -16,7 +16,7 @@ include_directories("${INCLUDE_PATH}")
option(ENABLE_DIAGNOSTICS "Print diagnostic messages when parsing json to help identify issues" ON) option(ENABLE_DIAGNOSTICS "Print diagnostic messages when parsing json to help identify issues" ON)
option(ENABLE_SHARED "Build shared library" OFF) option(ENABLE_SHARED "Build shared library" OFF)
set(SOURCE_LIST "src/input.c" "src/output.c" "src/strings.c" "src/memory.c") set(SOURCE_LIST "src/input.c" "src/output.c" "src/strings.c" "src/memory.c" "src/rjp.c")
if(ENABLE_SHARED) if(ENABLE_SHARED)
add_library(rjp SHARED ${SOURCE_LIST}) add_library(rjp SHARED ${SOURCE_LIST})
else() else()

View File

@ -75,17 +75,17 @@ typedef struct RJP_value{
enum RJP_type type; //flag to determine active member of union enum RJP_type type; //flag to determine active member of union
}RJP_value; }RJP_value;
//Convert C string consisting of json data into RJP's format //Convert C string consisting of json data into RJP's format
RJP_value* rjp_parse(const char* str); RJP_value* rjp_parse(const char* str);
//Free an RJP_value and all members/elements
void rjp_free_value(RJP_value* root);
//Initialize a root RJP_value to NULL //Initialize a root RJP_value to NULL
RJP_value* rjp_init_json(void); RJP_value* rjp_init_json(void);
//Initialize a root RJP_value to copy of value //Initialize a root RJP_value to copy of value
RJP_value* rjp_init_json_as(RJP_value value); RJP_value* rjp_init_json_as(RJP_value value);
//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);
//Allocate heap space for rjp to use. Use if the memory is to be freed by rjp //Allocate heap space for rjp to use. Use if the memory is to be freed by rjp
@ -95,8 +95,6 @@ void* rjp_calloc(size_t num, size_t nbytes);
//Free memory allocated by rjp_alloc or rjp_calloc //Free memory allocated by rjp_alloc or rjp_calloc
void rjp_free(void* dest); void rjp_free(void* dest);
//Deep copy an RJP_value
void rjp_copy_value(RJP_value* dest, const RJP_value* src);
//add a member to a json object, allocating a copy of the key //add a member to a json object, allocating a copy of the key
RJP_value* rjp_add_member(RJP_value* dest, const char* key, size_t keylen, RJP_value value); RJP_value* rjp_add_member(RJP_value* dest, const char* key, size_t keylen, RJP_value value);
//add a member to a json object without allocation. key must be allocated using rjp_alloc/rjp_calloc //add a member to a json object without allocation. key must be allocated using rjp_alloc/rjp_calloc

View File

@ -21,6 +21,19 @@
#include "rjp.h" #include "rjp.h"
#ifdef __GNUC__
#define MAYBE_UNUSED __attribute__((unused))
#else
#define MAYBE_UNUSED
#endif
#ifdef RJP_DIAGNOSTICS
#include <stdio.h>
#define DIAG_PRINT(...) fprintf(__VA_ARGS__)
#else
#define DIAG_PRINT(...)
#endif
// //
typedef struct RJP_array_element{ typedef struct RJP_array_element{
struct RJP_value value; struct RJP_value value;
@ -33,12 +46,8 @@ typedef struct RJP_object_member{
struct RJP_object_member* next; struct RJP_object_member* next;
}RJP_object_member; }RJP_object_member;
char* _rjp__parse_string(RJP_value* root, const char* str, int* len, int* row, int* column); void _rjp__add_element(RJP_array* j);
size_t _rjp__object_strlen(RJP_value* root);
void _rjp__add_member(RJP_object* j, const char* str, size_t len); void _rjp__add_member(RJP_object* j, const char* str, size_t len);
void _rjp__add_member_no_alloc(RJP_object* j, char* str, size_t len); void _rjp__add_member_no_alloc(RJP_object* j, char* str, size_t len);
void _rjp__add_element(RJP_array* j);
size_t _rjp__object_strlen(RJP_value* root);
size_t _rjp__value_strlen(RJP_value* root);
#endif #endif

32
include/strings.h Normal file
View File

@ -0,0 +1,32 @@
/**
rjp
Copyright (C) 2018 rexy712
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/>.
*/
#ifndef STRINGS_H
#define STRINGS_H
#include "rjp.h"
#include <stddef.h> //size_t
int _rjp__is_whitespace(char c);
char* _rjp__parse_string(RJP_value* root, const char* str, int* len, int* row, int* column);
size_t _rjp__array_strlen(RJP_value* arr);
size_t _rjp__object_strlen(RJP_value* root);
size_t _rjp__value_strlen(RJP_value* root);
void _rjp__strcpy(RJP_string* dest, const RJP_string* src);
#endif

View File

@ -20,22 +20,11 @@
#include "rjp.h" #include "rjp.h"
#include "rjp_internal.h" #include "rjp_internal.h"
#include <string.h> //strncpy #include "strings.h"
#include <stdlib.h> //malloc, calloc, free #include "memory.h"
#include <stdlib.h> //strtod, strtol
#include <stdio.h> //fprintf, stderr #include <stdio.h> //fprintf, stderr
#ifdef __GNUC__
#define MAYBE_UNUSED __attribute__((unused))
#else
#define MAYBE_UNUSED
#endif
#ifdef RJP_DIAGNOSTICS
#define DIAG_PRINT(...) fprintf(__VA_ARGS__)
#else
#define DIAG_PRINT(...)
#endif
//types of searches in the text //types of searches in the text
typedef enum json_search_target{ typedef enum json_search_target{
json_key, json_key,
@ -45,151 +34,21 @@ typedef enum json_search_target{
json_none json_none
}json_search_target; }json_search_target;
//Determine if the character is valid whitespace static RJP_value* _rjp__add_value(RJP_value* curr, RJP_value new_val){
static int _rjp__is_whitespace(char c){ new_val.parent = curr;
return c == ' ' || c == '\n' || c == '\r' || c == '\t';
}
//add an element to an array
void _rjp__add_element(RJP_array* j){
++j->num_elements;
if(!j->elements){
j->elements = rjp_calloc(1, sizeof(RJP_array_element));
j->last = j->elements;
}else{
j->last->next = rjp_calloc(1, sizeof(RJP_array_element));
j->last = j->last->next;
}
}
//create member of the object as a linked list member and assign a name with name allocation
void _rjp__add_member(RJP_object* j, const char* str, size_t len){
++j->num_members;
if(!j->members){
j->members = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->members;
}else{
j->last->next = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->last->next;
}
j->last->name.value = rjp_alloc(len + 1);
strncpy(j->last->name.value, str, len);
j->last->name.value[len] = 0;
j->last->name.length = len;
}
void _rjp__add_member_no_alloc(RJP_object* j, char* str, size_t len){
++j->num_members;
if(!j->members){
j->members = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->members;
}else{
j->last->next = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->last->next;
}
j->last->name.value = str;
j->last->name.length = len;
}
static RJP_value* _rjp__add_value(RJP_value* curr, RJP_value* new_val){
if(!curr){ if(!curr){
curr = rjp_calloc(1, sizeof(RJP_value)); curr = rjp_calloc(1, sizeof(RJP_value));
*curr = *new_val; *curr = new_val;
return curr; return curr;
} }
if(curr->type == json_array){ if(curr->type == json_array){
_rjp__add_element(&curr->array); _rjp__add_element(&curr->array);
curr->array.last->value = *new_val; curr->array.last->value = new_val;
return &curr->array.last->value; return &curr->array.last->value;
} }
curr->object.last->value = *new_val; curr->object.last->value = new_val;
return &curr->object.last->value; return &curr->object.last->value;
} }
//Assign object characteristics to previously allocated RJP_value
static RJP_value* _rjp__add_object(RJP_value* curr){
RJP_value new_object = {.type = json_object, .integer = 0, .parent = curr};
return _rjp__add_value(curr, &new_object);
}
//Assign array characteristics to previously allocated RJP_value
static RJP_value* _rjp__add_array(RJP_value* curr){
RJP_value new_array = {.type = json_array, .array = {.num_elements = 0, .elements = NULL}, .parent = curr};
return _rjp__add_value(curr, &new_array);
}
//Assign string characteristics to previously allocated RJP_value with no string allocation
static RJP_value* _rjp__add_string_no_alloc(RJP_value* curr, char* str, int len){
RJP_value new_string = {.type = json_string, .string = {.value = str, .length = len}, .parent = curr};
return _rjp__add_value(curr, &new_string);
}
//Assign double characteristics to previously allocated RJP_value
static RJP_value* _rjp__add_dfloat(RJP_value* curr, double value){
RJP_value new_double = {.type = json_dfloat, .dfloat = value, .parent = curr};
return _rjp__add_value(curr, &new_double);
}
//Assign integer characteristics to previously allocated RJP_value
static RJP_value* _rjp__add_integer(RJP_value* curr, long value){
RJP_value new_integer = {.type = json_integer, .integer = value, .parent = curr};
return _rjp__add_value(curr, &new_integer);
}
static RJP_value* _rjp__add_boolean(RJP_value* curr, int value){
RJP_value new_boolean = {.type = json_boolean, .boolean = value, .parent = curr};
return _rjp__add_value(curr, &new_boolean);
}
static RJP_value* _rjp__add_null(RJP_value* curr){
RJP_value new_null = {.type = json_null, .integer = 0, .parent = curr};
return _rjp__add_value(curr, &new_null);
}
static void _rjp__free_object_recurse(RJP_value* root);
static void _rjp__free_array(RJP_value* root){
RJP_array_element* arr = root->array.elements;
for(RJP_array_element* i = arr;i != NULL;i = arr){
arr = arr->next;
if(i->value.type == json_object){
_rjp__free_object_recurse(&i->value);
}else if(i->value.type == json_array){
_rjp__free_array(&i->value);
}else if(i->value.type == json_string){
free(i->value.string.value);
}
free(i);
}
}
//Recursively free JSON objects
static void _rjp__free_object_recurse(RJP_value* root){
RJP_object_member* next;
for(RJP_object_member* m = root->object.members;m;m = next){
next = m->next;
if(m->value.type == json_object)
_rjp__free_object_recurse(&m->value);
else if(m->value.type == json_string)
free(m->value.string.value);
else if(m->value.type == json_array)
_rjp__free_array(&m->value);
if(m->name.value)
free(m->name.value);
free(m);
}
}
void rjp_free_value_json(char* json){
free(json);
}
//Same as recurse but also frees root node
void rjp_free_value(RJP_value* root){
if(!root)
return;
if((root->type) == json_object)
_rjp__free_object_recurse(root);
else if((root->type) == json_array)
_rjp__free_array(root);
free(root);
}
MAYBE_UNUSED static int _rjp__is_array_empty(RJP_value* curr){
if(curr->object.members->value.type != json_array)
return 0;
return curr->object.members->value.array.num_elements == 0;
}
#define syntax_error(msg, row, column)\ #define syntax_error(msg, row, column)\
do{DIAG_PRINT(stderr, "Syntax error! %s (%i:%i)\n", msg, row, column);rjp_free_value(root);return NULL;}while(0) do{DIAG_PRINT(stderr, "Syntax error! %s (%i:%i)\n", msg, row, column);rjp_free_value(root);return NULL;}while(0)
@ -299,11 +158,11 @@ RJP_value* rjp_parse(const char* str){
//object //object
if(c == '{'){ if(c == '{'){
if(!root){ if(!root){
root = _rjp__add_object(NULL); root = _rjp__add_value(NULL, rjp_object());
curr = root; curr = root;
*top = json_key; *top = json_key;
}else{ }else{
curr = _rjp__add_object(curr); curr = _rjp__add_value(curr, rjp_object());
*top = json_comma; *top = json_comma;
++top; ++top;
*top = json_key; *top = json_key;
@ -311,11 +170,11 @@ RJP_value* rjp_parse(const char* str){
} }
else if(c == '['){ else if(c == '['){
if(!root){ if(!root){
root = _rjp__add_array(NULL); root = _rjp__add_value(NULL, rjp_array());
curr = root; curr = root;
}else{ }else{
curr = _rjp__add_array(curr); curr = _rjp__add_value(curr, rjp_array());
} }
} }
else if(c == ']' && curr->type == json_array){ //empty array else if(c == ']' && curr->type == json_array){ //empty array
@ -334,7 +193,7 @@ RJP_value* rjp_parse(const char* str){
return NULL; return NULL;
} }
} }
_rjp__add_string_no_alloc(curr, new_string, vallen); _rjp__add_value(curr, rjp_string(new_string, vallen));
str += vallen; str += vallen;
*top = json_comma; *top = json_comma;
} }
@ -363,15 +222,15 @@ RJP_value* rjp_parse(const char* str){
} }
if(floating){ if(floating){
if(!root){ if(!root){
root = curr = _rjp__add_dfloat(NULL, strtod(str, NULL)); root = curr = _rjp__add_value(NULL, rjp_dfloat(strtod(str, NULL)));
}else{ }else{
_rjp__add_dfloat(curr, strtod(str, NULL)); _rjp__add_value(curr, rjp_dfloat(strtod(str, NULL)));
} }
}else{ }else{
if(!root){ if(!root){
root = curr = _rjp__add_integer(NULL, strtol(str, NULL, 10)); root = curr = _rjp__add_value(NULL, rjp_integer(strtol(str, NULL, 10)));
}else{ }else{
_rjp__add_integer(curr, strtol(str, NULL, 10)); _rjp__add_value(curr, rjp_integer(strtol(str, NULL, 10)));
} }
} }
str += (numlen-1); str += (numlen-1);
@ -381,28 +240,28 @@ RJP_value* rjp_parse(const char* str){
else if(!strncmp(str, "true", 4)){ else if(!strncmp(str, "true", 4)){
if(!curr){ if(!curr){
*top = json_none; *top = json_none;
root = curr = _rjp__add_boolean(curr, 1); root = curr = _rjp__add_value(curr, rjp_boolean(1));
}else{ }else{
*top = json_comma; *top = json_comma;
_rjp__add_boolean(curr, 1); _rjp__add_value(curr, rjp_boolean(1));
} }
str += 3;column += 3; str += 3;column += 3;
}else if(!strncmp(str, "false", 5)){ }else if(!strncmp(str, "false", 5)){
if(!curr){ if(!curr){
*top = json_none; *top = json_none;
root = curr = _rjp__add_boolean(curr, 0); root = curr = _rjp__add_value(curr, rjp_boolean(0));
}else{ }else{
*top = json_comma; *top = json_comma;
_rjp__add_boolean(curr, 0); _rjp__add_value(curr, rjp_boolean(0));
} }
str += 4;column += 4; str += 4;column += 4;
}else if(!strncmp(str, "null", 4)){ }else if(!strncmp(str, "null", 4)){
if(!curr){ if(!curr){
*top = json_none; *top = json_none;
root = curr = _rjp__add_null(curr); root = curr = _rjp__add_value(curr, rjp_null());
}else{ }else{
*top = json_comma; *top = json_comma;
_rjp__add_null(curr); _rjp__add_value(curr, rjp_null());
} }
str += 3;column += 3; str += 3;column += 3;
} }

View File

@ -1,3 +1,21 @@
/**
rjp
Copyright (C) 2018 rexy712
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/>.
*/
#include "rjp_internal.h" #include "rjp_internal.h"
#include <stdlib.h> #include <stdlib.h>
@ -13,13 +31,6 @@ void rjp_free(void* data){
free(data); free(data);
} }
void _rjp__strcpy(RJP_string* dest, const RJP_string* src){
dest->value = rjp_alloc(src->length + 1);
strcpy(dest->value, src->value);
dest->value[src->length] = 0;
dest->length = src->length;
}
static void _rjp__copy_object(RJP_value* dest, const RJP_value* src){ static void _rjp__copy_object(RJP_value* dest, const RJP_value* src){
dest->object.members = dest->object.last = 0; dest->object.members = dest->object.last = 0;
for(RJP_value* curr = rjp_get_member(src);curr;curr = rjp_next_member(curr)){ for(RJP_value* curr = rjp_get_member(src);curr;curr = rjp_next_member(curr)){
@ -63,3 +74,48 @@ void rjp_copy_value(RJP_value* dest, const RJP_value* src){
break; break;
}; };
} }
static void _rjp__free_object_recurse(RJP_value* root);
static void _rjp__free_array(RJP_value* root){
RJP_array_element* arr = root->array.elements;
for(RJP_array_element* i = arr;i != NULL;i = arr){
arr = arr->next;
if(i->value.type == json_object){
_rjp__free_object_recurse(&i->value);
}else if(i->value.type == json_array){
_rjp__free_array(&i->value);
}else if(i->value.type == json_string){
free(i->value.string.value);
}
free(i);
}
}
//Recursively free JSON objects
static void _rjp__free_object_recurse(RJP_value* root){
RJP_object_member* next;
for(RJP_object_member* m = root->object.members;m;m = next){
next = m->next;
if(m->value.type == json_object)
_rjp__free_object_recurse(&m->value);
else if(m->value.type == json_string)
free(m->value.string.value);
else if(m->value.type == json_array)
_rjp__free_array(&m->value);
if(m->name.value)
free(m->name.value);
free(m);
}
}
//Same as recurse but also frees root node
void rjp_free_value(RJP_value* root){
if(!root)
return;
if((root->type) == json_object)
_rjp__free_object_recurse(root);
else if((root->type) == json_array)
_rjp__free_array(root);
free(root);
}

View File

@ -18,9 +18,9 @@
#include "rjp.h" #include "rjp.h"
#include "rjp_internal.h" #include "rjp_internal.h"
#include "memory.h"
#include <string.h> //strlen #include <string.h> //strlen
#include <stdlib.h> //malloc, calloc, free
#include <stdio.h> //sprintf #include <stdio.h> //sprintf
RJP_value* rjp_init_json(void){ RJP_value* rjp_init_json(void){
@ -32,100 +32,6 @@ RJP_value* rjp_init_json_as(RJP_value value){
*ret = value; *ret = value;
return ret; return ret;
} }
RJP_value* rjp_add_member(RJP_value* dest, const char* key, size_t keylen, RJP_value value){
if(!keylen)
keylen = strlen(key);
_rjp__add_member(&dest->object, key, keylen);
dest->object.last->value = value;
dest->object.last->value.parent = dest;
return &dest->object.last->value;
}
RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, size_t keylen, RJP_value value){
if(!keylen)
keylen = strlen(key);
_rjp__add_member_no_alloc(&dest->object, key, keylen);
dest->object.last->value = value;
dest->object.last->value.parent = dest;
return &dest->object.last->value;
}
RJP_value* rjp_add_element(RJP_value* dest, RJP_value value){
_rjp__add_element(&dest->array);
dest->array.last->value = value;
dest->array.last->value.parent = dest;
return &dest->array.last->value;
}
void rjp_set_value(RJP_value* dest, RJP_value value){
struct RJP_value* p = dest->parent;
*dest = value;
dest->parent = p;
}
RJP_value rjp_integer(long i){
return (RJP_value){.integer = i, .type = json_integer};
}
RJP_value rjp_boolean(char b){
return (RJP_value){.boolean = b, .type = json_boolean};
}
RJP_value rjp_dfloat(double d){
return (RJP_value){.dfloat = d, .type = json_dfloat};
}
RJP_value rjp_string(char* c, size_t len){
return (RJP_value){.string = {.value = c, .length = len}, .type = json_string};
}
RJP_value rjp_null(void){
return (RJP_value){.integer = 0, .type = json_null};
}
RJP_value rjp_object(void){
return (RJP_value){.object = {0}, .type = json_object};
}
RJP_value rjp_array(void){
return (RJP_value){.array = {0}, .type = json_array};
}
RJP_value* rjp_get_member(const RJP_value* object){
return &object->object.members->value;
}
RJP_value* rjp_next_member(const RJP_value* member){
//polymorphism
return (RJP_value*)(((RJP_object_member*)member)->next);
}
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);
}
char* rjp_member_name(const RJP_value* member){
return ((RJP_object_member*)member)->name.value;
}
size_t rjp_member_name_length(RJP_value* member){
return ((RJP_object_member*)member)->name.length;
}
RJP_value* rjp_value_parent(RJP_value* value){
return value->parent;
}
RJP_type rjp_value_type(RJP_value* value){
return value->type;
}
double rjp_value_dfloat(RJP_value* value){
return value->dfloat;
}
int rjp_value_integer(RJP_value* value){
return value->integer;
}
char rjp_value_boolean(RJP_value* value){
return value->boolean;
}
char* rjp_value_string(RJP_value* value){
return value->string.value;
}
size_t rjp_value_string_length(RJP_value* value){
return value->string.length;
}
static size_t _rjp__write_value(char* dest, RJP_value* val){ static size_t _rjp__write_value(char* dest, RJP_value* val){
size_t ret; size_t ret;

155
src/rjp.c Normal file
View File

@ -0,0 +1,155 @@
/**
rjp
Copyright (C) 2018 rexy712
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/>.
*/
#include "rjp_internal.h"
#include <string.h> //strncpy, strlen
void _rjp__add_element(RJP_array* j){
++j->num_elements;
if(!j->elements){
j->elements = rjp_calloc(1, sizeof(RJP_array_element));
j->last = j->elements;
}else{
j->last->next = rjp_calloc(1, sizeof(RJP_array_element));
j->last = j->last->next;
}
}
//create member of the object as a linked list member and assign a name with name allocation
void _rjp__add_member(RJP_object* j, const char* str, size_t len){
++j->num_members;
if(!j->members){
j->members = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->members;
}else{
j->last->next = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->last->next;
}
j->last->name.value = rjp_alloc(len + 1);
strncpy(j->last->name.value, str, len);
j->last->name.value[len] = 0;
j->last->name.length = len;
}
void _rjp__add_member_no_alloc(RJP_object* j, char* str, size_t len){
++j->num_members;
if(!j->members){
j->members = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->members;
}else{
j->last->next = rjp_calloc(1, sizeof(RJP_object_member));
j->last = j->last->next;
}
j->last->name.value = str;
j->last->name.length = len;
}
RJP_value* rjp_add_member(RJP_value* dest, const char* key, size_t keylen, RJP_value value){
if(!keylen)
keylen = strlen(key);
_rjp__add_member(&dest->object, key, keylen);
dest->object.last->value = value;
dest->object.last->value.parent = dest;
return &dest->object.last->value;
}
RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, size_t keylen, RJP_value value){
if(!keylen)
keylen = strlen(key);
_rjp__add_member_no_alloc(&dest->object, key, keylen);
dest->object.last->value = value;
dest->object.last->value.parent = dest;
return &dest->object.last->value;
}
RJP_value* rjp_add_element(RJP_value* dest, RJP_value value){
_rjp__add_element(&dest->array);
dest->array.last->value = value;
dest->array.last->value.parent = dest;
return &dest->array.last->value;
}
void rjp_set_value(RJP_value* dest, RJP_value value){
struct RJP_value* p = dest->parent;
*dest = value;
dest->parent = p;
}
RJP_value rjp_integer(long i){
return (RJP_value){.integer = i, .type = json_integer};
}
RJP_value rjp_boolean(char b){
return (RJP_value){.boolean = b, .type = json_boolean};
}
RJP_value rjp_dfloat(double d){
return (RJP_value){.dfloat = d, .type = json_dfloat};
}
RJP_value rjp_string(char* c, size_t len){
return (RJP_value){.string = {.value = c, .length = len}, .type = json_string};
}
RJP_value rjp_null(void){
return (RJP_value){.integer = 0, .type = json_null};
}
RJP_value rjp_object(void){
return (RJP_value){.object = {0}, .type = json_object};
}
RJP_value rjp_array(void){
return (RJP_value){.array = {0}, .type = json_array};
}
RJP_value* rjp_get_member(const RJP_value* object){
return &object->object.members->value;
}
RJP_value* rjp_next_member(const RJP_value* member){
//polymorphism
return (RJP_value*)(((RJP_object_member*)member)->next);
}
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);
}
char* rjp_member_name(const RJP_value* member){
return ((RJP_object_member*)member)->name.value;
}
size_t rjp_member_name_length(RJP_value* member){
return ((RJP_object_member*)member)->name.length;
}
RJP_value* rjp_value_parent(RJP_value* value){
return value->parent;
}
RJP_type rjp_value_type(RJP_value* value){
return value->type;
}
double rjp_value_dfloat(RJP_value* value){
return value->dfloat;
}
int rjp_value_integer(RJP_value* value){
return value->integer;
}
char rjp_value_boolean(RJP_value* value){
return value->boolean;
}
char* rjp_value_string(RJP_value* value){
return value->string.value;
}
size_t rjp_value_string_length(RJP_value* value){
return value->string.length;
}

View File

@ -16,12 +16,18 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "rjp.h" #include "strings.h"
#include "rjp_internal.h" #include "rjp_internal.h"
#include <stdio.h> //fprintf #include <stdio.h> //fprintf
#include <stdlib.h> //malloc, free #include <stdlib.h> //malloc, free
#include <stdint.h> #include <stdint.h> //uintN_t
#include <string.h> //strcpy
//Determine if the character is valid whitespace
int _rjp__is_whitespace(char c){
return c == ' ' || c == '\n' || c == '\r' || c == '\t';
}
static uint32_t utf_strtol_4(const char* c){ static uint32_t utf_strtol_4(const char* c){
uint32_t ret = 0; uint32_t ret = 0;
@ -261,6 +267,13 @@ size_t rjp_escape_strcpy(char* dest, const char* src){
dest[j] = 0; dest[j] = 0;
return j; return j;
} }
void _rjp__strcpy(RJP_string* dest, const RJP_string* src){
dest->value = rjp_alloc(src->length + 1);
strcpy(dest->value, src->value);
dest->value[src->length] = 0;
dest->length = src->length;
}
size_t rjp_escape_strlen(const char* str){ size_t rjp_escape_strlen(const char* str){
size_t count = 0; size_t count = 0;
for(size_t i = 0;str[i];++i){ for(size_t i = 0;str[i];++i){