summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--demo.c11
-rw-r--r--jsmn.c226
-rw-r--r--jsmn.h27
4 files changed, 130 insertions, 136 deletions
diff --git a/Makefile b/Makefile
index cda64f530..dc90eab07 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS=-Wall -std=c89
+CFLAGS=-Wall -std=c89 -g
OBJS=jsmn.o demo.o
diff --git a/demo.c b/demo.c
index a9dfa41f5..0c2d18bb5 100644
--- a/demo.c
+++ b/demo.c
@@ -50,7 +50,6 @@ static void jsmn_dump_obj(jsontok_t *obj, const char *js) {
int main(int argc, char *argv[]) {
int i;
int r;
- int errpos;
jsontok_t tokens[NUM_TOKENS];
FILE *f;
int filesize = 0;
@@ -85,14 +84,18 @@ int main(int argc, char *argv[]) {
fclose(f);
- r = jsmn_parse((unsigned char *) js, tokens, NUM_TOKENS, &errpos);
+ jsmn_parser parser;
+
+ jsmn_init_parser(&parser, js, tokens, NUM_TOKENS);
+
+ r = jsmn_parse(&parser);
if (r < 0) {
- printf("error %d at pos %d: %s\n", r, errpos, &js[errpos]);
+ printf("error %d at pos %d: %s\n", r, parser.pos, &js[parser.pos]);
exit(EXIT_FAILURE);
}
for (i = 0; i<NUM_TOKENS; i++) {
- jsmn_dump_obj(&tokens[i], js);
+ jsmn_dump_obj(&parser.tokens[i], js);
}
free(js);
diff --git a/jsmn.c b/jsmn.c
index dbf5b2fba..a1c711624 100644
--- a/jsmn.c
+++ b/jsmn.c
@@ -2,77 +2,28 @@
#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;
-}
+void jsmn_init_parser(jsmn_parser *parser, const char *js,
+ jsontok_t *tokens, size_t num_tokens) {
+ unsigned int i;
-static int jsmn_parse_primitive(const unsigned char *js, jsontok_t *token) {
- const unsigned char *p;
+ parser->js = js;
+ parser->pos = 0;
+ parser->tokens = tokens;
+ parser->num_tokens = num_tokens;
- 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;
- }
+ for (i = 0; i < parser->num_tokens; i++) {
+ parser->tokens[i].start = -1;
+ parser->tokens[i].end = -1;
+ parser->tokens[i].type = JSON_OTHER;
}
- return -1;
}
-static jsontok_t *jsmn_token_start(struct jsmn_params *params, jsontype_t type, int pos) {
+jsontok_t *jsmn_start_token(jsmn_parser *parser, jsontype_t type) {
unsigned int i;
- jsontok_t *tokens = params->tokens;
- for (i = 0; i<params->num_tokens; i++) {
+ jsontok_t *tokens = parser->tokens;
+ for (i = 0; i<parser->num_tokens; i++) {
if (tokens[i].start == -1 && tokens[i].end == -1) {
- tokens[i].start = pos;
+ tokens[i].start = parser->pos;
tokens[i].type = type;
return &tokens[i];
}
@@ -80,98 +31,121 @@ static jsontok_t *jsmn_token_start(struct jsmn_params *params, jsontype_t type,
return NULL;
}
-static jsontok_t *jsmn_token_end(struct jsmn_params *params, jsontype_t type, int pos) {
+jsontok_t *jsmn_end_token(jsmn_parser *parser, jsontype_t type) {
int i;
- jsontok_t *tokens = params->tokens;
- for (i = params->num_tokens - 1; i>= 0; i--) {
+ jsontok_t *tokens = parser->tokens;
+ for (i = parser->num_tokens - 1; i>= 0; i--) {
if (tokens[i].type == type && tokens[i].start != -1 && tokens[i].end == -1) {
- tokens[i].end = pos;
+ tokens[i].end = parser->pos;
return &tokens[i];
}
}
return NULL;
}
-int jsmn_parse(const unsigned char *js, jsontok_t *tokens, size_t num_tokens, int *errpos) {
+static int jsmn_parse_primitive(jsmn_parser *parser) {
+ const char *js;
+ jsontok_t *token;
-#define jsmn_return(error) \
- do { \
- if ((errpos) != NULL) { \
- *(errpos) = (p - js); \
- } \
- return (error); \
- } while (0)
+ js = parser->js;
-#define jsmn_assert(cond, error) \
- if (!(cond)) { \
- jsmn_return(error); \
+ token = jsmn_start_token(parser, JSON_NUMBER);
+
+ for (; js[parser->pos] != '\0'; parser->pos++) {
+ switch (js[parser->pos]) {
+ case '\t' : case '\r' : case '\n' : case ' ' :
+ case ',' : case ']' : case '}' :
+ token->end = parser->pos;
+ parser->pos--;
+ return JSMN_SUCCESS;
+ }
+ if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+ return JSMN_ERROR_INVAL;
+ }
}
+ return JSMN_ERROR_PART;
+}
- struct jsmn_params params;
- int r;
- unsigned int i;
- const unsigned char *p;
- jsontype_t type;
- jsontok_t *cur_token;
+static int jsmn_parse_string(jsmn_parser *parser) {
+ const char *js;
+ jsontok_t *token;
+
+ js = parser->js;
- params.num_tokens = num_tokens;
- params.tokens = tokens;
- params.errpos = errpos;
+ /* Check if string begins from a quote */
+ if (js[parser->pos] != '\"') {
+ return JSMN_ERROR_INVAL;
+ }
- for (i = 0; i<num_tokens; i++) {
- tokens[i].start = tokens[i].end = -1;
- tokens[i].type = JSON_OTHER;
+ parser->pos++;
+
+ token = jsmn_start_token(parser, JSON_STRING);
+ /* Skip starting quote */
+ for (; js[parser->pos] != '\0'; parser->pos++) {
+ char c = js[parser->pos];
+
+ /* Quote: end of string */
+ if (c == '\"') {
+ token->end = parser->pos;
+ return JSMN_SUCCESS;
+ }
+
+ /* Backslash: Quoted symbol expected */
+ if (c == '\\') {
+ parser->pos++;
+ switch (js[parser->pos]) {
+ /* 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 JSMN_ERROR_INVAL;
+ }
+ }
}
+ return JSMN_ERROR_PART;
+}
+
- for (p = js; *p != '\0'; ) {
- switch (*p) {
+jsmnerr_t jsmn_parse(jsmn_parser *parser) {
+ const char *js;
+ jsontype_t type;
+ jsontok_t *token;
+
+ js = parser->js;
+
+ for (; js[parser->pos] != '\0'; parser->pos++) {
+ char c;
+ c = js[parser->pos];
+ switch (c) {
case '{': case '[':
- type = (*p == '{' ? JSON_OBJECT : JSON_ARRAY);
- cur_token = jsmn_token_start(&params, type, p - js);
- jsmn_assert(cur_token != NULL, JSMN_ERROR_NOMEM);
+ type = (c == '{' ? JSON_OBJECT : JSON_ARRAY);
+ token = jsmn_start_token(parser, type);
break;
- case '}' : case ']':
- type = (*p == '}' ? JSON_OBJECT : JSON_ARRAY);
- cur_token = jsmn_token_end(&params, type, p - js + 1);
- jsmn_assert(cur_token != NULL, JSMN_ERROR_PART);
+ case '}': case ']':
+ type = (c == '}' ? JSON_OBJECT : JSON_ARRAY);
+ token = jsmn_end_token(parser, type);
break;
-
case '-': case '0': case '1' : case '2': case '3' : case '4':
case '5': case '6': case '7' : case '8': case '9':
- cur_token = jsmn_token_start(&params, JSON_NUMBER, p - js);
- jsmn_assert(cur_token != NULL, JSMN_ERROR_NOMEM);
- r = jsmn_parse_primitive(js, cur_token);
- jsmn_assert(r == 0, JSMN_ERROR_INVAL);
- p = &js[cur_token->end] - 1;
- break;
case 't': case 'f': case 'n' :
- cur_token = jsmn_token_start(&params, JSON_OTHER, p - js);
- jsmn_assert(cur_token != NULL, JSMN_ERROR_NOMEM);
- r = jsmn_parse_primitive(js, cur_token);
- jsmn_assert(r == 0, JSMN_ERROR_INVAL);
- p = &js[cur_token->end] - 1;
+ jsmn_parse_primitive(parser);
break;
-
case '\"':
- cur_token = jsmn_token_start(&params, JSON_STRING, p - js);
- jsmn_assert(cur_token != NULL, JSMN_ERROR_NOMEM);
- r = jsmn_parse_string(js, cur_token);
- jsmn_assert(r == 0, JSMN_ERROR_INVAL);
- p = &js[cur_token->end];
+ jsmn_parse_string(parser);
break;
-
case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ':
break;
-
default:
- jsmn_return(JSMN_ERROR_INVAL);
+ return JSMN_ERROR_INVAL;
}
- p++;
}
- if (errpos != NULL) *errpos = 0;
- return 0;
-#undef jsmn_return
-#undef jsmn_assert
+ return JSMN_SUCCESS;
}
diff --git a/jsmn.h b/jsmn.h
index 408c53843..f045a0853 100644
--- a/jsmn.h
+++ b/jsmn.h
@@ -11,10 +11,10 @@
*/
typedef enum {
JSON_OTHER = 0,
- JSON_OBJECT,
- JSON_ARRAY,
- JSON_STRING,
- JSON_NUMBER
+ JSON_OBJECT = 1,
+ JSON_ARRAY = 2,
+ JSON_STRING = 3,
+ JSON_NUMBER = 4
} jsontype_t;
typedef enum {
@@ -37,9 +37,26 @@ typedef struct {
} jsontok_t;
/**
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string
+ */
+typedef struct {
+ const char *js;
+ unsigned int pos;
+ size_t num_tokens;
+ jsontok_t *tokens;
+} jsmn_parser;
+
+/**
+ * Create JSON parser over an array of tokens
+ */
+void jsmn_init_parser(jsmn_parser *parser, const char *js,
+ jsontok_t *tokens, size_t num_tokens);
+
+/**
* Run JSON parser. It parses a JSON data string into and array of tokens, each describing
* a single JSON object.
*/
-int jsmn_parse(const unsigned char *js, jsontok_t *tokens, size_t num_tokens, int *errpos);
+jsmnerr_t jsmn_parse(jsmn_parser *parser);
#endif /* __JSMN_H_ */