ref: ce337681f8bd4f02899db63d8c64bc4ccd94095e
parent: 72417b0cf814952d4e6e3e8858bf595d97a3c459
author: BurnZeZ <brz-9dev@intma.in>
date: Sun Oct 27 11:44:33 EDT 2013
make libjson from /sys/src/cmd/btc/json.c
--- /dev/null
+++ b/sys/include/json.h
@@ -1,0 +1,35 @@
+#pragma src "/sys/src/libjson"
+#pragma lib "libjson.a"
+
+typedef struct JSONEl JSONEl;
+typedef struct JSON JSON;
+
+enum {+ JSONNull,
+ JSONBool,
+ JSONNumber,
+ JSONString,
+ JSONArray,
+ JSONObject,
+};
+
+struct JSONEl {+ char *name;
+ JSON *val;
+ JSONEl *next;
+};
+
+struct JSON
+{+ int t;
+ union {+ double n;
+ char *s;
+ JSONEl *first;
+ };
+};
+
+JSON* jsonparse(char *);
+void jsonfree(JSON *);
+JSON* jsonbyname(JSON *, char *);
+char* jsonstr(JSON *);
--- a/sys/src/cmd/btc/httpfs.c
+++ b/sys/src/cmd/btc/httpfs.c
@@ -4,8 +4,8 @@
#include <thread.h>
#include <9p.h>
#include <String.h>
+#include <json.h>
#include "dat.h"
-#include "json.h"
void gofs(void);
--- a/sys/src/cmd/btc/json.c
+++ /dev/null
@@ -1,326 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <ctype.h>
-#include "json.h"
-
-typedef struct Lex Lex;
-
-enum {- TEOF,
- TSTRING = (1<<(8*sizeof(Rune)))+1,
- TNUM,
- TNULL,
- TFALSE,
- TTRUE,
-};
-
-struct Lex
-{- char *s;
- int t;
- double n;
- char buf[4096];
- Rune peeked;
- jmp_buf jmp;
- int canjmp;
-};
-
-static Rune
-getch(Lex *l)
-{- Rune r;
-
- if(l->peeked){- r = l->peeked;
- l->peeked = 0;
- return r;
- }
- l->s += chartorune(&r, l->s);
- return r;
-}
-
-static Rune
-peekch(Lex *l)
-{- if(!l->peeked)
- l->peeked = getch(l);
- return l->peeked;
-}
-
-static int
-lex(Lex *l)
-{- Rune r;
- char *t;
-
- for(;;){- r = peekch(l);
- if(r != 0x20 && r != 0x09 && r != 0x0A && r != 0x0D)
- break;
- getch(l);
- }
- r = getch(l);
- if(r == ']' && l->canjmp)
- longjmp(l->jmp, 1);
- l->canjmp = 0;
- if(r == 0 || r == '{' || r == '[' || r == ']' || r == '}' || r == ':' || r == ','){- l->t = r;
- return 0;
- }
- if(r >= 0x80 || isalpha(r)){- t = l->buf;
- for(;;){- t += runetochar(t, &r);
- if(t >= l->buf + sizeof(l->buf)){- werrstr("json: literal too long");- return -1;
- }
- r = peekch(l);
- if(r < 0x80 && !isalpha(r))
- break;
- getch(l);
- }
- *t = 0;
- if(strcmp(l->buf, "true") == 0)
- l->t = TTRUE;
- else if(strcmp(l->buf, "false") == 0)
- l->t = TFALSE;
- else if(strcmp(l->buf, "null") == 0)
- l->t = TNULL;
- else{- werrstr("json: invalid literal");- return -1;
- }
- return 0;
- }
- if(isdigit(r) || r == '-'){- l->n = strtod(l->s-1, &l->s);
- l->t = TNUM;
- return 0;
- }
- if(r == '"'){- t = l->buf;
- for(;;){- r = getch(l);
- if(r == '"')
- break;
- if(r < ' '){- werrstr("json: invalid char in string %x", r);- return -1;
- }
- if(r == '\\'){- r = getch(l);
- switch(r){- case 'n':
- r = '\n';
- break;
- case 'r':
- r = '\r';
- break;
- case 't':
- r = '\t';
- break;
- case 'f':
- r = '\f';
- break;
- case 'b':
- r = '\b';
- break;
- case '"': case '/': case '\\':
- break;
- default:
- werrstr("json: invalid escape sequence \\%C", r);- return -1;
- }
- }
- t += runetochar(t, &r);
- if(t >= l->buf + sizeof(l->buf)){- werrstr("json: string too long");- return -1;
- }
- }
- *t = 0;
- l->t = TSTRING;
- return 0;
- }
- werrstr("json: invalid char %C", peekch(l));- return -1;
-}
-
-static JSON*
-jsonobj(Lex *l)
-{- JSON *j;
- JSONEl *e;
- JSONEl **ln;
- int obj;
-
- j = mallocz(sizeof(*j), 1);
- if(j == nil)
- return nil;
- if(lex(l) < 0){-error:
- free(j);
- return nil;
- }
- switch(l->t){- case TEOF:
- werrstr("json: unexpected eof");- goto error;
- case TNULL:
- j->t = JSONNull;
- break;
- case TTRUE:
- j->t = JSONBool;
- j->n = 1;
- break;
- case TFALSE:
- j->t = JSONBool;
- j->n = 0;
- break;
- case TSTRING:
- j->t = JSONString;
- j->s = strdup(l->buf);
- if(j->s == nil)
- goto error;
- break;
- case TNUM:
- j->t = JSONNumber;
- j->n = l->n;
- break;
- case '{':- case '[':
- obj = l->t == '{';- ln = &j->first;
- e = nil;
- if(obj){- j->t = JSONObject;
- if(lex(l) < 0)
- goto abort;
- if(l->t == '}')
- return j;
- goto firstobj;
- }else{- j->t = JSONArray;
- l->canjmp = 1;
- if(setjmp(l->jmp) > 0){- free(e);
- return j;
- }
- }
- for(;;){- if(obj){- if(lex(l) < 0)
- goto abort;
- firstobj:
- if(l->t != TSTRING){- werrstr("json: syntax error, not string");- goto abort;
- }
- e = mallocz(sizeof(*e), 1);
- if(e == nil)
- goto abort;
- e->name = strdup(l->buf);
- if(e->name == nil || lex(l) < 0){- free(e);
- goto abort;
- }
- if(l->t != ':'){- werrstr("json: syntax error, not colon");- free(e);
- goto abort;
- }
- }else{- e = mallocz(sizeof(*e), 1);
- if(e == nil)
- goto abort;
- }
- e->val = jsonobj(l);
- if(e->val == nil){- free(e);
- goto abort;
- }
- *ln = e;
- ln = &e->next;
- if(lex(l) < 0)
- goto abort;
- if(l->t == (obj ? '}' : ']'))
- break;
- if(l->t != ','){- werrstr("json: syntax error, neither comma nor ending paren");- goto abort;
- }
- }
- break;
- abort:
- jsonfree(j);
- return nil;
- case ']': case '}': case ',': case ':':
- werrstr("json: unexpected %C", l->t);- goto error;
- default:
- werrstr("json: the front fell off");- goto error;
- }
- return j;
-}
-
-JSON*
-jsonparse(char *s)
-{- Lex l;
-
- memset(&l, 0, sizeof(l));
- l.s = s;
- return jsonobj(&l);
-}
-
-void
-jsonfree(JSON *j)
-{- JSONEl *e, *f;
-
- switch(j->t){- case JSONString:
- if(j->s)
- free(j->s);
- break;
- case JSONArray: case JSONObject:
- for(e = j->first; e != nil; e = f){- if(e->name)
- free(e->name);
- jsonfree(e->val);
- f = e->next;
- free(e);
- }
- }
- free(j);
-}
-
-JSON *
-jsonbyname(JSON *j, char *n)
-{- JSONEl *e;
-
- if(j->t != JSONObject){- werrstr("not an object");- return nil;
- }
- for(e = j->first; e != nil; e = e->next)
- if(strcmp(e->name, n) == 0)
- return e->val;
- werrstr("key '%s' not found", n);- return nil;
-}
-
-char *
-jsonstr(JSON *j)
-{- if(j == nil)
- return nil;
- if(j->t != JSONString){- werrstr("not a string");- return nil;
- }
- return j->s;
-}
--- a/sys/src/cmd/btc/json.h
+++ /dev/null
@@ -1,32 +1,0 @@
-typedef struct JSONEl JSONEl;
-typedef struct JSON JSON;
-
-enum {- JSONNull,
- JSONBool,
- JSONNumber,
- JSONString,
- JSONArray,
- JSONObject,
-};
-
-struct JSONEl {- char *name;
- JSON *val;
- JSONEl *next;
-};
-
-struct JSON
-{- int t;
- union {- double n;
- char *s;
- JSONEl *first;
- };
-};
-
-JSON* jsonparse(char *);
-void jsonfree(JSON *);
-JSON* jsonbyname(JSON *, char *);
-char* jsonstr(JSON *);
--- a/sys/src/cmd/btc/mkfile
+++ b/sys/src/cmd/btc/mkfile
@@ -4,9 +4,6 @@
BIN=/$objtype/bin/btc
-OFILES=\
- json.$O\
-
HFILES=\
dat.h\
--- /dev/null
+++ b/sys/src/libjson/json.c
@@ -1,0 +1,326 @@
+#include <u.h>
+#include <libc.h>
+#include <ctype.h>
+#include <json.h>
+
+typedef struct Lex Lex;
+
+enum {+ TEOF,
+ TSTRING = (1<<(8*sizeof(Rune)))+1,
+ TNUM,
+ TNULL,
+ TFALSE,
+ TTRUE,
+};
+
+struct Lex
+{+ char *s;
+ int t;
+ double n;
+ char buf[4096];
+ Rune peeked;
+ jmp_buf jmp;
+ int canjmp;
+};
+
+static Rune
+getch(Lex *l)
+{+ Rune r;
+
+ if(l->peeked){+ r = l->peeked;
+ l->peeked = 0;
+ return r;
+ }
+ l->s += chartorune(&r, l->s);
+ return r;
+}
+
+static Rune
+peekch(Lex *l)
+{+ if(!l->peeked)
+ l->peeked = getch(l);
+ return l->peeked;
+}
+
+static int
+lex(Lex *l)
+{+ Rune r;
+ char *t;
+
+ for(;;){+ r = peekch(l);
+ if(r != 0x20 && r != 0x09 && r != 0x0A && r != 0x0D)
+ break;
+ getch(l);
+ }
+ r = getch(l);
+ if(r == ']' && l->canjmp)
+ longjmp(l->jmp, 1);
+ l->canjmp = 0;
+ if(r == 0 || r == '{' || r == '[' || r == ']' || r == '}' || r == ':' || r == ','){+ l->t = r;
+ return 0;
+ }
+ if(r >= 0x80 || isalpha(r)){+ t = l->buf;
+ for(;;){+ t += runetochar(t, &r);
+ if(t >= l->buf + sizeof(l->buf)){+ werrstr("json: literal too long");+ return -1;
+ }
+ r = peekch(l);
+ if(r < 0x80 && !isalpha(r))
+ break;
+ getch(l);
+ }
+ *t = 0;
+ if(strcmp(l->buf, "true") == 0)
+ l->t = TTRUE;
+ else if(strcmp(l->buf, "false") == 0)
+ l->t = TFALSE;
+ else if(strcmp(l->buf, "null") == 0)
+ l->t = TNULL;
+ else{+ werrstr("json: invalid literal");+ return -1;
+ }
+ return 0;
+ }
+ if(isdigit(r) || r == '-'){+ l->n = strtod(l->s-1, &l->s);
+ l->t = TNUM;
+ return 0;
+ }
+ if(r == '"'){+ t = l->buf;
+ for(;;){+ r = getch(l);
+ if(r == '"')
+ break;
+ if(r < ' '){+ werrstr("json: invalid char in string %x", r);+ return -1;
+ }
+ if(r == '\\'){+ r = getch(l);
+ switch(r){+ case 'n':
+ r = '\n';
+ break;
+ case 'r':
+ r = '\r';
+ break;
+ case 't':
+ r = '\t';
+ break;
+ case 'f':
+ r = '\f';
+ break;
+ case 'b':
+ r = '\b';
+ break;
+ case '"': case '/': case '\\':
+ break;
+ default:
+ werrstr("json: invalid escape sequence \\%C", r);+ return -1;
+ }
+ }
+ t += runetochar(t, &r);
+ if(t >= l->buf + sizeof(l->buf)){+ werrstr("json: string too long");+ return -1;
+ }
+ }
+ *t = 0;
+ l->t = TSTRING;
+ return 0;
+ }
+ werrstr("json: invalid char %C", peekch(l));+ return -1;
+}
+
+static JSON*
+jsonobj(Lex *l)
+{+ JSON *j;
+ JSONEl *e;
+ JSONEl **ln;
+ int obj;
+
+ j = mallocz(sizeof(*j), 1);
+ if(j == nil)
+ return nil;
+ if(lex(l) < 0){+error:
+ free(j);
+ return nil;
+ }
+ switch(l->t){+ case TEOF:
+ werrstr("json: unexpected eof");+ goto error;
+ case TNULL:
+ j->t = JSONNull;
+ break;
+ case TTRUE:
+ j->t = JSONBool;
+ j->n = 1;
+ break;
+ case TFALSE:
+ j->t = JSONBool;
+ j->n = 0;
+ break;
+ case TSTRING:
+ j->t = JSONString;
+ j->s = strdup(l->buf);
+ if(j->s == nil)
+ goto error;
+ break;
+ case TNUM:
+ j->t = JSONNumber;
+ j->n = l->n;
+ break;
+ case '{':+ case '[':
+ obj = l->t == '{';+ ln = &j->first;
+ e = nil;
+ if(obj){+ j->t = JSONObject;
+ if(lex(l) < 0)
+ goto abort;
+ if(l->t == '}')
+ return j;
+ goto firstobj;
+ }else{+ j->t = JSONArray;
+ l->canjmp = 1;
+ if(setjmp(l->jmp) > 0){+ free(e);
+ return j;
+ }
+ }
+ for(;;){+ if(obj){+ if(lex(l) < 0)
+ goto abort;
+ firstobj:
+ if(l->t != TSTRING){+ werrstr("json: syntax error, not string");+ goto abort;
+ }
+ e = mallocz(sizeof(*e), 1);
+ if(e == nil)
+ goto abort;
+ e->name = strdup(l->buf);
+ if(e->name == nil || lex(l) < 0){+ free(e);
+ goto abort;
+ }
+ if(l->t != ':'){+ werrstr("json: syntax error, not colon");+ free(e);
+ goto abort;
+ }
+ }else{+ e = mallocz(sizeof(*e), 1);
+ if(e == nil)
+ goto abort;
+ }
+ e->val = jsonobj(l);
+ if(e->val == nil){+ free(e);
+ goto abort;
+ }
+ *ln = e;
+ ln = &e->next;
+ if(lex(l) < 0)
+ goto abort;
+ if(l->t == (obj ? '}' : ']'))
+ break;
+ if(l->t != ','){+ werrstr("json: syntax error, neither comma nor ending paren");+ goto abort;
+ }
+ }
+ break;
+ abort:
+ jsonfree(j);
+ return nil;
+ case ']': case '}': case ',': case ':':
+ werrstr("json: unexpected %C", l->t);+ goto error;
+ default:
+ werrstr("json: the front fell off");+ goto error;
+ }
+ return j;
+}
+
+JSON*
+jsonparse(char *s)
+{+ Lex l;
+
+ memset(&l, 0, sizeof(l));
+ l.s = s;
+ return jsonobj(&l);
+}
+
+void
+jsonfree(JSON *j)
+{+ JSONEl *e, *f;
+
+ switch(j->t){+ case JSONString:
+ if(j->s)
+ free(j->s);
+ break;
+ case JSONArray: case JSONObject:
+ for(e = j->first; e != nil; e = f){+ if(e->name)
+ free(e->name);
+ jsonfree(e->val);
+ f = e->next;
+ free(e);
+ }
+ }
+ free(j);
+}
+
+JSON *
+jsonbyname(JSON *j, char *n)
+{+ JSONEl *e;
+
+ if(j->t != JSONObject){+ werrstr("not an object");+ return nil;
+ }
+ for(e = j->first; e != nil; e = e->next)
+ if(strcmp(e->name, n) == 0)
+ return e->val;
+ werrstr("key '%s' not found", n);+ return nil;
+}
+
+char *
+jsonstr(JSON *j)
+{+ if(j == nil)
+ return nil;
+ if(j->t != JSONString){+ werrstr("not a string");+ return nil;
+ }
+ return j->s;
+}
--- /dev/null
+++ b/sys/src/libjson/mkfile
@@ -1,0 +1,10 @@
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libjson.a
+OFILES=\
+ json.$O
+
+HFILES=\
+ /sys/include/json.h
+
+</sys/src/cmd/mksyslib
--- a/sys/src/mkfile
+++ b/sys/src/mkfile
@@ -22,6 +22,7 @@
libhttpd\
libip\
liblex\
+ libjson\
libmach\
libmemdraw\
libmemlayer\
--
⑨