rcx

library of miscellaneous bits of C code
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

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:
Minc/rcx/str.h | 3+++
Msrc/str.c | 62+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
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));