#include #include "jsmn.h" struct jsmn_params { jsontok_t *tokens; size_t num_tokens; int *errpos; }; /** * Read the string from JSON data. Store string */ static int jsmn_parse_string(const unsigned char *js, jsontok_t *token) { const unsigned char *p; /* Check if string begins from a quote */ if (js[token->start] != '\"') { return -1; } /* Skip starting quote */ token->start++; for (p = &js[token->start]; *p != '\0'; p++) { /* Quote: end of string */ if (*p == '\"') { token->end = p - js; return 0; } /* Backslash: Quoted symbol expected */ if (*p == '\\') { p++; switch (*p) { /* Allowed escaped symbols */ case '\"': case '/' : case '\\' : case 'b' : case 'f' : case 'r' : case 'n' : case 't' : break; /* Allows escaped symbol \uXXXX */ case 'u': /* TODO */ break; /* Unexpected symbol */ default: return -1; } } } return -1; } static int jsmn_parse_primitive(const unsigned char *js, jsontok_t *token) { const unsigned char *p; for (p = &js[token->start]; *p != '\0'; p++) { switch (*p) { case '\t' : case '\r' : case '\n' : case ' ' : case ',' : case ']' : case '}' : token->end = p - js; return 0; } if (*p < 32 || *p >= 127) { return -1; } } return -1; } static jsontok_t *jsmn_token_start(struct jsmn_params *params, jsontype_t type, int pos) { unsigned int i; jsontok_t *tokens = params->tokens; for (i = 0; inum_tokens; i++) { if (tokens[i].start == -1 && tokens[i].end == -1) { tokens[i].start = pos; tokens[i].type = type; return &tokens[i]; } } return NULL; } static jsontok_t *jsmn_token_end(struct jsmn_params *params, jsontype_t type, int pos) { int i; jsontok_t *tokens = params->tokens; for (i = params->num_tokens - 1; i>= 0; i--) { if (tokens[i].type == type && tokens[i].start != -1 && tokens[i].end == -1) { tokens[i].end = pos; return &tokens[i]; } } return NULL; } int jsmn_parse(const unsigned char *js, jsontok_t *tokens, size_t num_tokens, int *errpos) { #define jsmn_return(error) \ do { \ if ((errpos) != NULL) { \ *(errpos) = (p - js); \ } \ return (error); \ } while (0) #define jsmn_assert(cond, error) \ if (!(cond)) { \ jsmn_return(error); \ } struct jsmn_params params; int r; unsigned int i; const unsigned char *p; jsontype_t type; jsontok_t *cur_token; params.num_tokens = num_tokens; params.tokens = tokens; params.errpos = errpos; for (i = 0; iend] - 1; break; case 't': case 'f': case 'n' : cur_token = jsmn_token_start(¶ms, JSON_OTHER, p - js); jsmn_assert(cur_token != NULL, -1); r = jsmn_parse_primitive(js, cur_token); jsmn_assert(r == 0, -2); p = &js[cur_token->end] - 1; break; case '\"': cur_token = jsmn_token_start(¶ms, JSON_STRING, p - js); jsmn_assert(cur_token != NULL, -1); r = jsmn_parse_string(js, cur_token); jsmn_assert(r == 0, -2); p = &js[cur_token->end]; break; case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ': break; default: jsmn_assert(0, -1); /* Assert always fails */ } p++; } if (errpos != NULL) *errpos = 0; return 0; #undef jsmn_return #undef jsmn_assert }