/** @brief Parse an array, and create a JSON_ARRAY for it. @param parser Pointer to a Parser. @return Pointer to a newly created jsonObject of type JSON_ARRAY, or NULL upon error. Look for a series of JSON nodes, separated by commas and terminated by a right square bracket. Parse each node recursively, collect them all into a newly created jsonObject of type JSON_ARRAY, and return a pointer to the result. Upon error, log an error message and return NULL. */ static jsonObject* get_array( Parser* parser ) { jsonObject* array = jsonNewObjectType( JSON_ARRAY ); char c = skip_white_space( parser ); if( ']' == c ) return array; // Empty array for( ;; ) { jsonObject* obj = get_json_node( parser, c ); if( !obj ) { jsonObjectFree( array ); return NULL; // Failed to get anything } // Add the entry to the array jsonObjectPush( array, obj ); // Look for a comma or right bracket c = skip_white_space( parser ); if( ']' == c ) break; else if( c != ',' ) { report_error( parser, c, "Expected comma or bracket in array; didn't find it\n" ); jsonObjectFree( array ); return NULL; } c = skip_white_space( parser ); } return array; }
/** @brief Parse a JSON string into a jsonObject. @param s Pointer to the string to be parsed. @param decode A boolean; true means decode class hints, false means don't. @return Pointer to the newly created jsonObject. Set up a Parser. Call get_json_node() to do the real work, then make sure that there's nothing but white space at the end. */ static jsonObject* parse_it( const char* s, int decode ) { if( !s || !*s ) return NULL; // Nothing to parse Parser parser; parser.str_buf = NULL; parser.index = 0; parser.buff = s; parser.decode = decode; jsonObject* obj = get_json_node( &parser, skip_white_space( &parser ) ); // Make sure there's nothing but white space at the end char c; if( obj && (c = skip_white_space( &parser )) ) { report_error( &parser, c, "Extra material follows JSON string" ); jsonObjectFree( obj ); obj = NULL; } buffer_free( parser.str_buf ); return obj; }
int json_solve_str(void ** root, char *str) { JSON_NODE * root_node; JSON_NODE * father_node; JSON_NODE * curr_node; JSON_VALUE * curr_value; int value_type; char value_buffer[1024]; char * tempstr; int i; int offset=0; int state=0; int ret; // give the root node value root_node=get_json_node(NULL); if(root_node==NULL) return -ENOMEM; father_node=NULL; curr_node=root_node; curr_node->layer=0; root_node->elem_type=JSON_ELEM_INIT; curr_node->solve_state=SOLVE_INIT; while(str[offset]!='\0') { switch(curr_node->solve_state) { case SOLVE_INIT: while(str[offset]!=0) { if(!IsSplitChar(str[offset])) break; offset++; } if(str[offset]!='{') return -EINVAL; // get an object node,then switch to the SOLVE_OBJECT father_node=curr_node; curr_node=get_json_node(father_node); curr_node->elem_type=JSON_ELEM_MAP; curr_node->solve_state=SOLVE_MAP; offset++; break; case SOLVE_MAP: while(str[offset]!=0) { if(!IsSplitChar(str[offset])) break; offset++; } if(str[offset]!='\"'){ // if this map is empty,then finish this MAP if(str[offset]=='}') { offset++; curr_node->solve_state=SOLVE_UPGRADE; break; } // if we should to find another elem if(str[offset]==',') { offset++; break; } else return -EINVAL; } // we should build a name:value json node father_node=curr_node; curr_node=get_json_node(father_node); curr_node->elem_str=str+offset; offset++; curr_node->solve_state=SOLVE_NAME; break; case SOLVE_NAME: ret=get_json_strvalue(value_buffer,str+offset); if(ret<0) return ret; if(ret>=DIGEST_SIZE*2) return ret; offset+=ret; { int len=strlen(value_buffer); if(len<=DIGEST_SIZE*2) memcpy(curr_node->name,value_buffer,len+1); else memcpy(curr_node->name,value_buffer,DIGEST_SIZE*2); offset++; } while(str[offset]!=0) { if(!IsSplitChar(str[offset])) break; offset++; } if(str[offset]!=':') return -EINVAL; offset++; curr_node->solve_state=SOLVE_VALUE; break; case SOLVE_VALUE: while(str[offset]!=0) { if(!IsSplitChar(str[offset])) break; offset++; } if(str[offset]=='{') { // get an object node,then switch to the SOLVE_MAP curr_node->elem_type=JSON_ELEM_MAP; offset++; curr_node->solve_state=SOLVE_MAP; break; } if(str[offset]=='[') { // get an array node,then switch to the SOLVE_ARRAY curr_node->elem_type=JSON_ELEM_ARRAY; offset++; curr_node->solve_state=SOLVE_ARRAY; break; } if(str[offset]=='\"') // value is JSON_STRING { offset++; i=get_json_strvalue(value_buffer,str+offset); if(i>=0) { offset+=i+1; curr_node->elem_type=JSON_ELEM_STRING; } else return -EINVAL; } else { i=get_json_numvalue(value_buffer,str+offset); if(i>0) { offset+=i; curr_node->elem_type=JSON_ELEM_NUM; } else { i=get_json_boolvalue(value_buffer,str+offset); if(i>0) { offset+=i; curr_node->elem_type=JSON_ELEM_BOOL; } else { i=get_json_nullvalue(value_buffer,str+offset); if(i>0) { offset+=i; curr_node->elem_type=JSON_ELEM_NULL; } else return -EINVAL; } } } curr_node->value_str=dup_str(value_buffer,0); curr_node->solve_state=SOLVE_UPGRADE; break; case SOLVE_ARRAY: while(str[offset]!=0) { if(!IsSplitChar(str[offset])) break; offset++; } if(str[offset]==']') { offset++; curr_node->solve_state=SOLVE_UPGRADE; break; } // if we should to find another elem if(str[offset]==',') { offset++; break; } // we should build a name:value json node father_node=curr_node; curr_node=get_json_node(father_node); curr_node->elem_str=str+offset; // offset++; curr_node->solve_state=SOLVE_VALUE; break; case SOLVE_UPGRADE: // get value process curr_node->solve_state=SOLVE_FINISH; if(father_node->elem_type==JSON_ELEM_INIT) break; curr_node=father_node; father_node=curr_node->father; break; default: return -EINVAL; } if(curr_node->solve_state==SOLVE_FINISH) break; } *root=curr_node; return offset; }
/** @brief Parse a hash (JSON object), and create a JSON_HASH for it; decode class hints. @param parser Pointer to a Parser. @return Pointer to a newly created jsonObject, or NULL upon error. This function is similar to get_hash(), @em except: If the hash includes a member with a key equal to JSON_CLASS_KEY ("__c" by default), then look for a member whose key is JSON_DATA_KEY ("__p" by default). If you find one, return the data associated with it; otherwise return a jsonObject of type JSON_NULL. If there is no member with a key equal to JSON_CLASS_KEY, then return the same sort of jsonObject as get_hash() would return (except of course that lower levels may be decoded as described above). */ static jsonObject* get_decoded_hash( Parser* parser ) { jsonObject* hash = jsonNewObjectType( JSON_HASH ); char c = skip_white_space( parser ); if( '}' == c ) return hash; // Empty hash char* class_name = NULL; for( ;; ) { // Get the key string if( '"' != c ) { report_error( parser, c, "Expected quotation mark to begin hash key; didn't find it\n" ); jsonObjectFree( hash ); return NULL; } const char* key = get_string( parser ); if( ! key ) { jsonObjectFree( hash ); return NULL; } char* key_copy = strdup( key ); if( jsonObjectGetKeyConst( hash, key_copy ) ) { report_error( parser, '"', "Duplicate key in JSON object" ); jsonObjectFree( hash ); return NULL; } // Get the colon c = skip_white_space( parser ); if( c != ':' ) { report_error( parser, c, "Expected colon after hash key; didn't find it\n" ); free( key_copy ); jsonObjectFree( hash ); return NULL; } // Get the associated value jsonObject* obj = get_json_node( parser, skip_white_space( parser ) ); if( !obj ) { free( key_copy ); jsonObjectFree( hash ); return NULL; } // Add a new entry to the hash jsonObjectSetKey( hash, key_copy, obj ); // Save info for class hint, if present if( !strcmp( key_copy, JSON_CLASS_KEY ) ) class_name = jsonObjectToSimpleString( obj ); free( key_copy ); // Look for comma or right brace c = skip_white_space( parser ); if( '}' == c ) break; else if( c != ',' ) { report_error( parser, c, "Expected comma or brace in hash, didn't find it" ); jsonObjectFree( hash ); return NULL; } c = skip_white_space( parser ); } if( class_name ) { // We found a class hint. Extract the data node and return it. jsonObject* class_data = osrfHashExtract( hash->value.h, JSON_DATA_KEY ); if( class_data ) { class_data->parent = NULL; jsonObjectFree( hash ); hash = class_data; hash->parent = NULL; hash->classname = class_name; } else { // Huh? We have a class name but no data for it. // Throw away what we have and return a JSON_NULL. jsonObjectFree( hash ); hash = jsonNewObjectType( JSON_NULL ); } } else { if( class_name ) free( class_name ); } return hash; }
/** @brief Parse a hash (JSON object), and create a JSON_HASH for it. @param parser Pointer to a Parser. @return Pointer to a newly created jsonObject of type JSON_HASH, or NULL upon error. Look for a series of name/value pairs, separated by commas and terminated by a right curly brace. Each name/value pair consists of a quoted string, followed by a colon, followed a JSON node of any sort. Parse the value recursively. Collect the name/value pairs into a newly created jsonObject of type JSON_ARRAY, and return a pointer to it. Upon error, log an error message and return NULL. */ static jsonObject* get_hash( Parser* parser ) { jsonObject* hash = jsonNewObjectType( JSON_HASH ); char c = skip_white_space( parser ); if( '}' == c ) return hash; // Empty hash for( ;; ) { // Get the key string if( '"' != c ) { report_error( parser, c, "Expected quotation mark to begin hash key; didn't find it\n" ); jsonObjectFree( hash ); return NULL; } const char* key = get_string( parser ); if( ! key ) { jsonObjectFree( hash ); return NULL; } char* key_copy = strdup( key ); if( jsonObjectGetKeyConst( hash, key_copy ) ) { report_error( parser, '"', "Duplicate key in JSON object" ); jsonObjectFree( hash ); return NULL; } // Get the colon c = skip_white_space( parser ); if( c != ':' ) { report_error( parser, c, "Expected colon after hash key; didn't find it\n" ); free( key_copy ); jsonObjectFree( hash ); return NULL; } // Get the associated value jsonObject* obj = get_json_node( parser, skip_white_space( parser ) ); if( !obj ) { free( key_copy ); jsonObjectFree( hash ); return NULL; } // Add a new entry to the hash jsonObjectSetKey( hash, key_copy, obj ); free( key_copy ); // Look for comma or right brace c = skip_white_space( parser ); if( '}' == c ) break; else if( c != ',' ) { report_error( parser, c, "Expected comma or brace in hash, didn't find it" ); jsonObjectFree( hash ); return NULL; } c = skip_white_space( parser ); } return hash; }