5 Commits
v0.1 ... v0.2

Author SHA1 Message Date
rexy712
036c732ee8 changed member/element addition to be more convenient in most situations 2018-11-30 13:49:51 -08:00
rexy712
f1d8dbde97 Fixed a memory leak and removed main function (again) 2018-11-30 13:32:21 -08:00
rexy712
890876a490 cleaned up object/array output and version bump 2018-11-30 11:22:54 -08:00
rexy712
e70b0833e6 Working json output and split source into multiple files 2018-11-29 14:26:20 -08:00
rexy712
9eaa734fbb Rudimentary output to json 2018-11-25 16:19:14 -08:00
6 changed files with 455 additions and 163 deletions

View File

@@ -4,7 +4,7 @@ include(GNUInstallDirs)
cmake_minimum_required(VERSION 3.0.2)
project(rjp)
set(rjp_VERSION_MAJOR 0)
set(rjp_VERSION_MINOR 1)
set(rjp_VERSION_MINOR 2)
set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include)
configure_file(
"${INCLUDE_PATH}/config.h.in"
@@ -12,7 +12,7 @@ configure_file(
)
include_directories("${INCLUDE_PATH}")
add_library (rjp STATIC src/rjp.c)
add_library (rjp STATIC src/input.c src/output.c src/strings.c)
set_target_properties(rjp PROPERTIES PUBLIC_HEADER ${INCLUDE_PATH}/rjp.h)
install(TARGETS rjp

View File

@@ -24,6 +24,7 @@
#ifdef __cplusplus
extern "C"{
#endif
//type of data
enum JSON_type{
json_object,
@@ -64,7 +65,6 @@ struct JSON_array{
//hold any json data type
struct JSON_value{
enum JSON_type type;
union{
long integer;
double dfloat;
@@ -74,6 +74,7 @@ struct JSON_value{
struct JSON_array array;
};
struct JSON_value* parent;
enum JSON_type type;
};
struct JSON_array_element{
@@ -92,6 +93,7 @@ struct JSON_object_member{
struct JSON_value* rjp_parse(const char* str);
//deallocate a json handle
void rjp_free_json(char* json);
void rjp_free(struct JSON_value* root);
struct JSON_object_member* rjp_get_members(struct JSON_object* j);
@@ -105,26 +107,26 @@ enum JSON_type rjp_get_value_type(struct JSON_value* j);
//initialize an empty json handle (outputting to string would result in '{}')
struct JSON_value* rjp_init_json(void);
//initialize an empty json object
struct JSON_object* rjp_init_object(void);
//initialize an empty json array
struct JSON_array* rjp_init_array(void);
//add a member to a json object
struct JSON_value* rjp_add_member(struct JSON_object* dest, const char* key, size_t keylen, struct JSON_value* value);
struct JSON_value* rjp_add_member(struct JSON_value* dest, int alloc_key, char* key, size_t keylen, struct JSON_value value);
//add an element to a json array
struct JSON_value* rjp_add_element(struct JSON_array* dest, struct JSON_value* value);
struct JSON_value* rjp_add_element(struct JSON_value* dest, struct JSON_value value);
struct JSON_value* rjp_init_integer(long i);
struct JSON_value* rjp_init_dfloat(double d);
struct JSON_value* rjp_init_boolean(char b);
struct JSON_value* rjp_init_string(const char* str, size_t len);
struct JSON_value rjp_integer(long i);
struct JSON_value rjp_boolean(char b);
struct JSON_value rjp_dfloat(double d);
struct JSON_value rjp_string(char* c, size_t len);
struct JSON_value rjp_null(void);
struct JSON_value rjp_object(void);
struct JSON_value rjp_array(void);
size_t rjp_escape_strcpy(char* dest, const char* src);
size_t rjp_escape_strlen(const char* str);
size_t rjp_dump_object(struct JSON_value* root, char* dest);
size_t rjp_dump_array(struct JSON_value* arr, char* dest);
char* rjp_to_json(struct JSON_value* root);
/*struct JSON_value* root = rjp_init_json();
rjp_add_member(root, "intel_backlight", 15, rjp_init_integer(100));
rjp_free(root);
//{intel_backlight:100}
*/
#ifdef __cplusplus
}
#endif

13
include/rjp_internal.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef RJP_INTERNAL_H
#define RJP_INTERNAL_H
#include "rjp.h"
char* _rjp__parse_string(struct JSON_value* root, const char* str, int* len, int* row, int* column);
size_t _rjp__object_strlen(struct JSON_value* root);
void _rjp__add_member(struct JSON_object* j, char* str, size_t len);
void _rjp__add_member_no_alloc(struct JSON_object* j, char* str, size_t len);
void _rjp__add_element(struct JSON_array* j);
size_t _rjp__object_strlen(struct JSON_value* root);
#endif

View File

@@ -20,8 +20,9 @@
//TODO: \e escape sequence in strings
#include "rjp.h"
#include "rjp_internal.h"
#include <string.h> //strncpy
#include <stdlib.h> //malloc, calloc
#include <stdlib.h> //malloc, calloc, free
#include <stdio.h> //fprintf, stderr
#ifdef __GNUC__
@@ -44,55 +45,58 @@ enum json_search_target{
};
//Determine if the character is valid whitespace
static int is_whitespace(char c){
static int _rjp__is_whitespace(char c){
return c == ' ' || c == '\n' || c == '\r' || c == '\t';
}
//allocate a member of the object as a linked list member and assign a name
MAYBE_UNUSED static void add_member(struct JSON_value* j, const char* str, size_t len){
++j->object.num_members;
struct JSON_object_member* prev = j->object.members;
j->object.members = calloc(1, sizeof(struct JSON_object_member));
j->object.members->name.value = malloc(len + 1);
j->object.members->name.length = len;
strncpy(j->object.members->name.value, str, len);
j->object.members->name.value[len] = 0;
j->object.members->next = prev;
}
//add an element to an array
static void add_element(struct JSON_value* j){
++j->array.num_elements;
if(!j->array.elements){
j->array.elements = calloc(1, sizeof(struct JSON_array_element));
j->array.last = j->array.elements;
void _rjp__add_element(struct JSON_array* j){
++j->num_elements;
if(!j->elements){
j->elements = calloc(1, sizeof(struct JSON_array_element));
j->last = j->elements;
}else{
j->array.last->next = calloc(1, sizeof(struct JSON_array_element));
j->array.last = j->array.last->next;
j->last->next = calloc(1, sizeof(struct JSON_array_element));
j->last = j->last->next;
}
}
//create member of the object as a linked list member and assign a name with no name allocation
static void add_member_no_alloc(struct JSON_value* j, char* str, size_t len){
++j->object.num_members;
if(!j->object.members){
j->object.members = calloc(1, sizeof(struct JSON_object_member));
j->object.last = j->object.members;
//create member of the object as a linked list member and assign a name with name allocation
void _rjp__add_member(struct JSON_object* j, char* str, size_t len){
++j->num_members;
if(!j->members){
j->members = calloc(1, sizeof(struct JSON_object_member));
j->last = j->members;
}else{
j->object.last->next = calloc(1, sizeof(struct JSON_object_member));
j->object.last = j->object.last->next;
j->last->next = calloc(1, sizeof(struct JSON_object_member));
j->last = j->last->next;
}
j->object.last->name.value = str;
j->object.last->name.length = len;
j->last->name.value = malloc(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(struct JSON_object* j, char* str, size_t len){
++j->num_members;
if(!j->members){
j->members = calloc(1, sizeof(struct JSON_object_member));
j->last = j->members;
}else{
j->last->next = calloc(1, sizeof(struct JSON_object_member));
j->last = j->last->next;
}
j->last->name.value = str;
j->last->name.length = len;
}
static struct JSON_value* add_element_to_array(struct JSON_value* curr, struct JSON_state* state, struct JSON_value* element){
static struct JSON_value* _rjp__add_element_to_array(struct JSON_value* curr, struct JSON_state* state, struct JSON_value* element){
struct JSON_value* tmp = &curr->object.members->value;
for(int i = state->in_array-1;i > 0;--i, tmp = &tmp->array.last->value);
add_element(tmp);
tmp->array.elements->value = *element;
return &tmp->array.elements->value;
_rjp__add_element(&tmp->array);
tmp->array.last->value = *element;
return &tmp->array.last->value;
}
//Assign object characteristics to previously allocated JSON_value
static struct JSON_value* add_object(struct JSON_value* curr, struct JSON_state* state){
static struct JSON_value* _rjp__add_object(struct JSON_value* curr, struct JSON_state* state){
if(!curr){
curr = calloc(1, sizeof(struct JSON_value));
curr->type = json_object;
@@ -100,67 +104,67 @@ static struct JSON_value* add_object(struct JSON_value* curr, struct JSON_state*
}
struct JSON_value new_object = {.type = json_object, .integer = 0, .parent = curr};
if(state->in_array)
return add_element_to_array(curr, state, &new_object);
curr->object.members->value = new_object;
return &curr->object.members->value;
return _rjp__add_element_to_array(curr, state, &new_object);
curr->object.last->value = new_object;
return &curr->object.last->value;
}
//Assign array characteristics to previously allocated JSON_value
static struct JSON_value* add_array(struct JSON_value* curr, struct JSON_state* state){
static struct JSON_value* _rjp__add_array(struct JSON_value* curr, struct JSON_state* state){
struct JSON_value new_array = {.type = json_array, .array = {.num_elements = 0, .elements = NULL}, .parent = curr};
if(state->in_array)
return add_element_to_array(curr, state, &new_array);
curr->object.members->value = new_array;
return &curr->object.members->value;
return _rjp__add_element_to_array(curr, state, &new_array);
curr->object.last->value = new_array;
return &curr->object.last->value;
}
//Assign string characteristics to previously allocated JSON_value with no string allocation
static struct JSON_value* add_string_no_alloc(struct JSON_value* curr, char* str, int len, struct JSON_state* state){
static struct JSON_value* _rjp__add_string_no_alloc(struct JSON_value* curr, char* str, int len, struct JSON_state* state){
struct JSON_value new_string = {.type = json_string, .string = {.value = str, .length = len}, .parent = curr};
if(state->in_array)
return add_element_to_array(curr, state, &new_string);
curr->object.members->value = new_string;
return &curr->object.members->value;
return _rjp__add_element_to_array(curr, state, &new_string);
curr->object.last->value = new_string;
return &curr->object.last->value;
}
//Assign double characteristics to previously allocated JSON_value
static struct JSON_value* add_double(struct JSON_value* curr, double value, struct JSON_state* state){
static struct JSON_value* _rjp__add_dfloat(struct JSON_value* curr, double value, struct JSON_state* state){
struct JSON_value new_double = {.type = json_dfloat, .dfloat = value, .parent = curr};
if(state->in_array)
return add_element_to_array(curr, state, &new_double);
curr->object.members->value = new_double;
return &curr->object.members->value;
return _rjp__add_element_to_array(curr, state, &new_double);
curr->object.last->value = new_double;
return &curr->object.last->value;
}
//Assign integer characteristics to previously allocated JSON_value
static struct JSON_value* add_integer(struct JSON_value* curr, long value, struct JSON_state* state){
static struct JSON_value* _rjp__add_integer(struct JSON_value* curr, long value, struct JSON_state* state){
struct JSON_value new_integer = {.type = json_integer, .integer = value, .parent = curr};
if(state->in_array)
return add_element_to_array(curr, state, &new_integer);
curr->object.members->value = new_integer;
return &curr->object.members->value;
return _rjp__add_element_to_array(curr, state, &new_integer);
curr->object.last->value = new_integer;
return &curr->object.last->value;
}
static struct JSON_value* add_boolean(struct JSON_value* curr, int value, struct JSON_state* state){
static struct JSON_value* _rjp__add_boolean(struct JSON_value* curr, int value, struct JSON_state* state){
struct JSON_value new_boolean = {.type = json_boolean, .boolean = value, .parent = curr};
if(state->in_array)
return add_element_to_array(curr, state, &new_boolean);
curr->object.members->value = new_boolean;
return &curr->object.members->value;
return _rjp__add_element_to_array(curr, state, &new_boolean);
curr->object.last->value = new_boolean;
return &curr->object.last->value;
}
static struct JSON_value* add_null(struct JSON_value* curr, struct JSON_state* state){
static struct JSON_value* _rjp__add_null(struct JSON_value* curr, struct JSON_state* state){
struct JSON_value new_null = {.type = json_null, .integer = 0, .parent = curr};
if(state->in_array)
return add_element_to_array(curr, state, &new_null);
curr->object.members->value = new_null;
return &curr->object.members->value;
return _rjp__add_element_to_array(curr, state, &new_null);
curr->object.last->value = new_null;
return &curr->object.last->value;
}
static void free_json_recurse(struct JSON_value* root);
static void _rjp__free_object_recurse(struct JSON_value* root);
static void free_json_array(struct JSON_value* root){
static void _rjp__free_array(struct JSON_value* root){
struct JSON_array_element* arr = root->array.elements;
for(struct JSON_array_element* i = arr;i != NULL;i = arr){
arr = arr->next;
if(i->value.type == json_object){
free_json_recurse(&i->value);
_rjp__free_object_recurse(&i->value);
}else if(i->value.type == json_array){
free_json_array(&i->value);
_rjp__free_array(&i->value);
}else if(i->value.type == json_string){
free(i->value.string.value);
}
@@ -168,30 +172,33 @@ static void free_json_array(struct JSON_value* root){
}
}
//Recursively free JSON objects
static void free_json_recurse(struct JSON_value* root){
static void _rjp__free_object_recurse(struct JSON_value* root){
struct JSON_object_member* next;
for(struct JSON_object_member* m = root->object.members;m;m = next){
next = m->next;
if(m->value.type == json_object)
free_json_recurse(&m->value);
_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)
free_json_array(&m->value);
_rjp__free_array(&m->value);
if(m->name.value)
free(m->name.value);
free(m);
}
}
void rjp_free_json(char* json){
free(json);
}
//Same as recurse but also frees root node
void rjp_free(struct JSON_value* root){
if(!root)
return;
free_json_recurse(root);
_rjp__free_object_recurse(root);
free(root);
}
MAYBE_UNUSED static int is_array_empty(struct JSON_value* curr){
MAYBE_UNUSED static int _rjp__is_array_empty(struct JSON_value* curr){
if(curr->object.members->value.type != json_array)
return 0;
return curr->object.members->value.array.num_elements == 0;
@@ -200,63 +207,6 @@ MAYBE_UNUSED static int is_array_empty(struct JSON_value* curr){
#define syntax_error(msg, row, column)\
do{fprintf(stderr, "Syntax error! %s (%i:%i)\n", msg, row, column);rjp_free(root);return NULL;}while(0)
//Convert escape sequences in strings
static char* parse_string(struct JSON_value* root, const char* str, int* len, int* row, int* column){
char* new_string;
++(*column); //account for starting quotation mark
for(*len = 0;*(str+*len) != '"';++(*len), ++(*column)){
if(*(str+*len) == '\\'){
++(*len);
++(*column);
}else if(*(str+*len) == '\0'){
*len = 1;
syntax_error("Unexpected EOF in string!", *row, *column);
}else if(*(str+*len) == '\n'){
++(*row);
*column = 0;
}
}
if(*len == 0){
return NULL;
}
new_string = malloc(*len + 1);
new_string[*len] = 0;
for(int i = 0;*str != '"';++i,++str){
if(*str == '\\'){
++str;
switch(*str){
case '"':
new_string[i] = '"';
break;
case 'n':
new_string[i] = '\n';
break;
case 'r':
new_string[i] = '\r';
break;
case 'b':
new_string[i] = '\b';
break;
case '\\':
new_string[i] = '\\';
break;
case 't':
new_string[i] = '\t';
break;
case 'f':
new_string[i] = '\f';
break;
default:
new_string[i] = *str;
break;
}
}else{
new_string[i] = *str;
}
}
return new_string;
}
#define MAX_DEPTH 16
struct JSON_value* rjp_parse(const char* str){
struct JSON_value* root = 0;
@@ -310,13 +260,13 @@ struct JSON_value* rjp_parse(const char* str){
syntax_error("Key found outside of object definition!", row, column);
int keylen;
char* new_string = parse_string(root, ++str, &keylen, &row, &column);
char* new_string = _rjp__parse_string(root, ++str, &keylen, &row, &column);
if(!new_string){
if(!keylen)
syntax_error("Cannot have empty key name!", row, column);
return NULL;
}
add_member_no_alloc(curr, new_string, keylen);
_rjp__add_member_no_alloc(&curr->object, new_string, keylen);
str += keylen;
top->search_target = json_colon;
//end of this object (object is empty)
@@ -326,7 +276,7 @@ struct JSON_value* rjp_parse(const char* str){
--top;
//unrecognized character
}else if(!is_whitespace(c)){
}else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character, expected '\"'!", row, column);
}
}
@@ -335,7 +285,7 @@ struct JSON_value* rjp_parse(const char* str){
if(c == ':'){
top->search_target = json_value;
//unrecognized character
}else if(!is_whitespace(c)){
}else if(!_rjp__is_whitespace(c)){
syntax_error( "Unexpected character, expected ':'!", row, column);
}
}
@@ -356,7 +306,7 @@ struct JSON_value* rjp_parse(const char* str){
}else if(c == ']' && top->in_array){
--top->in_array;
//unrecognized character
}else if(!is_whitespace(c)){
}else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character, expected ','!", row, column);
}
}
@@ -364,11 +314,11 @@ struct JSON_value* rjp_parse(const char* str){
//object
if(c == '{'){
if(!root){
root = add_object(NULL, top);
root = _rjp__add_object(NULL, top);
curr = root;
top->search_target = json_key;
}else{
curr = add_object(curr, top);
curr = _rjp__add_object(curr, top);
top->search_target = json_comma;
++top;
top->in_array = 0;
@@ -381,7 +331,7 @@ struct JSON_value* rjp_parse(const char* str){
}
//arrays
else if(c == '['){
add_array(curr, top);
_rjp__add_array(curr, top);
++top->in_array;
}
else if(c == ']' && top->in_array){ //empty array
@@ -392,7 +342,7 @@ struct JSON_value* rjp_parse(const char* str){
else if(c == '"'){
int vallen;
++str;
char* new_string = parse_string(root, str, &vallen, &row, &column);
char* new_string = _rjp__parse_string(root, str, &vallen, &row, &column);
if(!new_string){
if(vallen == 0){
new_string = calloc(1, 1);
@@ -400,7 +350,7 @@ struct JSON_value* rjp_parse(const char* str){
return NULL;
}
}
add_string_no_alloc(curr, new_string, vallen, top);
_rjp__add_string_no_alloc(curr, new_string, vallen, top);
str += vallen;
top->search_target = json_comma;
}
@@ -424,9 +374,9 @@ struct JSON_value* rjp_parse(const char* str){
syntax_error("Missing numerals ofter '-' sign!", row, column);
}
if(floating){
add_double(curr, strtod(str, NULL), top);
_rjp__add_dfloat(curr, strtod(str, NULL), top);
}else{
add_integer(curr, strtol(str, NULL, 10), top);
_rjp__add_integer(curr, strtol(str, NULL, 10), top);
}
str += (numlen-1);
column += numlen;
@@ -434,20 +384,20 @@ struct JSON_value* rjp_parse(const char* str){
}
//booleans and null
else if(!strncmp(str, "true", 4)){
add_boolean(curr, 1, top);
_rjp__add_boolean(curr, 1, top);
str += 3;
top->search_target = json_comma;
}else if(!strncmp(str, "false", 5)){
add_boolean(curr, 0, top);
_rjp__add_boolean(curr, 0, top);
str += 4;
top->search_target = json_comma;
}else if(!strncmp(str, "null", 4)){
add_null(curr, top);
_rjp__add_null(curr, top);
str += 3;
top->search_target = json_comma;
}
//unrecognized character
else if(!is_whitespace(c)){
else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character!", row, column);
}
}
@@ -457,6 +407,7 @@ struct JSON_value* rjp_parse(const char* str){
#undef syntax_error
//TODO
struct JSON_object_member* rjp_get_members(struct JSON_object* j){
return j->members;
}

130
src/output.c Normal file
View File

@@ -0,0 +1,130 @@
#include "rjp.h"
#include "rjp_internal.h"
#include <string.h> //strlen
#include <stdlib.h> //malloc, calloc, free
#include <stdio.h> //sprintf
struct JSON_value* rjp_init_json(void){
struct JSON_value* ret = calloc(1, sizeof(struct JSON_value));
ret->type = json_object;
return ret;
}
struct JSON_value* rjp_add_member(struct JSON_value* dest, int alloc_key, char* key, size_t keylen, struct JSON_value value){
if(!keylen && alloc_key)
keylen = strlen(key);
if(alloc_key)
_rjp__add_member(&dest->object, key, keylen);
else
_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;
}
struct JSON_value* rjp_add_element(struct JSON_value* dest, struct JSON_value value){
_rjp__add_element(&dest->array);
dest->array.last->value = value;
dest->array.last->value.parent = dest;
return &dest->array.last->value;
}
struct JSON_value rjp_integer(long i){
return (struct JSON_value){.integer = i, .type = json_integer};
}
struct JSON_value rjp_boolean(char b){
return (struct JSON_value){.boolean = b, .type = json_boolean};
}
struct JSON_value rjp_dfloat(double d){
return (struct JSON_value){.dfloat = d, .type = json_dfloat};
}
struct JSON_value rjp_string(char* c, size_t len){
return (struct JSON_value){.string = {.value = c, .length = len}, .type = json_string};
}
struct JSON_value rjp_null(void){
return (struct JSON_value){.integer = 0, .type = json_null};
}
struct JSON_value rjp_object(void){
return (struct JSON_value){.object = {0}, .type = json_object};
}
struct JSON_value rjp_array(void){
return (struct JSON_value){.array = {0}, .type = json_array};
}
static size_t _rjp__write_value(char* dest, struct JSON_value* val){
size_t ret;
switch(val->type){
case json_integer:
ret = sprintf(dest, "%li", val->integer);
break;
case json_dfloat:
ret = sprintf(dest, "%lf", val->dfloat);
break;
case json_boolean:
ret = sprintf(dest, val->boolean ? "true" : "false");
break;
case json_null:
ret = sprintf(dest, "null");
break;
case json_string:;
ret = sprintf(dest, "\"%s\"", val->string.value);
break;
case json_array:
ret = sprintf(dest, "[");
ret += rjp_dump_array(val, dest+ret);
ret += sprintf(dest+ret, "]");
break;
case json_object:
ret = sprintf(dest, "{");
ret += rjp_dump_object(val, dest+ret);
ret += sprintf(dest+ret, "}");
break;
default:
ret = 0;
break;
};
return ret;
}
size_t rjp_dump_array(struct JSON_value* arr, char* dest){
struct JSON_array* array = &arr->array;
struct JSON_array_element* element_list = array->elements;
size_t pos = 0;
for(;element_list;element_list = element_list->next){
pos += _rjp__write_value(dest+pos, &element_list->value);
if(element_list->next)
pos += sprintf(dest+pos, ",");
else
break;
}
return pos;
}
size_t rjp_dump_object(struct JSON_value* root, char* dest){
struct JSON_object* root_obj = &root->object;
struct JSON_object_member* member_list = root_obj->members;
size_t pos = 0;
for(;member_list;member_list = member_list->next){
pos += sprintf(dest+pos, "\"%s\":", member_list->name.value);
pos += _rjp__write_value(dest+pos, &member_list->value);
if(member_list->next)
pos += sprintf(dest+pos, ",");
else
break;
}
return pos;
}
char* rjp_to_json(struct JSON_value* root){
size_t len = _rjp__object_strlen(root);
char* tmp = malloc(len + 1);
tmp[len] = 0;
size_t pos = 1;
sprintf(tmp, "{");
pos += rjp_dump_object(root, tmp+pos);
sprintf(tmp+pos, "}");
return tmp;
}

196
src/strings.c Normal file
View File

@@ -0,0 +1,196 @@
#include "rjp.h"
#include "rjp_internal.h"
#include <stdio.h> //fprintf
#include <stdlib.h> //malloc, free
//Convert escape sequences in strings
char* _rjp__parse_string(struct JSON_value* root, const char* str, int* len, int* row, int* column){
char* new_string;
++(*column); //account for starting quotation mark
for(*len = 0;*(str+*len) != '"';++(*len), ++(*column)){
if(*(str+*len) == '\\'){
++(*len);
++(*column);
}else if(*(str+*len) == '\0'){
*len = 1;
fprintf(stderr, "Syntax error! %s (%i:%i)\n", "Unexpected EOF in string!", *row, *column);
rjp_free(root);
return NULL;
}else if(*(str+*len) == '\n'){
++(*row);
*column = 0;
}
}
if(*len == 0){
return NULL;
}
new_string = malloc(*len + 1);
new_string[*len] = 0;
for(int i = 0;*str != '"';++i,++str){
if(*str == '\\'){
++str;
switch(*str){
case '"':
new_string[i] = '"';
break;
case 'n':
new_string[i] = '\n';
break;
case 'r':
new_string[i] = '\r';
break;
case 'b':
new_string[i] = '\b';
break;
case '\\':
new_string[i] = '\\';
break;
case 't':
new_string[i] = '\t';
break;
case 'f':
new_string[i] = '\f';
break;
default:
new_string[i] = *str;
break;
}
}else{
new_string[i] = *str;
}
}
return new_string;
}
size_t rjp_escape_strcpy(char* dest, const char* src){
size_t j = 0;
for(size_t i = 0;src[i];++i){
switch(src[i]){
case '"':
dest[j++] = '\\';
dest[j++] = '"';
break;
case '\n':
dest[j++] = '\\';
dest[j++] = 'n';
break;
case '\r':
dest[j++] = '\\';
dest[j++] = 'r';
break;
case '\b':
dest[j++] = '\\';
dest[j++] = 'b';
break;
case '\\':
dest[j++] = '\\';
dest[j++] = '\\';
break;
case '\t':
dest[j++] = '\\';
dest[j++] = 't';
break;
case '\f':
dest[j++] = '\\';
dest[j++] = 'f';
break;
default:
dest[j++] = src[i];
break;
};
}
return j;
}
size_t rjp_escape_strlen(const char* str){
size_t count = 0;
for(size_t i = 0;str[i];++i){
switch(str[i]){
case '"':
case '\n':
case '\r':
case '\b':
case '\\':
case '\t':
case '\f':
++count;
//fallthrough
default:
++count;
};
}
return count;
}
size_t _rjp__array_strlen(struct JSON_value* arr){
size_t count = 2; //[]
struct JSON_array* array = &arr->array;
struct JSON_array_element* element_list = array->elements;
for(;element_list;element_list = element_list->next){
switch(element_list->value.type){
case json_integer:
count += snprintf(NULL, 0, "%li", element_list->value.integer);
break;
case json_dfloat:
count += snprintf(NULL, 0, "%lf", element_list->value.dfloat);
break;
case json_boolean:
count += element_list->value.boolean ? 4 : 5;
break;
case json_null:
count += 4;
break;
case json_string:
count += element_list->value.string.length;
break;
case json_array:
count += _rjp__array_strlen(&element_list->value);
break;
case json_object:
count += _rjp__object_strlen(&element_list->value);
break;
};
if(element_list->next)
++count;
else
break;
}
return count;
}
size_t _rjp__object_strlen(struct JSON_value* root){
size_t count = 2; //{}
struct JSON_object* root_obj = &root->object;
struct JSON_object_member* member_list = root_obj->members;
for(;member_list;member_list = member_list->next){
count += member_list->name.length + 3; //"":
switch(member_list->value.type){
case json_integer:
count += snprintf(NULL, 0, "%li", member_list->value.integer);
break;
case json_dfloat:
count += snprintf(NULL, 0, "%lf", member_list->value.dfloat);
break;
case json_boolean:
count += member_list->value.boolean ? 4 : 5; //true, false
break;
case json_null:
count += 4; //null
break;
case json_string:
count += member_list->value.string.length;
break;
case json_array:
count += _rjp__array_strlen(&member_list->value);
break;
case json_object:
count += _rjp__object_strlen(&member_list->value);
break;
};
if(member_list->next)
++count; //,
else
break;
}
return count;
}