rcx

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

commit dd4e201390262f46d2b91b9815706a82561eb3d9
parent c7333b81160c0ae825586046cd02db441ae107e5
Author: robert <robertrussell.72001@gmail.com>
Date:   Tue,  9 Aug 2022 14:23:39 -0700

Add string handling functions

Untested!

Diffstat:
MMakefile | 2++
Minc/cext/all.h | 1+
Ainc/cext/str.h | 27+++++++++++++++++++++++++++
Msrc/str.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
4 files changed, 95 insertions(+), 8 deletions(-)

diff --git a/Makefile b/Makefile @@ -6,6 +6,7 @@ SRC =\ src/alloc.c\ src/log.c\ src/opt.c\ + src/str.c\ src/utf8.c libcext.a: $(SRC:.c=.o) @@ -17,6 +18,7 @@ libcext.a: $(SRC:.c=.o) src/alloc.o: src/alloc.c inc/cext/cext.h inc/cext/def.h inc/cext/alloc.h inc/cext/log.h config.mk src/log.o: src/log.c inc/cext/cext.h inc/cext/def.h inc/cext/log.h config.mk src/opt.o: src/opt.c inc/cext/cext.h inc/cext/def.h inc/cext/opt.h config.mk +src/str.o: src/str.c inc/cext/cext.h inc/cext/def.h inc/cext/str.h config.mk src/utf8.o: src/utf8.c inc/cext/cext.h inc/cext/def.h inc/cext/utf8.h config.mk clean: diff --git a/inc/cext/all.h b/inc/cext/all.h @@ -3,5 +3,6 @@ #include "cext/deque.h" #include "cext/log.h" #include "cext/opt.h" +#include "cext/str.h" #include "cext/utf8.h" #include "cext/vector.h" diff --git a/inc/cext/str.h b/inc/cext/str.h @@ -0,0 +1,27 @@ +#pragma once + +#include <stdarg.h> +#include <stdbool.h> + +#include "cext/def.h" + +char *estrdup(char *s); + +bool strstartswith(char *s, char *sub); +bool strendswith(char *s, char *sub); + +/* Return the number of the nonoverlapping occurences of sub in s. */ +usize strcount(char *s, char *sub); + +/* Split s into substrings separated by sep (which must be nonempty) and return + * the number of separated substrings found. If n > 0, then fields must point + * to an array of at least n strings; in this case, place at most n substrings + * in fields, with the last substring being the unsplit remainder. Otherwise, + * set *fields to an allocated array containing every separated substring in s. + * If there is an allocation failure, set *fields to NULL and return 0. In + * either case, the elements of *fields are pointers into s, and s will be + * modified in order to null-terminate the substrings. */ +usize strsplit(char ***fields, char *s, char *sep, usize n); + +int vaprintf(char **s, const char *fmt, va_list args); +int aprintf(char **s, const char *fmt, ...); diff --git a/src/str.c b/src/str.c @@ -1,4 +1,68 @@ -/* TODO */ +#define _XOPEN_SOURCE 500 /* strdup, vsnprintf */ +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "cext/alloc.h" +#include "cext/cext.h" +#include "cext/log.h" +#include "cext/str.h" + +/* TODO: strtoTYPE converters */ + +char * +estrdup(char *s) { + char *dup = strdup(s); + if (!dup) fatalf("allocation failure"); + return dup; +} + +bool +strstartswith(char *s, char *sub) { + return !strncmp(s, sub, strlen(sub)); +} + +bool +strendswith(char *s, char *sub) { + usize slen = strlen(s); + usize sublen = strlen(sub); + return slen >= sublen && !strcmp(s + slen - sublen, sub); +} + +usize +strcount(char *s, char *sub) { + usize n = 0; + usize sublen = strlen(sub); + while ((s = strstr(s, sub))) { + n++; + s += sublen; + } + return n; +} + +usize +strsplit(char ***fields, char *s, char *sep, usize n) { + assert(strcmp(sep, "")); + + if (n == 0) { + n = strcount(s, sep) + 1; + if (!(*fields = allocn(n, sizeof **fields))) + return 0; + } + + usize seplen = strlen(sep); + usize i = 0; + while (i < n - 1) { + char *t = strstr(s, sep); + if (!t) break; + (*fields)[i++] = s; + memset(t, 0, seplen); + s = t + seplen; + } + (*fields)[i++] = s; + + return i; +} int vaprintf(char **s, const char *fmt, va_list args) { @@ -30,10 +94,3 @@ aprintf(char **s, const char *fmt, ...) { va_end(args); return ret; } - -char * -estrdup(char *s) { - char *dup = strdup(s); - if (!dup) CEXT_ALLOC_FAIL(false); - return dup; -}