gbranden pushed a commit to branch master in repository groff. commit c9c316578963a07995bb6cf6a8e00d7aa7a2efed Author: G. Branden Robinson <g.branden.robin...@gmail.com> AuthorDate: Tue Mar 4 03:27:09 2025 -0600
[libgroff]: Support object dumping in JSON (2/3). Support JSON dumping of `string`s. Add `json_length()`, `json_extract()`, and `json_dump()` public member functions to `string` class. The enhanced node printing feature will require them. * src/include/stringclass.h (class string): Declare them. * src/libs/libgroff/string.cpp (string::json_length): (string::json_extract, string::json_dump): Implement them. --- ChangeLog | 10 ++++++ src/include/stringclass.h | 5 ++- src/libs/libgroff/string.cpp | 86 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 95 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3225d05ea..5480dee2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2025-03-04 G. Branden Robinson <g.branden.robin...@gmail.com> + + [libgroff]: Add `json_length()`, `json_extract()`, and + `json_dump()` public member functions to `string` class. The + enhanced node printing feature will require them. + + * src/include/stringclass.h (class string): Declare them. + * src/libs/libgroff/string.cpp (string::json_length): + (string::json_extract, string::json_dump): Implement them. + 2025-03-15 G. Branden Robinson <g.branden.robin...@gmail.com> [libgroff]: Support dumping of some object types in JSON format. diff --git a/src/include/stringclass.h b/src/include/stringclass.h index 445b44152..11cc56d7b 100644 --- a/src/include/stringclass.h +++ b/src/include/stringclass.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1989-2024 Free Software Foundation, Inc. +/* Copyright (C) 1989-2025 Free Software Foundation, Inc. Written by James Clark (j...@jclark.com) This file is part of groff. @@ -69,6 +69,9 @@ public: int search(const char) const; int find(const char *) const; char *extract() const; + size_t json_length() const; + const char *json_extract() const; + void json_dump() const; void remove_spaces(); void clear(); void move(string &); diff --git a/src/libs/libgroff/string.cpp b/src/libs/libgroff/string.cpp index c8d759528..739fdfe05 100644 --- a/src/libs/libgroff/string.cpp +++ b/src/libs/libgroff/string.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 1989-2024 Free Software Foundation, Inc. +/* Copyright (C) 1989-2025 Free Software Foundation, Inc. Written by James Clark (j...@jclark.com) This file is part of groff. @@ -21,11 +21,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #endif #include <stdio.h> // FILE, putc(), sprintf() -#include <stdlib.h> // malloc() +#include <stdlib.h> // calloc() #include <string.h> // memchr(), memcmp(), memcpy(), memmem(), memset(), // strlen(), size_t +#include "cset.h" // csprint() #include "lib.h" +#include "json-encode.h" // json_encode_char() #include "stringclass.h" @@ -299,8 +301,9 @@ int string::find(const char *c) const return (p != 0 /* nullptr */) ? (p - ptr) : -1; } -// we silently strip nuls - +// Return pointer to null-terminated C string; any nulls internal to the +// string are omitted. The caller is responsible for `free()`ing the +// returned storage. char *string::extract() const { char *p = ptr; @@ -310,7 +313,7 @@ char *string::extract() const for (i = 0; i < n; i++) if (p[i] == '\0') nnuls++; - char *q = static_cast<char *>(malloc(n + 1 - nnuls)); + char *q = static_cast<char *>(calloc(n + 1 - nnuls, sizeof(char))); if (q != 0 /* nullptr */) { char *r = q; for (i = 0; i < n; i++) @@ -321,6 +324,79 @@ char *string::extract() const return q; } +// Compute length of JSON representation of object. +size_t string::json_length() const +{ + size_t n = len; + const char *p = ptr; + char ch; + int nextrachars = 2; // leading and trailing double quotes + for (size_t i = 0; i < n; i++) { + ch = p[i]; + // Handle the most common cases first. + if (ch < 128) { + if (csprint(ch)) + ; + else + switch (ch) { + case '"': + case '\\': + case '/': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + nextrachars++; + break; + default: + nextrachars += 5; + } + } + else + nextrachars += 5; + } + return (n + nextrachars); +} + +// Like `extract()`, but double-quote the string and escape characters +// per JSON and emit nulls. This string is not null-terminated! Caller +// MUST use .json_length(). +const char *string::json_extract() const +{ + const char *p = ptr; + size_t n = len; + size_t i; + char *q = static_cast<char *>(calloc(this->json_length(), + sizeof (char))); + if (q != 0 /* nullptr */) { + char *r = q; + *r++ = '"'; + json_char ch; + for (i = 0; i < n; i++, p++) { + ch = json_encode_char(*p); + for (size_t j = 0; j < ch.len; j++) + *r++ = ch.buf[j]; + } + *r++ = '"'; + } + else + return strdup("\"\""); + return q; +} + +// Dump string in JSON representation to standard error stream. +void string::json_dump() const +{ + const char *repr = this->json_extract(); + size_t jsonlen = this->json_length(); + // Write it out by character to keep libc string functions from + // interpreting escape sequences. + for (size_t i = 0; i < jsonlen; i++) + fputc(repr[i], stderr); + free(const_cast<char *>(repr)); +} + void string::remove_spaces() { int l = len - 1; _______________________________________________ groff-commit mailing list groff-commit@gnu.org https://lists.gnu.org/mailman/listinfo/groff-commit