aboutsummaryrefslogtreecommitdiff
path: root/butl/path.txx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-07-30 16:36:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-07-30 16:36:53 +0200
commite37cf91f24fc409fa0aa84500245f57c685fc8ea (patch)
tree2c0730f6c4226b054cb5eaf640fd0bb704536dae /butl/path.txx
parent6597c9b777b608a96974b4a7a8c15234b05ffdd8 (diff)
Implement support for Windows path actualization
Diffstat (limited to 'butl/path.txx')
-rw-r--r--butl/path.txx50
1 files changed, 44 insertions, 6 deletions
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 <vector>
+#include <cassert>
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 <typename C>
+ bool
+ basic_path_append_actual_name (std::basic_string<C>& result,
+ const std::basic_string<C>& dir,
+ const std::basic_string<C>& name);
+#endif
+
template <typename C, typename K>
basic_path<C, K>& basic_path<C, K>::
- 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<string_type> 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;