summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-05-03 09:04:41 -0400
committerAndrew Opalach <andrew@akon.city> 2025-05-03 09:20:38 -0400
commit549812812d2265709e4be00caf1d2041b4d588f5 (patch)
tree72ed245b78301869e759b5dd43c950267fdbb839
parenta5516233d66eb1552cf7fdfe03779b2bf896c82d (diff)
downloadlibalabaster-549812812d2265709e4be00caf1d2041b4d588f5.tar.gz
libalabaster-549812812d2265709e4be00caf1d2041b4d588f5.tar.bz2
libalabaster-549812812d2265709e4be00caf1d2041b4d588f5.zip
str: Add remove_at() and replace() + tests
- Bring wstr_remove_at() in line with str. - Add a test for correct snprintf usage with str. Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--include/al/str.h17
-rw-r--r--include/al/wstr.h9
-rw-r--r--tests/str.c52
3 files changed, 72 insertions, 6 deletions
diff --git a/include/al/str.h b/include/al/str.h
index 4ff936b..e9ac8f2 100644
--- a/include/al/str.h
+++ b/include/al/str.h
@@ -103,6 +103,23 @@ static inline void al_str_prepend(str *s, str *c)
al_str_insert(s, 0, c);
}
+static inline void al_str_remove_at(str *s, u32 i)
+{
+ al_assert(i < s->length);
+ if (i != --s->length) {
+ al_memmove(s->data + i, s->data + i + 1, s->length - i);
+ }
+}
+
+static inline void al_str_replace(str *s, char c, char n)
+{
+ for (u32 i = 0; i < s->length; i++) {
+ if (al_str_at(s, i) == c) {
+ al_str_at(s, i) = n;
+ }
+ }
+}
+
static inline s32 al_str_cmp(str *s, str *c, u32 start, u32 length)
{
if (length > c->length) return 1;
diff --git a/include/al/wstr.h b/include/al/wstr.h
index efecbfe..f700037 100644
--- a/include/al/wstr.h
+++ b/include/al/wstr.h
@@ -147,13 +147,10 @@ static inline void al_wstr_insert(wstr *w, u32 i, wstr *c)
static inline void al_wstr_remove_at(wstr *w, u32 i)
{
- if (i >= w->length) {
- return;
- } else if (i != w->length - 1) {
- wchar_t *data = w->data + i;
- al_memmove(data, data + 1, (w->length - i - 1) * sizeof(wchar_t));
+ al_assert(i < w->length);
+ if (i != --w->length) {
+ al_memmove(w->data + i, w->data + i + 1, (w->length - i) * sizeof(wchar_t));
}
- w->length--;
w->data[w->length] = L'\0';
}
diff --git a/tests/str.c b/tests/str.c
index 2f7f686..de5f576 100644
--- a/tests/str.c
+++ b/tests/str.c
@@ -129,6 +129,28 @@ static bool str_test_substr(void)
AL_TEST_END();
}
+static bool str_test_replace_and_remove(void)
+{
+ AL_TEST_START("str_replace_and_remove");
+
+ str string0 = al_str_c("beanie weenies");
+ str s;
+ al_str_clone(&s, &string0);
+
+ str result0 = al_str_c("beeneeweee");
+
+ al_str_replace(&s, 'a', 'e');
+ al_str_replace(&s, 'i', 'e');
+ s.length -= 3;
+ al_str_atr(&s, 1) = 'e';
+
+ al_str_remove_at(&s, 6);
+
+ AL_TEST_TRUE(al_str_eq(&s, &result0));
+
+ AL_TEST_END();
+}
+
static bool str_test_get_line(void)
{
AL_TEST_START("str_get_line");
@@ -352,6 +374,34 @@ static bool str_test_error_prone_str_c(void)
AL_TEST_END();
}
+static bool str_test_snprintf_truncate(void)
+{
+ AL_TEST_START("str_snprintf_truncate");
+
+ str s;
+ al_str_sized(&s, 12);
+
+ u32 num = 1232;
+ const char *st = "wuddup";
+ s32 expected_length = 12;
+ // If the string is truncated, the return value is how many bytes would have been written.
+ // Meaning if ret = size, the output was truncated by 1 character but will still have a null terminator.
+ // This test is to show we should always expect snprintf to add a null terminator. Meaning there's no
+ // trick we can do for str's in terms of truncating, we just have to make space for an extra null byte.
+ AL_IGNORE_WARNING("-Wformat-truncation")
+ s32 ret = al_snprintf(s.data, expected_length, "%05u_%s", num, st);
+ AL_IGNORE_WARNING_END
+ AL_TEST_EQ(ret, expected_length, s32);
+ s.length = expected_length - 1;
+
+ AL_TEST_TRUE(al_str_eq(&s, &al_str_c("01232_wuddu")));
+ AL_TEST_FALSE(al_str_eq(&s, &al_str_c("01232_wuddup")));
+
+ al_str_free(&s);
+
+ AL_TEST_END();
+}
+
bool str_tests_run(u32 skip_mask)
{
AL_TEST_START_GROUP("str");
@@ -361,12 +411,14 @@ bool str_tests_run(u32 skip_mask)
AL_TEST_RUN(str_test_insert);
AL_TEST_RUN(str_test_find_rfind);
AL_TEST_RUN(str_test_substr);
+ AL_TEST_RUN(str_test_replace_and_remove);
AL_TEST_RUN(str_test_get_line);
AL_TEST_RUN(str_test_to_long);
if (skip_mask & AL_TESTS_RUN_LIMITS) {
AL_TEST_RUN(str_test_limits);
}
AL_TEST_RUN(str_test_error_prone_str_c);
+ AL_TEST_RUN(str_test_snprintf_truncate);
AL_TEST_END_GROUP();
}