Permalink
Browse files

first p0st woooo, not quite usable yet as it's in the process of gett…

…ing converted from a test harness
  • Loading branch information...
0 parents commit 8084600e3f0e27bc5af785716e7b0c8442ca8228 @quartzjer committed Sep 22, 2010
Showing with 149 additions and 0 deletions.
  1. +2 −0 Makefile
  2. +12 −0 README
  3. +93 −0 js0n.c
  4. +6 −0 js0n.h
  5. +29 −0 js0n_test.c
  6. +7 −0 test.js
2 Makefile
@@ -0,0 +1,2 @@
+all:
+ gcc -o js0n_test js0n_test.c js0n.c
12 README
@@ -0,0 +1,12 @@
+js0n - the "cheapest" c json parser possible?
+
+A one-pass super low overhead parsing walk of the raw bytes and no mem copying of any sort, fills in a simple array of offsets and lengths of the first depth array values or object key/values.
+
+Parsing this:
+
+{"foo":"bar","barbar":[1,2,3],"obj":{"a":"b"}}
+
+Would result in:
+
+2,3,8,3,14,6,22,7,30,3,35,9
+
93 js0n.c
@@ -0,0 +1,93 @@
+
+int js0n(unsigned char *js, unsigned int len, unsigned short **out)
+{
+ unsigned char buff[1024], *cur, *end;
+ int mode=0; // 0=structures 1=strings
+ int depth=0;
+ int kind=0; // 0=obj 1=array
+ char quote;
+ static void *gostruct[] =
+ {
+ [0 ... 255] = &&l_bad,
+ ['\t'] = &&l_ws, [' '] = &&l_ws, ['\r'] = &&l_ws, ['\n'] = &&l_ws,
+ ['"'] = &&l_quot,
+ [':'] = &&l_is,[','] = &&l_more,
+ ['['] = &&l_ko, [']'] = &&l_kc,
+ ['{'] = &&l_ko, ['}'] = &&l_kc,
+ ['-'] = &&l_bare, [48 ... 57] = &&l_bare, // 0-9
+ ['t'] = &&l_bare, ['f'] = &&l_bare, ['n'] = &&l_bare // true, false, null
+ };
+ static void *gobare[] =
+ {
+ [0 ... 31] = &&l_bad,
+ [32 ... 126] = &&l_char,
+ ['\t'] = &&l_unbare, [' '] = &&l_unbare, ['\r'] = &&l_unbare, ['\n'] = &&l_unbare,
+ [','] = &&l_unbare, [']'] = &&l_unbare, ['}'] = &&l_unbare,
+ [127 ... 255] = &&l_bad
+ };
+ static void *gostring[] =
+ {
+ [0 ... 31] = &&l_bad, [127] = &&l_bad,
+ [32 ... 126] = &&l_char,
+ ['\\'] = &&l_esc, ['"'] = &&l_quot,
+ [128 ... 255] = &&l_char
+ };
+ static void *goesc[] =
+ {
+ [0 ... 255] = &&l_bad,
+ ['"'] = &&l_unesc, ['\\'] = &&l_unesc, ['/'] = &&l_unesc, ['b'] = &&l_unesc,
+ ['f'] = &&l_unesc, ['n'] = &&l_unesc, ['r'] = &&l_unesc, ['t'] = &&l_unesc, ['u'] = &&l_unesc
+ };
+ static void **go = gostruct;
+
+ for(cur=js,end=js+len; cur<end; cur++)
+ {
+ goto *go[*cur];
+ l_loop:;
+ }
+
+ l_bad:
+ printf("bad char %d\n",*cur);
+ return 1;
+
+ l_char:
+ printf("%c",mode?'.':'*');
+ goto l_loop;
+
+ l_ko:
+ printf("%d%c",++depth,*cur);
+ goto l_loop;
+ l_kc:
+ printf("%d%c",--depth,*cur);
+ goto l_loop;
+
+ l_ws:
+ l_is:
+ l_more:
+ printf("%c",*cur);
+ goto l_loop;
+
+ l_quot:
+ printf("%c",*cur);
+ go = mode?gostruct:gostring;
+ mode^=1;
+ goto l_loop;
+
+ l_esc:
+ go = goesc;
+ goto l_loop;
+
+ l_unesc:
+ go = gostring;
+ goto l_loop;
+
+ l_bare:
+ go = gobare;
+ goto l_loop;
+
+ l_unbare:
+ go = gostruct;
+ goto *go[*cur];
+
+}
+
6 js0n.h
@@ -0,0 +1,6 @@
+
+// pass it a raw json string and length, it will return an array of unsigned shorts, see js0n.c for more
+int js0n(unsigned char *js, unsigned int len, unsigned short **out);
+
+// TODO: decode a string value, copy into new while unescaping things and unicode stuffs
+// int js0n(unsigned char *in, unsigned int len, unsigned char *out);
29 js0n_test.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include "js0n.h"
+
+int main(int argc, char **argv)
+{
+ unsigned char buff[1024], *json;
+ int len, lastlen=0;
+ unsigned short **res;
+ FILE *f;
+
+ if((f = fopen(argv[1],"r")) == NULL)
+ {
+ printf("uhoh opening %s\n",argv[1]);
+ exit(1);
+ }
+ while((len = fread(buff,1,1024,f)) > 0)
+ {
+ json = realloc(json,lastlen+len);
+ memcpy(json+lastlen,buff,len);
+ lastlen+=len;
+ }
+ fclose(f);
+ printf("got[%.*s]\n",lastlen,json);
+ return 0;
+}
+
7 test.js
@@ -0,0 +1,7 @@
+{
+ "foo":"b\"a and \\ r",
+ "bar":[1,2,3],
+ "baz":{"a":"b"},
+ "num":123.45,
+ "obj":{"true":false}
+}

0 comments on commit 8084600

Please sign in to comment.