diff --git a/src/util-strings.h b/src/util-strings.h index 73c23d90..2c31ff80 100644 --- a/src/util-strings.h +++ b/src/util-strings.h @@ -338,3 +338,29 @@ strstrip(const char *input, const char *what) return str; } + +/** + * Return true if str ends in suffix, false otherwise. If the suffix is the + * empty string, strendswith() always returns false. + */ +static inline bool +strendswith(const char *str, const char *suffix) +{ + size_t slen = strlen(str); + size_t suffixlen = strlen(suffix); + size_t offset; + + if (slen == 0 || suffixlen == 0 || suffixlen > slen) + return false; + + offset = slen - suffixlen; + return strneq(&str[offset], suffix, suffixlen); +} + +static inline bool +strstartswith(const char *str, const char *prefix) +{ + size_t prefixlen = strlen(prefix); + + return prefixlen > 0 ? strneq(str, prefix, strlen(prefix)) : false; +} diff --git a/test/test-utils.c b/test/test-utils.c index 007a9411..5faec0e4 100644 --- a/test/test-utils.c +++ b/test/test-utils.c @@ -1102,6 +1102,54 @@ START_TEST(strstrip_test) } END_TEST +START_TEST(strendswith_test) +{ + struct strendswith_test { + const char *string; + const char *suffix; + bool expected; + } tests[] = { + { "foobar", "bar", true }, + { "foobar", "foo", false }, + { "foobar", "foobar", true }, + { "foo", "foobar", false }, + { "foobar", "", false }, + { "", "", false }, + { "", "foo", false }, + { NULL, NULL, false }, + }; + + for (struct strendswith_test *t = tests; t->string; t++) { + ck_assert_int_eq(strendswith(t->string, t->suffix), + t->expected); + } +} +END_TEST + +START_TEST(strstartswith_test) +{ + struct strstartswith_test { + const char *string; + const char *suffix; + bool expected; + } tests[] = { + { "foobar", "foo", true }, + { "foobar", "bar", false }, + { "foobar", "foobar", true }, + { "foo", "foobar", false }, + { "foo", "", false }, + { "", "", false }, + { "foo", "", false }, + { NULL, NULL, false }, + }; + + for (struct strstartswith_test *t = tests; t->string; t++) { + ck_assert_int_eq(strstartswith(t->string, t->suffix), + t->expected); + } +} +END_TEST + START_TEST(list_test_insert) { struct list_test { @@ -1208,6 +1256,8 @@ litest_utils_suite(void) tcase_add_test(tc, kvsplit_double_test); tcase_add_test(tc, strjoin_test); tcase_add_test(tc, strstrip_test); + tcase_add_test(tc, strendswith_test); + tcase_add_test(tc, strstartswith_test); tcase_add_test(tc, time_conversion); tcase_add_test(tc, human_time);