gbranden pushed a commit to branch master in repository groff. commit de62829ca4ce5a8d84a76393f43fbd9bf890f3e9 Author: G. Branden Robinson <g.branden.robin...@gmail.com> AuthorDate: Tue Mar 4 04:30:10 2025 -0600
[libgroff]: Support object dumping in JSON (3/3). Support JSON dumping of `symbol`s. Add `json_length()`, `json_extract()`, and `json_dump()` public member functions to `symbol` class. The enhanced node printing feature will require them. * src/include/symbol.h (class symbol): Declare them. * src/libs/libgroff/symbol.cpp (symbol::json_length): (symbol::json_extract, symbol::json_dump): Implement them. --- ChangeLog | 10 ++++++ src/include/symbol.h | 3 ++ src/libs/libgroff/symbol.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5480dee2a..c7512f7f4 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 `symbol` class. The + enhanced node printing feature will require them. + + * src/include/symbol.h (class symbol): Declare them. + * src/libs/libgroff/symbol.cpp (symbol::json_length): + (symbol::json_extract, symbol::json_dump): Implement them. + 2025-03-04 G. Branden Robinson <g.branden.robin...@gmail.com> [libgroff]: Add `json_length()`, `json_extract()`, and diff --git a/src/include/symbol.h b/src/include/symbol.h index d82d7cd29..ef8805354 100644 --- a/src/include/symbol.h +++ b/src/include/symbol.h @@ -38,6 +38,9 @@ public: const char *contents() const; bool is_null() const; bool is_empty() const; + size_t json_length() const; + const char *json_extract() const; + void json_dump() const; }; diff --git a/src/libs/libgroff/symbol.cpp b/src/libs/libgroff/symbol.cpp index 7bc8a8f4c..1ed91f359 100644 --- a/src/libs/libgroff/symbol.cpp +++ b/src/libs/libgroff/symbol.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. @@ -22,7 +22,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <assert.h> #include <string.h> // strcat(), strcmp(), strcpy(), strlen() +#include <stdlib.h> // calloc() +#include "cset.h" // csprint() +#include "json-encode.h" // json_encode_char() #include "lib.h" #include "errarg.h" @@ -160,6 +163,81 @@ symbol concat(symbol s1, symbol s2) return res; } +// Compute length of JSON representation of object. +size_t symbol::json_length() const +{ + size_t len = 0; + const char *p = s; + char ch; + int nextrachars = 2; // leading and trailing double quotes + for (size_t i = 0; p[i] != '\0'; i++, len++) { + 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 (len + nextrachars); +} + +// Like `extract()`, but double-quote the string and escape characters +// per JSON. (Unlike groff's `string`, a `symbol` doesn't contain +// embedded null characters.) This string is not null-terminated! +// Caller MUST use .json_length(). (The member variable backing us up +// _is_ a null-terminated C string.) +const char *symbol::json_extract() const +{ + const char *p = s; + size_t n = strlen(s); + 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("\"\""); // so it can be free()d + return q; +} + +// Dump symbol in JSON representation to standard error stream. +void symbol::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)); +} + symbol default_symbol("default"); // Local Variables: _______________________________________________ groff-commit mailing list groff-commit@gnu.org https://lists.gnu.org/mailman/listinfo/groff-commit