ICU-20545 Ensure that path ends with detected file separator
CharString, when asked, appends U_FILE_SEP_CHAR at the end of the string
it holds, if it won't find U_FILE_SEP_CHAR or U_FILE_ALT_SEP_CHAR there.
The problem starts if the dir variable uses
U_FILE_ALT_SEP_CHAR which is not equal to U_FILE_SEP_CHAR. Then the
resulting path could look like this
../data\
instead of this
../data/
This patch uses U_FILE_SEP_CHAR unless it detects that the dir variable
doesn't use it, and uses U_FILE_ALT_SEP_CHAR instead.
diff --git a/icu4c/source/common/charstr.cpp b/icu4c/source/common/charstr.cpp
index dda29da..4878c73 100644
--- a/icu4c/source/common/charstr.cpp
+++ b/icu4c/source/common/charstr.cpp
@@ -197,7 +197,7 @@ CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) {
}
char c;
if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
- append(U_FILE_SEP_CHAR, errorCode);
+ append(getDirSepChar(), errorCode);
}
append(s, errorCode);
return *this;
@@ -207,9 +207,19 @@ CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) {
char c;
if(U_SUCCESS(errorCode) && len>0 &&
(c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
- append(U_FILE_SEP_CHAR, errorCode);
+ append(getDirSepChar(), errorCode);
}
return *this;
}
+char CharString::getDirSepChar() const {
+ char dirSepChar = U_FILE_SEP_CHAR;
+#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
+ // We may need to return a different directory separator when building for Cygwin or MSYS2.
+ if(len>0 && !uprv_strchr(data(), U_FILE_SEP_CHAR) && uprv_strchr(data(), U_FILE_ALT_SEP_CHAR))
+ dirSepChar = U_FILE_ALT_SEP_CHAR;
+#endif
+ return dirSepChar;
+}
+
U_NAMESPACE_END
diff --git a/icu4c/source/common/charstr.h b/icu4c/source/common/charstr.h
index 23b950e..9400fbb 100644
--- a/icu4c/source/common/charstr.h
+++ b/icu4c/source/common/charstr.h
@@ -141,13 +141,13 @@ class U_COMMON_API CharString : public UMemory {
/**
* Appends a filename/path part, e.g., a directory name.
- * First appends a U_FILE_SEP_CHAR if necessary.
+ * First appends a U_FILE_SEP_CHAR or U_FILE_ALT_SEP_CHAR if necessary.
* Does nothing if s is empty.
*/
CharString &appendPathPart(StringPiece s, UErrorCode &errorCode);
/**
- * Appends a U_FILE_SEP_CHAR if this string is not empty
+ * Appends a U_FILE_SEP_CHAR or U_FILE_ALT_SEP_CHAR if this string is not empty
* and does not already end with a U_FILE_SEP_CHAR or U_FILE_ALT_SEP_CHAR.
*/
CharString &ensureEndsWithFileSeparator(UErrorCode &errorCode);
@@ -160,6 +160,12 @@ class U_COMMON_API CharString : public UMemory {
CharString(const CharString &other); // forbid copying of this class
CharString &operator=(const CharString &other); // forbid copying of this class
+
+ /**
+ * Returns U_FILE_ALT_SEP_CHAR if found in string, and U_FILE_SEP_CHAR is not found.
+ * Otherwise returns U_FILE_SEP_CHAR.
+ */
+ char getDirSepChar() const;
};
U_NAMESPACE_END