From 22f2b6a44d670039c7dca399e665ad115bd8436d Mon Sep 17 00:00:00 2001 From: Linnnus Date: Mon, 12 Feb 2024 16:39:22 +0100 Subject: feat: Change suffixes when converting --- src/strutil.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'src/strutil.c') diff --git a/src/strutil.c b/src/strutil.c index 9192989..46778ae 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -6,6 +6,7 @@ #include // bool, false #include // vsnprintf #include // strlen, strncmp +#include // errno, E* macros int aprintf(struct arena *a, char **out, const char *fmt, ...) { va_list ap; @@ -56,3 +57,65 @@ bool endswith(const char *haystack, const char *needle) { return strncmp(haystack + (haystack_len - needle_len), needle, needle_len) == 0; } + +char *replace_suffix(struct arena *a, const char *orig, const char *suffix, const char *with) +{ + size_t orig_len = strlen(orig); + size_t suffix_len = strlen(suffix); + size_t with_len = strlen(with); + + size_t new_len = orig_len - suffix_len + with_len; + char *new = new(a, char, new_len + 1); + + memcpy(new, orig, orig_len - suffix_len); + memcpy(new + orig_len - suffix_len, with, with_len); + + new[new_len] = '\0'; + + return new; +} + +// Based on +char *replace(struct arena *a, const char *orig, const char *rep, const char *with) { + assert(orig != NULL); + assert(rep != NULL); + + char *tmp; // varies + + int len_rep = strlen(rep); + if (len_rep == 0) { + errno = EINVAL; // empty rep causes infinite loop during count + return NULL; + } + + int len_with; + if (with == NULL) + with = ""; + len_with = strlen(with); + + // count the number of replacements needed + const char *ins; // the next insert point + int count; // number of replacements + ins = orig; + for (count = 0; (tmp = strstr(ins, rep)) != NULL; ++count) { + ins = tmp + len_rep; + } + + char *result; + tmp = result = new(a, char, strlen(orig) + (len_with - len_rep) * count + 1); + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + int len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} -- cgit v1.2.3