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:
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;
-}