gbranden pushed a commit to branch master
in repository groff.
commit c9c316578963a07995bb6cf6a8e00d7aa7a2efed
Author: G. Branden Robinson <[email protected]>
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 <[email protected]>
+
+ [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 <[email protected]>
[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 ([email protected])
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 ([email protected])
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
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit