aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2014-09-06 14:26:41 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2014-09-06 14:26:41 +0200
commit75205dd307c57df24d282b94f1bca3b668579c1e (patch)
tree0e9af30ffee9bb99df557909a01dba008c1d0fb2
parent1801a430cd5059b1220b48a1ecd58f0bbee7e4b6 (diff)
Do not low-case paths in normalize() for Win32
Instead, do case-insensitive comparison. Also handle separators while at it.
-rw-r--r--cutl/fs/path.hxx46
-rw-r--r--cutl/fs/path.ixx32
-rw-r--r--cutl/fs/path.txx8
-rw-r--r--tests/fs/path/driver.cxx15
4 files changed, 63 insertions, 38 deletions
diff --git a/cutl/fs/path.hxx b/cutl/fs/path.hxx
index cbe71a6..45a7891 100644
--- a/cutl/fs/path.hxx
+++ b/cutl/fs/path.hxx
@@ -39,7 +39,6 @@ namespace cutl
// could be multiple seperators. For example, on Windows
// we check for both '/' and '\'.
//
-
static bool
is_separator (C c)
{
@@ -78,6 +77,33 @@ namespace cutl
return string_type::npos;
}
+
+ static int
+ compare (string_type const& l, string_type const& r)
+ {
+ size_type ln (l.size ()), rn (r.size ()), n (ln < rn ? ln : rn);
+ for (size_type i (0); i != n; ++i)
+ {
+#ifdef _WIN32
+ C lc (tolower (l[i])), rc (tolower (r[i]));
+#else
+ C lc (l[i]), rc (r[i]);
+#endif
+ if (is_separator (lc) && is_separator (rc))
+ continue;
+
+ if (lc < rc) return -1;
+ if (lc > rc) return 1;
+ }
+
+ return ln < rn ? -1 : (ln > rn ? 1 : 0);
+ }
+
+ private:
+#ifdef _WIN32
+ static C
+ tolower (C);
+#endif
};
template <typename C>
@@ -210,10 +236,8 @@ namespace cutl
public:
// Normalize the path. This includes collapsing the '.' and '..'
// directories if possible, collapsing multiple directory
- // separators, converting all directory separators to the
- // canonical form, and making the path lower-case if the
- // filesystem is not case-sensitive (e.g., Windows). Returns
- // *this.
+ // separators, and converting all directory separators to the
+ // canonical form. Returns *this.
//
basic_path&
normalize ();
@@ -249,10 +273,13 @@ namespace cutl
return *this;
}
+ // Note that comparison is case-insensitive if the filesystem is
+ // not case-sensitive (e.g., Windows).
+ //
bool
operator== (basic_path const& x) const
{
- return path_ == x.path_;
+ return traits::compare (path_, x.path_) == 0;
}
bool
@@ -264,7 +291,7 @@ namespace cutl
bool
operator< (basic_path const& x) const
{
- return path_ < x.path_;
+ return traits::compare (path_, x.path_) < 0;
}
public:
@@ -287,11 +314,6 @@ namespace cutl
void
init ();
-#ifdef _WIN32
- static C
- tolower (C);
-#endif
-
private:
string_type path_;
};
diff --git a/cutl/fs/path.ixx b/cutl/fs/path.ixx
index 80d3bb3..64d05a6 100644
--- a/cutl/fs/path.ixx
+++ b/cutl/fs/path.ixx
@@ -11,6 +11,22 @@ namespace cutl
{
namespace fs
{
+#ifdef _WIN32
+ template <>
+ inline char path_traits<char>::
+ tolower (char c)
+ {
+ return std::tolower (c);
+ }
+
+ template <>
+ inline wchar_t path_traits<wchar_t>::
+ tolower (wchar_t c)
+ {
+ return std::towlower (c);
+ }
+#endif
+
template <typename C>
inline bool basic_path<C>::
absolute () const
@@ -51,21 +67,5 @@ namespace cutl
return string ();
}
#endif
-
-#ifdef _WIN32
- template <>
- inline char basic_path<char>::
- tolower (char c)
- {
- return std::tolower (c);
- }
-
- template <>
- inline wchar_t basic_path<wchar_t>::
- tolower (wchar_t c)
- {
- return std::towlower (c);
- }
-#endif
}
}
diff --git a/cutl/fs/path.txx b/cutl/fs/path.txx
index e95c890..8939665 100644
--- a/cutl/fs/path.txx
+++ b/cutl/fs/path.txx
@@ -182,15 +182,9 @@ namespace cutl
for (typename paths::const_iterator i (r.begin ()), e (r.end ());
i != e;)
{
-#ifdef _WIN32
- for (size_type j (0), n (i->size ()); j < n; ++j)
- p += tolower ((*i)[j]);
-#else
p += *i;
-#endif
- ++i;
- if (i != e)
+ if (++i != e)
p += traits::directory_separator;
}
diff --git a/tests/fs/path/driver.cxx b/tests/fs/path/driver.cxx
index 6c77e67..c6bf46a 100644
--- a/tests/fs/path/driver.cxx
+++ b/tests/fs/path/driver.cxx
@@ -112,11 +112,20 @@ main ()
assert (path ("./..").normalize ().string () == "..");
assert (path ("../.").normalize ().string () == "..");
assert (path ("foo/./..").normalize ().string () == "");
- assert (path ("C:/foo/./..").normalize ().string () == "c:");
+ assert (path ("C:/foo/./..").normalize ().string () == "C:");
assert (path ("./foo").normalize ().string () == "foo");
- assert (path ("C:").normalize ().string () == "c:");
- assert (path ("C:\\Foo12//Bar").normalize ().string () == "c:\\foo12\\bar");
+ assert (path ("C:").normalize ().string () == "C:");
+ assert (path ("C:\\Foo12//Bar").normalize ().string () == "C:\\Foo12\\Bar");
+#endif
+
+ // comparison
+ //
+ assert (path ("./foo") == path("./foo"));
+ assert (path ("./boo") < path("./foo"));
+#ifdef _WIN32
+ assert (path (".\\foo") == path("./FoO"));
+ assert (path (".\\boo") < path(".\\Foo"));
#endif
// posix_string