Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edcfee90eb |
112
src/input.c
112
src/input.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user