library/src/javascript/JSON/BP-JSON.cc
// Attempt to parse JSON from buffer, storing it in the "in" registry of the P_BP_JSON session.
Attempt to parse JSON from buffer, storing it in the "in" registry of the P_BP_JSON session.
Attempt to parse JSON from buffer storing it in the " in " registry of the P_BP_JSON session .
BP_ERROR_T BP_JSONParseFromBuffer
(
		P_BP_JSON json,
		char * buffer,
		size_t buffer_size,
		size_t max_depth_for_token_allocation,
		size_t max_tokens_total
)
{
	if(!json)
		return ERR_FAILURE;
	if(json->parse_messages_reg)
	{
		BP_DestroyHashTableRegistry(json->parse_messages_reg);
		json->parse_messages_reg = NULL;
	}
	if(!buffer)
	{
		BP_JSONParseAddErrorMsg(json, NULL, "Provided JSON buffer was NULL");
		return ERR_FAILURE;
	}
	 size
	if(!buffer_size)
	{
		BP_JSONParseAddErrorMsg(json, NULL, "Provided JSON buffer had a zero length");
		return ERR_FAILURE;
	}
	if(!max_depth_for_token_allocation)
	{
		BP_JSONParseAddErrorMsg(json, NULL, "No max depth for token allocation provided to JSON parsing routine.  This is a developer error either in a module or the core system.");
		return ERR_FAILURE;
	}
	if(!max_tokens_total)
	{
		BP_JSONParseAddErrorMsg(json, NULL, "No max total tokens have been provided to the JSON parsing routine.  This means there is no cue to trigger allocation of memory.  This is a developer error either in a module or the core system.");
		return ERR_FAILURE;
	}
	if(!BP_StringIsReasonablePrintableString(buffer, buffer_size, BP_TRUE, BP_TRUE))
	{
		BP_JSONParseAddErrorMsg(json, NULL, "Provided JSON buffer was not reasonable/printable.  It contains non-printable/unreasonable characters.  Please use ASCII only.");
		return ERR_FAILURE;
	}
	if(json->parse_state)
	{
		BP_JSONDestroyParseState(json->parse_state);
		json->parse_state = NULL;
	}
	if(json->json_out)
	{
		ht_free(json->system_hreg, json->json_out);
		json->json_out = NULL;
	}
	if(json->json_out_hreg)
	{
		BP_DestroyHashTableRegistry(json->json_out_hreg);
		json->json_out_hreg = NULL;
	}
	P_BP_JSON_PARSE_STATE parse_state = BP_JSONCreateInitialParseState
	(
			json,
			buffer,
			buffer_size,
			max_depth_for_token_allocation,
			max_tokens_total
	);
	if(!parse_state)
	{
		BP_JSONParseAddErrorMsg(json, NULL, "Creating initial JSON parse state failed.");
		return ERR_FAILURE;
	}
	int debug_exit_after_preset_iter_count = -1;
	while(BP_JSONPushAdvanceParseState(parse_state) == ERR_SUCCESS)
	{
		if(debug_exit_after_preset_iter_count != -1)
		{
			if(debug_exit_after_preset_iter_count == 0)
				break;
			debug_exit_after_preset_iter_count--;
		}
	}
	if(!parse_state->token_element_stack)
	{
		BP_JSONDestroyParseState(parse_state);
		return ERR_FAILURE;
	}
	if(!parse_state->token_element_stack_items_allocated_n)
	{
		BP_JSONDestroyParseState(parse_state);
		return ERR_FAILURE;
	}
	size_t element_iter = 0;
	P_BP_JSON_PARSE_TOKEN_ELEMENT curr_element = NULL;
	P_BP_JSON_PARSE_TOKEN_ELEMENT parent_element = NULL;
	for(; element_iter < parse_state->current_token_element_index; element_iter++)
	{
		curr_element = &parse_state->token_element_stack[element_iter];
		if(!curr_element)
			break;
		parent_element = (P_BP_JSON_PARSE_TOKEN_ELEMENT) curr_element->parent_token_element;
		P_BP_HASH_TABLE_KEYED_ENTRY curr_hreg_entry = NULL;
		%%%%%
		%%%%%
		if(curr_element->path_query_to_current)
		{
			if(curr_element->current_token->type == JSMN_OBJECT || curr_element->current_token->type == JSMN_ARRAY )
			{
				curr_hreg_entry = BP_HashRegLookupTableByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
			}
			else
				curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
			if(curr_hreg_entry)
			{
				if(parent_element)
				{
					if(parent_element->current_token)
					{
						if(parent_element->current_token->type == JSMN_OBJECT)
							parse_state->parse_encountered_duplicate_keys_in_the_same_object = BP_TRUE;
						if(parent_element->current_token->type == JSMN_ARRAY)
							parse_state->parse_encountered_duplicate_keys_in_the_same_array = BP_TRUE;
					}
				}
				parse_state->parse_encountered_duplicate_keys_in_array_or_object = BP_TRUE;
			}
		}
		%%%%%
		%%%%%
		switch(curr_element->current_token->type)
		{
			case JSMN_OBJECT:
				BP_JSONAddTableByPathQuery(json, curr_element->path_query_to_current);
				curr_hreg_entry = BP_HashRegLookupTableByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
				break;
			case JSMN_ARRAY:
				BP_JSONAddTableByPathQuery(json, curr_element->path_query_to_current);
				curr_hreg_entry = BP_HashRegLookupTableByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
				break;
			case JSMN_STRING:
				if(curr_element->child_as_string && curr_element->child_is_string_only)
				{
					BP_JSONAddNodeByPathQuery(json, curr_element->path_query_to_current, curr_element->child_as_string, bpstrlen(curr_element->child_as_string), BP_FALSE);
					curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
				}
				else if(curr_element->child_as_primitive && curr_element->child_is_primitive_only)
				{
					BP_JSONAddNodeByPathQuery(json, curr_element->path_query_to_current, curr_element->child_as_primitive, bpstrlen(curr_element->child_as_primitive), BP_FALSE);
					curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
				}
				else if(!curr_element->child_tokens_start && !curr_element->parent_is_string && !curr_element->parent_is_primitive)
				{
					BP_JSONAddNodeByPathQuery(json, curr_element->path_query_to_current, curr_element->current_string_val, bpstrlen(curr_element->current_string_val), BP_FALSE);
					curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
					printf("\n String hreg entry3?: %p - %s", curr_hreg_entry, curr_element->current_string_val);
					printf("\n Current Path: %s", curr_element->path_query_to_current);
				}
				break;
			case JSMN_PRIMITIVE:
				if(curr_element->child_as_primitive  && curr_element->child_is_primitive_only)
				{
					BP_JSONAddNodeByPathQuery(json, curr_element->path_query_to_current, curr_element->child_as_primitive, bpstrlen(curr_element->child_as_primitive), BP_FALSE);
					curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
				}
				else if(curr_element->child_as_string && curr_element->child_is_string_only)
				{
					BP_JSONAddNodeByPathQuery(json, curr_element->path_query_to_current, curr_element->child_as_string, bpstrlen(curr_element->child_as_string), BP_FALSE);
					curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
				}
				else if(!curr_element->child_tokens_start && !curr_element->parent_is_string && !curr_element->parent_is_primitive)
				{
					BP_JSONAddNodeByPathQuery(json, curr_element->path_query_to_current, curr_element->current_primitive_val, bpstrlen(curr_element->current_primitive_val), BP_FALSE);
					curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery(json->json_out_hreg, curr_element->path_query_to_current);
				}
				break;
			default:
				break;
		}
		%%%
		%%%
		if(curr_hreg_entry)
		{
			curr_hreg_entry->external_entry_metadata = (void *) curr_element;
		}
	}
	json->parse_state = parse_state;
	return ERR_SUCCESS;
}
BP_ERROR_T BP_JSONParseFromBuffer ( P_BP_JSON json , char * buffer , size_t buffer_size , size_t max_depth_for_token_allocation , size_t max_tokens_total ) { if ( ! json ) return ERR_FAILURE ; if ( json -> parse_messages_reg ) { BP_DestroyHashTableRegistry ( json -> parse_messages_reg ) ; json -> parse_messages_reg = NULL ; } if ( ! buffer ) { BP_JSONParseAddErrorMsg ( json , NULL , " " ) ; return ERR_FAILURE ; } if ( ! buffer_size ) { BP_JSONParseAddErrorMsg ( json , NULL , " " ) ; return ERR_FAILURE ; } if ( ! max_depth_for_token_allocation ) { BP_JSONParseAddErrorMsg ( json , NULL , " " ) ; return ERR_FAILURE ; } if ( ! max_tokens_total ) { BP_JSONParseAddErrorMsg ( json , NULL , " " ) ; return ERR_FAILURE ; } if ( ! BP_StringIsReasonablePrintableString ( buffer , buffer_size , BP_TRUE , BP_TRUE ) ) { BP_JSONParseAddErrorMsg ( json , NULL , " " ) ; return ERR_FAILURE ; } if ( json -> parse_state ) { BP_JSONDestroyParseState ( json -> parse_state ) ; json -> parse_state = NULL ; } if ( json -> json_out ) { ht_free ( json -> system_hreg , json -> json_out ) ; json -> json_out = NULL ; } if ( json -> json_out_hreg ) { BP_DestroyHashTableRegistry ( json -> json_out_hreg ) ; json -> json_out_hreg = NULL ; } P_BP_JSON_PARSE_STATE parse_state = BP_JSONCreateInitialParseState ( json , buffer , buffer_size , max_depth_for_token_allocation , max_tokens_total ) ; if ( ! parse_state ) { BP_JSONParseAddErrorMsg ( json , NULL , " " ) ; return ERR_FAILURE ; } int debug_exit_after_preset_iter_count = -1 ; while ( BP_JSONPushAdvanceParseState ( parse_state ) == ERR_SUCCESS ) { if ( debug_exit_after_preset_iter_count != -1 ) { if ( debug_exit_after_preset_iter_count == 0 ) break ; debug_exit_after_preset_iter_count -- ; } } if ( ! parse_state -> token_element_stack ) { BP_JSONDestroyParseState ( parse_state ) ; return ERR_FAILURE ; } if ( ! parse_state -> token_element_stack_items_allocated_n ) { BP_JSONDestroyParseState ( parse_state ) ; return ERR_FAILURE ; } size_t element_iter = 0 ; P_BP_JSON_PARSE_TOKEN_ELEMENT curr_element = NULL ; P_BP_JSON_PARSE_TOKEN_ELEMENT parent_element = NULL ; for ( ; element_iter < parse_state -> current_token_element_index ; element_iter ++ ) { curr_element = & parse_state -> token_element_stack [ element_iter ] ; if ( ! curr_element ) break ; parent_element = ( P_BP_JSON_PARSE_TOKEN_ELEMENT ) curr_element -> parent_token_element ; P_BP_HASH_TABLE_KEYED_ENTRY curr_hreg_entry = NULL ; if ( curr_element -> path_query_to_current ) { if ( curr_element -> current_token -> type == JSMN_OBJECT || curr_element -> current_token -> type == JSMN_ARRAY ) { curr_hreg_entry = BP_HashRegLookupTableByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; } else curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; if ( curr_hreg_entry ) { if ( parent_element ) { if ( parent_element -> current_token ) { if ( parent_element -> current_token -> type == JSMN_OBJECT ) parse_state -> parse_encountered_duplicate_keys_in_the_same_object = BP_TRUE ; if ( parent_element -> current_token -> type == JSMN_ARRAY ) parse_state -> parse_encountered_duplicate_keys_in_the_same_array = BP_TRUE ; } } parse_state -> parse_encountered_duplicate_keys_in_array_or_object = BP_TRUE ; } } switch ( curr_element -> current_token -> type ) { case JSMN_OBJECT : BP_JSONAddTableByPathQuery ( json , curr_element -> path_query_to_current ) ; curr_hreg_entry = BP_HashRegLookupTableByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; break ; case JSMN_ARRAY : BP_JSONAddTableByPathQuery ( json , curr_element -> path_query_to_current ) ; curr_hreg_entry = BP_HashRegLookupTableByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; break ; case JSMN_STRING : if ( curr_element -> child_as_string && curr_element -> child_is_string_only ) { BP_JSONAddNodeByPathQuery ( json , curr_element -> path_query_to_current , curr_element -> child_as_string , bpstrlen ( curr_element -> child_as_string ) , BP_FALSE ) ; curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; } else if ( curr_element -> child_as_primitive && curr_element -> child_is_primitive_only ) { BP_JSONAddNodeByPathQuery ( json , curr_element -> path_query_to_current , curr_element -> child_as_primitive , bpstrlen ( curr_element -> child_as_primitive ) , BP_FALSE ) ; curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; } else if ( ! curr_element -> child_tokens_start && ! curr_element -> parent_is_string && ! curr_element -> parent_is_primitive ) { BP_JSONAddNodeByPathQuery ( json , curr_element -> path_query_to_current , curr_element -> current_string_val , bpstrlen ( curr_element -> current_string_val ) , BP_FALSE ) ; curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; printf ( " \n " , curr_hreg_entry , curr_element -> current_string_val ) ; printf ( " \n " , curr_element -> path_query_to_current ) ; } break ; case JSMN_PRIMITIVE : if ( curr_element -> child_as_primitive && curr_element -> child_is_primitive_only ) { BP_JSONAddNodeByPathQuery ( json , curr_element -> path_query_to_current , curr_element -> child_as_primitive , bpstrlen ( curr_element -> child_as_primitive ) , BP_FALSE ) ; curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; } else if ( curr_element -> child_as_string && curr_element -> child_is_string_only ) { BP_JSONAddNodeByPathQuery ( json , curr_element -> path_query_to_current , curr_element -> child_as_string , bpstrlen ( curr_element -> child_as_string ) , BP_FALSE ) ; curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; } else if ( ! curr_element -> child_tokens_start && ! curr_element -> parent_is_string && ! curr_element -> parent_is_primitive ) { BP_JSONAddNodeByPathQuery ( json , curr_element -> path_query_to_current , curr_element -> current_primitive_val , bpstrlen ( curr_element -> current_primitive_val ) , BP_FALSE ) ; curr_hreg_entry = BP_HashRegLookupTableEntryByPathQuery ( json -> json_out_hreg , curr_element -> path_query_to_current ) ; } break ; default : break ; } if ( curr_hreg_entry ) { curr_hreg_entry -> external_entry_metadata = ( void * ) curr_element ; } } json -> parse_state = parse_state ; return ERR_SUCCESS ; }
Attempt to parse JSON from buffer, storing it in the "in" registry of the P_BP_JSON session.
Attempt to parse JSON from buffer storing it in the " in " registry of the P_BP_JSON session .
// ensure we have a json object // destroy dangling parse messages if any are set // ensure we have a buffer // ensure we have a buffer size // ensure we have a max depth set // ensure we have a max alloc set // ensure string is reasonable printable string // dbg message/optional // printf("\n [dbg] JSON Parser Passes Initial Checks"); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Perform Cleanup in Case of Misuse %%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // destroy existing parse state if one already exists // destroy json output buffer upon parse attempt // destroy the output hreg // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Step 1: Parse via libjsmn %%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // create parser state information structure // ensure we could create our initial parse state // you can set this to any nonzero number and debug the loop below if // necessary.  Set it to -1 to disable this functionality. // display the current parse state // printf("\n [+] Displaying Parse State at Start of Advance Loop"); // BP_JSONDisplayParseState(parse_state); // Advancing the parse state adds information for all tokens, walking // each token and creating required state/path information. // run debug loop exit checks // break the loop if we've hit our trigger // decrement the iterator count // display parse state path query list // printf("\n [+] Full path query list."); // BP_JSONDisplayParseStatePathsQueriesOnly(parse_state); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Step 2: Translate Parsed Token Elements into HREG %%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // if the parse state indicates we have no tokens, the parse was bad // if we have no elements allocated, exit // set element iter to zero // set current element // set parent element // top level is always going to be the current parsed element index // set current JSON token element // ensure we have a pointer // get parent element // display path query to current // printf("\n [PARENT] ADD LOOP HERE: %s", curr_element->path_query_to_parent); // printf("\n [CHILD]  ADD LOOP HERE: %s", curr_element->path_query_to_current); // This will hold our hreg entry.  The registry entries external data pointer will be // used to link the current_hreg_entry (later retrieved via lookup), with a parse element. // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Run Duplicate Key Check %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // if we have a path, check to ensure it doesn't already exist // check to see if the object already exists // if the hreg exists, check it's parents and set markers // set duplicate keys marker // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Attempt Additions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // check the current token type // add table if it's an object // add array if it's an array // jsmn string // BP_JSONAddNodeByPathQuery(json, curr_element->path_query_to_current, curr_element->); // printf("\n Attempting to add child as string only?: %s - %s", curr_element->child_as_string, curr_element->path_query_to_current); // if the child is a string, just add the token to the current table // printf("\n String hreg entry1?: %p - %s", curr_hreg_entry, curr_element->child_as_string); // printf("\n Attempting to add child as primitive only?: %s - %s", curr_element->child_as_primitive, curr_element->path_query_to_current); // if the child is a string, just add the token to the current table // printf("\n String hreg entry2?: %p", curr_hreg_entry); // add self reference if there are no children to this comment // printf("\n TRYING TO ADD BY PARENT HERE(STR): %s", curr_element->path_query_to_current); // BP_JSONAddNodeByPathQuery(json, curr_element->path_query_to_current, curr_element->); // if the child is a string, just add the token to the current table // printf("\n Primitive hreg entry1?: %p", curr_hreg_entry); // if the child is a string, just add the token to the current table // printf("\n Primitive hreg entry2?: %p", curr_hreg_entry); // add self reference if there are no children to this comment // printf("\n TRYING TO ADD BY PARENT HERE: %s", curr_element->path_query_to_current); // printf("\n Primitive hreg entry3?: %p", curr_hreg_entry); // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // %%% Examine Current Node and Add Data Element Reference %%%%%% // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // if we were able to look up our new entry in the tree, perform necessary // data associations // printf("\n [dbg] Setting metadata ok!"); // set the current element (pointer into array) as the element metadata // set the parse state within the json object here // return indicating success