summaryrefslogtreecommitdiff
path: root/jsmn.c
diff options
context:
space:
mode:
authorSerge A. Zaitsev <devnull@localhost>2010-11-15 13:11:08 +0200
committerSerge A. Zaitsev <devnull@localhost>2010-11-15 13:11:08 +0200
commitf22c2d30b7c73ebf1a7815b4a3eb5df18c251ed1 (patch)
treed57979b1a9c4299e4994b6806a154fa50c59ab3e /jsmn.c
Initial commit. Demo program is included in the jsmn.c code. Ugly names and no comments. Please, don't read this changeset
Diffstat (limited to 'jsmn.c')
-rw-r--r--jsmn.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/jsmn.c b/jsmn.c
new file mode 100644
index 000000000..334249476
--- /dev/null
+++ b/jsmn.c
@@ -0,0 +1,198 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "jsmn.h"
+
+enum {
+ JSON_SKIP = 0,
+ JSON_OPEN = 1,
+ JSON_CLOSE = 2,
+ JSON_BARE = 3,
+ JSON_UNBARE = 4,
+ JSON_QUOTE = 5,
+ JSON_UNQUOTE = 6,
+ JSON_ERROR = 7
+};
+
+#define JSON_SYM_SKIP(sym) \
+ [sym] = JSON_SKIP
+
+#define JSON_SYM_ERROR(sym) \
+ [sym] = JSON_ERROR
+
+#define JSON_SYM_OPEN(sym) \
+ [sym] = JSON_OPEN
+
+#define JSON_SYM_CLOSE(sym) \
+ [sym] = JSON_CLOSE
+
+#define JSON_SYM_BARE(sym) \
+ [sym] = JSON_BARE
+
+#define JSON_SYM_UNBARE(sym) \
+ [sym] = JSON_UNBARE
+
+#define JSON_SYM_QUOTE(sym) \
+ [sym] = JSON_QUOTE
+
+#define JSON_SYM_UNQUOTE(sym) \
+ [sym] = JSON_UNQUOTE
+
+int jsmn_parse(const unsigned char *js, jsontok_t *tokens, size_t num_tokens, int **errpos) {
+
+ int jsmn_token_start(jsontype_t type, int pos) {
+ unsigned int i;
+ for (i = 0; i<num_tokens; i++) {
+ if (tokens[i].start == -1 && tokens[i].end == -1) {
+ tokens[i].start = pos;
+ tokens[i].type = type;
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ int jsmn_token_end(jsontype_t type, int pos) {
+ unsigned int i;
+ for (i = num_tokens - 1; i>= 0; i--) {
+ if (tokens[i].type == type && tokens[i].start != -1 && tokens[i].end == -1) {
+ tokens[i].end = pos;
+ return 0;
+ }
+ }
+ return -1;
+ }
+
+ const unsigned char *p;
+ jsontok_t *cur_token;
+
+ int obj_common[] = {
+ JSON_SYM_ERROR(0 ... 255),
+ JSON_SYM_SKIP('\t'), JSON_SYM_SKIP('\r'),JSON_SYM_SKIP('\n'),
+ JSON_SYM_SKIP(':'), JSON_SYM_SKIP(','), JSON_SYM_SKIP(' '),
+ JSON_SYM_QUOTE('\"'),
+ JSON_SYM_OPEN('['), JSON_SYM_CLOSE(']'),
+ JSON_SYM_OPEN('{'), JSON_SYM_CLOSE('}'),
+ JSON_SYM_BARE('-'), JSON_SYM_BARE('0'...'9'),
+ JSON_SYM_BARE('t'), JSON_SYM_BARE('f'), JSON_SYM_BARE('n') /* true false null */
+ };
+
+ int obj_bare[] = {
+ JSON_SYM_ERROR(0 ... 31),
+ JSON_SYM_ERROR(127 ... 255),
+ JSON_SYM_SKIP(32 ... 126),
+ JSON_SYM_UNBARE('\t'), JSON_SYM_UNBARE(' '),
+ JSON_SYM_UNBARE('\r'), JSON_SYM_UNBARE('\n'),
+ JSON_SYM_UNBARE(','), JSON_SYM_UNBARE(']'),
+ JSON_SYM_UNBARE('}')
+ };
+
+ int obj_string[] = {
+ JSON_SYM_ERROR(0 ... 31), JSON_SYM_ERROR(127),
+ JSON_SYM_SKIP(32 ... 126),
+ JSON_SYM_UNQUOTE('\"'),
+ JSON_SYM_ERROR(248 ... 255),
+ };
+
+ int *obj_state = obj_common;
+
+ cur_token = tokens;
+
+ int i;
+ for (i = 0; i<num_tokens; i++) {
+ tokens[i].start = tokens[i].end = -1;
+ tokens[i].type = JSON_OTHER;
+ }
+
+ for (p = js; *p != '\0'; ) {
+ switch (obj_state[*p]) {
+ case JSON_ERROR:
+ if (errpos != NULL) {
+ *errpos = p;
+ }
+ return -1;
+
+ case JSON_OPEN:
+ jsmn_token_start(JSON_OBJECT, p - js);
+ break;
+ case JSON_CLOSE:
+ jsmn_token_end(JSON_OBJECT, p - js + 1);
+ break;
+
+ case JSON_BARE:
+ jsmn_token_start(JSON_OTHER, p - js);
+ obj_state = obj_bare;
+ break;
+ case JSON_UNBARE:
+ jsmn_token_end(JSON_OTHER, p - js);
+ obj_state = obj_common;
+ continue;
+
+ case JSON_QUOTE:
+ jsmn_token_start(JSON_STRING, p - js + 1);
+ obj_state = obj_string;
+ break;
+ case JSON_UNQUOTE:
+ jsmn_token_end(JSON_STRING, p - js);
+ obj_state = obj_common;
+ break;
+ case JSON_SKIP:
+ break;
+ }
+ p++;
+ }
+ return 0;
+}
+
+void json_dump_obj(jsontok_t *obj, const char *js) {
+ int len;
+
+ printf("[%d,%d]", obj->start, obj->end);
+ len = obj->end - obj->start;
+
+ char *type;
+ switch (obj->type) {
+ case JSON_OTHER:
+ type = "other";
+ break;
+ case JSON_STRING:
+ type = "string";
+ break;
+ case JSON_ARRAY:
+ type = "array";
+ break;
+ case JSON_OBJECT:
+ type = "object";
+ break;
+ }
+
+ printf(" %s ", type);
+
+ if (len > 0) {
+ char *s = strndup(&js[obj->start], len);
+ printf("%s", s);
+ free(s);
+ }
+ printf("\n");
+}
+
+int main(int argc, char *argv[]) {
+ int i;
+#define NUM_TOKENS 20
+ jsontok_t tokens[NUM_TOKENS];
+
+ const char *js =
+ "{"
+ "\"foo\": \"bar\","
+ "\"bar\": [1,2, 3],"
+ "\"obj\": { \"true\": false}"
+ "}";
+
+ jsmn_parse(js, tokens, NUM_TOKENS, NULL);
+
+ for (i = 0; i<NUM_TOKENS; i++) {
+ json_dump_obj(&tokens[i], js);
+ }
+
+ return 0;
+}