Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
jsmn.c
00001 #include <stdlib.h> 00002 00003 #include "jsmn.h" 00004 00005 /** 00006 * Allocates a fresh unused token from the token pull. 00007 */ 00008 static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 00009 jsmntok_t *tokens, size_t num_tokens) { 00010 jsmntok_t *tok; 00011 if (parser->toknext >= num_tokens) { 00012 return NULL; 00013 } 00014 tok = &tokens[parser->toknext++]; 00015 tok->start = tok->end = -1; 00016 tok->size = 0; 00017 #ifdef JSMN_PARENT_LINKS 00018 tok->parent = -1; 00019 #endif 00020 return tok; 00021 } 00022 00023 /** 00024 * Fills token type and boundaries. 00025 */ 00026 static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 00027 int start, int end) { 00028 token->type = type; 00029 token->start = start; 00030 token->end = end; 00031 token->size = 0; 00032 } 00033 00034 /** 00035 * Fills next available token with JSON primitive. 00036 */ 00037 static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, char *js, 00038 jsmntok_t *tokens, size_t num_tokens) { 00039 jsmntok_t *token; 00040 int start; 00041 00042 start = parser->pos; 00043 00044 for (; js[parser->pos] != '\0'; parser->pos++) { 00045 switch (js[parser->pos]) { 00046 #ifndef JSMN_STRICT 00047 /* In strict mode primitive must be followed by "," or "}" or "]" */ 00048 case ':': 00049 #endif 00050 case '\t' : case '\r' : case '\n' : case ' ' : 00051 case ',' : case ']' : case '}' : 00052 goto found; 00053 } 00054 if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 00055 parser->pos = start; 00056 return JSMN_ERROR_INVAL; 00057 } 00058 } 00059 #ifdef JSMN_STRICT 00060 /* In strict mode primitive must be followed by a comma/object/array */ 00061 parser->pos = start; 00062 return JSMN_ERROR_PART; 00063 #endif 00064 00065 found: 00066 token = jsmn_alloc_token(parser, tokens, num_tokens); 00067 if (token == NULL) { 00068 parser->pos = start; 00069 return JSMN_ERROR_NOMEM; 00070 } 00071 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 00072 #ifdef JSMN_PARENT_LINKS 00073 token->parent = parser->toksuper; 00074 #endif 00075 parser->pos--; 00076 return JSMN_SUCCESS; 00077 } 00078 00079 /** 00080 * Filsl next token with JSON string. 00081 */ 00082 static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, 00083 jsmntok_t *tokens, size_t num_tokens) { 00084 jsmntok_t *token; 00085 00086 int start = parser->pos; 00087 00088 parser->pos++; 00089 00090 /* Skip starting quote */ 00091 for (; js[parser->pos] != '\0'; parser->pos++) { 00092 char c = js[parser->pos]; 00093 00094 /* Quote: end of string */ 00095 if (c == '\"') { 00096 token = jsmn_alloc_token(parser, tokens, num_tokens); 00097 if (token == NULL) { 00098 parser->pos = start; 00099 return JSMN_ERROR_NOMEM; 00100 } 00101 jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 00102 #ifdef JSMN_PARENT_LINKS 00103 token->parent = parser->toksuper; 00104 #endif 00105 return JSMN_SUCCESS; 00106 } 00107 00108 /* Backslash: Quoted symbol expected */ 00109 if (c == '\\') { 00110 parser->pos++; 00111 switch (js[parser->pos]) { 00112 /* Allowed escaped symbols */ 00113 case '\"': case '/' : case '\\' : case 'b' : 00114 case 'f' : case 'r' : case 'n' : case 't' : 00115 break; 00116 /* Allows escaped symbol \uXXXX */ 00117 case 'u': 00118 /* TODO */ 00119 break; 00120 /* Unexpected symbol */ 00121 default: 00122 parser->pos = start; 00123 return JSMN_ERROR_INVAL; 00124 } 00125 } 00126 } 00127 parser->pos = start; 00128 return JSMN_ERROR_PART; 00129 } 00130 00131 /** 00132 * Parse JSON string and fill tokens. 00133 */ 00134 jsmnerr_t jsmn_parse(jsmn_parser *parser, char *js, jsmntok_t *tokens, 00135 unsigned int num_tokens) { 00136 jsmnerr_t r; 00137 int i; 00138 jsmntok_t *token; 00139 00140 for (; js[parser->pos] != '\0'; parser->pos++) { 00141 char c; 00142 jsmntype_t type; 00143 00144 c = js[parser->pos]; 00145 switch (c) { 00146 case '{': case '[': 00147 token = jsmn_alloc_token(parser, tokens, num_tokens); 00148 if (token == NULL) 00149 return JSMN_ERROR_NOMEM; 00150 if (parser->toksuper != -1) { 00151 tokens[parser->toksuper].size++; 00152 #ifdef JSMN_PARENT_LINKS 00153 token->parent = parser->toksuper; 00154 #endif 00155 } 00156 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 00157 token->start = parser->pos; 00158 parser->toksuper = parser->toknext - 1; 00159 break; 00160 case '}': case ']': 00161 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 00162 #ifdef JSMN_PARENT_LINKS 00163 if (parser->toknext < 1) { 00164 return JSMN_ERROR_INVAL; 00165 } 00166 token = &tokens[parser->toknext - 1]; 00167 for (;;) { 00168 if (token->start != -1 && token->end == -1) { 00169 if (token->type != type) { 00170 return JSMN_ERROR_INVAL; 00171 } 00172 token->end = parser->pos + 1; 00173 parser->toksuper = token->parent; 00174 break; 00175 } 00176 if (token->parent == -1) { 00177 break; 00178 } 00179 token = &tokens[token->parent]; 00180 } 00181 #else 00182 for (i = parser->toknext - 1; i >= 0; i--) { 00183 token = &tokens[i]; 00184 if (token->start != -1 && token->end == -1) { 00185 if (token->type != type) { 00186 return JSMN_ERROR_INVAL; 00187 } 00188 parser->toksuper = -1; 00189 token->end = parser->pos + 1; 00190 break; 00191 } 00192 } 00193 /* Error if unmatched closing bracket */ 00194 if (i == -1) return JSMN_ERROR_INVAL; 00195 for (; i >= 0; i--) { 00196 token = &tokens[i]; 00197 if (token->start != -1 && token->end == -1) { 00198 parser->toksuper = i; 00199 break; 00200 } 00201 } 00202 #endif 00203 break; 00204 case '\"': 00205 r = jsmn_parse_string(parser, js, tokens, num_tokens); 00206 if (r < 0) return r; 00207 if (parser->toksuper != -1) 00208 tokens[parser->toksuper].size++; 00209 break; 00210 case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ': 00211 break; 00212 #ifdef JSMN_STRICT 00213 /* In strict mode primitives are: numbers and booleans */ 00214 case '-': case '0': case '1' : case '2': case '3' : case '4': 00215 case '5': case '6': case '7' : case '8': case '9': 00216 case 't': case 'f': case 'n' : 00217 #else 00218 /* In non-strict mode every unquoted value is a primitive */ 00219 default: 00220 #endif 00221 r = jsmn_parse_primitive(parser, js, tokens, num_tokens); 00222 if (r < 0) return r; 00223 if (parser->toksuper != -1) 00224 tokens[parser->toksuper].size++; 00225 break; 00226 00227 #ifdef JSMN_STRICT 00228 /* Unexpected char in strict mode */ 00229 default: 00230 return JSMN_ERROR_INVAL; 00231 #endif 00232 00233 } 00234 } 00235 00236 for (i = parser->toknext - 1; i >= 0; i--) { 00237 /* Unmatched opened object or array */ 00238 if (tokens[i].start != -1 && tokens[i].end == -1) { 00239 return JSMN_ERROR_PART; 00240 } 00241 } 00242 00243 return JSMN_SUCCESS; 00244 } 00245 00246 /** 00247 * Creates a new parser based over a given buffer with an array of tokens 00248 * available. 00249 */ 00250 void jsmn_init(jsmn_parser *parser) { 00251 parser->pos = 0; 00252 parser->toknext = 0; 00253 parser->toksuper = -1; 00254 }
Generated on Sat Jul 30 2022 22:42:10 by
1.7.2