From 312d9b88dba4dac3254fe3bdff4c49104cc94b2f Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Mon, 28 Apr 2025 11:14:01 +0100 Subject: [PATCH] Update TOML C99 library From https://github.com/cktan/tomlc99, merge commits after 894902820a3ea2f1ec470cd7fe338bde54045cf5 (2022-09-12) up to and including df627177cd1e80176c7a5245f26fd3b8e6187368 (2025-05-01) --- third_party/tomlc99/README.md | 6 ++- third_party/tomlc99/test1/build.sh | 9 ++-- third_party/tomlc99/test1/run.sh | 6 +-- third_party/tomlc99/test2/build.sh | 3 +- third_party/tomlc99/test2/run.sh | 12 +++-- third_party/tomlc99/toml.c | 78 +++++++++++++++++------------- third_party/tomlc99/toml.h | 2 +- third_party/tomlc99/toml_json.c | 52 +++++++++++--------- 8 files changed, 95 insertions(+), 73 deletions(-) mode change 100644 => 100755 third_party/tomlc99/test1/build.sh mode change 100644 => 100755 third_party/tomlc99/test1/run.sh mode change 100644 => 100755 third_party/tomlc99/test2/build.sh mode change 100644 => 100755 third_party/tomlc99/test2/run.sh diff --git a/third_party/tomlc99/README.md b/third_party/tomlc99/README.md index 2c90c26a..f647d970 100644 --- a/third_party/tomlc99/README.md +++ b/third_party/tomlc99/README.md @@ -1,12 +1,14 @@ # tomlc99 +> **Note: there is a newer version of this library available at [tomlc17](https://github.com/cktan/tomlc17).** + TOML in c99; v1.0 compliant. If you are looking for a C++ library, you might try this wrapper: [https://github.com/cktan/tomlcpp](https://github.com/cktan/tomlcpp). * Compatible with [TOML v1.0.0](https://toml.io/en/v1.0.0). * Tested with multiple test suites, including -[BurntSushi/toml-test](https://github.com/BurntSushi/toml-test) and +[toml-lang/toml-test](https://github.com/toml-lang/toml-test) and [iarna/toml-spec-tests](https://github.com/iarna/toml-spec-tests). * Provides very simple and intuitive interface. @@ -174,7 +176,7 @@ Alternatively, specify `make install prefix=/a/file/path` to install into ## Testing -To test against the standard test set provided by BurntSushi/toml-test: +To test against the standard test set provided by toml-lang/toml-test: ```sh % make diff --git a/third_party/tomlc99/test1/build.sh b/third_party/tomlc99/test1/build.sh old mode 100644 new mode 100755 index 645a2719..496806a6 --- a/third_party/tomlc99/test1/build.sh +++ b/third_party/tomlc99/test1/build.sh @@ -1,9 +1,6 @@ +#!/usr/bin/env bash DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -mkdir -p $DIR/goworkspace -export GOPATH=$DIR/goworkspace -go get github.com/BurntSushi/toml-test@latest # install test suite -go install github.com/BurntSushi/toml/cmd/toml-test-decoder@latest # e.g., install my parser -cp $GOPATH/bin/* . - +export GOBIN=$DIR +go install github.com/toml-lang/toml-test/cmd/toml-test@latest # install test suite \ No newline at end of file diff --git a/third_party/tomlc99/test1/run.sh b/third_party/tomlc99/test1/run.sh old mode 100644 new mode 100755 index 356a8cb3..2e50ba48 --- a/third_party/tomlc99/test1/run.sh +++ b/third_party/tomlc99/test1/run.sh @@ -1,5 +1,5 @@ +#!/usr/bin/env bash + DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -rm -f tests -ln -s ./goworkspace/pkg/mod/github.com/\!burnt\!sushi/toml-test@v0.1.0/tests -./toml-test ../toml_json +$DIR/toml-test $DIR/../toml_json diff --git a/third_party/tomlc99/test2/build.sh b/third_party/tomlc99/test2/build.sh old mode 100644 new mode 100755 index 74da4d05..1f25f8c8 --- a/third_party/tomlc99/test2/build.sh +++ b/third_party/tomlc99/test2/build.sh @@ -1,6 +1,7 @@ +#!/usr/bin/env bash + set -e DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" [ -d toml-spec-tests ] || git clone https://github.com/cktan/toml-spec-tests.git - diff --git a/third_party/tomlc99/test2/run.sh b/third_party/tomlc99/test2/run.sh old mode 100644 new mode 100755 index e1d93df5..f67995aa --- a/third_party/tomlc99/test2/run.sh +++ b/third_party/tomlc99/test2/run.sh @@ -1,4 +1,6 @@ -if ! (which jq >& /dev/null); then +#!/usr/bin/env bash + +if ! (which jq >& /dev/null); then echo "ERROR: please install the 'jq' utility" exit 1 fi @@ -12,11 +14,11 @@ for i in toml-spec-tests/values/*.toml; do fname="${fname%.*}" echo -n $fname ' ' res='[OK]' - if (../toml_json $fname.toml >& $fname.json.out); then + if (../toml_json $fname.toml >& $fname.json.out); then jq -S . $fname.json.out > t.json mv t.json $fname.json.out if [ -f $fname.json ]; then - if ! (diff $fname.json $fname.json.out >& /dev/null); then + if ! (diff $fname.json $fname.json.out >& /dev/null); then res='[FAILED]' else rm -f $fname.json.out @@ -32,10 +34,10 @@ done # # NEGATIVE tests # -for i in toml-spec-tests/errors/*.toml; do +for i in toml-spec-tests/errors/*.toml; do echo -n $i ' ' res='[OK]' - if (../toml_json $i >& $i.json.out); then + if (../toml_json $i >& $i.json.out); then res='[FAILED]' fi echo ... $res diff --git a/third_party/tomlc99/toml.c b/third_party/tomlc99/toml.c index 67dd0f80..e7b878ee 100644 --- a/third_party/tomlc99/toml.c +++ b/third_party/tomlc99/toml.c @@ -221,8 +221,8 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) { 110xxxxx 10xxxxxx */ if (code <= 0x000007FF) { - buf[0] = (unsigned char) (0xc0 | (code >> 6)); - buf[1] = (unsigned char) (0x80 | (code & 0x3f)); + buf[0] = (unsigned char)(0xc0 | (code >> 6)); + buf[1] = (unsigned char)(0x80 | (code & 0x3f)); return 2; } @@ -230,9 +230,9 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) { 1110xxxx 10xxxxxx 10xxxxxx */ if (code <= 0x0000FFFF) { - buf[0] = (unsigned char) (0xe0 | (code >> 12)); - buf[1] = (unsigned char) (0x80 | ((code >> 6) & 0x3f)); - buf[2] = (unsigned char) (0x80 | (code & 0x3f)); + buf[0] = (unsigned char)(0xe0 | (code >> 12)); + buf[1] = (unsigned char)(0x80 | ((code >> 6) & 0x3f)); + buf[2] = (unsigned char)(0x80 | (code & 0x3f)); return 3; } @@ -240,10 +240,10 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) { 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (code <= 0x001FFFFF) { - buf[0] = (unsigned char) (0xf0 | (code >> 18)); - buf[1] = (unsigned char) (0x80 | ((code >> 12) & 0x3f)); - buf[2] = (unsigned char) (0x80 | ((code >> 6) & 0x3f)); - buf[3] = (unsigned char) (0x80 | (code & 0x3f)); + buf[0] = (unsigned char)(0xf0 | (code >> 18)); + buf[1] = (unsigned char)(0x80 | ((code >> 12) & 0x3f)); + buf[2] = (unsigned char)(0x80 | ((code >> 6) & 0x3f)); + buf[3] = (unsigned char)(0x80 | (code & 0x3f)); return 4; } @@ -251,11 +251,11 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) { 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (code <= 0x03FFFFFF) { - buf[0] = (unsigned char) (0xf8 | (code >> 24)); - buf[1] = (unsigned char) (0x80 | ((code >> 18) & 0x3f)); - buf[2] = (unsigned char) (0x80 | ((code >> 12) & 0x3f)); - buf[3] = (unsigned char) (0x80 | ((code >> 6) & 0x3f)); - buf[4] = (unsigned char) (0x80 | (code & 0x3f)); + buf[0] = (unsigned char)(0xf8 | (code >> 24)); + buf[1] = (unsigned char)(0x80 | ((code >> 18) & 0x3f)); + buf[2] = (unsigned char)(0x80 | ((code >> 12) & 0x3f)); + buf[3] = (unsigned char)(0x80 | ((code >> 6) & 0x3f)); + buf[4] = (unsigned char)(0x80 | (code & 0x3f)); return 5; } @@ -263,12 +263,12 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) { 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ if (code <= 0x7FFFFFFF) { - buf[0] = (unsigned char) (0xfc | (code >> 30)); - buf[1] = (unsigned char) (0x80 | ((code >> 24) & 0x3f)); - buf[2] = (unsigned char) (0x80 | ((code >> 18) & 0x3f)); - buf[3] = (unsigned char) (0x80 | ((code >> 12) & 0x3f)); - buf[4] = (unsigned char) (0x80 | ((code >> 6) & 0x3f)); - buf[5] = (unsigned char) (0x80 | (code & 0x3f)); + buf[0] = (unsigned char)(0xfc | (code >> 30)); + buf[1] = (unsigned char)(0x80 | ((code >> 24) & 0x3f)); + buf[2] = (unsigned char)(0x80 | ((code >> 18) & 0x3f)); + buf[3] = (unsigned char)(0x80 | ((code >> 12) & 0x3f)); + buf[4] = (unsigned char)(0x80 | ((code >> 6) & 0x3f)); + buf[5] = (unsigned char)(0x80 | (code & 0x3f)); return 6; } @@ -412,8 +412,10 @@ static void *expand(void *p, int sz, int newsz) { if (!s) return 0; - memcpy(s, p, sz); - FREE(p); + if (p) { + memcpy(s, p, sz); + FREE(p); + } return s; } @@ -423,8 +425,10 @@ static void **expand_ptrarr(void **p, int n) { return 0; s[n] = 0; - memcpy(s, p, n * sizeof(void *)); - FREE(p); + if (p) { + memcpy(s, p, n * sizeof(void *)); + FREE(p); + } return s; } @@ -2212,6 +2216,7 @@ int toml_rtos(toml_raw_t src, char **ret) { if (!src) return -1; + // for strings, first char must be a s-quote or d-quote int qchar = src[0]; int srclen = strlen(src); if (!(qchar == '\'' || qchar == '"')) { @@ -2220,12 +2225,14 @@ int toml_rtos(toml_raw_t src, char **ret) { // triple quotes? if (qchar == src[1] && qchar == src[2]) { - multiline = 1; - sp = src + 3; - sq = src + srclen - 3; - /* last 3 chars in src must be qchar */ - if (!(sp <= sq && sq[0] == qchar && sq[1] == qchar && sq[2] == qchar)) + multiline = 1; // triple-quote implies multiline + sp = src + 3; // first char after quote + sq = src + srclen - 3; // first char of ending quote + + if (!(sp <= sq && sq[0] == qchar && sq[1] == qchar && sq[2] == qchar)) { + // last 3 chars in src must be qchar return -1; + } /* skip new line immediate after qchar */ if (sp[0] == '\n') @@ -2234,13 +2241,18 @@ int toml_rtos(toml_raw_t src, char **ret) { sp += 2; } else { - sp = src + 1; - sq = src + srclen - 1; - /* last char in src must be qchar */ - if (!(sp <= sq && *sq == qchar)) + sp = src + 1; // first char after quote + sq = src + srclen - 1; // ending quote + if (!(sp <= sq && *sq == qchar)) { + /* last char in src must be qchar */ return -1; + } } + // at this point: + // sp points to first valid char after quote. + // sq points to one char beyond last valid char. + // string len is (sq - sp). if (qchar == '\'') { *ret = norm_lit_str(sp, sq - sp, multiline, 0, 0); } else { diff --git a/third_party/tomlc99/toml.h b/third_party/tomlc99/toml.h index 19dc3d2f..c6aabd0d 100644 --- a/third_party/tomlc99/toml.h +++ b/third_party/tomlc99/toml.h @@ -26,7 +26,7 @@ #define TOML_H #ifdef _MSC_VER -#pragma warning(disable: 4996) +#pragma warning(disable : 4996) #endif #include diff --git a/third_party/tomlc99/toml_json.c b/third_party/tomlc99/toml_json.c index a939a232..936252de 100644 --- a/third_party/tomlc99/toml_json.c +++ b/third_party/tomlc99/toml_json.c @@ -91,15 +91,16 @@ static void print_raw(const char *s) { else millisec[0] = 0; if (ts.year && ts.hour) { - printf("{\"type\":\"datetime\",\"value\":\"%04d-%02d-%02dT%02d:%02d:%02d%" + printf("{\"type\":\"%s\",\"value\":\"%04d-%02d-%02dT%02d:%02d:%02d%" "s%s\"}", + (ts.z ? "datetime" : "datetime-local"), *ts.year, *ts.month, *ts.day, *ts.hour, *ts.minute, *ts.second, millisec, (ts.z ? ts.z : "")); } else if (ts.year) { - printf("{\"type\":\"date\",\"value\":\"%04d-%02d-%02d\"}", *ts.year, + printf("{\"type\":\"date-local\",\"value\":\"%04d-%02d-%02d\"}", *ts.year, *ts.month, *ts.day); } else if (ts.hour) { - printf("{\"type\":\"time\",\"value\":\"%02d:%02d:%02d%s\"}", *ts.hour, + printf("{\"type\":\"time-local\",\"value\":\"%02d:%02d:%02d%s\"}", *ts.hour, *ts.minute, *ts.second, millisec); } } else { @@ -149,36 +150,43 @@ static void print_table_array(toml_array_t *curarr) { } static void print_array(toml_array_t *curarr) { - toml_array_t *arr; - const char *raw; - int i; - if (toml_array_kind(curarr) == 't') { print_table_array(curarr); return; } - printf("{\"type\":\"array\",\"value\":["); - switch (toml_array_kind(curarr)) { + printf("["); - case 'v': - for (i = 0; 0 != (raw = toml_raw_at(curarr, i)); i++) { - printf("%s", i > 0 ? "," : ""); - print_raw(raw); - } - break; + const char *raw; + toml_array_t *arr; + toml_table_t *tab; - case 'a': - for (i = 0; 0 != (arr = toml_array_at(curarr, i)); i++) { - printf("%s", i > 0 ? "," : ""); + const int n = toml_array_nelem(curarr); + for (int i = 0; i < n; i++) { + printf("%s", i > 0 ? "," : ""); + + if (0 != (arr = toml_array_at(curarr, i))) { print_array(arr); + continue; } - break; - default: - break; + if (0 != (tab = toml_table_at(curarr, i))) { + print_table(tab); + continue; + } + + raw = toml_raw_at(curarr, i); + if (raw) { + print_raw(raw); + continue; + } + + fflush(stdout); + fprintf(stderr, "ERROR: unable to decode value in array\n"); + exit(1); } - printf("]}"); + + printf("]"); } static void cat(FILE *fp) {