iot_water_monitor_v2
Dependencies: easy-connect-v16 Watchdog FP MQTTPacket RecordType-v-16 watersenor_and_temp_code
jsmn.c
00001 /* Author: Faheem Inayat 00002 * Created by "Night Crue" Team @ TechShop San Jose, CA 00003 * 00004 * --- DISCLAIMER --- 00005 * This code is a modified version of original JSMN lirary, written by 00006 * *** Serge A. Zaitsev *** 00007 * and hosted at https://github.com/zserge/jsmn 00008 * Any modification to the original source is not guaranteed to be included 00009 * in this version. As of writing of this file, the original source is 00010 * licensed under MIT License 00011 * (http://www.opensource.org/licenses/mit-license.php). 00012 */ 00013 00014 #include "jsmn.h" 00015 00016 /** 00017 * Allocates a fresh unused token from the token pull. 00018 */ 00019 static jsmntok_t *jsmn_alloc_token ( jsmn_parser *parser, jsmntok_t *tokens, size_t num_tokens ) 00020 { 00021 jsmntok_t *tok; 00022 if ( parser->toknext >= num_tokens ) 00023 { 00024 return NULL ; 00025 } 00026 tok = &tokens [ parser->toknext++ ]; 00027 tok->start = tok->end = -1; 00028 tok->childCount = 0; 00029 tok->parent = -1; 00030 return tok; 00031 } 00032 00033 /** 00034 * Fills token type and boundaries. 00035 */ 00036 static void jsmn_fill_token ( jsmntok_t *token, jsmntype_t type, int start, int end ) 00037 { 00038 token->type = type; 00039 token->start = start; 00040 token->end = end; 00041 token->childCount = 0; 00042 } 00043 00044 /** 00045 * Fills next available token with JSON primitive. 00046 */ 00047 static int jsmn_parse_primitive ( jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens ) 00048 { 00049 jsmntok_t *token; 00050 int start; 00051 00052 start = parser->pos; 00053 00054 for ( ; parser->pos < len && js [ parser->pos ] != '\0'; parser->pos++ ) 00055 { 00056 switch ( js [ parser->pos ] ) 00057 { 00058 case '\t': 00059 case '\r': 00060 case '\n': 00061 case ' ': 00062 case ',': 00063 case ']': 00064 case '}': 00065 goto found; 00066 } 00067 if ( js [ parser->pos ] < 32 || js [ parser->pos ] >= 127 ) 00068 { 00069 parser->pos = start; 00070 return JSMN_ERROR_INVAL; 00071 } 00072 } 00073 /* primitive must be followed by a comma/object/array */ 00074 parser->pos = start; 00075 return JSMN_ERROR_PART; 00076 00077 found: if ( tokens == NULL ) 00078 { 00079 parser->pos--; 00080 return 0; 00081 } 00082 token = jsmn_alloc_token ( parser, tokens, num_tokens ); 00083 if ( token == NULL ) 00084 { 00085 parser->pos = start; 00086 return JSMN_ERROR_NOMEM; 00087 } 00088 jsmn_fill_token ( token, JSMN_PRIMITIVE, start, parser->pos ); 00089 token->parent = parser->toksuper; 00090 parser->pos--; 00091 return 0; 00092 } 00093 00094 /** 00095 * Fills next token with JSON string. 00096 */ 00097 static int jsmn_parse_string ( jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens, unsigned char isKey ) 00098 { 00099 jsmntok_t *token; 00100 00101 int start = parser->pos; 00102 00103 parser->pos++; 00104 00105 /* Skip starting quote */ 00106 for ( ; parser->pos < len && js [ parser->pos ] != '\0'; parser->pos++ ) 00107 { 00108 char c = js [ parser->pos ]; 00109 00110 /* Quote: end of string */ 00111 if ( c == '\"' ) 00112 { 00113 if ( tokens == NULL ) 00114 { 00115 return 0; 00116 } 00117 token = jsmn_alloc_token ( parser, tokens, num_tokens ); 00118 if ( token == NULL ) 00119 { 00120 parser->pos = start; 00121 return JSMN_ERROR_NOMEM; 00122 } 00123 if ( isKey == 1 ) 00124 { 00125 jsmn_fill_token ( token, JSMN_KEY, start + 1, parser->pos ); 00126 } 00127 else 00128 { 00129 jsmn_fill_token ( token, JSMN_STRING, start + 1, parser->pos ); 00130 } 00131 token->parent = parser->toksuper; 00132 return 0; 00133 } 00134 00135 /* Backslash: Quoted symbol expected */ 00136 if ( c == '\\' && parser->pos + 1 < len ) 00137 { 00138 int i; 00139 parser->pos++; 00140 switch ( js [ parser->pos ] ) 00141 { 00142 /* Allowed escaped symbols */ 00143 case '\"': 00144 case '/': 00145 case '\\': 00146 case 'b': 00147 case 'f': 00148 case 'r': 00149 case 'n': 00150 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 { 00157 /* If it isn't a hex character we have an error */ 00158 if ( ! ( ( js [ parser->pos ] >= 48 && js [ parser->pos ] <= 57 ) || /* 0-9 */ 00159 ( js [ parser->pos ] >= 65 && js [ parser->pos ] <= 70 ) 00160 || /* A-F */ 00161 ( js [ parser->pos ] >= 97 && js [ parser->pos ] <= 102 ) ) ) 00162 { /* a-f */ 00163 parser->pos = start; 00164 return JSMN_ERROR_INVAL; 00165 } 00166 parser->pos++; 00167 } 00168 parser->pos--; 00169 break; 00170 /* Unexpected symbol */ 00171 default: 00172 parser->pos = start; 00173 return JSMN_ERROR_INVAL; 00174 } 00175 } 00176 } 00177 parser->pos = start; 00178 return JSMN_ERROR_PART; 00179 } 00180 00181 /** 00182 * Parse JSON string and fill tokens. 00183 */ 00184 int jsmn_parse ( jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, unsigned int num_tokens ) 00185 { 00186 int r; 00187 int i; 00188 jsmntok_t *token; 00189 int count = parser->toknext; 00190 00191 unsigned char isKey = 1; 00192 00193 for ( ; parser->pos < len && js [ parser->pos ] != '\0'; parser->pos++ ) 00194 { 00195 char c; 00196 jsmntype_t type; 00197 00198 c = js [ parser->pos ]; 00199 switch ( c ) 00200 { 00201 case '{': 00202 case '[': 00203 count++; 00204 if ( tokens == NULL ) 00205 { 00206 break; 00207 } 00208 token = jsmn_alloc_token ( parser, tokens, num_tokens ); 00209 if ( token == NULL ) 00210 return JSMN_ERROR_NOMEM; 00211 if ( parser->toksuper != -1 ) 00212 { 00213 tokens [ parser->toksuper ].childCount++; 00214 token->parent = parser->toksuper; 00215 } 00216 token->type = ( c == '{' ? JSMN_OBJECT : JSMN_ARRAY ); 00217 token->start = parser->pos; 00218 parser->toksuper = parser->toknext - 1; 00219 if ( token->type == JSMN_OBJECT ) 00220 { 00221 isKey = 1; 00222 } 00223 break; 00224 case '}': 00225 case ']': 00226 if ( tokens == NULL ) 00227 break; 00228 type = ( c == '}' ? JSMN_OBJECT : JSMN_ARRAY ); 00229 if ( parser->toknext < 1 ) 00230 { 00231 return JSMN_ERROR_INVAL; 00232 } 00233 token = &tokens [ parser->toknext - 1 ]; 00234 for ( ;; ) 00235 { 00236 if ( token->start != -1 && token->end == -1 ) 00237 { 00238 if ( token->type != type ) 00239 { 00240 return JSMN_ERROR_INVAL; 00241 } 00242 token->end = parser->pos + 1; 00243 parser->toksuper = token->parent; 00244 break; 00245 } 00246 if ( token->parent == -1 ) 00247 { 00248 break; 00249 } 00250 token = &tokens [ token->parent ]; 00251 } 00252 break; 00253 case '\"': 00254 r = jsmn_parse_string ( parser, js, len, tokens, num_tokens, isKey ); 00255 if ( r < 0 ) 00256 return r; 00257 count++; 00258 if ( parser->toksuper != -1 && tokens != NULL ) 00259 tokens [ parser->toksuper ].childCount++; 00260 break; 00261 case '\t': 00262 case '\r': 00263 case '\n': 00264 case ' ': 00265 break; 00266 case ':': 00267 isKey = 0; 00268 parser->toksuper = parser->toknext - 1; 00269 break; 00270 case ',': 00271 if ( tokens != NULL && parser->toksuper != -1 && tokens [ parser->toksuper ].type != JSMN_ARRAY && tokens [ parser->toksuper ].type != JSMN_OBJECT ) 00272 { 00273 parser->toksuper = tokens [ parser->toksuper ].parent; 00274 } 00275 isKey = 1; 00276 break; 00277 /* In strict mode primitives are: numbers and booleans */ 00278 case '-': 00279 case '0': 00280 case '1': 00281 case '2': 00282 case '3': 00283 case '4': 00284 case '5': 00285 case '6': 00286 case '7': 00287 case '8': 00288 case '9': 00289 case 't': 00290 case 'f': 00291 case 'n': 00292 /* And they must not be keys of the object */ 00293 if ( tokens != NULL && parser->toksuper != -1 ) 00294 { 00295 jsmntok_t *t = &tokens [ parser->toksuper ]; 00296 if ( t->type == JSMN_OBJECT || ( t->type == JSMN_STRING && t->childCount != 0 ) ) 00297 { 00298 return JSMN_ERROR_INVAL; 00299 } 00300 } 00301 r = jsmn_parse_primitive ( parser, js, len, tokens, num_tokens ); 00302 if ( r < 0 ) 00303 return r; 00304 count++; 00305 if ( parser->toksuper != -1 && tokens != NULL ) 00306 tokens [ parser->toksuper ].childCount++; 00307 break; 00308 00309 /* Unexpected char in strict mode */ 00310 default: 00311 return JSMN_ERROR_INVAL; 00312 } 00313 } 00314 00315 if ( tokens != NULL ) 00316 { 00317 for ( i = parser->toknext - 1; i >= 0; i-- ) 00318 { 00319 /* Unmatched opened object or array */ 00320 if ( tokens [ i ].start != -1 && tokens [ i ].end == -1 ) 00321 { 00322 return JSMN_ERROR_PART; 00323 } 00324 } 00325 } 00326 00327 return count; 00328 } 00329 00330 /** 00331 * Creates a new parser based over a given buffer with an array of tokens 00332 * available. 00333 */ 00334 void jsmn_init ( jsmn_parser *parser ) 00335 { 00336 parser->pos = 0; 00337 parser->toknext = 0; 00338 parser->toksuper = -1; 00339 } 00340
Generated on Tue Jul 12 2022 20:06:04 by 1.7.2