From 9393fc899e8126243dbeebedab68eb63022a7b30 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Mon, 10 Sep 2001 13:30:41 +0000 Subject: [PATCH] Add g_build_path(), g_build_filename(), to create separated paths, Sat Sep 8 17:14:51 2001 Owen Taylor * glib/gfileutils.[ch]: Add g_build_path(), g_build_filename(), to create separated paths, suppressing duplicate separators, from varargs lists. * tests/strfunc-test.c: Add tests for g_build_path(), g_build_filename(). --- ChangeLog | 10 ++++ ChangeLog.pre-2-0 | 10 ++++ ChangeLog.pre-2-10 | 10 ++++ ChangeLog.pre-2-12 | 10 ++++ ChangeLog.pre-2-2 | 10 ++++ ChangeLog.pre-2-4 | 10 ++++ ChangeLog.pre-2-6 | 10 ++++ ChangeLog.pre-2-8 | 10 ++++ glib/gfileutils.c | 119 +++++++++++++++++++++++++++++++++++++++++++ glib/gfileutils.h | 6 +++ tests/strfunc-test.c | 64 +++++++++++++++++++++++ 11 files changed, 269 insertions(+) diff --git a/ChangeLog b/ChangeLog index 551b2511..77152eac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Sat Sep 8 17:14:51 2001 Owen Taylor + + * glib/gfileutils.[ch]: Add g_build_path(), + g_build_filename(), to create separated paths, + suppressing duplicate separators, from varargs + lists. + + * tests/strfunc-test.c: Add tests for g_build_path(), + g_build_filename(). + Sat Sep 8 14:11:53 2001 Owen Taylor * glib/Makefile.am (libglib_1_3_la_SOURCES): Add diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 551b2511..77152eac 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,13 @@ +Sat Sep 8 17:14:51 2001 Owen Taylor + + * glib/gfileutils.[ch]: Add g_build_path(), + g_build_filename(), to create separated paths, + suppressing duplicate separators, from varargs + lists. + + * tests/strfunc-test.c: Add tests for g_build_path(), + g_build_filename(). + Sat Sep 8 14:11:53 2001 Owen Taylor * glib/Makefile.am (libglib_1_3_la_SOURCES): Add diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 551b2511..77152eac 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,13 @@ +Sat Sep 8 17:14:51 2001 Owen Taylor + + * glib/gfileutils.[ch]: Add g_build_path(), + g_build_filename(), to create separated paths, + suppressing duplicate separators, from varargs + lists. + + * tests/strfunc-test.c: Add tests for g_build_path(), + g_build_filename(). + Sat Sep 8 14:11:53 2001 Owen Taylor * glib/Makefile.am (libglib_1_3_la_SOURCES): Add diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 551b2511..77152eac 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,13 @@ +Sat Sep 8 17:14:51 2001 Owen Taylor + + * glib/gfileutils.[ch]: Add g_build_path(), + g_build_filename(), to create separated paths, + suppressing duplicate separators, from varargs + lists. + + * tests/strfunc-test.c: Add tests for g_build_path(), + g_build_filename(). + Sat Sep 8 14:11:53 2001 Owen Taylor * glib/Makefile.am (libglib_1_3_la_SOURCES): Add diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 551b2511..77152eac 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,13 @@ +Sat Sep 8 17:14:51 2001 Owen Taylor + + * glib/gfileutils.[ch]: Add g_build_path(), + g_build_filename(), to create separated paths, + suppressing duplicate separators, from varargs + lists. + + * tests/strfunc-test.c: Add tests for g_build_path(), + g_build_filename(). + Sat Sep 8 14:11:53 2001 Owen Taylor * glib/Makefile.am (libglib_1_3_la_SOURCES): Add diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 551b2511..77152eac 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,13 @@ +Sat Sep 8 17:14:51 2001 Owen Taylor + + * glib/gfileutils.[ch]: Add g_build_path(), + g_build_filename(), to create separated paths, + suppressing duplicate separators, from varargs + lists. + + * tests/strfunc-test.c: Add tests for g_build_path(), + g_build_filename(). + Sat Sep 8 14:11:53 2001 Owen Taylor * glib/Makefile.am (libglib_1_3_la_SOURCES): Add diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 551b2511..77152eac 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,13 @@ +Sat Sep 8 17:14:51 2001 Owen Taylor + + * glib/gfileutils.[ch]: Add g_build_path(), + g_build_filename(), to create separated paths, + suppressing duplicate separators, from varargs + lists. + + * tests/strfunc-test.c: Add tests for g_build_path(), + g_build_filename(). + Sat Sep 8 14:11:53 2001 Owen Taylor * glib/Makefile.am (libglib_1_3_la_SOURCES): Add diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 551b2511..77152eac 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,13 @@ +Sat Sep 8 17:14:51 2001 Owen Taylor + + * glib/gfileutils.[ch]: Add g_build_path(), + g_build_filename(), to create separated paths, + suppressing duplicate separators, from varargs + lists. + + * tests/strfunc-test.c: Add tests for g_build_path(), + g_build_filename(). + Sat Sep 8 14:11:53 2001 Owen Taylor * glib/Makefile.am (libglib_1_3_la_SOURCES): Add diff --git a/glib/gfileutils.c b/glib/gfileutils.c index 031cbde6..a11048ab 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -28,6 +28,7 @@ #endif #include #include +#include #include #include #include @@ -697,3 +698,121 @@ g_file_open_tmp (const char *tmpl, return retval; } + +static gchar * +g_build_pathv (const gchar *separator, + const gchar *first_element, + va_list args) +{ + GString *result; + gint separator_len = strlen (separator); + gboolean is_first = TRUE; + const gchar *next_element; + + result = g_string_new (NULL); + + next_element = first_element; + + while (TRUE) + { + const gchar *element; + const gchar *start; + const gchar *end; + + if (next_element) + { + element = next_element; + next_element = va_arg (args, gchar *); + } + else + break; + + start = element; + + if (is_first) + is_first = FALSE; + else if (separator_len) + { + while (start && + strncmp (start, separator, separator_len) == 0) + start += separator_len; + } + + end = start + strlen (start); + + if (next_element && separator_len) + { + while (end > start + separator_len && + strncmp (end - separator_len, separator, separator_len) == 0) + end -= separator_len; + } + + if (end > start) + { + if (result->len > 0) + g_string_append (result, separator); + + g_string_append_len (result, start, end - start); + } + } + + return g_string_free (result, FALSE); +} + +/** + * g_build_path: + * @separator: a string used to separator the elements of the path. + * @first_element: the first element in the path + * + * Create a path from a series of elements using @separator as the + * separator between elements. At the boundary between two elements, + * any trailing occurrences of separator in the first element, or + * leading occurrences of separator in the second element are removed + * and exactly one copy of the separator is inserted. + * + * Return value: a newly allocated string that must be freed with g_free(). + **/ +gchar * +g_build_path (const gchar *separator, + const gchar *first_element, + ...) +{ + gchar *str; + va_list args; + + g_return_val_if_fail (separator != NULL, NULL); + + va_start (args, first_element); + str = g_build_pathv (separator, first_element, args); + va_end (args); + + return str; +} + +/** + * g_build_filename: + * @first_element: the first element in the path + * + * Create a filename from a series of elements using the correct + * separator for filenames. This function behaves identically + * to g_build_path (G_DIR_SEPARATOR_S, first_element, ....) + * + * No attempt is made to force the resulting filename to be an absolute + * path. If the first element is a relative path, the result will + * be a relative path. + * + * Return value: a newly allocated string that must be freed with g_free(). + **/ +gchar * +g_build_filename (const gchar *first_element, + ...) +{ + gchar *str; + va_list args; + + va_start (args, first_element); + str = g_build_pathv (G_DIR_SEPARATOR_S, first_element, args); + va_end (args); + + return str; +} diff --git a/glib/gfileutils.h b/glib/gfileutils.h index 161a131a..f966e014 100644 --- a/glib/gfileutils.h +++ b/glib/gfileutils.h @@ -88,6 +88,12 @@ int g_file_open_tmp (const char *tmpl, char **name_used, GError **error); +gchar *g_build_path (const gchar *separator, + const gchar *first_element, + ...); +gchar *g_build_filename (const gchar *first_element, + ...); + G_END_DECLS #endif /* __G_FILEUTILS_H__ */ diff --git a/tests/strfunc-test.c b/tests/strfunc-test.c index 30ff1168..fa3089a0 100644 --- a/tests/strfunc-test.c +++ b/tests/strfunc-test.c @@ -80,6 +80,17 @@ strv_check (gchar **strv, ...) return ok; } +static gboolean +str_check (gchar *str, + gchar *expected) +{ + gboolean ok = (strcmp (str, expected) == 0); + + g_free (str); + + return ok; +} + static gboolean test_isalnum (gchar c) { @@ -354,5 +365,58 @@ main (int argc, #undef TEST_DIGIT + /* Tests for g_build_path, g_build_filename */ + + TEST (NULL, str_check (g_build_path ("", NULL), "")); + TEST (NULL, str_check (g_build_path ("", "", NULL), "")); + TEST (NULL, str_check (g_build_path ("", "x", NULL), "x")); + TEST (NULL, str_check (g_build_path ("", "x", "y", NULL), "xy")); + TEST (NULL, str_check (g_build_path ("", "x", "y", "z", NULL), "xyz")); + + TEST (NULL, str_check (g_build_path (":", NULL), "")); + TEST (NULL, str_check (g_build_path (":", ":", NULL), ":")); + TEST (NULL, str_check (g_build_path (":", ":x", NULL), ":x")); + TEST (NULL, str_check (g_build_path (":", "x:", NULL), "x:")); + TEST (NULL, str_check (g_build_path (":", "x", "y", NULL), "x:y")); + TEST (NULL, str_check (g_build_path (":", ":x", "y", NULL), ":x:y")); + TEST (NULL, str_check (g_build_path (":", "x", "y:", NULL), "x:y:")); + TEST (NULL, str_check (g_build_path (":", ":x:", ":y:", NULL), ":x:y:")); + TEST (NULL, str_check (g_build_path (":", ":x::", "::y:", NULL), ":x:y:")); + TEST (NULL, str_check (g_build_path (":", "x", "y", "z", NULL), "x:y:z")); + TEST (NULL, str_check (g_build_path (":", ":x:", ":y:", ":z:", NULL), ":x:y:z:")); + TEST (NULL, str_check (g_build_path (":", "::x::", "::y::", "::z::", NULL), "::x:y:z::")); + + TEST (NULL, str_check (g_build_path ("::", NULL), "")); + TEST (NULL, str_check (g_build_path ("::", "::", NULL), "::")); + TEST (NULL, str_check (g_build_path ("::", "::x", NULL), "::x")); + TEST (NULL, str_check (g_build_path ("::", "x::", NULL), "x::")); + TEST (NULL, str_check (g_build_path ("::", "x", "y", NULL), "x::y")); + TEST (NULL, str_check (g_build_path ("::", "::x", "y", NULL), "::x::y")); + TEST (NULL, str_check (g_build_path ("::", "x", "y::", NULL), "x::y::")); + TEST (NULL, str_check (g_build_path ("::", "::x::", "::y::", NULL), "::x::y::")); + TEST (NULL, str_check (g_build_path ("::", "::x:::", ":::y::", NULL), "::x::::y::")); + TEST (NULL, str_check (g_build_path ("::", "::x::::", "::::y::", NULL), "::x::y::")); + TEST (NULL, str_check (g_build_path ("::", "x", "y", "z", NULL), "x::y::z")); + TEST (NULL, str_check (g_build_path ("::", "::x::", "::y::", "::z::", NULL), "::x::y::z::")); + TEST (NULL, str_check (g_build_path ("::", ":::x:::", ":::y:::", ":::z:::", NULL), ":::x::::y::::z:::")); + TEST (NULL, str_check (g_build_path ("::", "::::x::::", "::::y::::", "::::z::::", NULL), "::::x::y::z::::")); + +#define S G_DIR_SEPARATOR_S + + TEST (NULL, str_check (g_build_filename (NULL), "")); + TEST (NULL, str_check (g_build_filename (S, NULL), S)); + TEST (NULL, str_check (g_build_filename (S"x", NULL), S"x")); + TEST (NULL, str_check (g_build_filename ("x"S, NULL), "x"S)); + TEST (NULL, str_check (g_build_filename ("x", "y", NULL), "x"S"y")); + TEST (NULL, str_check (g_build_filename (S"x", "y", NULL), S"x"S"y")); + TEST (NULL, str_check (g_build_filename ("x", "y"S, NULL), "x"S"y"S)); + TEST (NULL, str_check (g_build_filename (S"x"S, S"y"S, NULL), S"x"S"y"S)); + TEST (NULL, str_check (g_build_filename (S"x"S S, S S"y"S, NULL), S"x"S"y"S)); + TEST (NULL, str_check (g_build_filename ("x", "y", "z", NULL), "x"S"y"S"z")); + TEST (NULL, str_check (g_build_filename (S"x"S, S"y"S, S"z"S, NULL), S"x"S"y"S"z"S)); + TEST (NULL, str_check (g_build_filename (S S"x"S S, S S"y"S S, S S"z"S S, NULL), S S"x"S"y"S"z"S S)); + +#undef S + return any_failed; } -- 2.34.1