BLI_path: only operate on native path slashes for BLI_path_join

Previously both slashes were considered when joining paths, meaning
slashes that were part of the path name could be stripped before joining
the path.

Prefer using the native path separator for low level path functions,
callers can always convert slashes into the expected direction if they
need. This also matches BLI_path_append behavior.
This commit is contained in:
Campbell Barton 2022-10-31 13:04:30 +11:00
parent fe5cbd5eea
commit 8f7ab1bf46
Notes: blender-bot 2023-02-14 01:11:05 +01:00
Referenced by commit a16ef95ff6, Fix T102914: bpy.ops.wm.append no longer supports / in paths for  WIN32
Referenced by commit db43aa7729, Fix T102201: File selector shows "\" before folder names on WIN32
Referenced by issue #102914, Regression: bpy.ops.wm.append can't run correct in blender 3.4
Referenced by issue #102201, Regression: Blender 3.4 -  (any directory) shows "\" or "\.." before their folder name and file name.
2 changed files with 48 additions and 12 deletions

View File

@ -1487,9 +1487,10 @@ size_t BLI_path_join_array(char *__restrict dst,
bool has_trailing_slash = false;
if (ofs != 0) {
size_t len = ofs;
while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) {
while ((len != 0) && (path[len - 1] == SEP)) {
len -= 1;
}
if (len != 0) {
ofs = len;
}
@ -1500,18 +1501,18 @@ size_t BLI_path_join_array(char *__restrict dst,
path = path_array[path_index];
has_trailing_slash = false;
const char *path_init = path;
while (ELEM(path[0], SEP, ALTSEP)) {
while (path[0] == SEP) {
path++;
}
size_t len = strlen(path);
if (len != 0) {
while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) {
while ((len != 0) && (path[len - 1] == SEP)) {
len -= 1;
}
if (len != 0) {
/* the very first path may have a slash at the end */
if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) {
if (ofs && (dst[ofs - 1] != SEP)) {
dst[ofs++] = SEP;
if (ofs == dst_last) {
break;
@ -1534,7 +1535,7 @@ size_t BLI_path_join_array(char *__restrict dst,
}
if (has_trailing_slash) {
if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) {
if ((ofs != dst_last) && (ofs != 0) && (dst[ofs - 1] != SEP)) {
dst[ofs++] = SEP;
}
}

View File

@ -201,20 +201,53 @@ TEST(path_util, NameAtIndex_NoneComplexNeg)
#undef AT_INDEX
#define JOIN(str_expect, out_size, ...) \
/* For systems with `/` path separator (non WIN32). */
#define JOIN_FORWARD_SLASH(str_expect, out_size, ...) \
{ \
const char *expect = str_expect; \
char result[(out_size) + 1024]; \
/* check we don't write past the last byte */ \
/* Check we don't write past the last byte. */ \
result[out_size] = '\0'; \
BLI_path_join(result, out_size, __VA_ARGS__); \
/* simplify expected string */ \
BLI_str_replace_char(result, '\\', '/'); \
EXPECT_STREQ(result, expect); \
EXPECT_EQ(result[out_size], '\0'); \
} \
((void)0)
/* For systems with `\` path separator (WIN32).
* Perform additional manipulation to behave as if input arguments used `\` separators.
* Needed since #BLI_path_join uses native slashes. */
#define JOIN_BACK_SLASH(str_expect, out_size, ...) \
{ \
const char *expect = str_expect; \
char result[(out_size) + 1024]; \
const char *input_forward_slash[] = {__VA_ARGS__}; \
char *input_back_slash[ARRAY_SIZE(input_forward_slash)] = {nullptr}; \
for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \
input_back_slash[i] = strdup(input_forward_slash[i]); \
BLI_str_replace_char(input_back_slash[i], '/', '\\'); \
} \
/* Check we don't write past the last byte. */ \
result[out_size] = '\0'; \
BLI_path_join_array(result, \
out_size, \
const_cast<const char **>(input_back_slash), \
ARRAY_SIZE(input_back_slash)); \
BLI_str_replace_char(result, '\\', '/'); \
EXPECT_STREQ(result, expect); \
EXPECT_EQ(result[out_size], '\0'); \
for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \
free(input_back_slash[i]); \
} \
} \
((void)0)
#ifdef WIN32
# define JOIN JOIN_BACK_SLASH
#else
# define JOIN JOIN_FORWARD_SLASH
#endif
/* BLI_path_join */
TEST(path_util, JoinNop)
{
@ -293,9 +326,9 @@ TEST(path_util, JoinTruncateLong)
TEST(path_util, JoinComplex)
{
JOIN("/a/b/c/d/e/f/g/", 100, "/", "\\a/b", "//////c/d", "", "e\\\\", "f", "g//");
JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "\\aa/bb", "//////cc/dd", "", "ee\\\\", "ff", "gg//");
JOIN("1/2/3/", 100, "1", "////////", "", "2", "3\\");
JOIN("/a/b/c/d/e/f/g/", 100, "/", "a/b", "//////c/d", "", "e", "f", "g//");
JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "aa/bb", "//////cc/dd", "", "ee", "ff", "gg//");
JOIN("1/2/3/", 100, "1", "////////", "", "2", "3///");
}
TEST(path_util, JoinRelativePrefix)
@ -306,6 +339,8 @@ TEST(path_util, JoinRelativePrefix)
}
#undef JOIN
#undef JOIN_BACK_SLASH
#undef JOIN_FORWARD_SLASH
/* BLI_path_frame */
TEST(path_util, Frame)