Andrew Reed
/
CITY1082-i2c_master_wifi_mqtt
CITY3032-wifi-mqtt
connectivity-utilities/JSON_parser/cy_json_parser.c@5:f62a9e4a499a, 2021-11-13 (annotated)
- Committer:
- reedas
- Date:
- Sat Nov 13 12:02:49 2021 +0000
- Revision:
- 5:f62a9e4a499a
- Parent:
- 4:7ebc3d28bcb2
trying to include mbed
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
reedas | 4:7ebc3d28bcb2 | 1 | /* |
reedas | 4:7ebc3d28bcb2 | 2 | * Copyright 2019-2021, Cypress Semiconductor Corporation (an Infineon company) or |
reedas | 4:7ebc3d28bcb2 | 3 | * an affiliate of Cypress Semiconductor Corporation. All rights reserved. |
reedas | 4:7ebc3d28bcb2 | 4 | * |
reedas | 4:7ebc3d28bcb2 | 5 | * This software, including source code, documentation and related |
reedas | 4:7ebc3d28bcb2 | 6 | * materials ("Software") is owned by Cypress Semiconductor Corporation |
reedas | 4:7ebc3d28bcb2 | 7 | * or one of its affiliates ("Cypress") and is protected by and subject to |
reedas | 4:7ebc3d28bcb2 | 8 | * worldwide patent protection (United States and foreign), |
reedas | 4:7ebc3d28bcb2 | 9 | * United States copyright laws and international treaty provisions. |
reedas | 4:7ebc3d28bcb2 | 10 | * Therefore, you may use this Software only as provided in the license |
reedas | 4:7ebc3d28bcb2 | 11 | * agreement accompanying the software package from which you |
reedas | 4:7ebc3d28bcb2 | 12 | * obtained this Software ("EULA"). |
reedas | 4:7ebc3d28bcb2 | 13 | * If no EULA applies, Cypress hereby grants you a personal, non-exclusive, |
reedas | 4:7ebc3d28bcb2 | 14 | * non-transferable license to copy, modify, and compile the Software |
reedas | 4:7ebc3d28bcb2 | 15 | * source code solely for use in connection with Cypress's |
reedas | 4:7ebc3d28bcb2 | 16 | * integrated circuit products. Any reproduction, modification, translation, |
reedas | 4:7ebc3d28bcb2 | 17 | * compilation, or representation of this Software except as specified |
reedas | 4:7ebc3d28bcb2 | 18 | * above is prohibited without the express written permission of Cypress. |
reedas | 4:7ebc3d28bcb2 | 19 | * |
reedas | 4:7ebc3d28bcb2 | 20 | * Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND, |
reedas | 4:7ebc3d28bcb2 | 21 | * EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED |
reedas | 4:7ebc3d28bcb2 | 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress |
reedas | 4:7ebc3d28bcb2 | 23 | * reserves the right to make changes to the Software without notice. Cypress |
reedas | 4:7ebc3d28bcb2 | 24 | * does not assume any liability arising out of the application or use of the |
reedas | 4:7ebc3d28bcb2 | 25 | * Software or any product or circuit described in the Software. Cypress does |
reedas | 4:7ebc3d28bcb2 | 26 | * not authorize its products for use in any products where a malfunction or |
reedas | 4:7ebc3d28bcb2 | 27 | * failure of the Cypress product may reasonably be expected to result in |
reedas | 4:7ebc3d28bcb2 | 28 | * significant property damage, injury or death ("High Risk Product"). By |
reedas | 4:7ebc3d28bcb2 | 29 | * including Cypress's product in a High Risk Product, the manufacturer |
reedas | 4:7ebc3d28bcb2 | 30 | * of such system or application assumes all risk of such use and in doing |
reedas | 4:7ebc3d28bcb2 | 31 | * so agrees to indemnify Cypress against all liability. |
reedas | 4:7ebc3d28bcb2 | 32 | */ |
reedas | 4:7ebc3d28bcb2 | 33 | |
reedas | 4:7ebc3d28bcb2 | 34 | /** @file |
reedas | 4:7ebc3d28bcb2 | 35 | * |
reedas | 4:7ebc3d28bcb2 | 36 | */ |
reedas | 4:7ebc3d28bcb2 | 37 | #include "cy_json_parser.h" |
reedas | 4:7ebc3d28bcb2 | 38 | #include <stddef.h> |
reedas | 4:7ebc3d28bcb2 | 39 | #include <string.h> |
reedas | 4:7ebc3d28bcb2 | 40 | #include <stdlib.h> |
reedas | 4:7ebc3d28bcb2 | 41 | /****************************************************** |
reedas | 4:7ebc3d28bcb2 | 42 | * Macros |
reedas | 4:7ebc3d28bcb2 | 43 | ******************************************************/ |
reedas | 4:7ebc3d28bcb2 | 44 | |
reedas | 4:7ebc3d28bcb2 | 45 | #define MAX_BACKUP_SIZE 500 |
reedas | 4:7ebc3d28bcb2 | 46 | #define MAX_PARENTS 4 |
reedas | 4:7ebc3d28bcb2 | 47 | |
reedas | 4:7ebc3d28bcb2 | 48 | /****************************************************** |
reedas | 4:7ebc3d28bcb2 | 49 | * Constants |
reedas | 4:7ebc3d28bcb2 | 50 | ******************************************************/ |
reedas | 4:7ebc3d28bcb2 | 51 | |
reedas | 4:7ebc3d28bcb2 | 52 | /****************************************************** |
reedas | 4:7ebc3d28bcb2 | 53 | * Enumerations |
reedas | 4:7ebc3d28bcb2 | 54 | ******************************************************/ |
reedas | 4:7ebc3d28bcb2 | 55 | |
reedas | 4:7ebc3d28bcb2 | 56 | /****************************************************** |
reedas | 4:7ebc3d28bcb2 | 57 | * Type Definitions |
reedas | 4:7ebc3d28bcb2 | 58 | ******************************************************/ |
reedas | 4:7ebc3d28bcb2 | 59 | |
reedas | 4:7ebc3d28bcb2 | 60 | /****************************************************** |
reedas | 4:7ebc3d28bcb2 | 61 | * Structures |
reedas | 4:7ebc3d28bcb2 | 62 | ******************************************************/ |
reedas | 4:7ebc3d28bcb2 | 63 | |
reedas | 4:7ebc3d28bcb2 | 64 | /****************************************************** |
reedas | 4:7ebc3d28bcb2 | 65 | * Static Function Declarations |
reedas | 4:7ebc3d28bcb2 | 66 | ******************************************************/ |
reedas | 4:7ebc3d28bcb2 | 67 | |
reedas | 4:7ebc3d28bcb2 | 68 | static cy_rslt_t validate_array_value( char* start, char* stop, uint8_t len ); |
reedas | 4:7ebc3d28bcb2 | 69 | |
reedas | 4:7ebc3d28bcb2 | 70 | /****************************************************** |
reedas | 4:7ebc3d28bcb2 | 71 | * Variable Definitions |
reedas | 4:7ebc3d28bcb2 | 72 | ******************************************************/ |
reedas | 4:7ebc3d28bcb2 | 73 | static cy_JSON_callback_t internal_json_callback; |
reedas | 4:7ebc3d28bcb2 | 74 | static void *internal_json_argument; |
reedas | 4:7ebc3d28bcb2 | 75 | |
reedas | 4:7ebc3d28bcb2 | 76 | static char* previous_token = NULL; |
reedas | 4:7ebc3d28bcb2 | 77 | static cy_JSON_object_t json_object = |
reedas | 4:7ebc3d28bcb2 | 78 | { |
reedas | 4:7ebc3d28bcb2 | 79 | .object_string = NULL, |
reedas | 4:7ebc3d28bcb2 | 80 | .object_string_length = 0, |
reedas | 4:7ebc3d28bcb2 | 81 | .value_type = UNKNOWN_JSON_TYPE, |
reedas | 4:7ebc3d28bcb2 | 82 | .value = NULL, |
reedas | 4:7ebc3d28bcb2 | 83 | .value_length = 0, |
reedas | 4:7ebc3d28bcb2 | 84 | .intval = 0, |
reedas | 4:7ebc3d28bcb2 | 85 | .floatval = 0.0, |
reedas | 4:7ebc3d28bcb2 | 86 | .boolval = true, |
reedas | 4:7ebc3d28bcb2 | 87 | .parent_object = NULL |
reedas | 4:7ebc3d28bcb2 | 88 | }; |
reedas | 4:7ebc3d28bcb2 | 89 | |
reedas | 4:7ebc3d28bcb2 | 90 | static int32_t parent_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 91 | static cy_JSON_object_t parent_json_object[ MAX_PARENTS ]; |
reedas | 4:7ebc3d28bcb2 | 92 | |
reedas | 4:7ebc3d28bcb2 | 93 | static bool incomplete_response = false; |
reedas | 4:7ebc3d28bcb2 | 94 | |
reedas | 4:7ebc3d28bcb2 | 95 | static int32_t object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 96 | |
reedas | 4:7ebc3d28bcb2 | 97 | static char* string_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 98 | static char* string_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 99 | |
reedas | 4:7ebc3d28bcb2 | 100 | static char* value_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 101 | static char* value_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 102 | |
reedas | 4:7ebc3d28bcb2 | 103 | static cy_JSON_type_t type = UNKNOWN_JSON_TYPE; |
reedas | 4:7ebc3d28bcb2 | 104 | |
reedas | 4:7ebc3d28bcb2 | 105 | static char* current_input_token; |
reedas | 4:7ebc3d28bcb2 | 106 | static char* end_of_input; |
reedas | 4:7ebc3d28bcb2 | 107 | |
reedas | 4:7ebc3d28bcb2 | 108 | static char* most_recent_object_marker = NULL; |
reedas | 4:7ebc3d28bcb2 | 109 | |
reedas | 4:7ebc3d28bcb2 | 110 | char packet_backup[ MAX_BACKUP_SIZE ]; |
reedas | 4:7ebc3d28bcb2 | 111 | |
reedas | 4:7ebc3d28bcb2 | 112 | uint32_t number_of_bytes_backed_up; |
reedas | 4:7ebc3d28bcb2 | 113 | |
reedas | 4:7ebc3d28bcb2 | 114 | static bool escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 115 | static int32_t array_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 116 | |
reedas | 4:7ebc3d28bcb2 | 117 | /****************************************************** |
reedas | 4:7ebc3d28bcb2 | 118 | * Function Definitions |
reedas | 4:7ebc3d28bcb2 | 119 | ******************************************************/ |
reedas | 4:7ebc3d28bcb2 | 120 | /* This function converts a string to appropriate format if the type is either |
reedas | 4:7ebc3d28bcb2 | 121 | * a JSON_NUMBER_TYPE or JSON_BOOLEAN_TYPE |
reedas | 4:7ebc3d28bcb2 | 122 | */ |
reedas | 4:7ebc3d28bcb2 | 123 | static void str_convertor( cy_JSON_object_t* json_object ) |
reedas | 4:7ebc3d28bcb2 | 124 | { |
reedas | 4:7ebc3d28bcb2 | 125 | if( json_object->value_type == JSON_NUMBER_TYPE ) |
reedas | 4:7ebc3d28bcb2 | 126 | { |
reedas | 4:7ebc3d28bcb2 | 127 | int i = 0; |
reedas | 4:7ebc3d28bcb2 | 128 | for( i=0; i<json_object->value_length; i++ ) |
reedas | 4:7ebc3d28bcb2 | 129 | { |
reedas | 4:7ebc3d28bcb2 | 130 | if( json_object->value[i] == '.' ) |
reedas | 4:7ebc3d28bcb2 | 131 | { |
reedas | 4:7ebc3d28bcb2 | 132 | json_object->floatval = strtof( json_object->value, NULL ); |
reedas | 4:7ebc3d28bcb2 | 133 | json_object->value_type = JSON_FLOAT_TYPE; |
reedas | 4:7ebc3d28bcb2 | 134 | return; |
reedas | 4:7ebc3d28bcb2 | 135 | } |
reedas | 4:7ebc3d28bcb2 | 136 | } |
reedas | 4:7ebc3d28bcb2 | 137 | json_object->intval = strtol( json_object->value, NULL, 10 ); |
reedas | 4:7ebc3d28bcb2 | 138 | } |
reedas | 4:7ebc3d28bcb2 | 139 | else if( json_object->value_type == JSON_BOOLEAN_TYPE ) |
reedas | 4:7ebc3d28bcb2 | 140 | { |
reedas | 4:7ebc3d28bcb2 | 141 | if( json_object->value[0] == 't' ) |
reedas | 4:7ebc3d28bcb2 | 142 | { |
reedas | 4:7ebc3d28bcb2 | 143 | json_object->boolval = true; |
reedas | 4:7ebc3d28bcb2 | 144 | } |
reedas | 4:7ebc3d28bcb2 | 145 | else |
reedas | 4:7ebc3d28bcb2 | 146 | { |
reedas | 4:7ebc3d28bcb2 | 147 | json_object->boolval = false; |
reedas | 4:7ebc3d28bcb2 | 148 | } |
reedas | 4:7ebc3d28bcb2 | 149 | } |
reedas | 4:7ebc3d28bcb2 | 150 | } |
reedas | 4:7ebc3d28bcb2 | 151 | static cy_rslt_t validate_array_value( char* start, char* stop, uint8_t len ) |
reedas | 4:7ebc3d28bcb2 | 152 | { |
reedas | 4:7ebc3d28bcb2 | 153 | char* temp = NULL; |
reedas | 4:7ebc3d28bcb2 | 154 | uint8_t e_count = 0; |
reedas | 4:7ebc3d28bcb2 | 155 | uint8_t dot = 0; |
reedas | 4:7ebc3d28bcb2 | 156 | uint8_t minus = 0; |
reedas | 4:7ebc3d28bcb2 | 157 | uint8_t plus = 0; |
reedas | 4:7ebc3d28bcb2 | 158 | |
reedas | 4:7ebc3d28bcb2 | 159 | /* TODO : Cases to be handled for example : e+- e.+1 .e-+2 -1.234e-3 */ |
reedas | 4:7ebc3d28bcb2 | 160 | |
reedas | 4:7ebc3d28bcb2 | 161 | if ( ( *start == 'f' ) && ( len == 5 ) ) |
reedas | 4:7ebc3d28bcb2 | 162 | { |
reedas | 4:7ebc3d28bcb2 | 163 | if ( !strncmp( (const char*) start, "false", ( sizeof( "false" ) - 1 ) ) ) |
reedas | 4:7ebc3d28bcb2 | 164 | { |
reedas | 4:7ebc3d28bcb2 | 165 | return CY_RSLT_SUCCESS; |
reedas | 4:7ebc3d28bcb2 | 166 | } |
reedas | 4:7ebc3d28bcb2 | 167 | else |
reedas | 4:7ebc3d28bcb2 | 168 | { |
reedas | 4:7ebc3d28bcb2 | 169 | return CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 170 | } |
reedas | 4:7ebc3d28bcb2 | 171 | } |
reedas | 4:7ebc3d28bcb2 | 172 | if ( ( *start == 't' ) && ( len == 4 ) ) |
reedas | 4:7ebc3d28bcb2 | 173 | { |
reedas | 4:7ebc3d28bcb2 | 174 | if ( !strncmp( (const char*) start, "true", ( sizeof( "true" ) - 1 ) ) ) |
reedas | 4:7ebc3d28bcb2 | 175 | { |
reedas | 4:7ebc3d28bcb2 | 176 | return CY_RSLT_SUCCESS; |
reedas | 4:7ebc3d28bcb2 | 177 | } |
reedas | 4:7ebc3d28bcb2 | 178 | else |
reedas | 4:7ebc3d28bcb2 | 179 | { |
reedas | 4:7ebc3d28bcb2 | 180 | return CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 181 | } |
reedas | 4:7ebc3d28bcb2 | 182 | } |
reedas | 4:7ebc3d28bcb2 | 183 | if ( ( *start == 'n' ) && ( len == 4 ) ) |
reedas | 4:7ebc3d28bcb2 | 184 | { |
reedas | 4:7ebc3d28bcb2 | 185 | if ( !strncmp( (const char*) start, "null", ( sizeof( "null" ) - 1 ) ) ) |
reedas | 4:7ebc3d28bcb2 | 186 | { |
reedas | 4:7ebc3d28bcb2 | 187 | return CY_RSLT_SUCCESS; |
reedas | 4:7ebc3d28bcb2 | 188 | } |
reedas | 4:7ebc3d28bcb2 | 189 | else |
reedas | 4:7ebc3d28bcb2 | 190 | { |
reedas | 4:7ebc3d28bcb2 | 191 | return CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 192 | } |
reedas | 4:7ebc3d28bcb2 | 193 | } |
reedas | 4:7ebc3d28bcb2 | 194 | |
reedas | 4:7ebc3d28bcb2 | 195 | temp = start; |
reedas | 4:7ebc3d28bcb2 | 196 | while ( temp <= stop ) |
reedas | 4:7ebc3d28bcb2 | 197 | { |
reedas | 4:7ebc3d28bcb2 | 198 | if( *temp == ' ') |
reedas | 4:7ebc3d28bcb2 | 199 | { |
reedas | 4:7ebc3d28bcb2 | 200 | temp++; |
reedas | 4:7ebc3d28bcb2 | 201 | continue; |
reedas | 4:7ebc3d28bcb2 | 202 | } |
reedas | 4:7ebc3d28bcb2 | 203 | if( *temp == '\n') |
reedas | 4:7ebc3d28bcb2 | 204 | { |
reedas | 4:7ebc3d28bcb2 | 205 | temp++; |
reedas | 4:7ebc3d28bcb2 | 206 | continue; |
reedas | 4:7ebc3d28bcb2 | 207 | } |
reedas | 4:7ebc3d28bcb2 | 208 | if( *temp == '\r') |
reedas | 4:7ebc3d28bcb2 | 209 | { |
reedas | 4:7ebc3d28bcb2 | 210 | temp++; |
reedas | 4:7ebc3d28bcb2 | 211 | continue; |
reedas | 4:7ebc3d28bcb2 | 212 | } |
reedas | 4:7ebc3d28bcb2 | 213 | |
reedas | 4:7ebc3d28bcb2 | 214 | switch ( *temp ) |
reedas | 4:7ebc3d28bcb2 | 215 | { |
reedas | 4:7ebc3d28bcb2 | 216 | case 'e': |
reedas | 4:7ebc3d28bcb2 | 217 | e_count++; |
reedas | 4:7ebc3d28bcb2 | 218 | break; |
reedas | 4:7ebc3d28bcb2 | 219 | |
reedas | 4:7ebc3d28bcb2 | 220 | case '+': |
reedas | 4:7ebc3d28bcb2 | 221 | plus++; |
reedas | 4:7ebc3d28bcb2 | 222 | break; |
reedas | 4:7ebc3d28bcb2 | 223 | |
reedas | 4:7ebc3d28bcb2 | 224 | case '-': |
reedas | 4:7ebc3d28bcb2 | 225 | minus++; |
reedas | 4:7ebc3d28bcb2 | 226 | break; |
reedas | 4:7ebc3d28bcb2 | 227 | |
reedas | 4:7ebc3d28bcb2 | 228 | case '.': |
reedas | 4:7ebc3d28bcb2 | 229 | dot++; |
reedas | 4:7ebc3d28bcb2 | 230 | break; |
reedas | 4:7ebc3d28bcb2 | 231 | |
reedas | 4:7ebc3d28bcb2 | 232 | default: |
reedas | 4:7ebc3d28bcb2 | 233 | break; |
reedas | 4:7ebc3d28bcb2 | 234 | } |
reedas | 4:7ebc3d28bcb2 | 235 | |
reedas | 4:7ebc3d28bcb2 | 236 | if ( !( ( ( *temp >= '0' ) && ( *temp <= '9' ) ) || ( *temp == 'e' ) || ( *temp == '-' ) || ( *temp == '.' ) || ( *temp == '+' ) ) ) |
reedas | 4:7ebc3d28bcb2 | 237 | { |
reedas | 4:7ebc3d28bcb2 | 238 | return CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 239 | } |
reedas | 4:7ebc3d28bcb2 | 240 | |
reedas | 4:7ebc3d28bcb2 | 241 | if ( ( e_count > 1 ) || ( minus > 1 ) || ( plus > 1 ) || ( dot > 1 ) ) |
reedas | 4:7ebc3d28bcb2 | 242 | { |
reedas | 4:7ebc3d28bcb2 | 243 | return CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 244 | } |
reedas | 4:7ebc3d28bcb2 | 245 | temp++; |
reedas | 4:7ebc3d28bcb2 | 246 | } |
reedas | 4:7ebc3d28bcb2 | 247 | |
reedas | 4:7ebc3d28bcb2 | 248 | return CY_RSLT_SUCCESS; |
reedas | 4:7ebc3d28bcb2 | 249 | } |
reedas | 4:7ebc3d28bcb2 | 250 | |
reedas | 4:7ebc3d28bcb2 | 251 | |
reedas | 4:7ebc3d28bcb2 | 252 | /* Register callbacks parser will use to populate fields*/ |
reedas | 4:7ebc3d28bcb2 | 253 | cy_rslt_t cy_JSON_parser_register_callback( cy_JSON_callback_t json_callback, void *arg ) |
reedas | 4:7ebc3d28bcb2 | 254 | { |
reedas | 4:7ebc3d28bcb2 | 255 | internal_json_callback = json_callback; |
reedas | 4:7ebc3d28bcb2 | 256 | internal_json_argument = arg; |
reedas | 4:7ebc3d28bcb2 | 257 | |
reedas | 4:7ebc3d28bcb2 | 258 | return CY_RSLT_SUCCESS; |
reedas | 4:7ebc3d28bcb2 | 259 | } |
reedas | 4:7ebc3d28bcb2 | 260 | |
reedas | 4:7ebc3d28bcb2 | 261 | |
reedas | 4:7ebc3d28bcb2 | 262 | /* Get current callback */ |
reedas | 4:7ebc3d28bcb2 | 263 | cy_JSON_callback_t cy_JSON_parser_get_callback( void ) |
reedas | 4:7ebc3d28bcb2 | 264 | { |
reedas | 4:7ebc3d28bcb2 | 265 | return internal_json_callback; |
reedas | 4:7ebc3d28bcb2 | 266 | } |
reedas | 4:7ebc3d28bcb2 | 267 | |
reedas | 4:7ebc3d28bcb2 | 268 | |
reedas | 4:7ebc3d28bcb2 | 269 | cy_rslt_t cy_JSON_parser( const char* json_input, uint32_t input_length ) |
reedas | 4:7ebc3d28bcb2 | 270 | { |
reedas | 4:7ebc3d28bcb2 | 271 | cy_rslt_t valid_json_string = CY_RSLT_SUCCESS; |
reedas | 4:7ebc3d28bcb2 | 272 | int space = 0; |
reedas | 4:7ebc3d28bcb2 | 273 | |
reedas | 4:7ebc3d28bcb2 | 274 | if ( incomplete_response ) |
reedas | 4:7ebc3d28bcb2 | 275 | { |
reedas | 4:7ebc3d28bcb2 | 276 | // If there is enough room on backup buffer to hold new data and old backed up |
reedas | 4:7ebc3d28bcb2 | 277 | // data, parse the backup buffer |
reedas | 4:7ebc3d28bcb2 | 278 | if ( ( input_length + number_of_bytes_backed_up ) < MAX_BACKUP_SIZE ) |
reedas | 4:7ebc3d28bcb2 | 279 | { |
reedas | 4:7ebc3d28bcb2 | 280 | memcpy( packet_backup + number_of_bytes_backed_up, json_input, input_length ); |
reedas | 4:7ebc3d28bcb2 | 281 | current_input_token = packet_backup; |
reedas | 4:7ebc3d28bcb2 | 282 | end_of_input = current_input_token + number_of_bytes_backed_up + input_length; |
reedas | 4:7ebc3d28bcb2 | 283 | } |
reedas | 4:7ebc3d28bcb2 | 284 | else |
reedas | 4:7ebc3d28bcb2 | 285 | { |
reedas | 4:7ebc3d28bcb2 | 286 | // We must drop entire json object from last buffer. Find start of new json object |
reedas | 4:7ebc3d28bcb2 | 287 | // in new packet, and being parsing from there |
reedas | 4:7ebc3d28bcb2 | 288 | while ( *json_input != '{' ) |
reedas | 4:7ebc3d28bcb2 | 289 | { |
reedas | 4:7ebc3d28bcb2 | 290 | json_input++; |
reedas | 4:7ebc3d28bcb2 | 291 | input_length--; |
reedas | 4:7ebc3d28bcb2 | 292 | } |
reedas | 4:7ebc3d28bcb2 | 293 | current_input_token = (char*) json_input; |
reedas | 4:7ebc3d28bcb2 | 294 | end_of_input = current_input_token + input_length; |
reedas | 4:7ebc3d28bcb2 | 295 | } |
reedas | 4:7ebc3d28bcb2 | 296 | |
reedas | 4:7ebc3d28bcb2 | 297 | incomplete_response = false; |
reedas | 4:7ebc3d28bcb2 | 298 | } |
reedas | 4:7ebc3d28bcb2 | 299 | else |
reedas | 4:7ebc3d28bcb2 | 300 | { |
reedas | 4:7ebc3d28bcb2 | 301 | current_input_token = (char*) json_input; |
reedas | 4:7ebc3d28bcb2 | 302 | end_of_input = current_input_token + input_length; |
reedas | 4:7ebc3d28bcb2 | 303 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 304 | } |
reedas | 4:7ebc3d28bcb2 | 305 | |
reedas | 4:7ebc3d28bcb2 | 306 | while ( *( current_input_token ) == ' ' ) |
reedas | 4:7ebc3d28bcb2 | 307 | { |
reedas | 4:7ebc3d28bcb2 | 308 | current_input_token++; |
reedas | 4:7ebc3d28bcb2 | 309 | } |
reedas | 4:7ebc3d28bcb2 | 310 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 311 | |
reedas | 4:7ebc3d28bcb2 | 312 | if ( ( *( current_input_token ) == OBJECT_START_TOKEN ) || ( *( current_input_token ) == ARRAY_START_TOKEN ) ) |
reedas | 4:7ebc3d28bcb2 | 313 | { |
reedas | 4:7ebc3d28bcb2 | 314 | /* Parse through entire input */ |
reedas | 4:7ebc3d28bcb2 | 315 | while ( current_input_token < end_of_input ) |
reedas | 4:7ebc3d28bcb2 | 316 | { |
reedas | 4:7ebc3d28bcb2 | 317 | switch ( *current_input_token ) |
reedas | 4:7ebc3d28bcb2 | 318 | { |
reedas | 4:7ebc3d28bcb2 | 319 | /* This is a start of object token */ |
reedas | 4:7ebc3d28bcb2 | 320 | case OBJECT_START_TOKEN: |
reedas | 4:7ebc3d28bcb2 | 321 | |
reedas | 4:7ebc3d28bcb2 | 322 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 323 | { |
reedas | 4:7ebc3d28bcb2 | 324 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 325 | break; |
reedas | 4:7ebc3d28bcb2 | 326 | } |
reedas | 4:7ebc3d28bcb2 | 327 | |
reedas | 4:7ebc3d28bcb2 | 328 | /* Skip in case we're parsing a string value */ |
reedas | 4:7ebc3d28bcb2 | 329 | if ( ( string_start != NULL ) && ( string_end == NULL ) ) |
reedas | 4:7ebc3d28bcb2 | 330 | { |
reedas | 4:7ebc3d28bcb2 | 331 | break; |
reedas | 4:7ebc3d28bcb2 | 332 | } |
reedas | 4:7ebc3d28bcb2 | 333 | |
reedas | 4:7ebc3d28bcb2 | 334 | /* In case the json is split across packets, record the most recent object market |
reedas | 4:7ebc3d28bcb2 | 335 | * and copy from this point forward |
reedas | 4:7ebc3d28bcb2 | 336 | */ |
reedas | 4:7ebc3d28bcb2 | 337 | most_recent_object_marker = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 338 | |
reedas | 4:7ebc3d28bcb2 | 339 | /* Keep track of the number of objects open */ |
reedas | 4:7ebc3d28bcb2 | 340 | object_counter++; |
reedas | 4:7ebc3d28bcb2 | 341 | |
reedas | 4:7ebc3d28bcb2 | 342 | type = JSON_OBJECT_TYPE; |
reedas | 4:7ebc3d28bcb2 | 343 | /* If we have already captured some string value, then this string must represent the name of this object */ |
reedas | 4:7ebc3d28bcb2 | 344 | if ( string_end ) |
reedas | 4:7ebc3d28bcb2 | 345 | { |
reedas | 4:7ebc3d28bcb2 | 346 | /* prepare JSON object. The object string was already piced up by the start of value token */ |
reedas | 4:7ebc3d28bcb2 | 347 | json_object.value_type = type; |
reedas | 4:7ebc3d28bcb2 | 348 | json_object.value = NULL; |
reedas | 4:7ebc3d28bcb2 | 349 | json_object.value_length = 0; |
reedas | 4:7ebc3d28bcb2 | 350 | |
reedas | 4:7ebc3d28bcb2 | 351 | /* Reset the string and value pointers */ |
reedas | 4:7ebc3d28bcb2 | 352 | string_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 353 | string_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 354 | value_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 355 | value_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 356 | } |
reedas | 4:7ebc3d28bcb2 | 357 | |
reedas | 4:7ebc3d28bcb2 | 358 | if ( ( ( json_object.value_type == JSON_ARRAY_TYPE ) || ( json_object.value_type == JSON_OBJECT_TYPE ) ) && ( parent_counter < MAX_PARENTS ) ) |
reedas | 4:7ebc3d28bcb2 | 359 | { |
reedas | 4:7ebc3d28bcb2 | 360 | parent_json_object[ parent_counter ] = json_object; |
reedas | 4:7ebc3d28bcb2 | 361 | json_object.parent_object = &parent_json_object[ parent_counter ]; |
reedas | 4:7ebc3d28bcb2 | 362 | parent_counter++; |
reedas | 4:7ebc3d28bcb2 | 363 | } |
reedas | 4:7ebc3d28bcb2 | 364 | else if ( *previous_token == COMMA_SEPARATOR ) |
reedas | 4:7ebc3d28bcb2 | 365 | { |
reedas | 4:7ebc3d28bcb2 | 366 | json_object.parent_object = &parent_json_object[ parent_counter ]; |
reedas | 4:7ebc3d28bcb2 | 367 | parent_counter++; |
reedas | 4:7ebc3d28bcb2 | 368 | } |
reedas | 4:7ebc3d28bcb2 | 369 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 370 | |
reedas | 4:7ebc3d28bcb2 | 371 | break; |
reedas | 4:7ebc3d28bcb2 | 372 | |
reedas | 4:7ebc3d28bcb2 | 373 | /* This is an end of object token */ |
reedas | 4:7ebc3d28bcb2 | 374 | case OBJECT_END_TOKEN: |
reedas | 4:7ebc3d28bcb2 | 375 | |
reedas | 4:7ebc3d28bcb2 | 376 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 377 | { |
reedas | 4:7ebc3d28bcb2 | 378 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 379 | break; |
reedas | 4:7ebc3d28bcb2 | 380 | } |
reedas | 4:7ebc3d28bcb2 | 381 | |
reedas | 4:7ebc3d28bcb2 | 382 | /* Skip in case we're parsing a string value */ |
reedas | 4:7ebc3d28bcb2 | 383 | if ( ( string_start != NULL ) && ( string_end == NULL ) ) |
reedas | 4:7ebc3d28bcb2 | 384 | { |
reedas | 4:7ebc3d28bcb2 | 385 | break; |
reedas | 4:7ebc3d28bcb2 | 386 | } |
reedas | 4:7ebc3d28bcb2 | 387 | |
reedas | 4:7ebc3d28bcb2 | 388 | object_counter--; |
reedas | 4:7ebc3d28bcb2 | 389 | |
reedas | 4:7ebc3d28bcb2 | 390 | if ( *( previous_token ) == COMMA_SEPARATOR ) |
reedas | 4:7ebc3d28bcb2 | 391 | { |
reedas | 4:7ebc3d28bcb2 | 392 | if ( *( current_input_token ) == ( OBJECT_END_TOKEN ) ) |
reedas | 4:7ebc3d28bcb2 | 393 | { |
reedas | 4:7ebc3d28bcb2 | 394 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 395 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 396 | array_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 397 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 398 | } |
reedas | 4:7ebc3d28bcb2 | 399 | } |
reedas | 4:7ebc3d28bcb2 | 400 | /* 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 */ |
reedas | 4:7ebc3d28bcb2 | 401 | if ( value_start ) |
reedas | 4:7ebc3d28bcb2 | 402 | { |
reedas | 4:7ebc3d28bcb2 | 403 | value_end = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 404 | /* If previous was a string token, then this must be a string value */ |
reedas | 4:7ebc3d28bcb2 | 405 | if ( *previous_token == STRING_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 406 | { |
reedas | 4:7ebc3d28bcb2 | 407 | type = JSON_STRING_TYPE; |
reedas | 4:7ebc3d28bcb2 | 408 | |
reedas | 4:7ebc3d28bcb2 | 409 | /* Move value token to point prior to string token and to last character of string value*/ |
reedas | 4:7ebc3d28bcb2 | 410 | value_end = previous_token - 1; |
reedas | 4:7ebc3d28bcb2 | 411 | value_start = string_start + 1; |
reedas | 4:7ebc3d28bcb2 | 412 | } |
reedas | 4:7ebc3d28bcb2 | 413 | else if ( *previous_token == TRUE_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 414 | { |
reedas | 4:7ebc3d28bcb2 | 415 | type = JSON_BOOLEAN_TYPE; |
reedas | 4:7ebc3d28bcb2 | 416 | |
reedas | 4:7ebc3d28bcb2 | 417 | value_end = previous_token + sizeof( "true" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 418 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 419 | } |
reedas | 4:7ebc3d28bcb2 | 420 | else if ( *previous_token == FALSE_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 421 | { |
reedas | 4:7ebc3d28bcb2 | 422 | type = JSON_BOOLEAN_TYPE; |
reedas | 4:7ebc3d28bcb2 | 423 | |
reedas | 4:7ebc3d28bcb2 | 424 | value_end = previous_token + sizeof( "false" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 425 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 426 | } |
reedas | 4:7ebc3d28bcb2 | 427 | else if ( *previous_token == NULL_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 428 | { |
reedas | 4:7ebc3d28bcb2 | 429 | type = JSON_NULL_TYPE; |
reedas | 4:7ebc3d28bcb2 | 430 | value_end = previous_token + sizeof( "null" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 431 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 432 | } |
reedas | 4:7ebc3d28bcb2 | 433 | else |
reedas | 4:7ebc3d28bcb2 | 434 | { |
reedas | 4:7ebc3d28bcb2 | 435 | char* start = NULL; |
reedas | 4:7ebc3d28bcb2 | 436 | char* end = NULL; |
reedas | 4:7ebc3d28bcb2 | 437 | uint8_t len = 0; |
reedas | 4:7ebc3d28bcb2 | 438 | /* This must be a number value if not string. Arrays would have been picked up already by the end of array token */ |
reedas | 4:7ebc3d28bcb2 | 439 | type = JSON_NUMBER_TYPE; |
reedas | 4:7ebc3d28bcb2 | 440 | |
reedas | 4:7ebc3d28bcb2 | 441 | end = value_end; |
reedas | 4:7ebc3d28bcb2 | 442 | |
reedas | 4:7ebc3d28bcb2 | 443 | start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 444 | start++; |
reedas | 4:7ebc3d28bcb2 | 445 | end--; |
reedas | 4:7ebc3d28bcb2 | 446 | while ( *end == ' ' ) |
reedas | 4:7ebc3d28bcb2 | 447 | { |
reedas | 4:7ebc3d28bcb2 | 448 | end--; |
reedas | 4:7ebc3d28bcb2 | 449 | } |
reedas | 4:7ebc3d28bcb2 | 450 | while ( *start == ' ' ) |
reedas | 4:7ebc3d28bcb2 | 451 | { |
reedas | 4:7ebc3d28bcb2 | 452 | start++; |
reedas | 4:7ebc3d28bcb2 | 453 | } |
reedas | 4:7ebc3d28bcb2 | 454 | |
reedas | 4:7ebc3d28bcb2 | 455 | len = end - start + 1; |
reedas | 4:7ebc3d28bcb2 | 456 | |
reedas | 4:7ebc3d28bcb2 | 457 | if ( validate_array_value( start, end, len ) != CY_RSLT_SUCCESS ) |
reedas | 4:7ebc3d28bcb2 | 458 | { |
reedas | 4:7ebc3d28bcb2 | 459 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 460 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 461 | array_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 462 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 463 | } |
reedas | 4:7ebc3d28bcb2 | 464 | |
reedas | 4:7ebc3d28bcb2 | 465 | /* Keep moving the value end token back till you encounter a digit */ |
reedas | 4:7ebc3d28bcb2 | 466 | while ( ( *value_end < '0' ) || ( *value_end > '9' ) ) |
reedas | 4:7ebc3d28bcb2 | 467 | { |
reedas | 4:7ebc3d28bcb2 | 468 | value_end--; |
reedas | 4:7ebc3d28bcb2 | 469 | } |
reedas | 4:7ebc3d28bcb2 | 470 | |
reedas | 4:7ebc3d28bcb2 | 471 | /* Initialise the value_start token with value_end */ |
reedas | 4:7ebc3d28bcb2 | 472 | value_start = value_end; |
reedas | 4:7ebc3d28bcb2 | 473 | |
reedas | 4:7ebc3d28bcb2 | 474 | /* Move value_start token until we encounter a non-digit value */ |
reedas | 4:7ebc3d28bcb2 | 475 | while ( ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) || ( *value_start == '.' ) || ( *value_start == '-' ) ) |
reedas | 4:7ebc3d28bcb2 | 476 | { |
reedas | 4:7ebc3d28bcb2 | 477 | value_start--; |
reedas | 4:7ebc3d28bcb2 | 478 | } |
reedas | 4:7ebc3d28bcb2 | 479 | |
reedas | 4:7ebc3d28bcb2 | 480 | /*Point to first number */ |
reedas | 4:7ebc3d28bcb2 | 481 | value_start++; |
reedas | 4:7ebc3d28bcb2 | 482 | } |
reedas | 4:7ebc3d28bcb2 | 483 | |
reedas | 4:7ebc3d28bcb2 | 484 | /* Prepare JSON object */ |
reedas | 4:7ebc3d28bcb2 | 485 | json_object.value_type = type; |
reedas | 4:7ebc3d28bcb2 | 486 | json_object.value = value_start; |
reedas | 4:7ebc3d28bcb2 | 487 | json_object.value_length = value_end - value_start + 1; |
reedas | 4:7ebc3d28bcb2 | 488 | |
reedas | 4:7ebc3d28bcb2 | 489 | if ( internal_json_callback != NULL ) |
reedas | 4:7ebc3d28bcb2 | 490 | { |
reedas | 4:7ebc3d28bcb2 | 491 | str_convertor( &json_object ); |
reedas | 4:7ebc3d28bcb2 | 492 | internal_json_callback( &json_object, internal_json_argument ); |
reedas | 4:7ebc3d28bcb2 | 493 | } |
reedas | 4:7ebc3d28bcb2 | 494 | |
reedas | 4:7ebc3d28bcb2 | 495 | /* Reset the value pointers */ |
reedas | 4:7ebc3d28bcb2 | 496 | value_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 497 | value_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 498 | string_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 499 | string_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 500 | type = UNKNOWN_JSON_TYPE; |
reedas | 4:7ebc3d28bcb2 | 501 | } |
reedas | 4:7ebc3d28bcb2 | 502 | if ( parent_counter ) |
reedas | 4:7ebc3d28bcb2 | 503 | { |
reedas | 4:7ebc3d28bcb2 | 504 | parent_counter--; |
reedas | 4:7ebc3d28bcb2 | 505 | |
reedas | 4:7ebc3d28bcb2 | 506 | if ( parent_counter ) |
reedas | 4:7ebc3d28bcb2 | 507 | { |
reedas | 4:7ebc3d28bcb2 | 508 | json_object.parent_object = &parent_json_object[ parent_counter - 1 ]; |
reedas | 4:7ebc3d28bcb2 | 509 | } |
reedas | 4:7ebc3d28bcb2 | 510 | else |
reedas | 4:7ebc3d28bcb2 | 511 | { |
reedas | 4:7ebc3d28bcb2 | 512 | json_object.parent_object = &parent_json_object[ parent_counter ]; |
reedas | 4:7ebc3d28bcb2 | 513 | } |
reedas | 4:7ebc3d28bcb2 | 514 | } |
reedas | 4:7ebc3d28bcb2 | 515 | else |
reedas | 4:7ebc3d28bcb2 | 516 | { |
reedas | 4:7ebc3d28bcb2 | 517 | json_object.parent_object = NULL; |
reedas | 4:7ebc3d28bcb2 | 518 | } |
reedas | 4:7ebc3d28bcb2 | 519 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 520 | |
reedas | 4:7ebc3d28bcb2 | 521 | break; |
reedas | 4:7ebc3d28bcb2 | 522 | |
reedas | 4:7ebc3d28bcb2 | 523 | case STRING_TOKEN: |
reedas | 4:7ebc3d28bcb2 | 524 | |
reedas | 4:7ebc3d28bcb2 | 525 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 526 | { |
reedas | 4:7ebc3d28bcb2 | 527 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 528 | break; |
reedas | 4:7ebc3d28bcb2 | 529 | } |
reedas | 4:7ebc3d28bcb2 | 530 | /* This indicates this must be closing token for object name */ |
reedas | 4:7ebc3d28bcb2 | 531 | if ( *previous_token == STRING_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 532 | { |
reedas | 4:7ebc3d28bcb2 | 533 | /* Get the last character of the string name */ |
reedas | 4:7ebc3d28bcb2 | 534 | string_end = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 535 | } |
reedas | 4:7ebc3d28bcb2 | 536 | else |
reedas | 4:7ebc3d28bcb2 | 537 | { |
reedas | 4:7ebc3d28bcb2 | 538 | /* Find start and end of of object name */ |
reedas | 4:7ebc3d28bcb2 | 539 | string_start = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 540 | string_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 541 | } |
reedas | 4:7ebc3d28bcb2 | 542 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 543 | |
reedas | 4:7ebc3d28bcb2 | 544 | break; |
reedas | 4:7ebc3d28bcb2 | 545 | |
reedas | 4:7ebc3d28bcb2 | 546 | case TRUE_TOKEN: |
reedas | 4:7ebc3d28bcb2 | 547 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 548 | { |
reedas | 4:7ebc3d28bcb2 | 549 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 550 | break; |
reedas | 4:7ebc3d28bcb2 | 551 | } |
reedas | 4:7ebc3d28bcb2 | 552 | if ( *previous_token == OBJECT_START_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 553 | { |
reedas | 4:7ebc3d28bcb2 | 554 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 555 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 556 | |
reedas | 4:7ebc3d28bcb2 | 557 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 558 | } |
reedas | 4:7ebc3d28bcb2 | 559 | if ( ( *previous_token == START_OF_VALUE ) && ( string_end ) ) |
reedas | 4:7ebc3d28bcb2 | 560 | { |
reedas | 4:7ebc3d28bcb2 | 561 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 562 | current_input_token = current_input_token + sizeof( "true" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 563 | } |
reedas | 4:7ebc3d28bcb2 | 564 | |
reedas | 4:7ebc3d28bcb2 | 565 | break; |
reedas | 4:7ebc3d28bcb2 | 566 | |
reedas | 4:7ebc3d28bcb2 | 567 | case FALSE_TOKEN: |
reedas | 4:7ebc3d28bcb2 | 568 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 569 | { |
reedas | 4:7ebc3d28bcb2 | 570 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 571 | break; |
reedas | 4:7ebc3d28bcb2 | 572 | } |
reedas | 4:7ebc3d28bcb2 | 573 | if ( *previous_token == OBJECT_START_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 574 | { |
reedas | 4:7ebc3d28bcb2 | 575 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 576 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 577 | array_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 578 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 579 | } |
reedas | 4:7ebc3d28bcb2 | 580 | if ( ( *previous_token == START_OF_VALUE ) && ( string_end ) ) |
reedas | 4:7ebc3d28bcb2 | 581 | { |
reedas | 4:7ebc3d28bcb2 | 582 | /* Skip ahead as this must be boolean false */ |
reedas | 4:7ebc3d28bcb2 | 583 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 584 | current_input_token = current_input_token + sizeof( "false" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 585 | } |
reedas | 4:7ebc3d28bcb2 | 586 | break; |
reedas | 4:7ebc3d28bcb2 | 587 | |
reedas | 4:7ebc3d28bcb2 | 588 | case NULL_TOKEN: |
reedas | 4:7ebc3d28bcb2 | 589 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 590 | { |
reedas | 4:7ebc3d28bcb2 | 591 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 592 | break; |
reedas | 4:7ebc3d28bcb2 | 593 | } |
reedas | 4:7ebc3d28bcb2 | 594 | if ( ( *previous_token == START_OF_VALUE ) && ( string_end ) ) |
reedas | 4:7ebc3d28bcb2 | 595 | { |
reedas | 4:7ebc3d28bcb2 | 596 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 597 | current_input_token = current_input_token + sizeof( "null" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 598 | } |
reedas | 4:7ebc3d28bcb2 | 599 | break; |
reedas | 4:7ebc3d28bcb2 | 600 | |
reedas | 4:7ebc3d28bcb2 | 601 | case ARRAY_START_TOKEN: |
reedas | 4:7ebc3d28bcb2 | 602 | |
reedas | 4:7ebc3d28bcb2 | 603 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 604 | { |
reedas | 4:7ebc3d28bcb2 | 605 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 606 | break; |
reedas | 4:7ebc3d28bcb2 | 607 | } |
reedas | 4:7ebc3d28bcb2 | 608 | |
reedas | 4:7ebc3d28bcb2 | 609 | /* Skip in case we're parsing a string value */ |
reedas | 4:7ebc3d28bcb2 | 610 | if ( ( string_start != NULL ) && ( string_end == NULL ) ) |
reedas | 4:7ebc3d28bcb2 | 611 | { |
reedas | 4:7ebc3d28bcb2 | 612 | break; |
reedas | 4:7ebc3d28bcb2 | 613 | } |
reedas | 4:7ebc3d28bcb2 | 614 | else if (string_start == NULL) |
reedas | 4:7ebc3d28bcb2 | 615 | { |
reedas | 4:7ebc3d28bcb2 | 616 | json_object.object_string = NULL; |
reedas | 4:7ebc3d28bcb2 | 617 | json_object.object_string_length = 0; |
reedas | 4:7ebc3d28bcb2 | 618 | } |
reedas | 4:7ebc3d28bcb2 | 619 | |
reedas | 4:7ebc3d28bcb2 | 620 | array_counter++; |
reedas | 4:7ebc3d28bcb2 | 621 | /*This means the last object name must have an array value type*/ |
reedas | 4:7ebc3d28bcb2 | 622 | type = JSON_ARRAY_TYPE; |
reedas | 4:7ebc3d28bcb2 | 623 | |
reedas | 4:7ebc3d28bcb2 | 624 | json_object.value_type = type; |
reedas | 4:7ebc3d28bcb2 | 625 | json_object.value = NULL; |
reedas | 4:7ebc3d28bcb2 | 626 | json_object.value_length = 0; |
reedas | 4:7ebc3d28bcb2 | 627 | |
reedas | 4:7ebc3d28bcb2 | 628 | if ( internal_json_callback != NULL ) |
reedas | 4:7ebc3d28bcb2 | 629 | { |
reedas | 4:7ebc3d28bcb2 | 630 | str_convertor( &json_object ); |
reedas | 4:7ebc3d28bcb2 | 631 | internal_json_callback( &json_object, internal_json_argument ); |
reedas | 4:7ebc3d28bcb2 | 632 | } |
reedas | 4:7ebc3d28bcb2 | 633 | |
reedas | 4:7ebc3d28bcb2 | 634 | /* Reset object string start/end tokens */ |
reedas | 4:7ebc3d28bcb2 | 635 | string_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 636 | string_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 637 | |
reedas | 4:7ebc3d28bcb2 | 638 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 639 | |
reedas | 4:7ebc3d28bcb2 | 640 | break; |
reedas | 4:7ebc3d28bcb2 | 641 | |
reedas | 4:7ebc3d28bcb2 | 642 | case ARRAY_END_TOKEN: |
reedas | 4:7ebc3d28bcb2 | 643 | |
reedas | 4:7ebc3d28bcb2 | 644 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 645 | { |
reedas | 4:7ebc3d28bcb2 | 646 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 647 | break; |
reedas | 4:7ebc3d28bcb2 | 648 | } |
reedas | 4:7ebc3d28bcb2 | 649 | |
reedas | 4:7ebc3d28bcb2 | 650 | /* Skip in case we're parsing a string value */ |
reedas | 4:7ebc3d28bcb2 | 651 | if ( ( string_start != NULL ) && ( string_end == NULL ) ) |
reedas | 4:7ebc3d28bcb2 | 652 | { |
reedas | 4:7ebc3d28bcb2 | 653 | break; |
reedas | 4:7ebc3d28bcb2 | 654 | } |
reedas | 4:7ebc3d28bcb2 | 655 | |
reedas | 4:7ebc3d28bcb2 | 656 | array_counter--; |
reedas | 4:7ebc3d28bcb2 | 657 | |
reedas | 4:7ebc3d28bcb2 | 658 | |
reedas | 4:7ebc3d28bcb2 | 659 | if ( *( previous_token ) == START_OF_VALUE ) |
reedas | 4:7ebc3d28bcb2 | 660 | { |
reedas | 4:7ebc3d28bcb2 | 661 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 662 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 663 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 664 | } |
reedas | 4:7ebc3d28bcb2 | 665 | |
reedas | 4:7ebc3d28bcb2 | 666 | if ( *( current_input_token - space - 1 ) == COMMA_SEPARATOR ) |
reedas | 4:7ebc3d28bcb2 | 667 | { |
reedas | 4:7ebc3d28bcb2 | 668 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 669 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 670 | array_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 671 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 672 | } |
reedas | 4:7ebc3d28bcb2 | 673 | |
reedas | 4:7ebc3d28bcb2 | 674 | /* Ignore comma separators in values */ |
reedas | 4:7ebc3d28bcb2 | 675 | if ( ( string_start ) && ( string_end == NULL ) ) |
reedas | 4:7ebc3d28bcb2 | 676 | { |
reedas | 4:7ebc3d28bcb2 | 677 | break; |
reedas | 4:7ebc3d28bcb2 | 678 | } |
reedas | 4:7ebc3d28bcb2 | 679 | /* If this comma is within an array, it must be delimiting values, so extract the comma delimited value */ |
reedas | 4:7ebc3d28bcb2 | 680 | else if ( type == JSON_ARRAY_TYPE ) |
reedas | 4:7ebc3d28bcb2 | 681 | { |
reedas | 4:7ebc3d28bcb2 | 682 | /* If the token prior to the comma was a string token, then the delimited value must be a string */ |
reedas | 4:7ebc3d28bcb2 | 683 | if ( *previous_token == STRING_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 684 | { |
reedas | 4:7ebc3d28bcb2 | 685 | type = JSON_STRING_TYPE; |
reedas | 4:7ebc3d28bcb2 | 686 | |
reedas | 4:7ebc3d28bcb2 | 687 | /* Move token to point prior to string token and to last character of string value*/ |
reedas | 4:7ebc3d28bcb2 | 688 | value_end = previous_token - 1; |
reedas | 4:7ebc3d28bcb2 | 689 | value_start = string_start + 1; |
reedas | 4:7ebc3d28bcb2 | 690 | } |
reedas | 4:7ebc3d28bcb2 | 691 | else if ( *previous_token == TRUE_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 692 | { |
reedas | 4:7ebc3d28bcb2 | 693 | type = JSON_BOOLEAN_TYPE; |
reedas | 4:7ebc3d28bcb2 | 694 | |
reedas | 4:7ebc3d28bcb2 | 695 | value_end = previous_token + sizeof( "true" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 696 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 697 | } |
reedas | 4:7ebc3d28bcb2 | 698 | else if ( *previous_token == FALSE_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 699 | { |
reedas | 4:7ebc3d28bcb2 | 700 | type = JSON_BOOLEAN_TYPE; |
reedas | 4:7ebc3d28bcb2 | 701 | |
reedas | 4:7ebc3d28bcb2 | 702 | value_end = previous_token + sizeof( "false" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 703 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 704 | } |
reedas | 4:7ebc3d28bcb2 | 705 | else if ( *previous_token == NULL_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 706 | { |
reedas | 4:7ebc3d28bcb2 | 707 | type = JSON_NULL_TYPE; |
reedas | 4:7ebc3d28bcb2 | 708 | value_end = previous_token + sizeof( "null" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 709 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 710 | } |
reedas | 4:7ebc3d28bcb2 | 711 | else |
reedas | 4:7ebc3d28bcb2 | 712 | { |
reedas | 4:7ebc3d28bcb2 | 713 | char* start = NULL; |
reedas | 4:7ebc3d28bcb2 | 714 | char* end = NULL; |
reedas | 4:7ebc3d28bcb2 | 715 | uint8_t len = 0; |
reedas | 4:7ebc3d28bcb2 | 716 | /* Delimited values must be a NUMBER if they are not a string */ |
reedas | 4:7ebc3d28bcb2 | 717 | type = JSON_NUMBER_TYPE; |
reedas | 4:7ebc3d28bcb2 | 718 | |
reedas | 4:7ebc3d28bcb2 | 719 | /* Set value_end to point to current location */ |
reedas | 4:7ebc3d28bcb2 | 720 | value_end = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 721 | |
reedas | 4:7ebc3d28bcb2 | 722 | /* This must be a number value if not string. Arrays would have been picked up already by the end of array token */ |
reedas | 4:7ebc3d28bcb2 | 723 | type = JSON_NUMBER_TYPE; |
reedas | 4:7ebc3d28bcb2 | 724 | |
reedas | 4:7ebc3d28bcb2 | 725 | end = value_end; |
reedas | 4:7ebc3d28bcb2 | 726 | |
reedas | 4:7ebc3d28bcb2 | 727 | start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 728 | start++; |
reedas | 4:7ebc3d28bcb2 | 729 | end--; |
reedas | 4:7ebc3d28bcb2 | 730 | while ( *end == ' ' ) |
reedas | 4:7ebc3d28bcb2 | 731 | { |
reedas | 4:7ebc3d28bcb2 | 732 | end--; |
reedas | 4:7ebc3d28bcb2 | 733 | } |
reedas | 4:7ebc3d28bcb2 | 734 | while ( *start == ' ' ) |
reedas | 4:7ebc3d28bcb2 | 735 | { |
reedas | 4:7ebc3d28bcb2 | 736 | start++; |
reedas | 4:7ebc3d28bcb2 | 737 | } |
reedas | 4:7ebc3d28bcb2 | 738 | |
reedas | 4:7ebc3d28bcb2 | 739 | len = end - start + 1; |
reedas | 4:7ebc3d28bcb2 | 740 | |
reedas | 4:7ebc3d28bcb2 | 741 | if ( validate_array_value( start, end, len ) != CY_RSLT_SUCCESS ) |
reedas | 4:7ebc3d28bcb2 | 742 | { |
reedas | 4:7ebc3d28bcb2 | 743 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 744 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 745 | array_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 746 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 747 | } |
reedas | 4:7ebc3d28bcb2 | 748 | |
reedas | 4:7ebc3d28bcb2 | 749 | /* Point to last number. Keep moving the value end token back till you encounter a digit */ |
reedas | 4:7ebc3d28bcb2 | 750 | while ( ( *value_end < '0' ) || ( *value_end > '9' ) ) |
reedas | 4:7ebc3d28bcb2 | 751 | { |
reedas | 4:7ebc3d28bcb2 | 752 | value_end--; |
reedas | 4:7ebc3d28bcb2 | 753 | } |
reedas | 4:7ebc3d28bcb2 | 754 | |
reedas | 4:7ebc3d28bcb2 | 755 | /* Initialise the value_start pointer to point to last digit */ |
reedas | 4:7ebc3d28bcb2 | 756 | value_start = value_end; |
reedas | 4:7ebc3d28bcb2 | 757 | |
reedas | 4:7ebc3d28bcb2 | 758 | /* Increment value_start until you reach first number */ |
reedas | 4:7ebc3d28bcb2 | 759 | while ( ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) || ( *value_start == '.' ) || ( *value_start == '-' ) ) |
reedas | 4:7ebc3d28bcb2 | 760 | { |
reedas | 4:7ebc3d28bcb2 | 761 | value_start--; |
reedas | 4:7ebc3d28bcb2 | 762 | } |
reedas | 4:7ebc3d28bcb2 | 763 | |
reedas | 4:7ebc3d28bcb2 | 764 | /*Point to first number */ |
reedas | 4:7ebc3d28bcb2 | 765 | value_start++; |
reedas | 4:7ebc3d28bcb2 | 766 | } |
reedas | 4:7ebc3d28bcb2 | 767 | |
reedas | 4:7ebc3d28bcb2 | 768 | /* prepare JSON object */ |
reedas | 4:7ebc3d28bcb2 | 769 | json_object.object_string = NULL; |
reedas | 4:7ebc3d28bcb2 | 770 | json_object.object_string_length = 0; |
reedas | 4:7ebc3d28bcb2 | 771 | json_object.value_type = type; |
reedas | 4:7ebc3d28bcb2 | 772 | json_object.value = value_start; |
reedas | 4:7ebc3d28bcb2 | 773 | json_object.value_length = value_end - value_start + 1; |
reedas | 4:7ebc3d28bcb2 | 774 | |
reedas | 4:7ebc3d28bcb2 | 775 | if ( internal_json_callback != NULL ) |
reedas | 4:7ebc3d28bcb2 | 776 | { |
reedas | 4:7ebc3d28bcb2 | 777 | str_convertor( &json_object ); |
reedas | 4:7ebc3d28bcb2 | 778 | internal_json_callback( &json_object, internal_json_argument ); |
reedas | 4:7ebc3d28bcb2 | 779 | } |
reedas | 4:7ebc3d28bcb2 | 780 | |
reedas | 4:7ebc3d28bcb2 | 781 | string_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 782 | string_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 783 | value_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 784 | value_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 785 | type = JSON_ARRAY_TYPE; |
reedas | 4:7ebc3d28bcb2 | 786 | } |
reedas | 4:7ebc3d28bcb2 | 787 | |
reedas | 4:7ebc3d28bcb2 | 788 | type = UNKNOWN_JSON_TYPE; |
reedas | 4:7ebc3d28bcb2 | 789 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 790 | |
reedas | 4:7ebc3d28bcb2 | 791 | break; |
reedas | 4:7ebc3d28bcb2 | 792 | |
reedas | 4:7ebc3d28bcb2 | 793 | case START_OF_VALUE: |
reedas | 4:7ebc3d28bcb2 | 794 | |
reedas | 4:7ebc3d28bcb2 | 795 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 796 | { |
reedas | 4:7ebc3d28bcb2 | 797 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 798 | break; |
reedas | 4:7ebc3d28bcb2 | 799 | } |
reedas | 4:7ebc3d28bcb2 | 800 | |
reedas | 4:7ebc3d28bcb2 | 801 | if ( ( *( previous_token ) == OBJECT_START_TOKEN ) || ( *( previous_token ) == ARRAY_START_TOKEN ) ) |
reedas | 4:7ebc3d28bcb2 | 802 | { |
reedas | 4:7ebc3d28bcb2 | 803 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 804 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 805 | array_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 806 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 807 | } |
reedas | 4:7ebc3d28bcb2 | 808 | if ( string_end ) |
reedas | 4:7ebc3d28bcb2 | 809 | { |
reedas | 4:7ebc3d28bcb2 | 810 | /* prepare JSON object */ |
reedas | 4:7ebc3d28bcb2 | 811 | json_object.object_string = string_start + 1; |
reedas | 4:7ebc3d28bcb2 | 812 | json_object.object_string_length = string_end - string_start - 1; |
reedas | 4:7ebc3d28bcb2 | 813 | type = UNKNOWN_JSON_TYPE; |
reedas | 4:7ebc3d28bcb2 | 814 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 815 | } |
reedas | 4:7ebc3d28bcb2 | 816 | if ( value_start == NULL ) |
reedas | 4:7ebc3d28bcb2 | 817 | { |
reedas | 4:7ebc3d28bcb2 | 818 | value_start = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 819 | } |
reedas | 4:7ebc3d28bcb2 | 820 | |
reedas | 4:7ebc3d28bcb2 | 821 | break; |
reedas | 4:7ebc3d28bcb2 | 822 | |
reedas | 4:7ebc3d28bcb2 | 823 | case COMMA_SEPARATOR: |
reedas | 4:7ebc3d28bcb2 | 824 | |
reedas | 4:7ebc3d28bcb2 | 825 | if ( escape_token ) |
reedas | 4:7ebc3d28bcb2 | 826 | { |
reedas | 4:7ebc3d28bcb2 | 827 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 828 | break; |
reedas | 4:7ebc3d28bcb2 | 829 | } |
reedas | 4:7ebc3d28bcb2 | 830 | |
reedas | 4:7ebc3d28bcb2 | 831 | /* Ignore comma separators in values */ |
reedas | 4:7ebc3d28bcb2 | 832 | if ( ( string_start ) && ( string_end == NULL ) ) |
reedas | 4:7ebc3d28bcb2 | 833 | { |
reedas | 4:7ebc3d28bcb2 | 834 | break; |
reedas | 4:7ebc3d28bcb2 | 835 | } |
reedas | 4:7ebc3d28bcb2 | 836 | /* If this comma is within an array, it must be delimiting values, so extract the comma delimited value */ |
reedas | 4:7ebc3d28bcb2 | 837 | else if ( type == JSON_ARRAY_TYPE ) |
reedas | 4:7ebc3d28bcb2 | 838 | { |
reedas | 4:7ebc3d28bcb2 | 839 | /* If the token prior to the comma was a string token, then the delimited value must be a string */ |
reedas | 4:7ebc3d28bcb2 | 840 | if ( *previous_token == STRING_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 841 | { |
reedas | 4:7ebc3d28bcb2 | 842 | type = JSON_STRING_TYPE; |
reedas | 4:7ebc3d28bcb2 | 843 | |
reedas | 4:7ebc3d28bcb2 | 844 | /* Move token to point prior to string token and to last character of string value*/ |
reedas | 4:7ebc3d28bcb2 | 845 | value_end = previous_token - 1; |
reedas | 4:7ebc3d28bcb2 | 846 | value_start = string_start + 1; |
reedas | 4:7ebc3d28bcb2 | 847 | } |
reedas | 4:7ebc3d28bcb2 | 848 | else if ( *previous_token == TRUE_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 849 | { |
reedas | 4:7ebc3d28bcb2 | 850 | type = JSON_BOOLEAN_TYPE; |
reedas | 4:7ebc3d28bcb2 | 851 | |
reedas | 4:7ebc3d28bcb2 | 852 | value_end = previous_token + sizeof( "true" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 853 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 854 | } |
reedas | 4:7ebc3d28bcb2 | 855 | else if ( *previous_token == FALSE_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 856 | { |
reedas | 4:7ebc3d28bcb2 | 857 | type = JSON_BOOLEAN_TYPE; |
reedas | 4:7ebc3d28bcb2 | 858 | |
reedas | 4:7ebc3d28bcb2 | 859 | value_end = previous_token + sizeof( "false" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 860 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 861 | } |
reedas | 4:7ebc3d28bcb2 | 862 | else if ( *previous_token == NULL_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 863 | { |
reedas | 4:7ebc3d28bcb2 | 864 | type = JSON_NULL_TYPE; |
reedas | 4:7ebc3d28bcb2 | 865 | value_end = previous_token + sizeof( "null" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 866 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 867 | } |
reedas | 4:7ebc3d28bcb2 | 868 | else |
reedas | 4:7ebc3d28bcb2 | 869 | { |
reedas | 4:7ebc3d28bcb2 | 870 | /* Delimited values must be a NUMBER if they are not a string */ |
reedas | 4:7ebc3d28bcb2 | 871 | type = JSON_NUMBER_TYPE; |
reedas | 4:7ebc3d28bcb2 | 872 | |
reedas | 4:7ebc3d28bcb2 | 873 | /* Set value_end to point to current location */ |
reedas | 4:7ebc3d28bcb2 | 874 | value_end = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 875 | |
reedas | 4:7ebc3d28bcb2 | 876 | /* Point to last number. Keep moving the value end token back till you encounter a digit */ |
reedas | 4:7ebc3d28bcb2 | 877 | while ( ( *value_end < '0' ) || ( *value_end > '9' ) ) |
reedas | 4:7ebc3d28bcb2 | 878 | { |
reedas | 4:7ebc3d28bcb2 | 879 | value_end--; |
reedas | 4:7ebc3d28bcb2 | 880 | } |
reedas | 4:7ebc3d28bcb2 | 881 | |
reedas | 4:7ebc3d28bcb2 | 882 | /* Initialise the value_start pointer to point to last digit */ |
reedas | 4:7ebc3d28bcb2 | 883 | value_start = value_end; |
reedas | 4:7ebc3d28bcb2 | 884 | |
reedas | 4:7ebc3d28bcb2 | 885 | /* Increment value_start until you reach first number */ |
reedas | 4:7ebc3d28bcb2 | 886 | while ( ( ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) || ( *value_start == '.' ) || ( *value_start == '-' ) ) && ( *previous_token != *value_start ) ) |
reedas | 4:7ebc3d28bcb2 | 887 | { |
reedas | 4:7ebc3d28bcb2 | 888 | value_start--; |
reedas | 4:7ebc3d28bcb2 | 889 | } |
reedas | 4:7ebc3d28bcb2 | 890 | |
reedas | 4:7ebc3d28bcb2 | 891 | /*Point to first number */ |
reedas | 4:7ebc3d28bcb2 | 892 | value_start++; |
reedas | 4:7ebc3d28bcb2 | 893 | } |
reedas | 4:7ebc3d28bcb2 | 894 | |
reedas | 4:7ebc3d28bcb2 | 895 | /* prepare JSON object */ |
reedas | 4:7ebc3d28bcb2 | 896 | json_object.object_string = NULL; |
reedas | 4:7ebc3d28bcb2 | 897 | json_object.object_string_length = 0; |
reedas | 4:7ebc3d28bcb2 | 898 | json_object.value_type = type; |
reedas | 4:7ebc3d28bcb2 | 899 | json_object.value = value_start; |
reedas | 4:7ebc3d28bcb2 | 900 | json_object.value_length = value_end - value_start + 1; |
reedas | 4:7ebc3d28bcb2 | 901 | |
reedas | 4:7ebc3d28bcb2 | 902 | if ( internal_json_callback != NULL ) |
reedas | 4:7ebc3d28bcb2 | 903 | { |
reedas | 4:7ebc3d28bcb2 | 904 | str_convertor( &json_object ); |
reedas | 4:7ebc3d28bcb2 | 905 | internal_json_callback( &json_object, internal_json_argument ); |
reedas | 4:7ebc3d28bcb2 | 906 | } |
reedas | 4:7ebc3d28bcb2 | 907 | value_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 908 | value_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 909 | string_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 910 | string_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 911 | type = JSON_ARRAY_TYPE; |
reedas | 4:7ebc3d28bcb2 | 912 | } |
reedas | 4:7ebc3d28bcb2 | 913 | else if ( value_start ) |
reedas | 4:7ebc3d28bcb2 | 914 | { |
reedas | 4:7ebc3d28bcb2 | 915 | value_end = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 916 | |
reedas | 4:7ebc3d28bcb2 | 917 | /* Commas are only used to seperate values so this must indicate an end of value, which means last object information is for us */ |
reedas | 4:7ebc3d28bcb2 | 918 | if ( *previous_token == STRING_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 919 | { |
reedas | 4:7ebc3d28bcb2 | 920 | type = JSON_STRING_TYPE; |
reedas | 4:7ebc3d28bcb2 | 921 | |
reedas | 4:7ebc3d28bcb2 | 922 | value_end = previous_token - 1; |
reedas | 4:7ebc3d28bcb2 | 923 | value_start = string_start + 1; |
reedas | 4:7ebc3d28bcb2 | 924 | } |
reedas | 4:7ebc3d28bcb2 | 925 | else if ( *previous_token == ARRAY_END_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 926 | { |
reedas | 4:7ebc3d28bcb2 | 927 | if ( string_start ) |
reedas | 4:7ebc3d28bcb2 | 928 | { |
reedas | 4:7ebc3d28bcb2 | 929 | type = JSON_STRING_TYPE; |
reedas | 4:7ebc3d28bcb2 | 930 | value_start = string_start + 1; |
reedas | 4:7ebc3d28bcb2 | 931 | value_end = string_end - 1; |
reedas | 4:7ebc3d28bcb2 | 932 | } |
reedas | 4:7ebc3d28bcb2 | 933 | else |
reedas | 4:7ebc3d28bcb2 | 934 | { |
reedas | 4:7ebc3d28bcb2 | 935 | type = JSON_NUMBER_TYPE; |
reedas | 4:7ebc3d28bcb2 | 936 | |
reedas | 4:7ebc3d28bcb2 | 937 | /* Keep moving the value end token back till you encounter a digit */ |
reedas | 4:7ebc3d28bcb2 | 938 | while ( ( *value_end < '0' ) || ( *value_end > '9' ) ) |
reedas | 4:7ebc3d28bcb2 | 939 | { |
reedas | 4:7ebc3d28bcb2 | 940 | value_end--; |
reedas | 4:7ebc3d28bcb2 | 941 | } |
reedas | 4:7ebc3d28bcb2 | 942 | |
reedas | 4:7ebc3d28bcb2 | 943 | value_start = value_end; |
reedas | 4:7ebc3d28bcb2 | 944 | |
reedas | 4:7ebc3d28bcb2 | 945 | while ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) |
reedas | 4:7ebc3d28bcb2 | 946 | { |
reedas | 4:7ebc3d28bcb2 | 947 | value_start--; |
reedas | 4:7ebc3d28bcb2 | 948 | } |
reedas | 4:7ebc3d28bcb2 | 949 | |
reedas | 4:7ebc3d28bcb2 | 950 | value_start++; |
reedas | 4:7ebc3d28bcb2 | 951 | } |
reedas | 4:7ebc3d28bcb2 | 952 | } |
reedas | 4:7ebc3d28bcb2 | 953 | else if ( *previous_token == TRUE_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 954 | { |
reedas | 4:7ebc3d28bcb2 | 955 | type = JSON_BOOLEAN_TYPE; |
reedas | 4:7ebc3d28bcb2 | 956 | |
reedas | 4:7ebc3d28bcb2 | 957 | value_end = previous_token + sizeof( "true" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 958 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 959 | } |
reedas | 4:7ebc3d28bcb2 | 960 | else if ( *previous_token == FALSE_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 961 | { |
reedas | 4:7ebc3d28bcb2 | 962 | type = JSON_BOOLEAN_TYPE; |
reedas | 4:7ebc3d28bcb2 | 963 | |
reedas | 4:7ebc3d28bcb2 | 964 | value_end = previous_token + sizeof( "false" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 965 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 966 | } |
reedas | 4:7ebc3d28bcb2 | 967 | else if ( *previous_token == NULL_TOKEN ) |
reedas | 4:7ebc3d28bcb2 | 968 | { |
reedas | 4:7ebc3d28bcb2 | 969 | type = JSON_NULL_TYPE; |
reedas | 4:7ebc3d28bcb2 | 970 | value_end = previous_token + sizeof( "null" ) - 2; |
reedas | 4:7ebc3d28bcb2 | 971 | value_start = previous_token; |
reedas | 4:7ebc3d28bcb2 | 972 | } |
reedas | 4:7ebc3d28bcb2 | 973 | else |
reedas | 4:7ebc3d28bcb2 | 974 | { |
reedas | 4:7ebc3d28bcb2 | 975 | type = JSON_NUMBER_TYPE; |
reedas | 4:7ebc3d28bcb2 | 976 | |
reedas | 4:7ebc3d28bcb2 | 977 | /* Keep moving the value end token back till you encounter a digit */ |
reedas | 4:7ebc3d28bcb2 | 978 | while ( ( ( *value_end < '0' ) || ( *value_end > '9' ) ) ) |
reedas | 4:7ebc3d28bcb2 | 979 | { |
reedas | 4:7ebc3d28bcb2 | 980 | value_end--; |
reedas | 4:7ebc3d28bcb2 | 981 | } |
reedas | 4:7ebc3d28bcb2 | 982 | |
reedas | 4:7ebc3d28bcb2 | 983 | value_start = value_end; |
reedas | 4:7ebc3d28bcb2 | 984 | |
reedas | 4:7ebc3d28bcb2 | 985 | while ( ( ( *value_start >= '0' ) && ( *value_start <= '9' ) ) || ( *value_start == '.' ) || ( *value_start == '-' ) ) |
reedas | 4:7ebc3d28bcb2 | 986 | { |
reedas | 4:7ebc3d28bcb2 | 987 | value_start--; |
reedas | 4:7ebc3d28bcb2 | 988 | } |
reedas | 4:7ebc3d28bcb2 | 989 | |
reedas | 4:7ebc3d28bcb2 | 990 | value_start++; |
reedas | 4:7ebc3d28bcb2 | 991 | } |
reedas | 4:7ebc3d28bcb2 | 992 | |
reedas | 4:7ebc3d28bcb2 | 993 | json_object.value_type = type; |
reedas | 4:7ebc3d28bcb2 | 994 | json_object.value = value_start; |
reedas | 4:7ebc3d28bcb2 | 995 | json_object.value_length = value_end - value_start + 1; |
reedas | 4:7ebc3d28bcb2 | 996 | |
reedas | 4:7ebc3d28bcb2 | 997 | if ( internal_json_callback != NULL ) |
reedas | 4:7ebc3d28bcb2 | 998 | { |
reedas | 4:7ebc3d28bcb2 | 999 | str_convertor( &json_object ); |
reedas | 4:7ebc3d28bcb2 | 1000 | internal_json_callback( &json_object, internal_json_argument ); |
reedas | 4:7ebc3d28bcb2 | 1001 | } |
reedas | 4:7ebc3d28bcb2 | 1002 | |
reedas | 4:7ebc3d28bcb2 | 1003 | string_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 1004 | string_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 1005 | value_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 1006 | value_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 1007 | type = UNKNOWN_JSON_TYPE; |
reedas | 4:7ebc3d28bcb2 | 1008 | } |
reedas | 4:7ebc3d28bcb2 | 1009 | |
reedas | 4:7ebc3d28bcb2 | 1010 | previous_token = current_input_token; |
reedas | 4:7ebc3d28bcb2 | 1011 | |
reedas | 4:7ebc3d28bcb2 | 1012 | break; |
reedas | 4:7ebc3d28bcb2 | 1013 | |
reedas | 4:7ebc3d28bcb2 | 1014 | case ESCAPE_TOKEN: |
reedas | 4:7ebc3d28bcb2 | 1015 | /* Clear escape token flag, if the previous token is an escape token. Else set it */ |
reedas | 4:7ebc3d28bcb2 | 1016 | escape_token = ( escape_token == true ) ? false : true; |
reedas | 4:7ebc3d28bcb2 | 1017 | |
reedas | 4:7ebc3d28bcb2 | 1018 | break; |
reedas | 4:7ebc3d28bcb2 | 1019 | |
reedas | 4:7ebc3d28bcb2 | 1020 | default: |
reedas | 4:7ebc3d28bcb2 | 1021 | /* Reset escape token flag */ |
reedas | 4:7ebc3d28bcb2 | 1022 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 1023 | if ( ( object_counter == 0 ) && ( array_counter == 0 ) && ( *current_input_token != ' ' ) && |
reedas | 4:7ebc3d28bcb2 | 1024 | ( JSON_IS_NOT_ESC_CHAR ( *current_input_token ) ) ) |
reedas | 4:7ebc3d28bcb2 | 1025 | { |
reedas | 4:7ebc3d28bcb2 | 1026 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 1027 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 1028 | array_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 1029 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 1030 | } |
reedas | 4:7ebc3d28bcb2 | 1031 | break; |
reedas | 4:7ebc3d28bcb2 | 1032 | } // switch |
reedas | 4:7ebc3d28bcb2 | 1033 | |
reedas | 4:7ebc3d28bcb2 | 1034 | /* Counting spaces*/ |
reedas | 4:7ebc3d28bcb2 | 1035 | if ( *( current_input_token ) == ' ' ) |
reedas | 4:7ebc3d28bcb2 | 1036 | { |
reedas | 4:7ebc3d28bcb2 | 1037 | space++; |
reedas | 4:7ebc3d28bcb2 | 1038 | } |
reedas | 4:7ebc3d28bcb2 | 1039 | else |
reedas | 4:7ebc3d28bcb2 | 1040 | { |
reedas | 4:7ebc3d28bcb2 | 1041 | space = 0; |
reedas | 4:7ebc3d28bcb2 | 1042 | } |
reedas | 4:7ebc3d28bcb2 | 1043 | current_input_token++; |
reedas | 4:7ebc3d28bcb2 | 1044 | if ( ( *( current_input_token ) == '\0' ) && ( ( ( *( previous_token ) == COMMA_SEPARATOR ) || ( *( previous_token ) == STRING_TOKEN ) || ( *( previous_token ) == START_OF_VALUE ) || ( *( previous_token ) == ARRAY_START_TOKEN ) ) ) ) |
reedas | 4:7ebc3d28bcb2 | 1045 | { |
reedas | 4:7ebc3d28bcb2 | 1046 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 1047 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 1048 | array_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 1049 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 1050 | } |
reedas | 4:7ebc3d28bcb2 | 1051 | } // while |
reedas | 4:7ebc3d28bcb2 | 1052 | } // if |
reedas | 4:7ebc3d28bcb2 | 1053 | else |
reedas | 4:7ebc3d28bcb2 | 1054 | { |
reedas | 4:7ebc3d28bcb2 | 1055 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 1056 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 1057 | } |
reedas | 4:7ebc3d28bcb2 | 1058 | |
reedas | 4:7ebc3d28bcb2 | 1059 | /* This means that a closing brace has not been found for an object. This data is split across packets */ |
reedas | 4:7ebc3d28bcb2 | 1060 | if ( object_counter || array_counter ) |
reedas | 4:7ebc3d28bcb2 | 1061 | { |
reedas | 4:7ebc3d28bcb2 | 1062 | memset( packet_backup, 0x0, sizeof( packet_backup ) ); |
reedas | 4:7ebc3d28bcb2 | 1063 | |
reedas | 4:7ebc3d28bcb2 | 1064 | // Copy everything from the most recent unfinished object onwards |
reedas | 4:7ebc3d28bcb2 | 1065 | |
reedas | 4:7ebc3d28bcb2 | 1066 | number_of_bytes_backed_up = end_of_input - most_recent_object_marker; |
reedas | 4:7ebc3d28bcb2 | 1067 | |
reedas | 4:7ebc3d28bcb2 | 1068 | memcpy( packet_backup, most_recent_object_marker, number_of_bytes_backed_up ); |
reedas | 4:7ebc3d28bcb2 | 1069 | |
reedas | 4:7ebc3d28bcb2 | 1070 | |
reedas | 4:7ebc3d28bcb2 | 1071 | incomplete_response = true; |
reedas | 4:7ebc3d28bcb2 | 1072 | valid_json_string = CY_RSLT_JSON_GENERIC_ERROR; |
reedas | 4:7ebc3d28bcb2 | 1073 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 1074 | |
reedas | 4:7ebc3d28bcb2 | 1075 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 1076 | } |
reedas | 4:7ebc3d28bcb2 | 1077 | |
reedas | 4:7ebc3d28bcb2 | 1078 | |
reedas | 4:7ebc3d28bcb2 | 1079 | memset( &parent_json_object, 0x0, sizeof( parent_json_object ) ); |
reedas | 4:7ebc3d28bcb2 | 1080 | |
reedas | 4:7ebc3d28bcb2 | 1081 | incomplete_response = false; |
reedas | 4:7ebc3d28bcb2 | 1082 | |
reedas | 4:7ebc3d28bcb2 | 1083 | object_counter = 0; |
reedas | 4:7ebc3d28bcb2 | 1084 | |
reedas | 4:7ebc3d28bcb2 | 1085 | string_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 1086 | string_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 1087 | |
reedas | 4:7ebc3d28bcb2 | 1088 | value_start = NULL; |
reedas | 4:7ebc3d28bcb2 | 1089 | value_end = NULL; |
reedas | 4:7ebc3d28bcb2 | 1090 | |
reedas | 4:7ebc3d28bcb2 | 1091 | type = UNKNOWN_JSON_TYPE; |
reedas | 4:7ebc3d28bcb2 | 1092 | |
reedas | 4:7ebc3d28bcb2 | 1093 | escape_token = false; |
reedas | 4:7ebc3d28bcb2 | 1094 | |
reedas | 4:7ebc3d28bcb2 | 1095 | previous_token = NULL; |
reedas | 4:7ebc3d28bcb2 | 1096 | |
reedas | 4:7ebc3d28bcb2 | 1097 | return valid_json_string; |
reedas | 4:7ebc3d28bcb2 | 1098 | } |