From: Michael Tremer Date: Mon, 25 Sep 2023 16:54:28 +0000 (+0000) Subject: string: Refactor replace function X-Git-Tag: 0.9.30~1644 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0d4e3f69d3029ded9522ecbc96b9802e7ee1f4c0;p=pakfire.git string: Refactor replace function The old version was slightly over-engineered and the static analyzer was not too happy with it. Instead of debugging any problems, I wrote this version which is a lot easier and should be more bug-free. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/string.c b/src/libpakfire/string.c index cf04f05b3..db4783aae 100644 --- a/src/libpakfire/string.c +++ b/src/libpakfire/string.c @@ -121,93 +121,54 @@ int pakfire_string_partition(const char* s, const char* delim, char** s1, char** } char* pakfire_string_replace(const char* s, const char* pattern, const char* repl) { - // Return NULL on no input or no pattern - if (!s || !pattern) { + const char* m = NULL; + char* buffer = ""; + size_t l = 0; + int r; + + // Check inputs + if (!s || !pattern || !repl) { errno = EINVAL; return NULL; } - // Replace with nothing when repl is NULL - if (!repl) - repl = ""; - - char* result = NULL; - const char** cache = NULL; - unsigned int count = 0; - const size_t pattern_length = strlen(pattern); - // Working pointer - const char* p = s; + // Walk through the string... + for (const char* p = s; *p;) { + // Search for the pattern + m = strstr(p, pattern); - // Find all occurrences of pattern and store their location - while (1) { - const char* needle = strstr(p, pattern); - if (!needle) - break; - - // Make space in the cache - cache = reallocarray(cache, sizeof(*cache), count + 1); - cache[count++] = needle; - - // Move p forward - p = needle + pattern_length; - } + // Pattern does not exist in the remaining string + if (!m) { + // Copy the remaining string + r = asprintf(&buffer, "%s%s", buffer, p); + if (r < 0) + goto ERROR; - // Copy the string if no occurence was found - if (count == 0) { - result = strdup(s); - goto ERROR; - } - - // Store the end pointer - cache = reallocarray(cache, sizeof(*cache), count + 1); - cache[count] = s + strlen(s); - - const size_t repl_length = strlen(repl); - - // Determine the length of the final string - const size_t length = strlen(s) + ((repl_length - pattern_length) * count); - - // Allocate enough memory for the result - result = malloc(length + 1); - if (!result) - goto ERROR; - - // Reset p - p = s; - - // Working pointer for the result - char* r = result; - - // Copy everything up to the first match - ssize_t l = cache[0] - s; - memcpy(r, p, l); - r += l; - p += l; + break; + } - for (unsigned int i = 0; i < count; i++) { - // Put replacement here - memcpy(r, repl, repl_length); - r += repl_length; - p += pattern_length; + // Determine the length of the string up to the match + l = m - p; - // Determine the length between two matches - l = cache[i+1] - (cache[i] + pattern_length); + // Copy the read string up to pattern and the replacement into the buffer + r = asprintf(&buffer, "%s%.*s%s", buffer, (int)l, p, repl); + if (r < 0) + goto ERROR; - memcpy(r, p, l); - r += l; - p += l; + // Advance p + p += l + pattern_length; } - // Terminate the string - result[length] = '\0'; + // Return the buffer + return buffer; ERROR: - if (cache) - free(cache); + if (buffer) + free(buffer); - return result; + return NULL; } static unsigned int pakfire_chrcnt(const char* s, char delim) {