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

Reply via email to