ref: 2dc7e311f43c41ecc412c237cbcb6293953c17e9
parent: 632b7adffbd137d9cbe95431fa6919f875c47e5b
author: BurnZeZ <[email protected]>
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\