CITY3032-wifi-mqtt

connectivity-utilities/JSON_parser/cy_json_parser.c

Committer:
reedas
Date:
2021-11-13
Revision:
5:f62a9e4a499a
Parent:
4:7ebc3d28bcb2

File content as of revision 5:f62a9e4a499a:

/*
 * 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;
}