Library for Yodiwo's Plegma API
jsmn.c@3:96b08b5f998f, 2015-09-15 (annotated)
- Committer:
- mitsarionas
- Date:
- Tue Sep 15 10:21:40 2015 +0000
- Revision:
- 3:96b08b5f998f
- Parent:
- 0:384a04dc912e
- Child:
- 6:4596aaa1a824
manual version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mitsarionas | 0:384a04dc912e | 1 | #include <stdlib.h> |
mitsarionas | 0:384a04dc912e | 2 | |
mitsarionas | 0:384a04dc912e | 3 | #include "jsmn.h" |
mitsarionas | 0:384a04dc912e | 4 | |
mitsarionas | 3:96b08b5f998f | 5 | int strcpy_escaped(char *dest, char *src) |
mitsarionas | 3:96b08b5f998f | 6 | { |
mitsarionas | 3:96b08b5f998f | 7 | char *scur = src; |
mitsarionas | 3:96b08b5f998f | 8 | char *dcur = dest; |
mitsarionas | 3:96b08b5f998f | 9 | while(*scur != '\0') { |
mitsarionas | 3:96b08b5f998f | 10 | if (*scur == '\"' || *scur == '\\') { |
mitsarionas | 3:96b08b5f998f | 11 | *(dcur++) = '\\'; |
mitsarionas | 3:96b08b5f998f | 12 | } |
mitsarionas | 3:96b08b5f998f | 13 | *(dcur++) = *(scur++); |
mitsarionas | 3:96b08b5f998f | 14 | } |
mitsarionas | 3:96b08b5f998f | 15 | *dcur = '\0'; |
mitsarionas | 3:96b08b5f998f | 16 | return dcur - dest; |
mitsarionas | 3:96b08b5f998f | 17 | } |
mitsarionas | 3:96b08b5f998f | 18 | |
mitsarionas | 3:96b08b5f998f | 19 | int memcpy_unescaped(void *dest, void *src, int n_source) |
mitsarionas | 3:96b08b5f998f | 20 | { |
mitsarionas | 3:96b08b5f998f | 21 | char *s = src; |
mitsarionas | 3:96b08b5f998f | 22 | char *d = dest; |
mitsarionas | 3:96b08b5f998f | 23 | int i; |
mitsarionas | 3:96b08b5f998f | 24 | int j = 0; |
mitsarionas | 3:96b08b5f998f | 25 | for(i = 0; i < n_source; i++, j++) { |
mitsarionas | 3:96b08b5f998f | 26 | if (s[i] == '\\' && i != n_source - 1) |
mitsarionas | 3:96b08b5f998f | 27 | i++; |
mitsarionas | 3:96b08b5f998f | 28 | d[j] = s[i]; |
mitsarionas | 3:96b08b5f998f | 29 | } |
mitsarionas | 3:96b08b5f998f | 30 | return j - 1; |
mitsarionas | 3:96b08b5f998f | 31 | } |
mitsarionas | 3:96b08b5f998f | 32 | |
mitsarionas | 3:96b08b5f998f | 33 | int count_escaped(char *buf, int len) |
mitsarionas | 3:96b08b5f998f | 34 | { |
mitsarionas | 3:96b08b5f998f | 35 | int cnt = 0; |
mitsarionas | 3:96b08b5f998f | 36 | int i = 0; |
mitsarionas | 3:96b08b5f998f | 37 | while(i < len - 1) { |
mitsarionas | 3:96b08b5f998f | 38 | if (buf[i] == '\\') { |
mitsarionas | 3:96b08b5f998f | 39 | cnt++; |
mitsarionas | 3:96b08b5f998f | 40 | i++; |
mitsarionas | 3:96b08b5f998f | 41 | } |
mitsarionas | 3:96b08b5f998f | 42 | i++; |
mitsarionas | 3:96b08b5f998f | 43 | } |
mitsarionas | 3:96b08b5f998f | 44 | return cnt; |
mitsarionas | 3:96b08b5f998f | 45 | } |
mitsarionas | 3:96b08b5f998f | 46 | |
mitsarionas | 0:384a04dc912e | 47 | /** |
mitsarionas | 0:384a04dc912e | 48 | * Allocates a fresh unused token from the token pull. |
mitsarionas | 0:384a04dc912e | 49 | */ |
mitsarionas | 0:384a04dc912e | 50 | static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, |
mitsarionas | 0:384a04dc912e | 51 | jsmntok_t *tokens, size_t num_tokens) { |
mitsarionas | 0:384a04dc912e | 52 | jsmntok_t *tok; |
mitsarionas | 0:384a04dc912e | 53 | if (parser->toknext >= num_tokens) { |
mitsarionas | 0:384a04dc912e | 54 | return NULL; |
mitsarionas | 0:384a04dc912e | 55 | } |
mitsarionas | 0:384a04dc912e | 56 | tok = &tokens[parser->toknext++]; |
mitsarionas | 0:384a04dc912e | 57 | tok->start = tok->end = -1; |
mitsarionas | 0:384a04dc912e | 58 | tok->size = 0; |
mitsarionas | 0:384a04dc912e | 59 | #ifdef JSMN_PARENT_LINKS |
mitsarionas | 0:384a04dc912e | 60 | tok->parent = -1; |
mitsarionas | 0:384a04dc912e | 61 | #endif |
mitsarionas | 0:384a04dc912e | 62 | return tok; |
mitsarionas | 0:384a04dc912e | 63 | } |
mitsarionas | 0:384a04dc912e | 64 | |
mitsarionas | 0:384a04dc912e | 65 | /** |
mitsarionas | 0:384a04dc912e | 66 | * Fills token type and boundaries. |
mitsarionas | 0:384a04dc912e | 67 | */ |
mitsarionas | 0:384a04dc912e | 68 | static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, |
mitsarionas | 0:384a04dc912e | 69 | int start, int end) { |
mitsarionas | 0:384a04dc912e | 70 | token->type = type; |
mitsarionas | 0:384a04dc912e | 71 | token->start = start; |
mitsarionas | 0:384a04dc912e | 72 | token->end = end; |
mitsarionas | 0:384a04dc912e | 73 | token->size = 0; |
mitsarionas | 0:384a04dc912e | 74 | } |
mitsarionas | 0:384a04dc912e | 75 | |
mitsarionas | 0:384a04dc912e | 76 | /** |
mitsarionas | 0:384a04dc912e | 77 | * Fills next available token with JSON primitive. |
mitsarionas | 0:384a04dc912e | 78 | */ |
mitsarionas | 0:384a04dc912e | 79 | static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, |
mitsarionas | 0:384a04dc912e | 80 | size_t len, jsmntok_t *tokens, size_t num_tokens) { |
mitsarionas | 0:384a04dc912e | 81 | jsmntok_t *token; |
mitsarionas | 0:384a04dc912e | 82 | int start; |
mitsarionas | 0:384a04dc912e | 83 | |
mitsarionas | 0:384a04dc912e | 84 | start = parser->pos; |
mitsarionas | 0:384a04dc912e | 85 | |
mitsarionas | 0:384a04dc912e | 86 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { |
mitsarionas | 0:384a04dc912e | 87 | switch (js[parser->pos]) { |
mitsarionas | 0:384a04dc912e | 88 | #ifndef JSMN_STRICT |
mitsarionas | 0:384a04dc912e | 89 | /* In strict mode primitive must be followed by "," or "}" or "]" */ |
mitsarionas | 0:384a04dc912e | 90 | case ':': |
mitsarionas | 0:384a04dc912e | 91 | #endif |
mitsarionas | 0:384a04dc912e | 92 | case '\t' : case '\r' : case '\n' : case ' ' : |
mitsarionas | 0:384a04dc912e | 93 | case ',' : case ']' : case '}' : |
mitsarionas | 0:384a04dc912e | 94 | goto found; |
mitsarionas | 0:384a04dc912e | 95 | } |
mitsarionas | 0:384a04dc912e | 96 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { |
mitsarionas | 0:384a04dc912e | 97 | parser->pos = start; |
mitsarionas | 0:384a04dc912e | 98 | return JSMN_ERROR_INVAL; |
mitsarionas | 0:384a04dc912e | 99 | } |
mitsarionas | 0:384a04dc912e | 100 | } |
mitsarionas | 0:384a04dc912e | 101 | #ifdef JSMN_STRICT |
mitsarionas | 0:384a04dc912e | 102 | /* In strict mode primitive must be followed by a comma/object/array */ |
mitsarionas | 0:384a04dc912e | 103 | parser->pos = start; |
mitsarionas | 0:384a04dc912e | 104 | return JSMN_ERROR_PART; |
mitsarionas | 0:384a04dc912e | 105 | #endif |
mitsarionas | 0:384a04dc912e | 106 | |
mitsarionas | 0:384a04dc912e | 107 | found: |
mitsarionas | 0:384a04dc912e | 108 | if (tokens == NULL) { |
mitsarionas | 0:384a04dc912e | 109 | parser->pos--; |
mitsarionas | 0:384a04dc912e | 110 | return 0; |
mitsarionas | 0:384a04dc912e | 111 | } |
mitsarionas | 0:384a04dc912e | 112 | token = jsmn_alloc_token(parser, tokens, num_tokens); |
mitsarionas | 0:384a04dc912e | 113 | if (token == NULL) { |
mitsarionas | 0:384a04dc912e | 114 | parser->pos = start; |
mitsarionas | 0:384a04dc912e | 115 | return JSMN_ERROR_NOMEM; |
mitsarionas | 0:384a04dc912e | 116 | } |
mitsarionas | 0:384a04dc912e | 117 | jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); |
mitsarionas | 0:384a04dc912e | 118 | #ifdef JSMN_PARENT_LINKS |
mitsarionas | 0:384a04dc912e | 119 | token->parent = parser->toksuper; |
mitsarionas | 0:384a04dc912e | 120 | #endif |
mitsarionas | 0:384a04dc912e | 121 | parser->pos--; |
mitsarionas | 0:384a04dc912e | 122 | return 0; |
mitsarionas | 0:384a04dc912e | 123 | } |
mitsarionas | 0:384a04dc912e | 124 | |
mitsarionas | 0:384a04dc912e | 125 | /** |
mitsarionas | 0:384a04dc912e | 126 | * Filsl next token with JSON string. |
mitsarionas | 0:384a04dc912e | 127 | */ |
mitsarionas | 0:384a04dc912e | 128 | static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, |
mitsarionas | 0:384a04dc912e | 129 | size_t len, jsmntok_t *tokens, size_t num_tokens) { |
mitsarionas | 0:384a04dc912e | 130 | jsmntok_t *token; |
mitsarionas | 0:384a04dc912e | 131 | |
mitsarionas | 0:384a04dc912e | 132 | int start = parser->pos; |
mitsarionas | 0:384a04dc912e | 133 | |
mitsarionas | 0:384a04dc912e | 134 | parser->pos++; |
mitsarionas | 0:384a04dc912e | 135 | |
mitsarionas | 0:384a04dc912e | 136 | /* Skip starting quote */ |
mitsarionas | 0:384a04dc912e | 137 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { |
mitsarionas | 0:384a04dc912e | 138 | char c = js[parser->pos]; |
mitsarionas | 0:384a04dc912e | 139 | |
mitsarionas | 0:384a04dc912e | 140 | /* Quote: end of string */ |
mitsarionas | 0:384a04dc912e | 141 | if (c == '\"') { |
mitsarionas | 0:384a04dc912e | 142 | if (tokens == NULL) { |
mitsarionas | 0:384a04dc912e | 143 | return 0; |
mitsarionas | 0:384a04dc912e | 144 | } |
mitsarionas | 0:384a04dc912e | 145 | token = jsmn_alloc_token(parser, tokens, num_tokens); |
mitsarionas | 0:384a04dc912e | 146 | if (token == NULL) { |
mitsarionas | 0:384a04dc912e | 147 | parser->pos = start; |
mitsarionas | 0:384a04dc912e | 148 | return JSMN_ERROR_NOMEM; |
mitsarionas | 0:384a04dc912e | 149 | } |
mitsarionas | 0:384a04dc912e | 150 | jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); |
mitsarionas | 0:384a04dc912e | 151 | #ifdef JSMN_PARENT_LINKS |
mitsarionas | 0:384a04dc912e | 152 | token->parent = parser->toksuper; |
mitsarionas | 0:384a04dc912e | 153 | #endif |
mitsarionas | 0:384a04dc912e | 154 | return 0; |
mitsarionas | 0:384a04dc912e | 155 | } |
mitsarionas | 0:384a04dc912e | 156 | |
mitsarionas | 0:384a04dc912e | 157 | /* Backslash: Quoted symbol expected */ |
mitsarionas | 0:384a04dc912e | 158 | if (c == '\\' && parser->pos + 1 < len) { |
mitsarionas | 0:384a04dc912e | 159 | int i; |
mitsarionas | 0:384a04dc912e | 160 | parser->pos++; |
mitsarionas | 0:384a04dc912e | 161 | switch (js[parser->pos]) { |
mitsarionas | 0:384a04dc912e | 162 | /* Allowed escaped symbols */ |
mitsarionas | 0:384a04dc912e | 163 | case '\"': case '/' : case '\\' : case 'b' : |
mitsarionas | 0:384a04dc912e | 164 | case 'f' : case 'r' : case 'n' : case 't' : |
mitsarionas | 0:384a04dc912e | 165 | break; |
mitsarionas | 0:384a04dc912e | 166 | /* Allows escaped symbol \uXXXX */ |
mitsarionas | 0:384a04dc912e | 167 | case 'u': |
mitsarionas | 0:384a04dc912e | 168 | parser->pos++; |
mitsarionas | 0:384a04dc912e | 169 | for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { |
mitsarionas | 0:384a04dc912e | 170 | /* If it isn't a hex character we have an error */ |
mitsarionas | 0:384a04dc912e | 171 | if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ |
mitsarionas | 0:384a04dc912e | 172 | (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ |
mitsarionas | 0:384a04dc912e | 173 | (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ |
mitsarionas | 0:384a04dc912e | 174 | parser->pos = start; |
mitsarionas | 0:384a04dc912e | 175 | return JSMN_ERROR_INVAL; |
mitsarionas | 0:384a04dc912e | 176 | } |
mitsarionas | 0:384a04dc912e | 177 | parser->pos++; |
mitsarionas | 0:384a04dc912e | 178 | } |
mitsarionas | 0:384a04dc912e | 179 | parser->pos--; |
mitsarionas | 0:384a04dc912e | 180 | break; |
mitsarionas | 0:384a04dc912e | 181 | /* Unexpected symbol */ |
mitsarionas | 0:384a04dc912e | 182 | default: |
mitsarionas | 0:384a04dc912e | 183 | parser->pos = start; |
mitsarionas | 0:384a04dc912e | 184 | return JSMN_ERROR_INVAL; |
mitsarionas | 0:384a04dc912e | 185 | } |
mitsarionas | 0:384a04dc912e | 186 | } |
mitsarionas | 0:384a04dc912e | 187 | } |
mitsarionas | 0:384a04dc912e | 188 | parser->pos = start; |
mitsarionas | 0:384a04dc912e | 189 | return JSMN_ERROR_PART; |
mitsarionas | 0:384a04dc912e | 190 | } |
mitsarionas | 0:384a04dc912e | 191 | |
mitsarionas | 0:384a04dc912e | 192 | /** |
mitsarionas | 0:384a04dc912e | 193 | * Parse JSON string and fill tokens. |
mitsarionas | 0:384a04dc912e | 194 | */ |
mitsarionas | 0:384a04dc912e | 195 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, |
mitsarionas | 0:384a04dc912e | 196 | jsmntok_t *tokens, unsigned int num_tokens) { |
mitsarionas | 0:384a04dc912e | 197 | jsmnerr_t r; |
mitsarionas | 0:384a04dc912e | 198 | int i; |
mitsarionas | 0:384a04dc912e | 199 | jsmntok_t *token; |
mitsarionas | 0:384a04dc912e | 200 | int count = 0; |
mitsarionas | 0:384a04dc912e | 201 | |
mitsarionas | 0:384a04dc912e | 202 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { |
mitsarionas | 0:384a04dc912e | 203 | char c; |
mitsarionas | 0:384a04dc912e | 204 | jsmntype_t type; |
mitsarionas | 0:384a04dc912e | 205 | |
mitsarionas | 0:384a04dc912e | 206 | c = js[parser->pos]; |
mitsarionas | 0:384a04dc912e | 207 | switch (c) { |
mitsarionas | 0:384a04dc912e | 208 | case '{': case '[': |
mitsarionas | 0:384a04dc912e | 209 | count++; |
mitsarionas | 0:384a04dc912e | 210 | if (tokens == NULL) { |
mitsarionas | 0:384a04dc912e | 211 | break; |
mitsarionas | 0:384a04dc912e | 212 | } |
mitsarionas | 0:384a04dc912e | 213 | token = jsmn_alloc_token(parser, tokens, num_tokens); |
mitsarionas | 0:384a04dc912e | 214 | if (token == NULL) |
mitsarionas | 0:384a04dc912e | 215 | return JSMN_ERROR_NOMEM; |
mitsarionas | 0:384a04dc912e | 216 | if (parser->toksuper != -1) { |
mitsarionas | 0:384a04dc912e | 217 | tokens[parser->toksuper].size++; |
mitsarionas | 0:384a04dc912e | 218 | #ifdef JSMN_PARENT_LINKS |
mitsarionas | 0:384a04dc912e | 219 | token->parent = parser->toksuper; |
mitsarionas | 0:384a04dc912e | 220 | #endif |
mitsarionas | 0:384a04dc912e | 221 | } |
mitsarionas | 0:384a04dc912e | 222 | token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); |
mitsarionas | 0:384a04dc912e | 223 | token->start = parser->pos; |
mitsarionas | 0:384a04dc912e | 224 | parser->toksuper = parser->toknext - 1; |
mitsarionas | 0:384a04dc912e | 225 | break; |
mitsarionas | 0:384a04dc912e | 226 | case '}': case ']': |
mitsarionas | 0:384a04dc912e | 227 | if (tokens == NULL) |
mitsarionas | 0:384a04dc912e | 228 | break; |
mitsarionas | 0:384a04dc912e | 229 | type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); |
mitsarionas | 0:384a04dc912e | 230 | #ifdef JSMN_PARENT_LINKS |
mitsarionas | 0:384a04dc912e | 231 | if (parser->toknext < 1) { |
mitsarionas | 0:384a04dc912e | 232 | return JSMN_ERROR_INVAL; |
mitsarionas | 0:384a04dc912e | 233 | } |
mitsarionas | 0:384a04dc912e | 234 | token = &tokens[parser->toknext - 1]; |
mitsarionas | 0:384a04dc912e | 235 | for (;;) { |
mitsarionas | 0:384a04dc912e | 236 | if (token->start != -1 && token->end == -1) { |
mitsarionas | 0:384a04dc912e | 237 | if (token->type != type) { |
mitsarionas | 0:384a04dc912e | 238 | return JSMN_ERROR_INVAL; |
mitsarionas | 0:384a04dc912e | 239 | } |
mitsarionas | 0:384a04dc912e | 240 | token->end = parser->pos + 1; |
mitsarionas | 0:384a04dc912e | 241 | parser->toksuper = token->parent; |
mitsarionas | 0:384a04dc912e | 242 | break; |
mitsarionas | 0:384a04dc912e | 243 | } |
mitsarionas | 0:384a04dc912e | 244 | if (token->parent == -1) { |
mitsarionas | 0:384a04dc912e | 245 | break; |
mitsarionas | 0:384a04dc912e | 246 | } |
mitsarionas | 0:384a04dc912e | 247 | token = &tokens[token->parent]; |
mitsarionas | 0:384a04dc912e | 248 | } |
mitsarionas | 0:384a04dc912e | 249 | #else |
mitsarionas | 0:384a04dc912e | 250 | for (i = parser->toknext - 1; i >= 0; i--) { |
mitsarionas | 0:384a04dc912e | 251 | token = &tokens[i]; |
mitsarionas | 0:384a04dc912e | 252 | if (token->start != -1 && token->end == -1) { |
mitsarionas | 0:384a04dc912e | 253 | if (token->type != type) { |
mitsarionas | 0:384a04dc912e | 254 | return JSMN_ERROR_INVAL; |
mitsarionas | 0:384a04dc912e | 255 | } |
mitsarionas | 0:384a04dc912e | 256 | parser->toksuper = -1; |
mitsarionas | 0:384a04dc912e | 257 | token->end = parser->pos + 1; |
mitsarionas | 0:384a04dc912e | 258 | break; |
mitsarionas | 0:384a04dc912e | 259 | } |
mitsarionas | 0:384a04dc912e | 260 | } |
mitsarionas | 0:384a04dc912e | 261 | /* Error if unmatched closing bracket */ |
mitsarionas | 0:384a04dc912e | 262 | if (i == -1) return JSMN_ERROR_INVAL; |
mitsarionas | 0:384a04dc912e | 263 | for (; i >= 0; i--) { |
mitsarionas | 0:384a04dc912e | 264 | token = &tokens[i]; |
mitsarionas | 0:384a04dc912e | 265 | if (token->start != -1 && token->end == -1) { |
mitsarionas | 0:384a04dc912e | 266 | parser->toksuper = i; |
mitsarionas | 0:384a04dc912e | 267 | break; |
mitsarionas | 0:384a04dc912e | 268 | } |
mitsarionas | 0:384a04dc912e | 269 | } |
mitsarionas | 0:384a04dc912e | 270 | #endif |
mitsarionas | 0:384a04dc912e | 271 | break; |
mitsarionas | 0:384a04dc912e | 272 | case '\"': |
mitsarionas | 0:384a04dc912e | 273 | r = jsmn_parse_string(parser, js, len, tokens, num_tokens); |
mitsarionas | 0:384a04dc912e | 274 | if (r < 0) return r; |
mitsarionas | 0:384a04dc912e | 275 | count++; |
mitsarionas | 0:384a04dc912e | 276 | if (parser->toksuper != -1 && tokens != NULL) |
mitsarionas | 0:384a04dc912e | 277 | tokens[parser->toksuper].size++; |
mitsarionas | 0:384a04dc912e | 278 | break; |
mitsarionas | 0:384a04dc912e | 279 | case '\t' : case '\r' : case '\n' : case ' ': |
mitsarionas | 0:384a04dc912e | 280 | break; |
mitsarionas | 0:384a04dc912e | 281 | case ':': |
mitsarionas | 0:384a04dc912e | 282 | parser->toksuper = parser->toknext - 1; |
mitsarionas | 0:384a04dc912e | 283 | break; |
mitsarionas | 0:384a04dc912e | 284 | case ',': |
mitsarionas | 0:384a04dc912e | 285 | if (tokens != NULL && |
mitsarionas | 0:384a04dc912e | 286 | tokens[parser->toksuper].type != JSMN_ARRAY && |
mitsarionas | 0:384a04dc912e | 287 | tokens[parser->toksuper].type != JSMN_OBJECT) { |
mitsarionas | 0:384a04dc912e | 288 | #ifdef JSMN_PARENT_LINKS |
mitsarionas | 0:384a04dc912e | 289 | parser->toksuper = tokens[parser->toksuper].parent; |
mitsarionas | 0:384a04dc912e | 290 | #else |
mitsarionas | 0:384a04dc912e | 291 | for (i = parser->toknext - 1; i >= 0; i--) { |
mitsarionas | 0:384a04dc912e | 292 | if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { |
mitsarionas | 0:384a04dc912e | 293 | if (tokens[i].start != -1 && tokens[i].end == -1) { |
mitsarionas | 0:384a04dc912e | 294 | parser->toksuper = i; |
mitsarionas | 0:384a04dc912e | 295 | break; |
mitsarionas | 0:384a04dc912e | 296 | } |
mitsarionas | 0:384a04dc912e | 297 | } |
mitsarionas | 0:384a04dc912e | 298 | } |
mitsarionas | 0:384a04dc912e | 299 | #endif |
mitsarionas | 0:384a04dc912e | 300 | } |
mitsarionas | 0:384a04dc912e | 301 | break; |
mitsarionas | 0:384a04dc912e | 302 | #ifdef JSMN_STRICT |
mitsarionas | 0:384a04dc912e | 303 | /* In strict mode primitives are: numbers and booleans */ |
mitsarionas | 0:384a04dc912e | 304 | case '-': case '0': case '1' : case '2': case '3' : case '4': |
mitsarionas | 0:384a04dc912e | 305 | case '5': case '6': case '7' : case '8': case '9': |
mitsarionas | 0:384a04dc912e | 306 | case 't': case 'f': case 'n' : |
mitsarionas | 0:384a04dc912e | 307 | /* And they must not be keys of the object */ |
mitsarionas | 0:384a04dc912e | 308 | if (tokens != NULL) { |
mitsarionas | 0:384a04dc912e | 309 | jsmntok_t *t = &tokens[parser->toksuper]; |
mitsarionas | 0:384a04dc912e | 310 | if (t->type == JSMN_OBJECT || |
mitsarionas | 0:384a04dc912e | 311 | (t->type == JSMN_STRING && t->size != 0)) { |
mitsarionas | 0:384a04dc912e | 312 | return JSMN_ERROR_INVAL; |
mitsarionas | 0:384a04dc912e | 313 | } |
mitsarionas | 0:384a04dc912e | 314 | } |
mitsarionas | 0:384a04dc912e | 315 | #else |
mitsarionas | 0:384a04dc912e | 316 | /* In non-strict mode every unquoted value is a primitive */ |
mitsarionas | 0:384a04dc912e | 317 | default: |
mitsarionas | 0:384a04dc912e | 318 | #endif |
mitsarionas | 0:384a04dc912e | 319 | r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); |
mitsarionas | 0:384a04dc912e | 320 | if (r < 0) return r; |
mitsarionas | 0:384a04dc912e | 321 | count++; |
mitsarionas | 0:384a04dc912e | 322 | if (parser->toksuper != -1 && tokens != NULL) |
mitsarionas | 0:384a04dc912e | 323 | tokens[parser->toksuper].size++; |
mitsarionas | 0:384a04dc912e | 324 | break; |
mitsarionas | 0:384a04dc912e | 325 | |
mitsarionas | 0:384a04dc912e | 326 | #ifdef JSMN_STRICT |
mitsarionas | 0:384a04dc912e | 327 | /* Unexpected char in strict mode */ |
mitsarionas | 0:384a04dc912e | 328 | default: |
mitsarionas | 0:384a04dc912e | 329 | return JSMN_ERROR_INVAL; |
mitsarionas | 0:384a04dc912e | 330 | #endif |
mitsarionas | 0:384a04dc912e | 331 | } |
mitsarionas | 0:384a04dc912e | 332 | } |
mitsarionas | 0:384a04dc912e | 333 | |
mitsarionas | 0:384a04dc912e | 334 | for (i = parser->toknext - 1; i >= 0; i--) { |
mitsarionas | 0:384a04dc912e | 335 | /* Unmatched opened object or array */ |
mitsarionas | 0:384a04dc912e | 336 | if (tokens[i].start != -1 && tokens[i].end == -1) { |
mitsarionas | 0:384a04dc912e | 337 | return JSMN_ERROR_PART; |
mitsarionas | 0:384a04dc912e | 338 | } |
mitsarionas | 0:384a04dc912e | 339 | } |
mitsarionas | 0:384a04dc912e | 340 | |
mitsarionas | 0:384a04dc912e | 341 | return count; |
mitsarionas | 0:384a04dc912e | 342 | } |
mitsarionas | 0:384a04dc912e | 343 | |
mitsarionas | 0:384a04dc912e | 344 | /** |
mitsarionas | 0:384a04dc912e | 345 | * Creates a new parser based over a given buffer with an array of tokens |
mitsarionas | 0:384a04dc912e | 346 | * available. |
mitsarionas | 0:384a04dc912e | 347 | */ |
mitsarionas | 0:384a04dc912e | 348 | void jsmn_init(jsmn_parser *parser) { |
mitsarionas | 0:384a04dc912e | 349 | parser->pos = 0; |
mitsarionas | 0:384a04dc912e | 350 | parser->toknext = 0; |
mitsarionas | 0:384a04dc912e | 351 | parser->toksuper = -1; |
mitsarionas | 0:384a04dc912e | 352 | } |
mitsarionas | 0:384a04dc912e | 353 |