return str;
}
+
+/**
+ * Similar to basename() but returns the trunk only without the (last)
+ * trailing suffix, so that:
+ *
+ * - foo.c returns foo
+ * - foo.a.b returns foo.a
+ * - foo returns foo
+ * - foo/ returns ""
+ *
+ * @return an allocated string representing the trunk name of the file
+ */
+char *
+trunkname(const char *filename)
+{
+ /* See basename(3), there are two versions and they depend on
+ * whether libgen.h is included. We can't be sure which basename()
+ * applies here, so let's play it safe and assume it's the POSIX
+ * one. */
+ char *tmp = strdup(filename);
+ char *base = basename(tmp);
+ char *suffix;
+ char *trunk;
+
+ if ((suffix = rindex(base, '.')))
+ *suffix = '\0';
+
+ trunk = strdup(base);
+ free(tmp);
+ return trunk;
+}
}
END_TEST
+START_TEST(trunkname_test)
+{
+ struct test {
+ const char *path;
+ const char *expected;
+ } tests[] = {
+ { "foo.c", "foo" },
+ { "/path/to/foo.h", "foo" },
+ { "../bar.foo", "bar" },
+ { "./bar.foo.baz", "bar.foo" },
+ { "./", "" },
+ { "/", "" },
+ { "/bar/", "" },
+ { "/bar", "bar" },
+ { "", "" },
+ };
+ struct test *t;
+
+ ARRAY_FOR_EACH(tests, t) {
+ char *result = trunkname(t->path);
+ ck_assert_str_eq(result, t->expected);
+ free(result);
+ }
+}
+END_TEST
+
static Suite *
litest_utils_suite(void)
{
tcase_add_test(tc, strverscmp_test);
tcase_add_test(tc, streq_test);
tcase_add_test(tc, strneq_test);
+ tcase_add_test(tc, trunkname_test);
suite_add_tcase(s, tc);