From e37cf91f24fc409fa0aa84500245f57c685fc8ea Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 30 Jul 2016 16:36:53 +0200 Subject: Implement support for Windows path actualization --- butl/path.txx | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'butl/path.txx') diff --git a/butl/path.txx b/butl/path.txx index 1d6995e..08af340 100644 --- a/butl/path.txx +++ b/butl/path.txx @@ -3,6 +3,7 @@ // license : MIT; see accompanying LICENSE file #include +#include namespace butl { @@ -97,18 +98,32 @@ namespace butl return r / leaf (d); } +#ifdef _WIN32 + // Find the actual spelling of a name in the specified dir. If the name is + // found, append it to the result and return true. Otherwise, return false. + // Throw system_error in case of other failures. Result and dir can be the + // same instance. + // + template + bool + basic_path_append_actual_name (std::basic_string& result, + const std::basic_string& dir, + const std::basic_string& name); +#endif + template basic_path& basic_path:: - normalize () + normalize (bool actual) { if (empty ()) return *this; + bool abs (absolute ()); + assert (!actual || abs); // Only absolue can be actualized. + string_type& s (this->path_); difference_type& d (this->diff_); - bool abs (absolute ()); - typedef std::vector paths; paths ps; @@ -188,14 +203,37 @@ namespace butl r.push_back (std::move (s)); } - // Reassemble the path. + // Reassemble the path, actualizing each component if requested. // string_type p; - for (typename paths::const_iterator i (r.begin ()), e (r.end ()); + for (typename paths::const_iterator b (r.begin ()), i (b), e (r.end ()); i != e;) { - p += *i; +#ifdef _WIN32 + if (actual) + { + if (i == b) + { + // The first component (the drive letter) we have to actualize + // ourselves. Capital seems to be canonical. This is, for example, + // what getcwd() returns. + // + p = *i; + p[0] = traits::toupper (p[0]); + } + else + { + if (!basic_path_append_actual_name (p, p, *i)) + { + p += *i; + actual = false; // Ignore for all subsequent components. + } + } + } + else +#endif + p += *i; if (++i != e) p += traits::directory_separator; -- cgit v1.1