1 Commits
v0.4 ... v0.4.1

Author SHA1 Message Date
rexy712
edcfee90eb vastly simplified logic and fixed a parsing bug 2018-12-06 16:02:40 -08:00

View File

@@ -37,11 +37,6 @@
#define DIAG_PRINT(...)
#endif
typedef struct RJP_state{
int in_array;
int search_target;
}RJP_state;
//types of searches in the text
typedef enum json_search_target{
json_key,
@@ -94,15 +89,7 @@ void _rjp__add_member_no_alloc(RJP_object* j, char* str, size_t len){
j->last->name.length = len;
}
static RJP_value* _rjp__add_element_to_array(RJP_value* curr, RJP_state* state, RJP_value* element){
RJP_value* tmp = &curr->object.members->value;
for(int i = state->in_array-1;i > 0;--i, tmp = &tmp->array.last->value);
_rjp__add_element(&tmp->array);
tmp->array.last->value = *element;
return &tmp->array.last->value;
}
static RJP_value* _rjp__add_value(RJP_value* curr, RJP_value* new_val, RJP_state* state){
static RJP_value* _rjp__add_value(RJP_value* curr, RJP_value* new_val, int* target){
if(!curr){
curr = rjp_calloc(1, sizeof(RJP_value));
*curr = *new_val;
@@ -113,43 +100,41 @@ static RJP_value* _rjp__add_value(RJP_value* curr, RJP_value* new_val, RJP_state
curr->array.last->value = *new_val;
return &curr->array.last->value;
}
if(state->in_array)
return _rjp__add_element_to_array(curr, state, new_val);
curr->object.last->value = *new_val;
return &curr->object.last->value;
}
//Assign object characteristics to previously allocated RJP_value
static RJP_value* _rjp__add_object(RJP_value* curr, RJP_state* state){
static RJP_value* _rjp__add_object(RJP_value* curr, int* target){
RJP_value new_object = {.type = json_object, .integer = 0, .parent = curr};
return _rjp__add_value(curr, &new_object, state);
return _rjp__add_value(curr, &new_object, target);
}
//Assign array characteristics to previously allocated RJP_value
static RJP_value* _rjp__add_array(RJP_value* curr, RJP_state* state){
static RJP_value* _rjp__add_array(RJP_value* curr, int* target){
RJP_value new_array = {.type = json_array, .array = {.num_elements = 0, .elements = NULL}, .parent = curr};
return _rjp__add_value(curr, &new_array, state);
return _rjp__add_value(curr, &new_array, target);
}
//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_state* state){
static RJP_value* _rjp__add_string_no_alloc(RJP_value* curr, char* str, int len, int* target){
RJP_value new_string = {.type = json_string, .string = {.value = str, .length = len}, .parent = curr};
return _rjp__add_value(curr, &new_string, state);
return _rjp__add_value(curr, &new_string, target);
}
//Assign double characteristics to previously allocated RJP_value
static RJP_value* _rjp__add_dfloat(RJP_value* curr, double value, RJP_state* state){
static RJP_value* _rjp__add_dfloat(RJP_value* curr, double value, int* target){
RJP_value new_double = {.type = json_dfloat, .dfloat = value, .parent = curr};
return _rjp__add_value(curr, &new_double, state);
return _rjp__add_value(curr, &new_double, target);
}
//Assign integer characteristics to previously allocated RJP_value
static RJP_value* _rjp__add_integer(RJP_value* curr, long value, RJP_state* state){
static RJP_value* _rjp__add_integer(RJP_value* curr, long value, int* target){
RJP_value new_integer = {.type = json_integer, .integer = value, .parent = curr};
return _rjp__add_value(curr, &new_integer, state);
return _rjp__add_value(curr, &new_integer, target);
}
static RJP_value* _rjp__add_boolean(RJP_value* curr, int value, RJP_state* state){
static RJP_value* _rjp__add_boolean(RJP_value* curr, int value, int* target){
RJP_value new_boolean = {.type = json_boolean, .boolean = value, .parent = curr};
return _rjp__add_value(curr, &new_boolean, state);
return _rjp__add_value(curr, &new_boolean, target);
}
static RJP_value* _rjp__add_null(RJP_value* curr, RJP_state* state){
static RJP_value* _rjp__add_null(RJP_value* curr, int* target){
RJP_value new_null = {.type = json_null, .integer = 0, .parent = curr};
return _rjp__add_value(curr, &new_null, state);
return _rjp__add_value(curr, &new_null, target);
}
static void _rjp__free_object_recurse(RJP_value* root);
@@ -218,11 +203,10 @@ RJP_value* rjp_parse(const char* str){
int in_block_comment = 0;
//keep track of where we are in a given subobject
RJP_state state_stack[MAX_DEPTH] = {0},*top = state_stack;
int state_stack[MAX_DEPTH] = {0},*top = state_stack;
//initially search for the root object
top->search_target = json_value;
top->in_array = 0;
*top = json_value;
for(;*str != '\0';++str){
char c = *str;
@@ -255,7 +239,7 @@ RJP_value* rjp_parse(const char* str){
++str;
}
else if(top->search_target == json_key){
else if(*top == json_key){
//start of key
if(c == '"'){
if(curr == NULL)
@@ -270,7 +254,7 @@ RJP_value* rjp_parse(const char* str){
}
_rjp__add_member_no_alloc(&curr->object, new_string, keylen);
str += keylen;
top->search_target = json_colon;
*top = json_colon;
//end of this object (object is empty)
}else if(c == '}'){
curr = curr->parent;
@@ -282,70 +266,62 @@ RJP_value* rjp_parse(const char* str){
syntax_error("Unexpected character, expected '\"'!", row, column);
}
}
else if(top->search_target == json_colon){
else if(*top == json_colon){
//colon after a key
if(c == ':'){
top->search_target = json_value;
*top = json_value;
//unrecognized character
}else if(!_rjp__is_whitespace(c)){
syntax_error( "Unexpected character, expected ':'!", row, column);
}
}
else if(top->search_target == json_comma){
else if(*top == json_comma){
//comma separating keys in an object or values in an array
if(c == ','){
top->search_target = top->in_array ? json_value : json_key;
*top = (curr->type == json_array ? json_value : json_key);
//end of object
}else if(c == '}'){
if(top->in_array){
if(curr->type == json_array){
syntax_error("Unexpected end of object within array!", row, column);
}
curr = curr->parent;
if(top != state_stack)
--top;
//end of array
}else if(c == ']' && top->in_array){
--top->in_array;
}else if(c == ']' && curr->type == json_array){
curr = curr->parent;
//unrecognized character
}else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character, expected ','!", row, column);
}
}
else if(top->search_target == json_value){
else if(*top == json_value){
//object
if(c == '{'){
if(!root){
root = _rjp__add_object(NULL, top);
curr = root;
top->search_target = json_key;
*top = json_key;
}else{
curr = _rjp__add_object(curr, top);
top->search_target = json_comma;
*top = json_comma;
++top;
top->in_array = 0;
top->search_target = json_key;
*top = json_key;
}
}
/* //something outside of any object
else if(!curr){
syntax_error("Unexpected character outside of object definition!", row, column);
}
*/ //arrays
else if(c == '['){
if(!root){
root = _rjp__add_array(NULL, top);
curr = root;
++top->in_array;
}else{
_rjp__add_array(curr, top);
++top->in_array;
curr = _rjp__add_array(curr, top);
}
}
else if(c == ']' && top->in_array){ //empty array
--top->in_array;
top->search_target = json_comma;
else if(c == ']' && curr->type == json_array){ //empty array
*top = json_comma;
curr = curr->parent;
}
//strings
else if(c == '"'){
@@ -361,14 +337,14 @@ RJP_value* rjp_parse(const char* str){
}
_rjp__add_string_no_alloc(curr, new_string, vallen, top);
str += vallen;
top->search_target = json_comma;
*top = json_comma;
}
//numbers
else if((c >= '0' && c <= '9') || c == '-'){
if(!curr)
top->search_target = json_none;
*top = json_none;
else
top->search_target = json_comma;
*top = json_comma;
int numlen;
int floating = 0; //is an int or a double
for(numlen = 1;*(str+numlen) >= '0' && *(str+numlen) <= '9';++numlen);
@@ -405,28 +381,28 @@ RJP_value* rjp_parse(const char* str){
//booleans and null
else if(!strncmp(str, "true", 4)){
if(!curr){
top->search_target = json_none;
*top = json_none;
root = curr = _rjp__add_boolean(curr, 1, top);
}else{
top->search_target = json_comma;
*top = json_comma;
_rjp__add_boolean(curr, 1, top);
}
str += 3;column += 3;
}else if(!strncmp(str, "false", 5)){
if(!curr){
top->search_target = json_none;
*top = json_none;
root = curr = _rjp__add_boolean(curr, 0, top);
}else{
top->search_target = json_comma;
*top = json_comma;
_rjp__add_boolean(curr, 0, top);
}
str += 4;column += 4;
}else if(!strncmp(str, "null", 4)){
if(!curr){
top->search_target = json_none;
*top = json_none;
root = curr = _rjp__add_null(curr, top);
}else{
top->search_target = json_comma;
*top = json_comma;
_rjp__add_null(curr, top);
}
str += 3;column += 3;
@@ -435,7 +411,7 @@ RJP_value* rjp_parse(const char* str){
else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character!", row, column);
}
}else if(top->search_target == json_none && !_rjp__is_whitespace(c)){
}else if(*top == json_none && !_rjp__is_whitespace(c)){
syntax_error("Unexpected character!", row, column);
}
}