aboutsummaryrefslogtreecommitdiff
path: root/butl/path.txx
diff options
context:
space:
mode:
Diffstat (limited to 'butl/path.txx')
-rw-r--r--butl/path.txx377
1 files changed, 0 insertions, 377 deletions
diff --git a/butl/path.txx b/butl/path.txx
deleted file mode 100644
index 3edd076..0000000
--- a/butl/path.txx
+++ /dev/null
@@ -1,377 +0,0 @@
-// file : butl/path.txx -*- C++ -*-
-// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <vector>
-#include <cassert>
-
-#ifdef _WIN32
-# include <algorithm> // replace()
-#endif
-
-namespace butl
-{
- template <typename C, typename K>
- basic_path<C, K> basic_path<C, K>::
- leaf (basic_path<C, K> const& d) const
- {
- size_type dn (d.path_.size ());
-
- if (dn == 0)
- return *this;
-
- const string_type& s (this->path_);
-
- if (!sub (d))
- throw invalid_basic_path<C> (s);
-
- // If there is implied trailing slash, add it to count. Unless it is
- // "matched" by the implied slash on the other side.
- //
- if (d.tsep_ > 0 && dn < s.size ())
- dn++;
-
- // Preserve trailing slash.
- //
- return basic_path (data_type (string_type (s, dn, s.size () - dn),
- this->tsep_));
- }
-
- template <typename C, typename K>
- typename basic_path<C, K>::dir_type basic_path<C, K>::
- directory (basic_path<C, K> const& l) const
- {
- size_type ln (l.path_.size ());
-
- const string_type& s (this->path_);
-
- if (ln == 0)
- {
- if (this->tsep_ == 0) // Must be a directory.
- throw invalid_basic_path<C> (s);
-
- return dir_type (data_type (string_type (s), this->tsep_));
- }
-
- if (!sup (l))
- throw invalid_basic_path<C> (s);
-
- return dir_type (
- data_type (string_type (s, 0, s.size () - ln))); // Include slash.
- }
-
-#ifdef _WIN32
- template <typename C, typename K>
- typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_string () const&
- {
- if (absolute ())
- throw invalid_basic_path<C> (this->path_);
-
- string_type r (string ());
- replace (r.begin (), r.end (), '\\', '/');
- return r;
- }
-
- template <typename C, typename K>
- typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_string () &&
- {
- if (absolute ())
- throw invalid_basic_path<C> (this->path_);
-
- string_type r (std::move (*this).string ());
- replace (r.begin (), r.end (), '\\', '/');
- return r;
- }
-
- template <typename C, typename K>
- typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_representation () const&
- {
- if (absolute ())
- throw invalid_basic_path<C> (this->path_);
-
- string_type r (representation ());
- replace (r.begin (), r.end (), '\\', '/');
- return r;
- }
-
- template <typename C, typename K>
- typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_representation () &&
- {
- if (absolute ())
- throw invalid_basic_path<C> (this->path_);
-
- string_type r (std::move (*this).representation ());
- replace (r.begin (), r.end (), '\\', '/');
- return r;
- }
-#endif
-
- template <typename C, typename K>
- basic_path<C, K> basic_path<C, K>::
- relative (basic_path<C, K> d) const
- {
- dir_type r;
-
- for (;; d = d.directory ())
- {
- if (sub (d))
- break;
-
- r /= "..";
-
- // Roots of the paths do not match.
- //
- if (d.root ())
- throw invalid_basic_path<C> (this->path_);
- }
-
- 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 (bool actual, bool cur_empty)
- {
- if (empty ())
- return *this;
-
- bool abs (absolute ());
- assert (!actual || abs); // Only absolue can be actualized.
-
- string_type& s (this->path_);
- difference_type& ts (this->tsep_);
-
- typedef std::vector<string_type> paths;
- paths ps;
-
- bool tsep (ts != 0); // Trailing directory separator.
- {
- size_type n (_size ());
-
- for (size_type b (0), e (traits::find_separator (s, 0, n));
- ;
- e = traits::find_separator (s, b, n))
- {
- ps.push_back (
- string_type (s, b, (e == string_type::npos ? n : e) - b));
-
- if (e == string_type::npos)
- break;
-
- ++e;
-
- // Skip consecutive directory separators.
- //
- while (e != n && traits::is_separator (s[e]))
- ++e;
-
- if (e == n)
- break;
-
- b = e;
- }
-
- // If the last component is "." or ".." then this is a directory.
- //
- if (!tsep)
- {
- const string_type& l (ps.back ());
- if (traits::current (l) || traits::parent (l))
- tsep = true;
- }
- }
-
- // Collapse "." and "..".
- //
- paths r;
-
- for (typename paths::iterator i (ps.begin ()), e (ps.end ()); i != e; ++i)
- {
- string_type& s (*i);
-
- if (traits::current (s))
- continue;
-
- // If '..' then pop the last directory from r unless it is '..'.
- //
- if (traits::parent (s) && !r.empty () && !traits::parent (r.back ()))
- {
- // Cannot go past the root directory.
- //
- if (abs && r.size () == 1)
- throw invalid_basic_path<C> (this->path_);
-
- r.pop_back ();
- continue;
- }
-
- r.push_back (std::move (s));
- }
-
- // Reassemble the path, actualizing each component if requested.
- //
- string_type p;
-
- for (typename paths::const_iterator b (r.begin ()), i (b), e (r.end ());
- i != e;)
- {
-#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;
- }
-
- if (tsep)
- {
- if (p.empty ())
- {
- // Distinguish "/"-empty and "."-empty.
- //
- if (abs)
- {
- p += traits::directory_separator;
- ts = -1;
- }
- else if (!cur_empty) // Collapse to canonical current directory.
- {
- p.assign (1, '.');
- ts = 1; // Canonical separator is always first.
- }
- else // Collapse to empty path.
- ts = 0;
- }
- else
- ts = 1; // Canonical separator is always first.
- }
- else
- ts = 0;
-
- s.swap (p);
- return *this;
- }
-
- template <typename C, typename K>
- void basic_path<C, K>::
- current_directory (basic_path const& p)
- {
- const string_type& s (p.string ());
-
- if (s.empty ())
- throw invalid_basic_path<char> (s);
-
- traits::current_directory (s);
- }
-
- template <typename C>
- auto any_path_kind<C>::
- init (string_type&& s, bool exact) -> data_type
- {
- using size_type = typename string_type::size_type;
- using difference_type = typename string_type::difference_type;
-
- size_type n (s.size ());
-
-#ifdef _WIN32
- // We do not support any special Windows path name notations like in C:abc,
- // /, \, /abc, \abc, \\?\c:\abc, \\server\abc and \\?\UNC\server\abc (more
- // about them in "Naming Files, Paths, and Namespaces" MSDN article).
- //
- if ((n > 2 && s[1] == ':' && s[2] != '\\' && s[2] != '/') ||
- (n > 0 && (s[0] == '\\' || s[0] == '/')))
- {
- if (exact)
- return data_type ();
- else
- throw invalid_basic_path<C> (s);
- }
-#endif
-
- // Strip trailing slashes.
- //
- size_type m (n), di (0);
- for (size_type i;
- m != 0 && (i = path_traits<C>::separator_index (s[m - 1])) != 0;
- --m) di = i;
-
- difference_type ts (0);
- if (size_t k = n - m)
- {
- // We can only accomodate one trailing slash in the exact mode.
- //
- if (exact && k > 1)
- return data_type ();
-
- if (m == 0) // The "/" case.
- {
- ++m; // Keep one slash in the string.
- ts = -1;
- }
- else
- ts = di;
-
- s.resize (m);
- }
-
- return data_type (std::move (s), ts);
- }
-
- template <typename C>
- auto dir_path_kind<C>::
- init (string_type&& s, bool exact) -> data_type
- {
- // If we don't already have the separator then this can't be the exact
- // initialization.
- //
- if (exact && !s.empty () && !path_traits<C>::is_separator (s.back ()))
- return data_type ();
-
- data_type r (any_path_kind<C>::init (std::move (s), exact));
-
- // Unless the result is empty, make sure we have the trailing slash.
- //
- if (!r.path_.empty () && r.tsep_ == 0)
- r.tsep_ = 1; // Canonical separator is always first.
-
- return r;
- }
-}