From 944f6d5425c0e8dbb85e82f810b313434ae703a2 Mon Sep 17 00:00:00 2001 From: Federico Angelilli Date: Wed, 15 Jan 2025 20:49:07 +0100 Subject: Implement string escape for any_json --- any_json.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- test/json.c | 10 +++++----- test/log.c | 2 +- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/any_json.h b/any_json.h index 021a997..e7e4419 100644 --- a/any_json.h +++ b/any_json.h @@ -39,6 +39,7 @@ bool any_json_write_null(any_json_write_t *json); #ifdef ANY_JSON_IMPLEMENT #include +#include #ifndef ANY_JSON_INDENT #define ANY_JSON_INDENT 4 @@ -108,17 +109,69 @@ bool any_json_write_member(any_json_write_t *json, const char *key) } } +#ifndef ANY_JSON_BUFFER_SIZE +#define ANY_JSON_BUFFER_SIZE 512 +#endif + bool any_json_write_string(any_json_write_t *json, const char *string) { json->fputs("\"", json->stream); - json->fputs(string, json->stream); + + char buffer[ANY_JSON_BUFFER_SIZE] = { 0 }; + size_t t = 0; + + for (size_t i = 0; string[i] != '\0'; ++i) { + if (t + 6 >= sizeof(buffer)) { + buffer[t] = '\0'; + json->fputs(buffer, json->stream); + t = 0; + } + + if (iscntrl(string[i])) { + buffer[t++] = '\\'; + + switch (string[i]) { + case '\b': + buffer[t++] = 'b'; + break; + case '\f': + buffer[t++] = 'f'; + break; + case '\n': + buffer[t++] = 'n'; + break; + case '\r': + buffer[t++] = 'r'; + break; + case '\t': + buffer[t++] = 't'; + break; + default: + t += sprintf(buffer + t, "u%04x", string[i]); + break; + } + } else { + if (string[i] == '"' || string[i] == '\\' || string[i] == '/') + buffer[t++] = '\\'; + + buffer[t++] = string[i]; + } + } + + buffer[t] = '\0'; + json->fputs(buffer, json->stream); + json->fputs("\"", json->stream); } +#ifndef ANY_JSON_NUMBER_FORMAT +#define ANY_JSON_NUMBER_FORMAT "%.17g" +#endif + bool any_json_write_number(any_json_write_t *json, double value) { - char buffer[1080] = { 0 }; - snprintf(buffer, sizeof(buffer), "%lf", value); + char buffer[ANY_JSON_BUFFER_SIZE] = { 0 }; + snprintf(buffer, sizeof(buffer), ANY_JSON_NUMBER_FORMAT, value); json->fputs(buffer, json->stream); } diff --git a/test/json.c b/test/json.c index 635f474..e491c44 100644 --- a/test/json.c +++ b/test/json.c @@ -55,9 +55,9 @@ void test_write(bool pretty) const char *props[][2] = { { "name", "test" }, - { "scope", "local" }, - { "project", "any_json" }, - { "author", "me" }, + { "scope", "local \x1f" }, + { "project", "any_json とてもクールで縮みません" }, + { "author", "me \"trying\" hard" }, { 0 }, }; @@ -82,10 +82,10 @@ void test_write(bool pretty) any_json_write_open_array(&json); { any_json_write_member(&json, NULL); - any_json_write_string(&json, "nested"); + any_json_write_string(&json, "nested \\ \" /"); any_json_write_member(&json, NULL); - any_json_write_string(&json, "array"); + any_json_write_string(&json, "array \f \b \n \r \t o"); } any_json_write_close_array(&json); } diff --git a/test/log.c b/test/log.c index c3e0dd5..7f7d889 100644 --- a/test/log.c +++ b/test/log.c @@ -1,6 +1,6 @@ #include -#define ANY_LOG_LOCKING +//#define ANY_LOG_LOCKING #define ANY_LOG_IMPLEMENT #define ANY_LOG_MODULE "test" -- cgit v1.2.3