From 087a8aa41221fd5842de06b08aa5e9a790c98d7c Mon Sep 17 00:00:00 2001 From: Attila Kovacs Date: Tue, 17 Dec 2024 17:40:12 +0100 Subject: [PATCH] Added xjsonFieldToIndentedString() --- README.md | 4 ++-- include/xchange.h | 10 --------- include/xjson.h | 1 + src/xjson.c | 56 +++++++++++++++++++++++++++++++++++------------ 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 95b103f..138d22f 100644 --- a/README.md +++ b/README.md @@ -464,12 +464,12 @@ or parse it from a file, which contains a JSON definition of the structured data ### Snippets -Alternatively, you can also create partial JSON snippets for individual fields, e.g.: +Alternatively, you can also create partial JSON fragments for individual fields, e.g.: ```c XField *f = ... - // Obtain a JSON string snippet of the field 'f'. + // Obtain a JSON fragment for the field 'f'. char *json = xjsonFieldToString(f); ``` diff --git a/include/xchange.h b/include/xchange.h index ea1c0d4..81a1403 100644 --- a/include/xchange.h +++ b/include/xchange.h @@ -287,16 +287,6 @@ char *xStringCopyOf(const char *str); # define NAN (0.0/0.0) #endif -# ifndef THREAD_LOCAL -# if __STDC_VERSION__ >= 201112L -# define THREAD_LOCAL _Thread_local ///< C11 standard for thread-local variables -# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) -# define THREAD_LOCAL __thread ///< pre C11 gcc >= 3.3 standard for thread-local variables -# else -# define THREAD_LOCAL ///< no thread-local variables -# endif -# endif - int x_error(int ret, int en, const char *from, const char *desc, ...); int x_warn(const char *from, const char *desc, ...); int x_trace(const char *loc, const char *op, int n); diff --git a/include/xjson.h b/include/xjson.h index b107522..40eac0f 100644 --- a/include/xjson.h +++ b/include/xjson.h @@ -24,6 +24,7 @@ int xjsonGetIndent(); char *xjsonToString(const XStructure *s); char *xjsonFieldToString(const XField *f); +char *xjsonFieldToIndentedString(int indent, const XField *f); XStructure *xjsonParseFilename(const char *fileName, int *lineNumber); XStructure *xjsonParseFile(FILE *file, size_t length, int *lineNumber); XStructure *xjsonParseAt(char **src, int *lineNumber); diff --git a/src/xjson.c b/src/xjson.c index a89dda0..567bef4 100644 --- a/src/xjson.c +++ b/src/xjson.c @@ -152,40 +152,51 @@ char *xjsonToString(const XStructure *s) { /** - * Converts an XField into its JSON representation. Conversion errors are reported to stderr - * or the altenate stream set by xSetErrorStream(). + * Converts an XField into its JSON representation, with the specified indentation of white spaces + * in front of every line. Conversion errors are reported to stderr or the altenate stream set by + * xSetErrorStream(). * - * @param f Pointer to field - * @return String JSON representation, or NULL if there was an error (errno set to EINVAL). + * @param indent Number of white spaces to insert in front of each line. + * @param f Pointer to field + * @return String JSON representation, or NULL if there was an error (errno set to EINVAL). * - * @sa xjsonToString() - * @sa xjsonSetIndent() - * @sa xjsonParseAt() - * @sa xjsonParseFile() - * @sa xjsonParseFilename() + * @sa xjsonFieldToString() */ -char *xjsonFieldToString(const XField *f) { - char *str; +char *xjsonFieldToIndentedString(int indent, const XField *f) { + static const char *fn = "xjsonFieldToIndentedString"; + char *prefix, *str; int n; if(!f) return xStringCopyOf(JSON_NULL); if(!xerr) xerr = stderr; + if(indent < 0) indent = 0; - n = GetFieldStringSize(0, f, FALSE); + n = GetFieldStringSize(indent, f, FALSE); if(n < 0) { Error("%s\n", xErrorDescription(n)); errno = EINVAL; return NULL; } + prefix = malloc(indent + 1); + if(!prefix) { + x_error(0, errno, fn, "alloc error (%d) bytes", (n + 1)); + return NULL; + } + if(indent > 0) memset(prefix, ' ', indent); + prefix[indent] = '\0'; + str = (char *) malloc(n + 1); // + '\0' if(!str) { - Error("Out of memory (need %ld bytes).\n", (long) (n+1)); + x_error(0, errno, fn, "alloc error (%d) bytes", (n + 1)); + free(prefix); return NULL; } - n = PrintField("", f, str); + n = PrintField(prefix, f, str); + free(prefix); + if (n < 0) { free(str); return NULL; @@ -194,6 +205,23 @@ char *xjsonFieldToString(const XField *f) { return str; } +/** + * Converts an XField into its JSON representation. Conversion errors are reported to stderr + * or the altenate stream set by xSetErrorStream(). + * + * @param f Pointer to field + * @return String JSON representation, or NULL if there was an error (errno set to EINVAL). + * + * @sa xjsonToString() + * @sa xjsonSetIndent() + * @sa xjsonParseAt() + * @sa xjsonParseFile() + * @sa xjsonParseFilename() + */ +char *xjsonFieldToString(const XField *f) { + return xjsonFieldToIndentedString(0, f); +} + /** * Parses a JSON object from the given parse position, returning the structured data * and updating the parse position. Parse errors are reported to stderr or the alternate