diff options
Diffstat (limited to 'src/m_misc.c')
-rw-r--r-- | src/m_misc.c | 111 |
1 files changed, 96 insertions, 15 deletions
diff --git a/src/m_misc.c b/src/m_misc.c index f3e11c36..7bab3f1b 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -298,55 +298,136 @@ char *M_StrCaseStr(char *haystack, char *needle) // // String replace function. -// Returns a Z_Malloc()ed string. // char *M_StringReplace(char *haystack, char *needle, char *replacement) { - char *result, *p, *dst; + char *result, *p; + char *dst; size_t needle_len = strlen(needle); - int n; + size_t result_len, dst_len; - // Count number of occurrences of 'p': + // Iterate through occurrences of 'needle' and calculate the size of + // the new string. + result_len = strlen(haystack) + 1; + p = haystack; - for (p = haystack, n = 0;; ++n) + for (;;) { p = strstr(p, needle); - if (p == NULL) { break; } p += needle_len; + result_len += strlen(replacement) - needle_len; } // Construct new string. - result = Z_Malloc(strlen(haystack) - + (strlen(replacement) - needle_len) * n - + 1, - PU_STATIC, NULL); + result = malloc(result_len); + if (result == NULL) + { + I_Error("M_StringReplace: Failed to allocate new string"); + return NULL; + } - dst = result; + dst = result; dst_len = result_len; p = haystack; while (*p != '\0') { if (!strncmp(p, needle, needle_len)) { - strcpy(dst, replacement); - dst += strlen(replacement); + M_StringCopy(dst, replacement, dst_len); p += needle_len; + dst += strlen(replacement); + dst_len -= strlen(replacement); } else { *dst = *p; - ++dst; + ++dst; --dst_len; ++p; } } - *dst = '\0'; + + return result; +} + +// Safe string copy function that works like OpenBSD's strlcpy(). +// Returns true if the string was not truncated. + +boolean M_StringCopy(char *dest, char *src, size_t dest_size) +{ + strncpy(dest, src, dest_size); + dest[dest_size - 1] = '\0'; + return strlen(dest) == strlen(src); +} + +// Returns true if 's' begins with the specified prefix. + +boolean M_StringStartsWith(char *s, char *prefix) +{ + return strlen(s) > strlen(prefix) + && strncmp(s, prefix, strlen(prefix)) == 0; +} + +// Returns true if 's' ends with the specified suffix. + +boolean M_StringEndsWith(char *s, char *suffix) +{ + return strlen(s) >= strlen(suffix) + && strcmp(s + strlen(s) - strlen(suffix), suffix) == 0; +} + +// Return a newly-malloced string with all the strings given as arguments +// concatenated together. + +char *M_StringJoin(char *s, ...) +{ + char *result, *v; + va_list args; + size_t result_len; + + result_len = strlen(s) + 1; + + va_start(args, s); + for (;;) + { + v = va_arg(args, char *); + if (v == NULL) + { + break; + } + + result_len += strlen(v); + } + va_end(args); + + result = malloc(result_len); + + if (result == NULL) + { + I_Error("M_StringJoin: Failed to allocate new string."); + return NULL; + } + + M_StringCopy(result, s, result_len); + + va_start(args, s); + for (;;) + { + v = va_arg(args, char *); + if (v == NULL) + { + break; + } + + strncat(result, v, result_len); + } + va_end(args); return result; } |