iot_water_monitor_v2

Dependencies:   easy-connect-v16 Watchdog FP MQTTPacket RecordType-v-16 watersenor_and_temp_code

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers jsmn.c Source File

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