* Fills next token with JSON string. */
| 192 | * Fills next token with JSON string. |
| 193 | */ |
| 194 | static int jsmn_parse_string(jsmn_parser *parser, const char *js, |
| 195 | const size_t len, jsmntok_t *tokens, |
| 196 | const size_t num_tokens) { |
| 197 | jsmntok_t *token; |
| 198 | |
| 199 | int start = parser->pos; |
| 200 | |
| 201 | parser->pos++; |
| 202 | |
| 203 | /* Skip starting quote */ |
| 204 | for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { |
| 205 | char c = js[parser->pos]; |
| 206 | |
| 207 | /* Quote: end of string */ |
| 208 | if (c == '\"') { |
| 209 | if (tokens == NULL) { |
| 210 | return 0; |
| 211 | } |
| 212 | token = jsmn_alloc_token(parser, tokens, num_tokens); |
| 213 | if (token == NULL) { |
| 214 | parser->pos = start; |
| 215 | return JSMN_ERROR_NOMEM; |
| 216 | } |
| 217 | jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); |
| 218 | #ifdef JSMN_PARENT_LINKS |
| 219 | token->parent = parser->toksuper; |
| 220 | #endif |
| 221 | return 0; |
| 222 | } |
| 223 | |
| 224 | /* Backslash: Quoted symbol expected */ |
| 225 | if (c == '\\' && parser->pos + 1 < len) { |
| 226 | int i; |
| 227 | parser->pos++; |
| 228 | switch (js[parser->pos]) { |
| 229 | /* Allowed escaped symbols */ |
| 230 | case '\"': |
| 231 | case '/': |
| 232 | case '\\': |
| 233 | case 'b': |
| 234 | case 'f': |
| 235 | case 'r': |
| 236 | case 'n': |
| 237 | case 't': |
| 238 | break; |
| 239 | /* Allows escaped symbol \uXXXX */ |
| 240 | case 'u': |
| 241 | parser->pos++; |
| 242 | for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; |
| 243 | i++) { |
| 244 | /* If it isn't a hex character we have an error */ |
| 245 | if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ |
| 246 | (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ |
| 247 | (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ |
| 248 | parser->pos = start; |
| 249 | return JSMN_ERROR_INVAL; |
| 250 | } |
| 251 | parser->pos++; |
no test coverage detected