Added charstring "class"
authorPhilipp Takacs <philipp@bureaucracy.de>
Thu, 21 Sep 2023 10:27:02 +0000 (12:27 +0200)
committerPhilipp Takacs <philipp@bureaucracy.de>
Thu, 21 Sep 2023 11:36:01 +0000 (13:36 +0200)
manual cherry-picked from nmh
Author: David Levine <levinedl@acm.org>
commit c61294eca5edf4f245c2d8818bf53d3bdc3d80c1

h/charstring.h [new file with mode: 0644]
h/mh.h
sbr/Makefile.in
sbr/charstring.c [new file with mode: 0644]

diff --git a/h/charstring.h b/h/charstring.h
new file mode 100644 (file)
index 0000000..b2a4fed
--- /dev/null
@@ -0,0 +1,34 @@
+/* charstring.h -- dynamically-sized char array that can report size
+ *               in both characters and bytes
+ *
+ * This code is Copyright (c) 2017, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information. */
+
+/*
+ * char array that keeps track of size in both bytes and characters
+ * Usage note:
+ *    Don't store return value of charstring_buffer() and use later
+ *    after intervening push_back's; use charstring_buffer_copy()
+ *    instead.
+ */
+
+typedef struct charstring *charstring_t;
+
+charstring_t charstring_create(size_t);
+charstring_t charstring_copy(const charstring_t) NONNULL(1);
+void charstring_free(charstring_t);
+/* Append a single-byte character: */
+void charstring_push_back(charstring_t, const char) NONNULL(1);
+/* Append possibly multi-byte character(s): */
+void charstring_push_back_chars(charstring_t, const char [], size_t) NONNULL(1);
+void charstring_append(charstring_t, const charstring_t) NONNULL(2);
+void charstring_append_cstring(charstring_t, const char []) NONNULL(2);
+void charstring_clear(charstring_t) NONNULL(1);
+/* Don't store return value of charstring_buffer() and use later after
+   intervening push_back's; use charstring_buffer_copy() instead. */
+const char *charstring_buffer(const charstring_t) NONNULL(1);
+/* User is responsible for free'ing result of buffer copy. */
+char *charstring_buffer_copy(const charstring_t) NONNULL(1);
+size_t charstring_bytes(const charstring_t) NONNULL(1) PURE;
+size_t charstring_chars(const charstring_t) NONNULL(1) PURE;
diff --git a/h/mh.h b/h/mh.h
index 88bcde5..3326185 100644 (file)
--- a/h/mh.h
+++ b/h/mh.h
@@ -326,4 +326,5 @@ extern char *version;
 extern char *lib_version;
 extern char *whatnowproc;
 
+#include <h/charstring.h>
 #include <h/prototypes.h>
index 142a7f2..cee1c45 100644 (file)
@@ -52,6 +52,7 @@ SRCS = addrsbr.c ambigsw.c brkstring.c  \
        context_find.c context_read.c  \
        context_replace.c context_save.c \
        cpydata.c crawl_folders.c  \
+       charstring.c \
        dtime.c dtimep.c  \
        error.c execprog.c ext_hook.c folder_addmsg.c folder_delmsgs.c  \
        folder_free.c folder_read.c  \
diff --git a/sbr/charstring.c b/sbr/charstring.c
new file mode 100644 (file)
index 0000000..ff311f1
--- /dev/null
@@ -0,0 +1,154 @@
+/* charstring.c -- dynamically-sized char array that can report size
+ *                        in both characters and bytes
+ *
+ * This code is Copyright (c) 2014, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <h/mh.h>
+#include <h/utils.h>
+
+#define CHARSTRING_DEFAULT_SIZE 64
+
+struct charstring {
+       char *buffer;  /* the char array, not always null-terminated */
+       size_t max;    /* current size of the char array, in bytes */
+       char *cur;     /* size in bytes = cur - buffer, without trailing null */
+};
+
+
+static void
+charstring_reserve(charstring_t s, size_t need)
+{
+       const size_t cur = s->cur - s->buffer;
+
+       while (need >= s->max - cur) {
+               /* Insufficient capacity, so double it. */
+               s->buffer = mh_xrealloc(s->buffer, s->max *= 2);
+               s->cur = s->buffer + cur;
+       }
+}
+
+/*
+ * max is in characters
+ */
+charstring_t
+charstring_create(size_t max)
+{
+       charstring_t s = mh_xcalloc(1, sizeof(*s));
+
+       s->max = max ? max : CHARSTRING_DEFAULT_SIZE;
+       s->cur = s->buffer = mh_xcalloc(s->max, 1);
+
+       return s;
+}
+
+charstring_t
+charstring_copy(const charstring_t src)
+{
+       const size_t num = src->cur - src->buffer;
+       charstring_t s = mh_xcalloc(1, sizeof(*s));
+
+       s->max = src->max;
+       s->buffer = mh_xcalloc(s->max, 1);
+       memcpy(s->buffer, src->buffer, num);
+       s->cur = s->buffer + num;
+
+       return s;
+}
+
+/*
+ * OK to call charstring_free with a NULL argument.
+ */
+void
+charstring_free(charstring_t s)
+{
+       if (s) {
+               free(s->buffer);
+               free(s);
+       }
+}
+
+void
+charstring_push_back(charstring_t s, const char c)
+{
+       charstring_reserve(s, s->cur - s->buffer + 1);
+       *s->cur++ = c;
+}
+
+/*
+ * num is the number of bytes in c
+ */
+void
+charstring_push_back_chars(charstring_t s, const char c[], size_t num)
+{
+       charstring_reserve(s, s->cur - s->buffer + num);
+       memcpy(s->cur, c, num);
+       s->cur += num;
+}
+
+void
+charstring_append(charstring_t dest, const charstring_t src)
+{
+       const size_t num = src->cur - src->buffer;
+
+       if (num > 0) {
+               charstring_reserve(dest, dest->cur - dest->buffer + num);
+               memcpy(dest->cur, src->buffer, num);
+               dest->cur += num;
+       }
+}
+
+void
+charstring_append_cstring(charstring_t dest, const char src[])
+{
+       const size_t num = strlen(src);
+
+       if (num > 0) {
+               charstring_reserve(dest, dest->cur - dest->buffer + num);
+               memcpy(dest->cur, src, num);  /* Exclude src's trailing NUL. */
+               dest->cur += num;
+       }
+}
+
+void
+charstring_clear(charstring_t s)
+{
+       s->cur = s->buffer;
+}
+
+/*
+ * Don't store return value of charstring_buffer() and use later after
+ * intervening push_back's; use charstring_buffer_copy() instead.
+ */
+const char *
+charstring_buffer(const charstring_t s)
+{
+       charstring_reserve(s, s->cur - s->buffer + 1);
+
+       /* This is the only place that we null-terminate the buffer. */
+       *s->cur = '\0';
+       /* Don't increment cur so that more can be appended later, and so
+          that charstring_bytes() behaves as strlen() by not counting the
+          null. */
+
+       return s->buffer;
+}
+
+char *
+charstring_buffer_copy(const charstring_t s)
+{
+       char *copy = mh_xcalloc(s->cur - s->buffer + 1, 1);
+
+       /* Use charstring_buffer() to null terminate the buffer. */
+       memcpy(copy, charstring_buffer(s), s->cur - s->buffer + 1);
+
+       return copy;
+}
+
+size_t
+charstring_bytes(const charstring_t s)
+{
+       return s->cur - s->buffer;
+}