commit 0d8e1bf40232d129474377734a748561e49fd96f
parent 10821efb8b7d9688408de07f4dbd0078ed6ec2fa
Author: Robert Russell <robertrussell.72001@gmail.com>
Date: Wed, 7 Sep 2022 14:49:50 -0700
Add cat and ecat functions
The interface of these is tentative. We may also add vcat and
evcat functions if the need arises.
Diffstat:
2 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/inc/rcx/str.h b/inc/rcx/str.h
@@ -8,6 +8,9 @@
char *r_str_dup(char *s);
char *r_str_edup(char *s);
+char *r_str_cat(char *buf, usize len, ...);
+char *r_str_ecat(char *buf, usize len, ...);
+
bool r_str_starts_with(char *s, char *sub);
bool r_str_ends_with(char *s, char *sub);
diff --git a/src/str.c b/src/str.c
@@ -1,5 +1,6 @@
#define _ISOC99_SOURCE /* vsnprintf */
#include <assert.h>
+#include <errno.h>
#include <stdio.h>
#include <string.h>
@@ -8,7 +9,46 @@
#include "rcx/rcx.h"
#include "rcx/str.h"
-/* TODO: str to int converters */
+/* TODO: e-versions of every function that can fail */
+
+static char *
+r_str_vcat(char *buf, usize len, va_list args) {
+ assert(buf || len == 0);
+
+ char *s;
+ usize need = 1; /* Null terminator */
+
+ va_list args2;
+ va_copy(args2, args);
+ while ((s = va_arg(args2, char*))) {
+ usize slen = strlen(s);
+ if (slen > USIZE_MAX - need) {
+ va_end(args2);
+ errno = EOVERFLOW;
+ return 0;
+ }
+ need += slen;
+ }
+ va_end(args2);
+
+ if (buf && len < need) {
+ errno = ERANGE;
+ return 0;
+ } else if (!buf) {
+ buf = r_alloc(need);
+ if (!buf)
+ return 0;
+ }
+
+ char *b = buf;
+ while ((s = va_arg(args, char*))) {
+ while (*s)
+ *b++ = *s++;
+ }
+ *b = '\0';
+
+ return buf;
+}
char *
r_str_dup(char *s) {
@@ -25,6 +65,26 @@ r_str_edup(char *s) {
return dup;
}
+char *
+r_str_cat(char *buf, usize len, ...) {
+ va_list args;
+ va_start(args, len);
+ char *ret = r_str_vcat(buf, len, args);
+ va_end(args);
+ return ret;
+}
+
+char *
+r_str_ecat(char *buf, usize len, ...) {
+ va_list args;
+ va_start(args, len);
+ char *ret = r_str_vcat(buf, len, args);
+ va_end(args);
+ if (!ret)
+ r_fatalf("r_str_ecat: %s", strerror(errno));
+ return ret;
+}
+
bool
r_str_starts_with(char *s, char *sub) {
return !strncmp(s, sub, strlen(sub));