plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

commit ef4c04671995054ba459d9c894eb94d51fac1cb2
parent c85cd9b72c57aedcaec989c8910a72ac3df46d32
Author: ssnf <ssnf@ssnf.xyz>
Date:   Fri, 22 Aug 2025 13:09:34 +0000

json

Diffstat:
Ainclude/json.h | 34++++++++++++++++++++++++++++++++++
Asrc/libjson/json.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/libjson/mkfile | 8++++++++
3 files changed, 196 insertions(+), 0 deletions(-)

diff --git a/include/json.h b/include/json.h @@ -0,0 +1,34 @@ +AUTOLIB(json) + +typedef enum { + JNone, + JNum, + JStr = 1 << 1, + JObj = 1 << 2, + JErr = 1 << 3 +} JsonType; + +typedef union { + String s; + double n; + char c; +} JsonVal; + +typedef struct { + String k; + JsonVal v; + JsonType t; +} JsonObj; + +typedef struct { + ulong st[8]; /*obj stack*/ + String s; /*data buffer*/ + JsonObj* o; /*obj vector*/ + JsonObj* cur; /*cur obj*/ + ulong n; /*stack number*/ + ulong pos; /*buffer pos*/ +} Json; + +void json_close(Json *j); +int json_init(Json *j, char *file); +JsonType json_next(Json *j, JsonType t); diff --git a/src/libjson/json.c b/src/libjson/json.c @@ -0,0 +1,154 @@ +#include <u.h> +#include <libc.h> + +#include <bio.h> +#include <str.h> +#include <vec.h> +#include <json.h> + +static JsonType +err(Json *j, char *msg) +{ + ulong i, n; + + if (!j->cur->k.s) + Strinit(&j->cur->k); + if (j->cur->t == JStr) + Strclose(&j->cur->v.s); + Strdup(&j->cur->k, Str(msg)); + n = 1; + for (i = 0; i < j->pos; ++i) + if (j->s.s[i] == '\n') + ++n; + j->cur->v.n = n; + j->cur->t = JErr; + return JNone; +} + +static void +JObjclose(JsonObj *o) +{ + if (o->k.s) + Strclose(&o->k); + if (o->t == JStr) + Strclose(&o->v.s); +} + +void +json_close(Json *j) +{ + Strclose(&j->s); + Vecclose(&j->o); +} + +int +json_init(Json *j, char *file) +{ + int fd; + + fd = 0; + memset(j, 0, sizeof(*j)); + Strinit(&j->s); + if (file) { + fd = open(file, OREAD); + if (fd == -1) + return 0; + } + Strgetf(&j->s, fd); + Vecinitf(&j->o, nil, JObjclose); + close(fd); + return 1; +} + +JsonType +json_next(Json *j, JsonType t) +{ + ulong i; + char c, *p, *q; + + if (j->cur && j->cur->t == JErr) + return JNone; +next: + if (j->pos == j->s.n) + return JNone; + j->cur = Vecadd(&j->o); +loop: + for (;j->pos < j->s.n && isspace(j->s.s[j->pos]); ++j->pos); + c = j->s.s[j->pos++]; + switch (c) { + case '{': + case '[': + if (j->cur->t != JNone) + return err(j, "double value"); + if (j->n + 1 >= nelem(j->st)) + return err(j, "Stack too big!" + " Fix your damn data"); + j->st[j->n++] = j->cur - j->o; + j->cur->v.c = c; + j->cur->t = JObj; + break; + case ']': + case '}': + if (!j->n) + return err(j, "bad stack"); + --j->n; + case ',': + if (j->cur->k.s && j->cur->t == JNone) + return err(j, "missing value"); + if (j->cur->t == JNone) + goto loop; + break; + case '"': + if (j->cur->t != JNone) + return err(j, "double value"); + for (i = j->pos; i < j->s.n; ++i) { + c = j->s.s[i]; + if (c == '\n') + return err(j, "invalid value"); + if (c == '"') + break; + if (c != '\\') + continue; + /* there is no escape in Ba Sing Se */ + c = j->s.s[i + 1]; + if (c == '\\' || c == '"') + ++i; + } + Strinit(&j->cur->v.s); + Stradds(&j->cur->v.s + , Strn(j->s.s + j->pos, i - j->pos)); + j->pos = i + 1; + j->cur->t = JStr; + goto loop; + case ':': + if (j->cur->k.s) + return err(j, "double key"); + j->cur->k = j->cur->v.s; + memset(&j->cur->v, 0, sizeof(j->cur->v)); + j->cur->t = JNone; + goto loop; + default: + if (--j->pos == j->s.n) + break; + if (j->cur->t != JNone) + return err(j, "double value"); + p = j->s.s + j->pos; + j->cur->v.n = strtod(p, &q); + if (p != q) { + j->pos += q - p; + j->cur->t = JNum; + goto loop; + } + i = strcspn(p, "{[:,]} \n\r\t"); + Strinit(&j->cur->v.s); + Stradds(&j->cur->v.s, Strn(p, i)); + j->pos += i; + j->cur->t = JStr; + goto loop; + } + if (t == JNone || (t & j->cur->t)) + return j->cur->t; + if (j->cur->t == JObj) + for (i = j->n - 1; json_next(j, 0) && j->n != i;); + goto next; +} diff --git a/src/libjson/mkfile b/src/libjson/mkfile @@ -0,0 +1,8 @@ +<$PLAN9/src/mkhdr + +LIB=libjson.a + +OFILES=json.$O +HFILES= $PLAN9/include/json.h + +<$PLAN9/src/mksyslib