Jeon byungchul
/
aws-iot-example
this is fork and i will modify for STM32
Fork of AWS-test by
Embed:
(wiki syntax)
Show/hide line numbers
jsmn.c
Go to the documentation of this file.
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 "jsmn.h" 00032 00033 /** 00034 * Allocates a fresh unused token from the token pull. 00035 */ 00036 static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 00037 jsmntok_t *tokens, size_t num_tokens) { 00038 jsmntok_t *tok; 00039 if (parser->toknext >= num_tokens) { 00040 return NULL; 00041 } 00042 tok = &tokens[parser->toknext++]; 00043 tok->start = tok->end = -1; 00044 tok->size = 0; 00045 #ifdef JSMN_PARENT_LINKS 00046 tok->parent = -1; 00047 #endif 00048 return tok; 00049 } 00050 00051 /** 00052 * Fills token type and boundaries. 00053 */ 00054 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 00055 int start, int end) { 00056 token->type = type; 00057 token->start = start; 00058 token->end = end; 00059 token->size = 0; 00060 } 00061 00062 /** 00063 * Fills next available token with JSON primitive. 00064 */ 00065 static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, 00066 size_t len, jsmntok_t *tokens, size_t num_tokens) { 00067 jsmntok_t *token; 00068 int start; 00069 00070 start = parser->pos; 00071 00072 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 00073 switch (js[parser->pos]) { 00074 #ifndef JSMN_STRICT 00075 /* In strict mode primitive must be followed by "," or "}" or "]" */ 00076 case ':': 00077 #endif 00078 case '\t' : case '\r' : case '\n' : case ' ' : 00079 case ',' : case ']' : case '}' : 00080 goto found; 00081 } 00082 if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 00083 parser->pos = start; 00084 return JSMN_ERROR_INVAL; 00085 } 00086 } 00087 #ifdef JSMN_STRICT 00088 /* In strict mode primitive must be followed by a comma/object/array */ 00089 parser->pos = start; 00090 return JSMN_ERROR_PART; 00091 #endif 00092 00093 found: 00094 if (tokens == NULL) { 00095 parser->pos--; 00096 return 0; 00097 } 00098 token = jsmn_alloc_token(parser, tokens, num_tokens); 00099 if (token == NULL) { 00100 parser->pos = start; 00101 return JSMN_ERROR_NOMEM; 00102 } 00103 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 00104 #ifdef JSMN_PARENT_LINKS 00105 token->parent = parser->toksuper; 00106 #endif 00107 parser->pos--; 00108 return 0; 00109 } 00110 00111 /** 00112 * Fills next token with JSON string. 00113 */ 00114 static int jsmn_parse_string(jsmn_parser *parser, const char *js, 00115 size_t len, jsmntok_t *tokens, size_t num_tokens) { 00116 jsmntok_t *token; 00117 00118 int start = parser->pos; 00119 00120 parser->pos++; 00121 00122 /* Skip starting quote */ 00123 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 00124 char c = js[parser->pos]; 00125 00126 /* Quote: end of string */ 00127 if (c == '\"') { 00128 if (tokens == NULL) { 00129 return 0; 00130 } 00131 token = jsmn_alloc_token(parser, tokens, num_tokens); 00132 if (token == NULL) { 00133 parser->pos = start; 00134 return JSMN_ERROR_NOMEM; 00135 } 00136 jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 00137 #ifdef JSMN_PARENT_LINKS 00138 token->parent = parser->toksuper; 00139 #endif 00140 return 0; 00141 } 00142 00143 /* Backslash: Quoted symbol expected */ 00144 if (c == '\\' && parser->pos + 1 < len) { 00145 int i; 00146 parser->pos++; 00147 switch (js[parser->pos]) { 00148 /* Allowed escaped symbols */ 00149 case '\"': case '/' : case '\\' : case 'b' : 00150 case 'f' : case 'r' : case 'n' : case 't' : 00151 break; 00152 /* Allows escaped symbol \uXXXX */ 00153 case 'u': 00154 parser->pos++; 00155 for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { 00156 /* If it isn't a hex character we have an error */ 00157 if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ 00158 (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ 00159 (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ 00160 parser->pos = start; 00161 return JSMN_ERROR_INVAL; 00162 } 00163 parser->pos++; 00164 } 00165 parser->pos--; 00166 break; 00167 /* Unexpected symbol */ 00168 default: 00169 parser->pos = start; 00170 return JSMN_ERROR_INVAL; 00171 } 00172 } 00173 } 00174 parser->pos = start; 00175 return JSMN_ERROR_PART; 00176 } 00177 00178 /** 00179 * Parse JSON string and fill tokens. 00180 */ 00181 int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 00182 jsmntok_t *tokens, unsigned int num_tokens) { 00183 int r; 00184 int i; 00185 jsmntok_t *token; 00186 int count = parser->toknext; 00187 00188 for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { 00189 char c; 00190 jsmntype_t type; 00191 00192 c = js[parser->pos]; 00193 switch (c) { 00194 case '{': case '[': 00195 count++; 00196 if (tokens == NULL) { 00197 break; 00198 } 00199 token = jsmn_alloc_token(parser, tokens, num_tokens); 00200 if (token == NULL) 00201 return JSMN_ERROR_NOMEM; 00202 if (parser->toksuper != -1) { 00203 tokens[parser->toksuper].size++; 00204 #ifdef JSMN_PARENT_LINKS 00205 token->parent = parser->toksuper; 00206 #endif 00207 } 00208 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 00209 token->start = parser->pos; 00210 parser->toksuper = parser->toknext - 1; 00211 break; 00212 case '}': case ']': 00213 if (tokens == NULL) 00214 break; 00215 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 00216 #ifdef JSMN_PARENT_LINKS 00217 if (parser->toknext < 1) { 00218 return JSMN_ERROR_INVAL; 00219 } 00220 token = &tokens[parser->toknext - 1]; 00221 for (;;) { 00222 if (token->start != -1 && token->end == -1) { 00223 if (token->type != type) { 00224 return JSMN_ERROR_INVAL; 00225 } 00226 token->end = parser->pos + 1; 00227 parser->toksuper = token->parent; 00228 break; 00229 } 00230 if (token->parent == -1) { 00231 break; 00232 } 00233 token = &tokens[token->parent]; 00234 } 00235 #else 00236 for (i = parser->toknext - 1; i >= 0; i--) { 00237 token = &tokens[i]; 00238 if (token->start != -1 && token->end == -1) { 00239 if (token->type != type) { 00240 return JSMN_ERROR_INVAL; 00241 } 00242 parser->toksuper = -1; 00243 token->end = parser->pos + 1; 00244 break; 00245 } 00246 } 00247 /* Error if unmatched closing bracket */ 00248 if (i == -1) return JSMN_ERROR_INVAL; 00249 for (; i >= 0; i--) { 00250 token = &tokens[i]; 00251 if (token->start != -1 && token->end == -1) { 00252 parser->toksuper = i; 00253 break; 00254 } 00255 } 00256 #endif 00257 break; 00258 case '\"': 00259 r = jsmn_parse_string(parser, js, len, tokens, num_tokens); 00260 if (r < 0) return r; 00261 count++; 00262 if (parser->toksuper != -1 && tokens != NULL) 00263 tokens[parser->toksuper].size++; 00264 break; 00265 case '\t' : case '\r' : case '\n' : case ' ': 00266 break; 00267 case ':': 00268 parser->toksuper = parser->toknext - 1; 00269 break; 00270 case ',': 00271 if (tokens != NULL && parser->toksuper != -1 && 00272 tokens[parser->toksuper].type != JSMN_ARRAY && 00273 tokens[parser->toksuper].type != JSMN_OBJECT) { 00274 #ifdef JSMN_PARENT_LINKS 00275 parser->toksuper = tokens[parser->toksuper].parent; 00276 #else 00277 for (i = parser->toknext - 1; i >= 0; i--) { 00278 if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { 00279 if (tokens[i].start != -1 && tokens[i].end == -1) { 00280 parser->toksuper = i; 00281 break; 00282 } 00283 } 00284 } 00285 #endif 00286 } 00287 break; 00288 #ifdef JSMN_STRICT 00289 /* In strict mode primitives are: numbers and booleans */ 00290 case '-': case '0': case '1' : case '2': case '3' : case '4': 00291 case '5': case '6': case '7' : case '8': case '9': 00292 case 't': case 'f': case 'n' : 00293 /* And they must not be keys of the object */ 00294 if (tokens != NULL && parser->toksuper != -1) { 00295 jsmntok_t *t = &tokens[parser->toksuper]; 00296 if (t->type == JSMN_OBJECT || 00297 (t->type == JSMN_STRING && t->size != 0)) { 00298 return JSMN_ERROR_INVAL; 00299 } 00300 } 00301 #else 00302 /* In non-strict mode every unquoted value is a primitive */ 00303 default: 00304 #endif 00305 r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); 00306 if (r < 0) return r; 00307 count++; 00308 if (parser->toksuper != -1 && tokens != NULL) 00309 tokens[parser->toksuper].size++; 00310 break; 00311 00312 #ifdef JSMN_STRICT 00313 /* Unexpected char in strict mode */ 00314 default: 00315 return JSMN_ERROR_INVAL; 00316 #endif 00317 } 00318 } 00319 00320 if (tokens != NULL) { 00321 for (i = parser->toknext - 1; i >= 0; i--) { 00322 /* Unmatched opened object or array */ 00323 if (tokens[i].start != -1 && tokens[i].end == -1) { 00324 return JSMN_ERROR_PART; 00325 } 00326 } 00327 } 00328 00329 return count; 00330 } 00331 00332 /** 00333 * Creates a new parser based over a given buffer with an array of tokens 00334 * available. 00335 */ 00336 void jsmn_init(jsmn_parser *parser) { 00337 parser->pos = 0; 00338 parser->toknext = 0; 00339 parser->toksuper = -1; 00340 } 00341
Generated on Tue Jul 12 2022 11:16:37 by 1.7.2