]> Sergey Matveev's repositories - bfs.git/commitdiff
dstring: New dchar typedef for dynamic strings
authorTavian Barnes <tavianator@tavianator.com>
Tue, 26 Sep 2023 16:48:21 +0000 (12:48 -0400)
committerTavian Barnes <tavianator@tavianator.com>
Tue, 26 Sep 2023 16:48:21 +0000 (12:48 -0400)
src/bar.c
src/bftw.c
src/color.c
src/color.h
src/diag.c
src/dstring.c
src/dstring.h
src/eval.c
src/exec.c
src/fsade.c
src/printf.c

index d2c663ca578c54a01eb81fbaf6f884de56db6569..e0b93931fbff9179fde619ee09fb5810140db8ad 100644 (file)
--- a/src/bar.c
+++ b/src/bar.c
@@ -129,7 +129,7 @@ BFS_FORMATTER(2, 3)
 static int bfs_bar_printf(struct bfs_bar *bar, const char *format, ...) {
        va_list args;
        va_start(args, format);
-       char *str = dstrvprintf(format, args);
+       dchar *str = dstrvprintf(format, args);
        va_end(args);
 
        if (!str) {
index f3060ce617b5e792786f4af93293333aa362a193..5e5f4a53c49ed8bfcff75442caf3790f1969c60b 100644 (file)
@@ -435,7 +435,7 @@ struct bftw_state {
        struct bftw_list batch;
 
        /** The current path. */
-       char *path;
+       dchar *path;
        /** The current file. */
        struct bftw_file *file;
        /** The previous file. */
index 5e78c6c9292899fba03d672f25f69b3c7505a43f..8d0b9950b53c2518106a7ed6a6d531244e5a856f 100644 (file)
@@ -558,8 +558,8 @@ static int unescape(char **str, const char *value, char end, const char **next)
 /** Parse the GNU $LS_COLORS format. */
 static int parse_gnu_ls_colors(struct colors *colors, const char *ls_colors) {
        int ret = -1;
-       char *key = NULL;
-       char *value = NULL;
+       dchar *key = NULL;
+       dchar *value = NULL;
 
        for (const char *chunk = ls_colors, *next; chunk; chunk = next) {
                if (chunk[0] == '*') {
@@ -943,7 +943,7 @@ static ssize_t first_broken_offset(const char *path, const struct BFTW *ftwbuf,
                goto out;
        }
 
-       char *at_path;
+       dchar *at_path;
        int at_fd;
        if (path == ftwbuf->path) {
                if (ftwbuf->depth == 0) {
index 0d46c33596cb885a5e3ca58f128475d1b143a557..b118f777d0baded4b86ac3469cb2d5035c4ac3b1 100644 (file)
@@ -9,6 +9,7 @@
 #define BFS_COLOR_H
 
 #include "config.h"
+#include "dstring.h"
 #include <stdarg.h>
 #include <stdio.h>
 
@@ -41,7 +42,7 @@ typedef struct CFILE {
        /** The color table to use, if any. */
        const struct colors *colors;
        /** A buffer for colored formatting. */
-       char *buffer;
+       dchar *buffer;
        /** Whether the next ${rs} is actually necessary. */
        bool need_reset;
        /** Whether to close the underlying stream. */
index 0590847e28a5c562c171d18614038e98e95c311d..fa9db397938411d2d8358cb0820426b87a862c1a 100644 (file)
@@ -158,7 +158,7 @@ static void bfs_argv_diag(const struct bfs_ctx *ctx, const bool args[], bool war
                bfs_error_prefix(ctx);
        }
 
-       char **argv = ZALLOC_ARRAY(char *, ctx->argc);
+       dchar **argv = ZALLOC_ARRAY(dchar *, ctx->argc);
        if (!argv) {
                return;
        }
index 60a7df9e83d54bb68f74063fcfe5784825a38eb2..ef4e733323fdbc48de27212711ee0b27b10ce30e 100644 (file)
@@ -4,6 +4,7 @@
 #include "dstring.h"
 #include "alloc.h"
 #include "bit.h"
+#include "config.h"
 #include "diag.h"
 #include <stdarg.h>
 #include <stdio.h>
 struct dstring {
        size_t capacity;
        size_t length;
-       char data[];
+       alignas(dchar) char data[];
 };
 
 /** Get the string header from the string data pointer. */
-static struct dstring *dstrheader(const char *dstr) {
+static struct dstring *dstrheader(const dchar *dstr) {
        return (struct dstring *)(dstr - offsetof(struct dstring, data));
 }
 
@@ -30,7 +31,7 @@ static size_t dstrsize(size_t capacity) {
 }
 
 /** Allocate a dstring with the given contents. */
-static char *dstralloc_impl(size_t capacity, size_t length, const char *data) {
+static dchar *dstralloc_impl(size_t capacity, size_t length, const char *data) {
        // Avoid reallocations for small strings
        if (capacity < 7) {
                capacity = 7;
@@ -49,31 +50,31 @@ static char *dstralloc_impl(size_t capacity, size_t length, const char *data) {
        return header->data;
 }
 
-char *dstralloc(size_t capacity) {
+dchar *dstralloc(size_t capacity) {
        return dstralloc_impl(capacity, 0, "");
 }
 
-char *dstrdup(const char *str) {
+dchar *dstrdup(const char *str) {
        return dstrxdup(str, strlen(str));
 }
 
-char *dstrndup(const char *str, size_t n) {
+dchar *dstrndup(const char *str, size_t n) {
        return dstrxdup(str, strnlen(str, n));
 }
 
-char *dstrddup(const char *dstr) {
+dchar *dstrddup(const dchar *dstr) {
        return dstrxdup(dstr, dstrlen(dstr));
 }
 
-char *dstrxdup(const char *str, size_t len) {
+dchar *dstrxdup(const char *str, size_t len) {
        return dstralloc_impl(len, len, str);
 }
 
-size_t dstrlen(const char *dstr) {
+size_t dstrlen(const dchar *dstr) {
        return dstrheader(dstr)->length;
 }
 
-int dstreserve(char **dstr, size_t capacity) {
+int dstreserve(dchar **dstr, size_t capacity) {
        if (!*dstr) {
                *dstr = dstralloc(capacity);
                return *dstr ? 0 : -1;
@@ -96,7 +97,7 @@ int dstreserve(char **dstr, size_t capacity) {
        return 0;
 }
 
-int dstresize(char **dstr, size_t length) {
+int dstresize(dchar **dstr, size_t length) {
        if (dstreserve(dstr, length) != 0) {
                return -1;
        }
@@ -107,19 +108,19 @@ int dstresize(char **dstr, size_t length) {
        return 0;
 }
 
-int dstrcat(char **dest, const char *src) {
+int dstrcat(dchar **dest, const char *src) {
        return dstrxcat(dest, src, strlen(src));
 }
 
-int dstrncat(char **dest, const char *src, size_t n) {
+int dstrncat(dchar **dest, const char *src, size_t n) {
        return dstrxcat(dest, src, strnlen(src, n));
 }
 
-int dstrdcat(char **dest, const char *src) {
+int dstrdcat(dchar **dest, const dchar *src) {
        return dstrxcat(dest, src, dstrlen(src));
 }
 
-int dstrxcat(char **dest, const char *src, size_t len) {
+int dstrxcat(dchar **dest, const char *src, size_t len) {
        size_t oldlen = dstrlen(*dest);
        size_t newlen = oldlen + len;
 
@@ -131,23 +132,23 @@ int dstrxcat(char **dest, const char *src, size_t len) {
        return 0;
 }
 
-int dstrapp(char **str, char c) {
+int dstrapp(dchar **str, char c) {
        return dstrxcat(str, &c, 1);
 }
 
-int dstrcpy(char **dest, const char *src) {
+int dstrcpy(dchar **dest, const char *src) {
        return dstrxcpy(dest, src, strlen(src));
 }
 
-int dstrncpy(char **dest, const char *src, size_t n) {
+int dstrncpy(dchar **dest, const char *src, size_t n) {
        return dstrxcpy(dest, src, strnlen(src, n));
 }
 
-int dstrdcpy(char **dest, const char *src) {
+int dstrdcpy(dchar **dest, const dchar *src) {
        return dstrxcpy(dest, src, dstrlen(src));
 }
 
-int dstrxcpy(char **dest, const char *src, size_t len) {
+int dstrxcpy(dchar **dest, const char *src, size_t len) {
        if (dstresize(dest, len) != 0) {
                return -1;
        }
@@ -160,7 +161,7 @@ char *dstrprintf(const char *format, ...) {
        va_list args;
 
        va_start(args, format);
-       char *str = dstrvprintf(format, args);
+       dchar *str = dstrvprintf(format, args);
        va_end(args);
 
        return str;
@@ -168,7 +169,7 @@ char *dstrprintf(const char *format, ...) {
 
 char *dstrvprintf(const char *format, va_list args) {
        // Guess a capacity to try to avoid reallocating
-       char *str = dstralloc(2*strlen(format));
+       dchar *str = dstralloc(2*strlen(format));
        if (!str) {
                return NULL;
        }
@@ -181,7 +182,7 @@ char *dstrvprintf(const char *format, va_list args) {
        return str;
 }
 
-int dstrcatf(char **str, const char *format, ...) {
+int dstrcatf(dchar **str, const char *format, ...) {
        va_list args;
 
        va_start(args, format);
@@ -191,7 +192,7 @@ int dstrcatf(char **str, const char *format, ...) {
        return ret;
 }
 
-int dstrvcatf(char **str, const char *format, va_list args) {
+int dstrvcatf(dchar **str, const char *format, va_list args) {
        // Guess a capacity to try to avoid calling vsnprintf() twice
        size_t len = dstrlen(*str);
        dstreserve(str, len + 2*strlen(format));
@@ -232,11 +233,11 @@ fail:
        return -1;
 }
 
-int dstrescat(char **dest, const char *str, enum wesc_flags flags) {
+int dstrescat(dchar **dest, const char *str, enum wesc_flags flags) {
        return dstrnescat(dest, str, SIZE_MAX, flags);
 }
 
-int dstrnescat(char **dest, const char *str, size_t n, enum wesc_flags flags) {
+int dstrnescat(dchar **dest, const char *str, size_t n, enum wesc_flags flags) {
        size_t len = *dest ? dstrlen(*dest) : 0;
 
        // Worst case growth is `ccc...` => $'\xCC\xCC\xCC...'
@@ -254,7 +255,7 @@ int dstrnescat(char **dest, const char *str, size_t n, enum wesc_flags flags) {
        return dstresize(dest, cur - *dest);
 }
 
-void dstrfree(char *dstr) {
+void dstrfree(dchar *dstr) {
        if (dstr) {
                free(dstrheader(dstr));
        }
index 88ca79f8a7e6cde9a5023fb43f843189b9b08efa..91a600c5cda9403f5592d06b7ecb5fd3c022c194 100644 (file)
 #include <stdarg.h>
 #include <stddef.h>
 
+/** Marker type for dynamic strings. */
+#if __clang__
+// Abuse __attribute__(aligned) to make a type that allows
+//
+//     dchar * -> char *
+//
+// conversions, but warns on
+//
+//     char * -> dchar *
+//
+// (with Clang's -Walign-mismatch).  The alignment is not a lie, due to the
+// layout of struct dstring, but we only enable this on Clang because GCC
+// tracks alignment through array accesses, reporting UBSan errors on (and
+// maybe even miscompiling) dstr[1].
+typedef __attribute__((aligned(alignof(size_t)))) char dchar;
+#else
+typedef char dchar;
+#endif
+
 /**
  * Allocate a dynamic string.
  *
  * @param capacity
  *         The initial capacity of the string.
  */
-char *dstralloc(size_t capacity);
+dchar *dstralloc(size_t capacity);
 
 /**
  * Create a dynamic copy of a string.
@@ -27,7 +46,7 @@ char *dstralloc(size_t capacity);
  * @param str
  *         The NUL-terminated string to copy.
  */
-char *dstrdup(const char *str);
+dchar *dstrdup(const char *str);
 
 /**
  * Create a length-limited dynamic copy of a string.
@@ -37,7 +56,7 @@ char *dstrdup(const char *str);
  * @param n
  *         The maximum number of characters to copy from str.
  */
-char *dstrndup(const char *str, size_t n);
+dchar *dstrndup(const char *str, size_t n);
 
 /**
  * Create a dynamic copy of a dynamic string.
@@ -45,7 +64,7 @@ char *dstrndup(const char *str, size_t n);
  * @param dstr
  *         The dynamic string to copy.
  */
-char *dstrddup(const char *dstr);
+dchar *dstrddup(const dchar *dstr);
 
 /**
  * Create an exact-sized dynamic copy of a string.
@@ -55,7 +74,7 @@ char *dstrddup(const char *dstr);
  * @param len
  *         The length of the string, which may include internal NUL bytes.
  */
-char *dstrxdup(const char *str, size_t len);
+dchar *dstrxdup(const char *str, size_t len);
 
 /**
  * Get a dynamic string's length.
@@ -65,7 +84,7 @@ char *dstrxdup(const char *str, size_t len);
  * @return
  *         The length of dstr.
  */
-size_t dstrlen(const char *dstr);
+size_t dstrlen(const dchar *dstr);
 
 /**
  * Reserve some capacity in a dynamic string.
@@ -77,7 +96,7 @@ size_t dstrlen(const char *dstr);
  * @return
  *         0 on success, -1 on failure.
  */
-int dstreserve(char **dstr, size_t capacity);
+int dstreserve(dchar **dstr, size_t capacity);
 
 /**
  * Resize a dynamic string.
@@ -89,7 +108,7 @@ int dstreserve(char **dstr, size_t capacity);
  * @return
  *         0 on success, -1 on failure.
  */
-int dstresize(char **dstr, size_t length);
+int dstresize(dchar **dstr, size_t length);
 
 /**
  * Append to a dynamic string.
@@ -100,7 +119,7 @@ int dstresize(char **dstr, size_t length);
  *         The string to append.
  * @return 0 on success, -1 on failure.
  */
-int dstrcat(char **dest, const char *src);
+int dstrcat(dchar **dest, const char *src);
 
 /**
  * Append to a dynamic string.
@@ -114,7 +133,7 @@ int dstrcat(char **dest, const char *src);
  * @return
  *         0 on success, -1 on failure.
  */
-int dstrncat(char **dest, const char *src, size_t n);
+int dstrncat(dchar **dest, const char *src, size_t n);
 
 /**
  * Append a dynamic string to another dynamic string.
@@ -126,7 +145,7 @@ int dstrncat(char **dest, const char *src, size_t n);
  * @return
  *         0 on success, -1 on failure.
  */
-int dstrdcat(char **dest, const char *src);
+int dstrdcat(dchar **dest, const dchar *src);
 
 /**
  * Append to a dynamic string.
@@ -140,7 +159,7 @@ int dstrdcat(char **dest, const char *src);
  * @return
  *         0 on success, -1 on failure.
  */
-int dstrxcat(char **dest, const char *src, size_t len);
+int dstrxcat(dchar **dest, const char *src, size_t len);
 
 /**
  * Append a single character to a dynamic string.
@@ -152,7 +171,7 @@ int dstrxcat(char **dest, const char *src, size_t len);
  * @return
  *         0 on success, -1 on failure.
  */
-int dstrapp(char **str, char c);
+int dstrapp(dchar **str, char c);
 
 /**
  * Copy a string into a dynamic string.
@@ -164,7 +183,7 @@ int dstrapp(char **str, char c);
  * @returns
  *         0 on success, -1 on failure.
  */
-int dstrcpy(char **dest, const char *str);
+int dstrcpy(dchar **dest, const char *str);
 
 /**
  * Copy a dynamic string into another one.
@@ -176,7 +195,7 @@ int dstrcpy(char **dest, const char *str);
  * @returns
  *         0 on success, -1 on failure.
  */
-int dstrdcpy(char **dest, const char *str);
+int dstrdcpy(dchar **dest, const dchar *str);
 
 /**
  * Copy a string into a dynamic string.
@@ -190,7 +209,7 @@ int dstrdcpy(char **dest, const char *str);
  * @returns
  *         0 on success, -1 on failure.
  */
-int dstrncpy(char **dest, const char *str, size_t n);
+int dstrncpy(dchar **dest, const char *str, size_t n);
 
 /**
  * Copy a string into a dynamic string.
@@ -204,7 +223,7 @@ int dstrncpy(char **dest, const char *str, size_t n);
  * @returns
  *         0 on success, -1 on failure.
  */
-int dstrxcpy(char **dest, const char *str, size_t len);
+int dstrxcpy(dchar **dest, const char *str, size_t len);
 
 /**
  * Create a dynamic string from a format string.
@@ -245,7 +264,7 @@ char *dstrvprintf(const char *format, va_list args);
  *         0 on success, -1 on failure.
  */
 BFS_FORMATTER(2, 3)
-int dstrcatf(char **str, const char *format, ...);
+int dstrcatf(dchar **str, const char *format, ...);
 
 /**
  * Format some text from a va_list onto the end of a dynamic string.
@@ -260,7 +279,7 @@ int dstrcatf(char **str, const char *format, ...);
  *         0 on success, -1 on failure.
  */
 BFS_FORMATTER(2, 0)
-int dstrvcatf(char **str, const char *format, va_list args);
+int dstrvcatf(dchar **str, const char *format, va_list args);
 
 /**
  * Concatenate while shell-escaping.
@@ -274,7 +293,7 @@ int dstrvcatf(char **str, const char *format, va_list args);
  * @return
  *         0 on success, -1 on failure.
  */
-int dstrescat(char **dest, const char *str, enum wesc_flags flags);
+int dstrescat(dchar **dest, const char *str, enum wesc_flags flags);
 
 /**
  * Concatenate while shell-escaping.
@@ -290,7 +309,7 @@ int dstrescat(char **dest, const char *str, enum wesc_flags flags);
  * @return
  *         0 on success, -1 on failure.
  */
-int dstrnescat(char **dest, const char *str, size_t n, enum wesc_flags flags);
+int dstrnescat(dchar **dest, const char *str, size_t n, enum wesc_flags flags);
 
 /**
  * Free a dynamic string.
@@ -298,6 +317,6 @@ int dstrnescat(char **dest, const char *str, size_t n, enum wesc_flags flags);
  * @param dstr
  *         The string to free.
  */
-void dstrfree(char *dstr);
+void dstrfree(dchar *dstr);
 
 #endif // BFS_DSTRING_H
index 0faf5332e64f6780e0ee0d6282bfe7ce257fe02c..35507510d2191eff3754fe9a2c574cc3742a6657 100644 (file)
@@ -1115,7 +1115,7 @@ static void eval_status(struct bfs_eval *state, struct bfs_bar *bar, struct time
 
        const struct BFTW *ftwbuf = state->ftwbuf;
 
-       char *rhs = dstrprintf(" (visited: %zu, depth: %2zu)", count, ftwbuf->depth);
+       dchar *rhs = dstrprintf(" (visited: %zu, depth: %2zu)", count, ftwbuf->depth);
        if (!rhs) {
                return;
        }
@@ -1126,7 +1126,7 @@ static void eval_status(struct bfs_eval *state, struct bfs_bar *bar, struct time
                rhslen = 0;
        }
 
-       char *status = dstralloc(0);
+       dchar *status = dstralloc(0);
        if (!status) {
                goto out_rhs;
        }
index ea7f897f7284483fb34a8873877f5aadb88fa1cc..7b55522b8e5f9623be446f5e1a9b1dfc891deb36 100644 (file)
@@ -227,7 +227,7 @@ static char *bfs_exec_format_arg(char *arg, const char *path) {
                return arg;
        }
 
-       char *ret = dstralloc(0);
+       dchar *ret = dstralloc(0);
        if (!ret) {
                return NULL;
        }
@@ -259,7 +259,7 @@ err:
 /** Free a formatted argument. */
 static void bfs_exec_free_arg(char *arg, const char *tmpl) {
        if (arg != tmpl) {
-               dstrfree(arg);
+               dstrfree((dchar *)arg);
        }
 }
 
index c401426c5f7f5053774f1cac2d7e2eea22e9a887..8dec5a8951e25a9fed9093f65766571f02db83a8 100644 (file)
@@ -37,7 +37,7 @@
 static const char *fake_at(const struct BFTW *ftwbuf) {
        static atomic int proc_works = -1;
 
-       char *path = NULL;
+       dchar *path = NULL;
        if (ftwbuf->at_fd == AT_FDCWD || load(&proc_works, relaxed) == 0) {
                goto fail;
        }
@@ -69,7 +69,7 @@ fail:
 
 static void free_fake_at(const struct BFTW *ftwbuf, const char *path) {
        if (path != ftwbuf->path) {
-               dstrfree((char *)path);
+               dstrfree((dchar *)path);
        }
 }
 
index f0910faecb3ba75a88a014b4cf7859fdf9990d51..5de5a2807425ee26dd7fcd7d59b618cf49a2755f 100644 (file)
@@ -38,7 +38,7 @@ struct bfs_printf {
        /** The printing function to invoke. */
        bfs_printf_fn *fn;
        /** String data associated with this directive. */
-       char *str;
+       dchar *str;
        /** The stat field to print. */
        enum bfs_stat_field stat_field;
        /** Character data associated with this directive. */
@@ -596,7 +596,7 @@ static int append_directive(const struct bfs_ctx *ctx, struct bfs_printf **forma
 int bfs_printf_parse(const struct bfs_ctx *ctx, struct bfs_expr *expr, const char *format) {
        expr->printf = NULL;
 
-       char *literal = dstralloc(0);
+       dchar *literal = dstralloc(0);
        if (!literal) {
                bfs_perror(ctx, "dstralloc()");
                goto error;