pathbuf: Treat forward slashes and backslashes as equivalent on Windows

The canonical directory separator is a backslash, but some Windows APIs
allow either, interchangeably. Do the same here.

Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/2914
Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
Simon McVittie 2023-02-10 11:13:06 +00:00
parent d5bf03cbcb
commit def7c0ac10
2 changed files with 17 additions and 3 deletions

View File

@ -288,9 +288,13 @@ g_path_buf_copy (GPathBuf *buf)
* *
* If @path is absolute, it replaces the current path. * If @path is absolute, it replaces the current path.
* *
* If @path contains `G_DIR_SEPARATOR_S`, the buffer is extended by * If @path contains a directory separator, the buffer is extended by
* as many elements the path provides. * as many elements the path provides.
* *
* On Windows, both forward slashes and backslashes are treated as
* directory separators. On other platforms, %G_DIR_SEPARATOR_S is the
* only directory separator.
*
* |[<!-- language="C" --> * |[<!-- language="C" -->
* GPathBuf buf, cmp; * GPathBuf buf, cmp;
* *
@ -323,7 +327,11 @@ g_path_buf_push (GPathBuf *buf,
if (g_path_is_absolute (path)) if (g_path_is_absolute (path))
{ {
#ifdef G_OS_WIN32
char **elements = g_strsplit_set (path, "\\/", -1);
#else
char **elements = g_strsplit (path, G_DIR_SEPARATOR_S, -1); char **elements = g_strsplit (path, G_DIR_SEPARATOR_S, -1);
#endif
#ifdef G_OS_UNIX #ifdef G_OS_UNIX
/* strsplit() will add an empty element for the leading root, /* strsplit() will add an empty element for the leading root,
@ -515,6 +523,9 @@ g_path_buf_set_extension (GPathBuf *buf,
* *
* Retrieves the built path from the path buffer. * Retrieves the built path from the path buffer.
* *
* On Windows, the result contains backslashes as directory separators,
* even if forward slashes were used in input.
*
* If the path buffer is empty, this function returns `NULL`. * If the path buffer is empty, this function returns `NULL`.
* *
* Returns: (transfer full) (type filename) (nullable): the path * Returns: (transfer full) (type filename) (nullable): the path

View File

@ -88,9 +88,12 @@ test_pathbuf_init (void)
GPathBuf buf; GPathBuf buf;
char *path; char *path;
g_path_buf_init_from_path (&buf, "C:\\windows\\system32.dll"); /* Forward slashes and backslashes are treated as interchangeable
* on input... */
g_path_buf_init_from_path (&buf, "C:\\windows/system32.dll");
path = g_path_buf_clear_to_path (&buf); path = g_path_buf_clear_to_path (&buf);
g_assert_nonnull (path); g_assert_nonnull (path);
/* ... and normalized to backslashes on output */
g_assert_cmpstr (path, ==, "C:\\windows\\system32.dll"); g_assert_cmpstr (path, ==, "C:\\windows\\system32.dll");
g_free (path); g_free (path);
@ -164,7 +167,7 @@ test_pathbuf_push_pop (void)
g_path_buf_push (&buf, "system32.dll"); g_path_buf_push (&buf, "system32.dll");
g_test_message ("Popping a path component"); g_test_message ("Popping a path component");
g_path_buf_init_from_path (&cmp, "C:\\windows\\system32.dll"); g_path_buf_init_from_path (&cmp, "C:\\windows/system32.dll");
g_assert_path_buf_equal (&buf, &cmp); g_assert_path_buf_equal (&buf, &cmp);
g_path_buf_clear (&cmp); g_path_buf_clear (&cmp);