Andrew Reed
/
CITY1082-i2c_master_wifi_mqtt
CITY3032-wifi-mqtt
Diff: connectivity-utilities/JSON_parser/cy_json_parser.c
- Revision:
- 4:7ebc3d28bcb2
diff -r 62825c5f3cd7 -r 7ebc3d28bcb2 connectivity-utilities/JSON_parser/cy_json_parser.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/connectivity-utilities/JSON_parser/cy_json_parser.c Sat Nov 13 11:31:22 2021 +0000 @@ -0,0 +1,1098 @@ +/* + * Copyright 2019-2021, Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation. All rights reserved. + * + * This software, including source code, documentation and related + * materials ("Software") is owned by Cypress Semiconductor Corporation + * or one of its affiliates ("Cypress") and is protected by and subject to + * worldwide patent protection (United States and foreign), + * United States copyright laws and international treaty provisions. + * Therefore, you may use this Software only as provided in the license + * agreement accompanying the software package from which you + * obtained this Software ("EULA"). + * If no EULA applies, Cypress hereby grants you a personal, non-exclusive, + * non-transferable license to copy, modify, and compile the Software + * source code solely for use in connection with Cypress's + * integrated circuit products. Any reproduction, modification, translation, + * compilation, or representation of this Software except as specified + * above is prohibited without the express written permission of Cypress. + * + * Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress + * reserves the right to make changes to the Software without notice. Cypress + * does not assume any liability arising out of the application or use of the + * Software or any product or circuit described in the Software. Cypress does + * not authorize its products for use in any products where a malfunction or + * failure of the Cypress product may reasonably be expected to result in + * significant property damage, injury or death ("High Risk Product"). By + * including Cypress's product in a High Risk Product, the manufacturer + * of such system or application assumes all risk of such use and in doing + * so agrees to indemnify Cypress against all liability. + */ + +/** @file + * + */ +#include "cy_json_parser.h" +#include <stddef.h> +#include <string.h> +#include <stdlib.h> +/****************************************************** + * Macros + ******************************************************/ + +#define MAX_BACKUP_SIZE 500 +#define MAX_PARENTS 4 + +/****************************************************** + * Constants + ******************************************************/ + +/****************************************************** + * Enumerations + ******************************************************/ + +/****************************************************** + * Type Definitions + ******************************************************/ + +/****************************************************** + * Structures + ******************************************************/ + +/****************************************************** + * Static Function Declarations + ******************************************************/ + +static cy_rslt_t validate_array_value( char* start, char* stop, uint8_t len ); + +/****************************************************** + * Variable Definitions + ******************************************************/ +static cy_JSON_callback_t internal_json_callback; +static void *internal_json_argument; + +static char* previous_token = NULL; +static cy_JSON_object_t json_object = +{ + .object_string = NULL, + .object_string_length = 0, + .value_type = UNKNOWN_JSON_TYPE, + .value = NULL, + .value_length = 0, + .intval = 0, + .floatval = 0.0, + .boolval = true, + .parent_object = NULL +}; + +static int32_t parent_counter = 0; +static cy_JSON_object_t parent_json_object[ MAX_PARENTS ]; + +static bool incomplete_response = false; + +static int32_t object_counter = 0; + +static char* string_start = NULL; +static char* string_end = NULL; + +static char* value_start = NULL; +static char* value_end = NULL; + +static cy_JSON_type_t type = UNKNOWN_JSON_TYPE; + +static char* current_input_token; +static char* end_of_input; + +static char* most_recent_object_marker = NULL; + +char packet_backup[ MAX_BACKUP_SIZE ]; + +uint32_t number_of_bytes_backed_up; + +static bool escape_token = false; +static int32_t array_counter = 0; + +/****************************************************** + * Function Definitions + ******************************************************/ + /* This function converts a string to appropriate format if the type is either + * a JSON_NUMBER_TYPE or JSON_BOOLEAN_TYPE + */ +static void str_convertor( cy_JSON_object_t* json_object ) +{ + if( json_object->value_type == JSON_NUMBER_TYPE ) + { + int i = 0; + for( i=0; i<json_object->value_length; i++ ) + { + if( json_object->value[i] == '.' ) + { + json_object->floatval = strtof( json_object->value, NULL ); + json_object->value_type = JSON_FLOAT_TYPE; + return; + } + } + json_object->intval = strtol( json_object->value, NULL, 10 ); + } + else if( json_object->value_type == JSON_BOOLEAN_TYPE ) + { + if( json_object->value[0] == 't' ) + { + json_object->boolval = true; + } + else + { + json_object->boolval = false; + } + } +} +static cy_rslt_t validate_array_value( char* start, char* stop, uint8_t len ) +{ + char* temp = NULL; + uint8_t e_count = 0; + uint8_t dot = 0; + uint8_t minus = 0; + uint8_t plus = 0; + + /* TODO : Cases to be handled for example : e+- e.+1 .e-+2 -1.234e-3 */ + + if ( ( *start == 'f' ) && ( len == 5 ) ) + { + if ( !strncmp( (const char*) start, "false", ( sizeof( "false" ) - 1 ) ) ) + { + return CY_RSLT_SUCCESS; + } + else + { + return CY_RSLT_JSON_GENERIC_ERROR; + } + } + if ( ( *start == 't' ) && ( len == 4 ) ) + { + if ( !strncmp( (const char*) start, "true", ( sizeof( "true" ) - 1 ) ) ) + { + return CY_RSLT_SUCCESS; + } + else + { + return CY_RSLT_JSON_GENERIC_ERROR; + } + } + if ( ( *start == 'n' ) && ( len == 4 ) ) + { + if ( !strncmp( (const char*) start, "null", ( sizeof( "null" ) - 1 ) ) ) + { + return CY_RSLT_SUCCESS; + } + else + { + return CY_RSLT_JSON_GENERIC_ERROR; + } + } + + temp = start; + while ( temp <= stop ) + { + if( *temp == ' ') + { + temp++; + continue; + } + if( *temp == '\n') + { + temp++; + continue; + } + if( *temp == '\r') + { + temp++; + continue; + } + + switch ( *temp ) + { + case 'e': + e_count++; + break; + + case '+': + plus++; + break; + + case '-': + minus++; + break; + + case '.': + dot++; + break; + + default: + break; + } + + if ( !( ( ( *temp >= '0' ) && ( *temp <= '9' ) ) || ( *temp == 'e' ) || ( *temp == '-' ) || ( *temp == '.' ) || ( *temp == '+' ) ) ) + { + return CY_RSLT_JSON_GENERIC_ERROR; + } + + if ( ( e_count > 1 ) || ( minus > 1 ) || ( plus > 1 ) || ( dot > 1 ) ) + { + return CY_RSLT_JSON_GENERIC_ERROR; + } + temp++; + } + + return CY_RSLT_SUCCESS; +} + + +/* Register callbacks parser will use to populate fields*/ +cy_rslt_t cy_JSON_parser_register_callback( cy_JSON_callback_t json_callback, void *arg ) +{ + internal_json_callback = json_callback; + internal_json_argument = arg; + + return CY_RSLT_SUCCESS; +} + + +/* Get current callback */ +cy_JSON_callback_t cy_JSON_parser_get_callback( void ) +{ + return internal_json_callback; +} + + +cy_rslt_t cy_JSON_parser( const char* json_input, uint32_t input_length ) +{ + cy_rslt_t valid_json_string = CY_RSLT_SUCCESS; + int space = 0; + + if ( incomplete_response ) + { + // If there is enough room on backup buffer to hold new data and old backed up + // data, parse the backup buffer + if ( ( input_length + number_of_bytes_backed_up ) < MAX_BACKUP_SIZE ) + { + memcpy( packet_backup + number_of_bytes_backed_up, json_input, input_length ); + current_input_token = packet_backup; + end_of_input = current_input_token + number_of_bytes_backed_up + input_length; + } + else + { + // We must drop entire json object from last buffer. Find start of new json object + // in new packet, and being parsing from there + while ( *json_input != '{' ) + { + json_input++; + input_length--; + } + current_input_token = (char*) json_input; + end_of_input = current_input_token + input_length; + } + + incomplete_response = false; + } + else + { + current_input_token = (char*) json_input; + end_of_input = current_input_token + input_length; + previous_token = current_input_token; + } + + while ( *( current_input_token ) == ' ' ) + { + current_input_token++; + } + previous_token = current_input_token; + + if ( ( *( current_input_token ) == OBJECT_START_TOKEN ) || ( *( current_input_token ) == ARRAY_START_TOKEN ) ) + { + /* Parse through entire input */ + while ( current_input_token < end_of_input ) + { + switch ( *current_input_token ) + { + /* This is a start of object token */ + case OBJECT_START_TOKEN: + + if ( escape_token ) + { + escape_token = false; + break; + } + + /* Skip in case we're parsing a string value */ + if ( ( string_start != NULL ) && ( string_end == NULL ) ) + { + break; + } + + /* In case the json is split across packets, record the most recent object market + * and copy from this point forward + */ + most_recent_object_marker = current_input_token; + + /* Keep track of the number of objects open */ + object_counter++; + + type = JSON_OBJECT_TYPE; + /* If we have already captured some string value, then this string must represent the name of this object */ + if ( string_end ) + { + /* prepare JSON object. The object string was already piced up by the start of value token */ + json_object.value_type = type; + json_object.value = NULL; + json_object.value_length = 0; + + /* Reset the string and value pointers */ + string_start = NULL; + string_end = NULL; + value_start = NULL; + value_end = NULL; + } + + if ( ( ( json_object.value_type == JSON_ARRAY_TYPE ) || ( json_object.value_type == JSON_OBJECT_TYPE ) ) && ( parent_counter < MAX_PARENTS ) ) + { + parent_json_object[ parent_counter ] = json_object; + json_object.parent_object = &parent_json_object[ parent_counter ]; + parent_counter++; + } + else if ( *previous_token == COMMA_SEPARATOR ) + { + json_object.parent_object = &parent_json_object[ parent_counter ]; + parent_counter++; + } + previous_token = current_input_token; + + break; + + /* This is an end of object token */ + case OBJECT_END_TOKEN: + + if ( escape_token ) + { + escape_token = false; + break; + } + + /* Skip in case we're parsing a string value */ + if ( ( string_start != NULL ) && ( string_end == NULL ) ) + { + break; + } + + object_counter--; + + if ( *( previous_token ) == COMMA_SEPARATOR ) + { + if ( *( current_input_token ) == ( OBJECT_END_TOKEN ) ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + array_counter = 0; + return valid_json_string; + } + } + /* Extract final value in object list. If we have already marked the beginning of a value, than this must be final value in object list */ + if ( value_start ) + { + value_end = current_input_token; + /* If previous was a string token, then this must be a string value */ + if ( *previous_token == STRING_TOKEN ) + { + type = JSON_STRING_TYPE; + + /* Move value token to point prior to string token and to last character of string value*/ + value_end = previous_token - 1; + value_start = string_start + 1; + } + else if ( *previous_token == TRUE_TOKEN ) + { + type = JSON_BOOLEAN_TYPE; + + value_end = previous_token + sizeof( "true" ) - 2; + value_start = previous_token; + } + else if ( *previous_token == FALSE_TOKEN ) + { + type = JSON_BOOLEAN_TYPE; + + value_end = previous_token + sizeof( "false" ) - 2; + value_start = previous_token; + } + else if ( *previous_token == NULL_TOKEN ) + { + type = JSON_NULL_TYPE; + value_end = previous_token + sizeof( "null" ) - 2; + value_start = previous_token; + } + else + { + char* start = NULL; + char* end = NULL; + uint8_t len = 0; + /* This must be a number value if not string. Arrays would have been picked up already by the end of array token */ + type = JSON_NUMBER_TYPE; + + end = value_end; + + start = previous_token; + start++; + end--; + while ( *end == ' ' ) + { + end--; + } + while ( *start == ' ' ) + { + start++; + } + + len = end - start + 1; + + if ( validate_array_value( start, end, len ) != CY_RSLT_SUCCESS ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + array_counter = 0; + return valid_json_string; + } + + /* Keep moving the value end token back till you encounter a digit */ + while ( ( *value_end < '0' ) || ( *value_end > '9' ) ) + { + value_end--; + } + + /* Initialise the value_start token with value_end */ + value_start = value_end; + + /* Move value_start token until we encounter a non-digit value */ + while ( ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) || ( *value_start == '.' ) || ( *value_start == '-' ) ) + { + value_start--; + } + + /*Point to first number */ + value_start++; + } + + /* Prepare JSON object */ + json_object.value_type = type; + json_object.value = value_start; + json_object.value_length = value_end - value_start + 1; + + if ( internal_json_callback != NULL ) + { + str_convertor( &json_object ); + internal_json_callback( &json_object, internal_json_argument ); + } + + /* Reset the value pointers */ + value_start = NULL; + value_end = NULL; + string_start = NULL; + string_end = NULL; + type = UNKNOWN_JSON_TYPE; + } + if ( parent_counter ) + { + parent_counter--; + + if ( parent_counter ) + { + json_object.parent_object = &parent_json_object[ parent_counter - 1 ]; + } + else + { + json_object.parent_object = &parent_json_object[ parent_counter ]; + } + } + else + { + json_object.parent_object = NULL; + } + previous_token = current_input_token; + + break; + + case STRING_TOKEN: + + if ( escape_token ) + { + escape_token = false; + break; + } + /* This indicates this must be closing token for object name */ + if ( *previous_token == STRING_TOKEN ) + { + /* Get the last character of the string name */ + string_end = current_input_token; + } + else + { + /* Find start and end of of object name */ + string_start = current_input_token; + string_end = NULL; + } + previous_token = current_input_token; + + break; + + case TRUE_TOKEN: + if ( escape_token ) + { + escape_token = false; + break; + } + if ( *previous_token == OBJECT_START_TOKEN ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + + return valid_json_string; + } + if ( ( *previous_token == START_OF_VALUE ) && ( string_end ) ) + { + previous_token = current_input_token; + current_input_token = current_input_token + sizeof( "true" ) - 2; + } + + break; + + case FALSE_TOKEN: + if ( escape_token ) + { + escape_token = false; + break; + } + if ( *previous_token == OBJECT_START_TOKEN ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + array_counter = 0; + return valid_json_string; + } + if ( ( *previous_token == START_OF_VALUE ) && ( string_end ) ) + { + /* Skip ahead as this must be boolean false */ + previous_token = current_input_token; + current_input_token = current_input_token + sizeof( "false" ) - 2; + } + break; + + case NULL_TOKEN: + if ( escape_token ) + { + escape_token = false; + break; + } + if ( ( *previous_token == START_OF_VALUE ) && ( string_end ) ) + { + previous_token = current_input_token; + current_input_token = current_input_token + sizeof( "null" ) - 2; + } + break; + + case ARRAY_START_TOKEN: + + if ( escape_token ) + { + escape_token = false; + break; + } + + /* Skip in case we're parsing a string value */ + if ( ( string_start != NULL ) && ( string_end == NULL ) ) + { + break; + } + else if (string_start == NULL) + { + json_object.object_string = NULL; + json_object.object_string_length = 0; + } + + array_counter++; + /*This means the last object name must have an array value type*/ + type = JSON_ARRAY_TYPE; + + json_object.value_type = type; + json_object.value = NULL; + json_object.value_length = 0; + + if ( internal_json_callback != NULL ) + { + str_convertor( &json_object ); + internal_json_callback( &json_object, internal_json_argument ); + } + + /* Reset object string start/end tokens */ + string_start = NULL; + string_end = NULL; + + previous_token = current_input_token; + + break; + + case ARRAY_END_TOKEN: + + if ( escape_token ) + { + escape_token = false; + break; + } + + /* Skip in case we're parsing a string value */ + if ( ( string_start != NULL ) && ( string_end == NULL ) ) + { + break; + } + + array_counter--; + + + if ( *( previous_token ) == START_OF_VALUE ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + return valid_json_string; + } + + if ( *( current_input_token - space - 1 ) == COMMA_SEPARATOR ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + array_counter = 0; + return valid_json_string; + } + + /* Ignore comma separators in values */ + if ( ( string_start ) && ( string_end == NULL ) ) + { + break; + } + /* If this comma is within an array, it must be delimiting values, so extract the comma delimited value */ + else if ( type == JSON_ARRAY_TYPE ) + { + /* If the token prior to the comma was a string token, then the delimited value must be a string */ + if ( *previous_token == STRING_TOKEN ) + { + type = JSON_STRING_TYPE; + + /* Move token to point prior to string token and to last character of string value*/ + value_end = previous_token - 1; + value_start = string_start + 1; + } + else if ( *previous_token == TRUE_TOKEN ) + { + type = JSON_BOOLEAN_TYPE; + + value_end = previous_token + sizeof( "true" ) - 2; + value_start = previous_token; + } + else if ( *previous_token == FALSE_TOKEN ) + { + type = JSON_BOOLEAN_TYPE; + + value_end = previous_token + sizeof( "false" ) - 2; + value_start = previous_token; + } + else if ( *previous_token == NULL_TOKEN ) + { + type = JSON_NULL_TYPE; + value_end = previous_token + sizeof( "null" ) - 2; + value_start = previous_token; + } + else + { + char* start = NULL; + char* end = NULL; + uint8_t len = 0; + /* Delimited values must be a NUMBER if they are not a string */ + type = JSON_NUMBER_TYPE; + + /* Set value_end to point to current location */ + value_end = current_input_token; + + /* This must be a number value if not string. Arrays would have been picked up already by the end of array token */ + type = JSON_NUMBER_TYPE; + + end = value_end; + + start = previous_token; + start++; + end--; + while ( *end == ' ' ) + { + end--; + } + while ( *start == ' ' ) + { + start++; + } + + len = end - start + 1; + + if ( validate_array_value( start, end, len ) != CY_RSLT_SUCCESS ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + array_counter = 0; + return valid_json_string; + } + + /* Point to last number. Keep moving the value end token back till you encounter a digit */ + while ( ( *value_end < '0' ) || ( *value_end > '9' ) ) + { + value_end--; + } + + /* Initialise the value_start pointer to point to last digit */ + value_start = value_end; + + /* Increment value_start until you reach first number */ + while ( ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) || ( *value_start == '.' ) || ( *value_start == '-' ) ) + { + value_start--; + } + + /*Point to first number */ + value_start++; + } + + /* prepare JSON object */ + json_object.object_string = NULL; + json_object.object_string_length = 0; + json_object.value_type = type; + json_object.value = value_start; + json_object.value_length = value_end - value_start + 1; + + if ( internal_json_callback != NULL ) + { + str_convertor( &json_object ); + internal_json_callback( &json_object, internal_json_argument ); + } + + string_start = NULL; + string_end = NULL; + value_start = NULL; + value_end = NULL; + type = JSON_ARRAY_TYPE; + } + + type = UNKNOWN_JSON_TYPE; + previous_token = current_input_token; + + break; + + case START_OF_VALUE: + + if ( escape_token ) + { + escape_token = false; + break; + } + + if ( ( *( previous_token ) == OBJECT_START_TOKEN ) || ( *( previous_token ) == ARRAY_START_TOKEN ) ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + array_counter = 0; + return valid_json_string; + } + if ( string_end ) + { + /* prepare JSON object */ + json_object.object_string = string_start + 1; + json_object.object_string_length = string_end - string_start - 1; + type = UNKNOWN_JSON_TYPE; + previous_token = current_input_token; + } + if ( value_start == NULL ) + { + value_start = current_input_token; + } + + break; + + case COMMA_SEPARATOR: + + if ( escape_token ) + { + escape_token = false; + break; + } + + /* Ignore comma separators in values */ + if ( ( string_start ) && ( string_end == NULL ) ) + { + break; + } + /* If this comma is within an array, it must be delimiting values, so extract the comma delimited value */ + else if ( type == JSON_ARRAY_TYPE ) + { + /* If the token prior to the comma was a string token, then the delimited value must be a string */ + if ( *previous_token == STRING_TOKEN ) + { + type = JSON_STRING_TYPE; + + /* Move token to point prior to string token and to last character of string value*/ + value_end = previous_token - 1; + value_start = string_start + 1; + } + else if ( *previous_token == TRUE_TOKEN ) + { + type = JSON_BOOLEAN_TYPE; + + value_end = previous_token + sizeof( "true" ) - 2; + value_start = previous_token; + } + else if ( *previous_token == FALSE_TOKEN ) + { + type = JSON_BOOLEAN_TYPE; + + value_end = previous_token + sizeof( "false" ) - 2; + value_start = previous_token; + } + else if ( *previous_token == NULL_TOKEN ) + { + type = JSON_NULL_TYPE; + value_end = previous_token + sizeof( "null" ) - 2; + value_start = previous_token; + } + else + { + /* Delimited values must be a NUMBER if they are not a string */ + type = JSON_NUMBER_TYPE; + + /* Set value_end to point to current location */ + value_end = current_input_token; + + /* Point to last number. Keep moving the value end token back till you encounter a digit */ + while ( ( *value_end < '0' ) || ( *value_end > '9' ) ) + { + value_end--; + } + + /* Initialise the value_start pointer to point to last digit */ + value_start = value_end; + + /* Increment value_start until you reach first number */ + while ( ( ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) || ( *value_start == '.' ) || ( *value_start == '-' ) ) && ( *previous_token != *value_start ) ) + { + value_start--; + } + + /*Point to first number */ + value_start++; + } + + /* prepare JSON object */ + json_object.object_string = NULL; + json_object.object_string_length = 0; + json_object.value_type = type; + json_object.value = value_start; + json_object.value_length = value_end - value_start + 1; + + if ( internal_json_callback != NULL ) + { + str_convertor( &json_object ); + internal_json_callback( &json_object, internal_json_argument ); + } + value_start = NULL; + value_end = NULL; + string_start = NULL; + string_end = NULL; + type = JSON_ARRAY_TYPE; + } + else if ( value_start ) + { + value_end = current_input_token; + + /* Commas are only used to seperate values so this must indicate an end of value, which means last object information is for us */ + if ( *previous_token == STRING_TOKEN ) + { + type = JSON_STRING_TYPE; + + value_end = previous_token - 1; + value_start = string_start + 1; + } + else if ( *previous_token == ARRAY_END_TOKEN ) + { + if ( string_start ) + { + type = JSON_STRING_TYPE; + value_start = string_start + 1; + value_end = string_end - 1; + } + else + { + type = JSON_NUMBER_TYPE; + + /* Keep moving the value end token back till you encounter a digit */ + while ( ( *value_end < '0' ) || ( *value_end > '9' ) ) + { + value_end--; + } + + value_start = value_end; + + while ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) + { + value_start--; + } + + value_start++; + } + } + else if ( *previous_token == TRUE_TOKEN ) + { + type = JSON_BOOLEAN_TYPE; + + value_end = previous_token + sizeof( "true" ) - 2; + value_start = previous_token; + } + else if ( *previous_token == FALSE_TOKEN ) + { + type = JSON_BOOLEAN_TYPE; + + value_end = previous_token + sizeof( "false" ) - 2; + value_start = previous_token; + } + else if ( *previous_token == NULL_TOKEN ) + { + type = JSON_NULL_TYPE; + value_end = previous_token + sizeof( "null" ) - 2; + value_start = previous_token; + } + else + { + type = JSON_NUMBER_TYPE; + + /* Keep moving the value end token back till you encounter a digit */ + while ( ( ( *value_end < '0' ) || ( *value_end > '9' ) ) ) + { + value_end--; + } + + value_start = value_end; + + while ( ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) || ( *value_start == '.' ) || ( *value_start == '-' ) ) + { + value_start--; + } + + value_start++; + } + + json_object.value_type = type; + json_object.value = value_start; + json_object.value_length = value_end - value_start + 1; + + if ( internal_json_callback != NULL ) + { + str_convertor( &json_object ); + internal_json_callback( &json_object, internal_json_argument ); + } + + string_start = NULL; + string_end = NULL; + value_start = NULL; + value_end = NULL; + type = UNKNOWN_JSON_TYPE; + } + + previous_token = current_input_token; + + break; + + case ESCAPE_TOKEN: + /* Clear escape token flag, if the previous token is an escape token. Else set it */ + escape_token = ( escape_token == true ) ? false : true; + + break; + + default: + /* Reset escape token flag */ + escape_token = false; + if ( ( object_counter == 0 ) && ( array_counter == 0 ) && ( *current_input_token != ' ' ) && + ( JSON_IS_NOT_ESC_CHAR ( *current_input_token ) ) ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + array_counter = 0; + return valid_json_string; + } + break; + } // switch + + /* Counting spaces*/ + if ( *( current_input_token ) == ' ' ) + { + space++; + } + else + { + space = 0; + } + current_input_token++; + if ( ( *( current_input_token ) == '\0' ) && ( ( ( *( previous_token ) == COMMA_SEPARATOR ) || ( *( previous_token ) == STRING_TOKEN ) || ( *( previous_token ) == START_OF_VALUE ) || ( *( previous_token ) == ARRAY_START_TOKEN ) ) ) ) + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + array_counter = 0; + return valid_json_string; + } + } // while + } // if + else + { + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + return valid_json_string; + } + + /* This means that a closing brace has not been found for an object. This data is split across packets */ + if ( object_counter || array_counter ) + { + memset( packet_backup, 0x0, sizeof( packet_backup ) ); + + // Copy everything from the most recent unfinished object onwards + + number_of_bytes_backed_up = end_of_input - most_recent_object_marker; + + memcpy( packet_backup, most_recent_object_marker, number_of_bytes_backed_up ); + + + incomplete_response = true; + valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; + object_counter = 0; + + return valid_json_string; + } + + + memset( &parent_json_object, 0x0, sizeof( parent_json_object ) ); + + incomplete_response = false; + + object_counter = 0; + + string_start = NULL; + string_end = NULL; + + value_start = NULL; + value_end = NULL; + + type = UNKNOWN_JSON_TYPE; + + escape_token = false; + + previous_token = NULL; + + return valid_json_string; +}