Demo application for using the AT&T IoT Starter Kit Powered by AWS.
Dependencies: SDFileSystem
Fork of ATT_AWS_IoT_demo by
jsmn.cpp
00001 /* 00002 * Copyright (c) 2010 Serge A. Zaitsev 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 * THE SOFTWARE. 00021 */ 00022 00023 /** 00024 * @file jsmn.c 00025 * @brief Implementation of the JSMN (Jasmine) JSON parser. 00026 * 00027 * For more information on JSMN: 00028 * @see http://zserge.com/jsmn.html 00029 */ 00030 00031 #include <stdlib.h> 00032 00033 #include "jsmn.h" 00034 00035 /** 00036 * Allocates a fresh unused token from the token pull. 00037 */ 00038 static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, 00039 size_t num_tokens) { 00040 jsmntok_t *tok; 00041 if (parser->toknext >= num_tokens) { 00042 return NULL; 00043 } 00044 tok = &tokens[parser->toknext++]; 00045 tok->start = tok->end = -1; 00046 tok->size = 0; 00047 #ifdef JSMN_PARENT_LINKS 00048 tok->parent = -1; 00049 #endif 00050 return tok; 00051 } 00052 00053 /** 00054 * Fills token type and boundaries. 00055 */ 00056 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, int start, 00057 int end) { 00058 token->type = type; 00059 token->start = start; 00060 token->end = end; 00061 token->size = 0; 00062 } 00063 00064 /** 00065 * Fills next available token with JSON primitive. 00066 */ 00067 static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, 00068 size_t len, jsmntok_t *tokens, size_t num_tokens) { 00069 jsmntok_t *token; 00070 int start; 00071 00072 start = parser->pos; 00073 00074 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 00075 switch (js[parser->pos]) { 00076 #ifndef JSMN_STRICT 00077 /* In strict mode primitive must be followed by "," or "}" or "]" */ 00078 case ':': 00079 #endif 00080 case '\t': 00081 case '\r': 00082 case '\n': 00083 case ' ': 00084 case ',': 00085 case ']': 00086 case '}': 00087 goto found; 00088 } 00089 if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 00090 parser->pos = start; 00091 return JSMN_ERROR_INVAL; 00092 } 00093 } 00094 #ifdef JSMN_STRICT 00095 /* In strict mode primitive must be followed by a comma/object/array */ 00096 parser->pos = start; 00097 return JSMN_ERROR_PART; 00098 #endif 00099 00100 found: if (tokens == NULL) { 00101 parser->pos--; 00102 return (jsmnerr_t) 0; 00103 } 00104 token = jsmn_alloc_token(parser, tokens, num_tokens); 00105 if (token == NULL) { 00106 parser->pos = start; 00107 return JSMN_ERROR_NOMEM; 00108 } 00109 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 00110 #ifdef JSMN_PARENT_LINKS 00111 token->parent = parser->toksuper; 00112 #endif 00113 parser->pos--; 00114 return (jsmnerr_t) 0; 00115 } 00116 00117 /** 00118 * Filsl next token with JSON string. 00119 */ 00120 static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, 00121 size_t len, jsmntok_t *tokens, size_t num_tokens) { 00122 jsmntok_t *token; 00123 00124 int start = parser->pos; 00125 00126 parser->pos++; 00127 00128 /* Skip starting quote */ 00129 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 00130 char c = js[parser->pos]; 00131 00132 /* Quote: end of string */ 00133 if (c == '\"') { 00134 if (tokens == NULL) { 00135 return (jsmnerr_t) 0; 00136 } 00137 token = jsmn_alloc_token(parser, tokens, num_tokens); 00138 if (token == NULL) { 00139 parser->pos = start; 00140 return JSMN_ERROR_NOMEM; 00141 } 00142 jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); 00143 #ifdef JSMN_PARENT_LINKS 00144 token->parent = parser->toksuper; 00145 #endif 00146 return (jsmnerr_t) 0; 00147 } 00148 00149 /* Backslash: Quoted symbol expected */ 00150 if (c == '\\') { 00151 parser->pos++; 00152 switch (js[parser->pos]) { 00153 /* Allowed escaped symbols */ 00154 case '\"': 00155 case '/': 00156 case '\\': 00157 case 'b': 00158 case 'f': 00159 case 'r': 00160 case 'n': 00161 case 't': 00162 break; 00163 /* Allows escaped symbol \uXXXX */ 00164 case 'u': 00165 parser->pos++; 00166 int i; 00167 for (i = 0; i < 4 && js[parser->pos] != '\0'; i++) { 00168 /* If it isn't a hex character we have an error */ 00169 if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ 00170 (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ 00171 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ 00172 parser->pos = start; 00173 return JSMN_ERROR_INVAL; 00174 } 00175 parser->pos++; 00176 } 00177 parser->pos--; 00178 break; 00179 /* Unexpected symbol */ 00180 default: 00181 parser->pos = start; 00182 return JSMN_ERROR_INVAL; 00183 } 00184 } 00185 } 00186 parser->pos = start; 00187 return JSMN_ERROR_PART; 00188 } 00189 00190 /** 00191 * Parse JSON string and fill tokens. 00192 */ 00193 jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 00194 jsmntok_t *tokens, unsigned int num_tokens) { 00195 jsmnerr_t r; 00196 int i; 00197 jsmntok_t *token; 00198 int count = 0; 00199 00200 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 00201 char c; 00202 jsmntype_t type; 00203 00204 c = js[parser->pos]; 00205 switch (c) { 00206 case '{': 00207 case '[': 00208 count++; 00209 if (tokens == NULL) { 00210 break; 00211 } 00212 token = jsmn_alloc_token(parser, tokens, num_tokens); 00213 if (token == NULL) 00214 return JSMN_ERROR_NOMEM; 00215 if (parser->toksuper != -1) { 00216 tokens[parser->toksuper].size++; 00217 #ifdef JSMN_PARENT_LINKS 00218 token->parent = parser->toksuper; 00219 #endif 00220 } 00221 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 00222 token->start = parser->pos; 00223 parser->toksuper = parser->toknext - 1; 00224 break; 00225 case '}': 00226 case ']': 00227 if (tokens == NULL) 00228 break; 00229 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 00230 #ifdef JSMN_PARENT_LINKS 00231 if (parser->toknext < 1) { 00232 return JSMN_ERROR_INVAL; 00233 } 00234 token = &tokens[parser->toknext - 1]; 00235 for (;;) { 00236 if (token->start != -1 && token->end == -1) { 00237 if (token->type != type) { 00238 return JSMN_ERROR_INVAL; 00239 } 00240 token->end = parser->pos + 1; 00241 parser->toksuper = token->parent; 00242 break; 00243 } 00244 if (token->parent == -1) { 00245 break; 00246 } 00247 token = &tokens[token->parent]; 00248 } 00249 #else 00250 for (i = parser->toknext - 1; i >= 0; i--) { 00251 token = &tokens[i]; 00252 if (token->start != -1 && token->end == -1) { 00253 if (token->type != type) { 00254 return JSMN_ERROR_INVAL; 00255 } 00256 parser->toksuper = -1; 00257 token->end = parser->pos + 1; 00258 break; 00259 } 00260 } 00261 /* Error if unmatched closing bracket */ 00262 if (i == -1) 00263 return JSMN_ERROR_INVAL; 00264 for (; i >= 0; i--) { 00265 token = &tokens[i]; 00266 if (token->start != -1 && token->end == -1) { 00267 parser->toksuper = i; 00268 break; 00269 } 00270 } 00271 #endif 00272 break; 00273 case '\"': 00274 r = jsmn_parse_string(parser, js, len, tokens, num_tokens); 00275 if (r < 0) 00276 return r; 00277 count++; 00278 if (parser->toksuper != -1 && tokens != NULL) 00279 tokens[parser->toksuper].size++; 00280 break; 00281 case '\t': 00282 case '\r': 00283 case '\n': 00284 case ':': 00285 case ',': 00286 case ' ': 00287 break; 00288 #ifdef JSMN_STRICT 00289 /* In strict mode primitives are: numbers and booleans */ 00290 case '-': 00291 case '0': 00292 case '1': 00293 case '2': 00294 case '3': 00295 case '4': 00296 case '5': 00297 case '6': 00298 case '7': 00299 case '8': 00300 case '9': 00301 case 't': 00302 case 'f': 00303 case 'n': 00304 #else 00305 /* In non-strict mode every unquoted value is a primitive */ 00306 default: 00307 #endif 00308 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); 00309 if (r < 0) 00310 return r; 00311 count++; 00312 if (parser->toksuper != -1 && tokens != NULL) 00313 tokens[parser->toksuper].size++; 00314 break; 00315 00316 #ifdef JSMN_STRICT 00317 /* Unexpected char in strict mode */ 00318 default: 00319 return JSMN_ERROR_INVAL; 00320 #endif 00321 } 00322 } 00323 00324 for (i = parser->toknext - 1; i >= 0; i--) { 00325 /* Unmatched opened object or array */ 00326 if (tokens[i].start != -1 && tokens[i].end == -1) { 00327 return JSMN_ERROR_PART; 00328 } 00329 } 00330 00331 return (jsmnerr_t) count; 00332 } 00333 00334 /** 00335 * Creates a new parser based over a given buffer with an array of tokens 00336 * available. 00337 */ 00338 void jsmn_init(jsmn_parser *parser) { 00339 parser->pos = 0; 00340 parser->toknext = 0; 00341 parser->toksuper = -1; 00342 } 00343
Generated on Tue Jul 12 2022 22:13:20 by 1.7.2