diff options
| author | Robin Haberkorn <rhaberkorn@fmsbw.de> | 2026-08-02 15:04:09 +0200 |
|---|---|---|
| committer | Robin Haberkorn <rhaberkorn@fmsbw.de> | 2026-08-10 23:55:40 +0200 |
| commit | 9b78fc83dbd29b5594431b1c49b7d13865141aaa (patch) | |
| tree | 8dff26ad46b7c44b32cdea7d37918c2dc31bb908 | |
| parent | d00ff9b4d72eff882eac4529d9e3c4cd9423cc4c (diff) | |
imported sj.h - a minimalist JSON parser
It will be useful for implementing LSP support.
It does not have JSON escape/unescape functions, so those
will still have to be written.
Source: https://github.com/rxi/sj.h
| -rw-r--r-- | Makefile.am | 5 | ||||
| -rw-r--r-- | contrib/sj.h/LICENSE | 24 | ||||
| -rw-r--r-- | contrib/sj.h/sj.h | 156 | ||||
| -rw-r--r-- | debian/copyright | 28 | ||||
| -rw-r--r-- | doc/sciteco.7.template | 1 |
5 files changed, 213 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index 567a3ec..f72d246 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,9 +8,12 @@ endif SUBDIRS = lib $(MAYBE_DLMALLOC) contrib/rb3ptr contrib/terex \ src tests doc +EXTRA_DIST = contrib/sj.h/sj.h \ + contrib/sj.h/LICENSE + dist_scitecodata_DATA = fallback.teco_ini -EXTRA_DIST = README TODO +EXTRA_DIST += README TODO # Used in many packaging recipes dist_noinst_SCRIPTS = gtk-broadway-run.sh diff --git a/contrib/sj.h/LICENSE b/contrib/sj.h/LICENSE new file mode 100644 index 0000000..c32dd18 --- /dev/null +++ b/contrib/sj.h/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <https://unlicense.org/>
\ No newline at end of file diff --git a/contrib/sj.h/sj.h b/contrib/sj.h/sj.h new file mode 100644 index 0000000..60bea9e --- /dev/null +++ b/contrib/sj.h/sj.h @@ -0,0 +1,156 @@ +// sj.h - v0.4 - rxi 2025 +// public domain - no warranty implied, use at your own risk + +#ifndef SJ_H +#define SJ_H + +#include <stddef.h> +#include <stdbool.h> + +typedef struct { + char *data, *cur, *end; + int depth; + char *error; +} sj_Reader; + +typedef struct { + int type; + char *start, *end; + int depth; +} sj_Value; + +enum { SJ_ERROR, SJ_END, SJ_ARRAY, SJ_OBJECT, SJ_NUMBER, SJ_STRING, SJ_BOOL, SJ_NULL }; + +sj_Reader sj_reader(char *data, size_t len); +sj_Value sj_read(sj_Reader *r); +bool sj_iter_array(sj_Reader *r, sj_Value arr, sj_Value *val); +bool sj_iter_object(sj_Reader *r, sj_Value obj, sj_Value *key, sj_Value *val); +void sj_location(sj_Reader *r, int *line, int *col); + +#endif // #ifndef SJ_H + +#ifdef SJ_IMPL + + +sj_Reader sj_reader(char *data, size_t len) { + return (sj_Reader){ .data = data, .cur = data, .end = data + len }; +} + + +static bool sj__is_number_cont(char c) { + return (c >= '0' && c <= '9') + || c == 'e' || c == 'E' || c == '.' || c == '-' || c == '+'; +} + +static bool sj__is_string(char *cur, char *end, char *expect) { + while (*expect) { + if (cur == end || *cur != *expect) { + return false; + } + expect++, cur++; + } + return true; +} + + +sj_Value sj_read(sj_Reader *r) { + sj_Value res; +top: + if (r->error) { return (sj_Value){ .type = SJ_ERROR, .start = r->cur, .end = r->cur }; } + if (r->cur == r->end) { r->error = "unexpected eof"; goto top; } + res.start = r->cur; + + switch (*r->cur) { + case ' ': case '\n': case '\r': case '\t': + case ':': case ',': + r->cur++; + goto top; + + case '-': case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + res.type = SJ_NUMBER; + while (r->cur != r->end && sj__is_number_cont(*r->cur)) { r->cur++; } + break; + + case '"': + res.type = SJ_STRING; + res.start = ++r->cur; + for (;;) { + if ( r->cur == r->end) { r->error = "unclosed string"; goto top; } + if (*r->cur == '"') { break; } + if (*r->cur == '\\') { r->cur++; } + if ( r->cur != r->end) { r->cur++; } + } + res.end = r->cur++; + return res; + + case '{': case '[': + res.type = (*r->cur == '{') ? SJ_OBJECT : SJ_ARRAY; + res.depth = ++r->depth; + r->cur++; + break; + + case '}': case ']': + res.type = SJ_END; + if (--r->depth < 0) { + r->error = (*r->cur == '}') ? "stray '}'" : "stray ']'"; + goto top; + } + r->cur++; + break; + + case 'n': case 't': case 'f': + res.type = (*r->cur == 'n') ? SJ_NULL : SJ_BOOL; + if (sj__is_string(r->cur, r->end, "null")) { r->cur += 4; break; } + if (sj__is_string(r->cur, r->end, "true")) { r->cur += 4; break; } + if (sj__is_string(r->cur, r->end, "false")) { r->cur += 5; break; } + // fallthrough + + default: + r->error = "unknown token"; + goto top; + } + res.end = r->cur; + return res; +} + + +static void sj__discard_until(sj_Reader *r, int depth) { + sj_Value val; + val.type = SJ_NULL; + while (r->depth != depth && val.type != SJ_ERROR) { + val = sj_read(r); + } +} + + +bool sj_iter_array(sj_Reader *r, sj_Value arr, sj_Value *val) { + sj__discard_until(r, arr.depth); + *val = sj_read(r); + if (val->type == SJ_ERROR || val->type == SJ_END) { return false; } + return true; +} + + +bool sj_iter_object(sj_Reader *r, sj_Value obj, sj_Value *key, sj_Value *val) { + sj__discard_until(r, obj.depth); + *key = sj_read(r); + if (key->type == SJ_ERROR || key->type == SJ_END) { return false; } + *val = sj_read(r); + if (val->type == SJ_END) { r->error = "unexpected object end"; return false; } + if (val->type == SJ_ERROR) { return false; } + return true; +} + + +void sj_location(sj_Reader *r, int *line, int *col) { + int ln = 1, cl = 1; + for (char *p = r->data; p != r->cur; p++) { + if (*p == '\n') { ln++; cl = 0; } + cl++; + } + *line = ln; + *col = cl; +} + +#endif // #ifdef SJ_IMPL
\ No newline at end of file diff --git a/debian/copyright b/debian/copyright index 35a8a49..b851048 100644 --- a/debian/copyright +++ b/debian/copyright @@ -33,6 +33,34 @@ License: MIT IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Files: contrib/sj.h/*.h +Copyright: Public Domain +License: Unlicense + This is free and unencumbered software released into the public domain. + . + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + . + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + . + For more information, please refer to <https://unlicense.org/> + Files: contrib/terex/*.c contrib/terex/*.h Copyright: Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. License: diff --git a/doc/sciteco.7.template b/doc/sciteco.7.template index 9d257a2..b62a371 100644 --- a/doc/sciteco.7.template +++ b/doc/sciteco.7.template @@ -2553,6 +2553,7 @@ Curses builds are based on the \fIScinterm\fP Scintilla backend by Mitchell. work for Tcl 8.1. Many builds of \*(ST use the \fIdlmalloc\fP malloc() replacement by Doug Lea. Red-Black trees use the \fIrb3ptr\fP library by Jens Stimpfle. +\fIsj.h\fP by rxi is helping with parsing JSON. .LP \*(ST is inspired by \fIVideo TECO\fP by Paul Cantrell. The first \fITECO\fP was written by Dan Murphy in 1962. |
