diff --git a/src/utils/string_utils/string_utils.c b/src/utils/string_utils/string_utils.c index 8a8176a..e5b7040 100644 --- a/src/utils/string_utils/string_utils.c +++ b/src/utils/string_utils/string_utils.c @@ -1,7 +1,8 @@ #include "string_utils.h" #include -#include +#include +#include char *trim_blank_left(char *str) { @@ -13,3 +14,31 @@ char *trim_blank_left(char *str) return str; } + +char *insert_into(char *dest, const char *src, size_t pos, size_t len) +{ + size_t res_len = strlen(dest); + size_t prefix_len = pos; + size_t suffix_len = res_len - (pos + len); + size_t src_len = strlen(src); + size_t new_len = prefix_len + src_len + suffix_len; + + if (dest == NULL || src == NULL || pos + len > res_len) + return NULL; + + if (res_len < new_len) + { + char *p = realloc(dest, new_len + 1); + if (p == NULL) + return NULL; // allocation failure + dest = p; + } + + memmove(dest + pos + src_len, dest + pos + len, suffix_len); + memcpy(dest + pos, src, src_len); + dest[new_len] = 0; + + if (res_len > new_len) + return realloc(dest, new_len + 1); + return dest; +} diff --git a/src/utils/string_utils/string_utils.h b/src/utils/string_utils/string_utils.h index 496c1d5..e411f0e 100644 --- a/src/utils/string_utils/string_utils.h +++ b/src/utils/string_utils/string_utils.h @@ -12,4 +12,10 @@ */ char *trim_blank_left(char *str); +/** + * Inserts a substring into a destination string at a specified position, + * replacing a specified length of characters. + */ +char *insert_into(char *dest, const char *src, size_t pos, size_t len); + #endif /* STRING_UTILS_H */ diff --git a/tests/unit/utils/insert_into.c b/tests/unit/utils/insert_into.c new file mode 100644 index 0000000..0bcc833 --- /dev/null +++ b/tests/unit/utils/insert_into.c @@ -0,0 +1,85 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include +#include +#include + +#include "../../../src/utils/string_utils/string_utils.h" + +TestSuite(insert_into); + +Test(insert_into, basic) +{ + char *dest = strdup("The is nice."); + const char *src = "weather"; + size_t pos = 4; + + char *result = insert_into(dest, src, pos, 6); + + cr_expect(result != NULL); + cr_expect(eq(str, result, "The weather is nice.")); + + if (result) + free(result); +} + +Test(insert_into, begin) +{ + char *dest = strdup("Hello World!"); + const char *src = "Hi"; + size_t pos = 0; + + char *result = insert_into(dest, src, pos, 5); + + cr_expect(result != NULL); + cr_expect(eq(str, result, "Hi World!")); + + if (result) + free(result); +} + +Test(insert_into, end) +{ + char *dest = strdup("The number is 1024"); + const char *src = "2048"; + size_t pos = 14; + + char *result = insert_into(dest, src, pos, 4); + + cr_expect(result != NULL); + cr_expect(eq(str, result, "The number is 2048")); + + if (result) + free(result); +} + +Test(insert_into, big) +{ + char *dest = strdup("I could insert [VAR] here."); + const char *src = "a very very long string"; + size_t pos = 15; + + char *result = insert_into(dest, src, pos, 5); + + cr_expect(result != NULL); + cr_expect(eq(str, result, "I could insert a very very long string here.")); + + if (result) + free(result); +} + +Test(insert_into, small) +{ + char *dest = strdup("I could insert [VARNAME_IS_SO_LONG] string here."); + const char *src = "a short"; + size_t pos = 15; + + char *result = insert_into(dest, src, pos, 20); + + cr_expect(result != NULL); + cr_expect(eq(str, result, "I could insert a short string here.")); + + if (result) + free(result); +}