aboutsummaryrefslogtreecommitdiff
path: root/butl/path.ixx
diff options
context:
space:
mode:
Diffstat (limited to 'butl/path.ixx')
-rw-r--r--butl/path.ixx508
1 files changed, 0 insertions, 508 deletions
diff --git a/butl/path.ixx b/butl/path.ixx
deleted file mode 100644
index b60f206..0000000
--- a/butl/path.ixx
+++ /dev/null
@@ -1,508 +0,0 @@
-// file : butl/path.ixx -*- C++ -*-
-// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifdef _WIN32
-# include <cwctype> // towlower(), towupper()
-#endif
-
-namespace butl
-{
-#ifdef _WIN32
- template <>
- inline char path_traits<char>::
- tolower (char c)
- {
- return lcase (c);
- }
-
- template <>
- inline wchar_t path_traits<wchar_t>::
- tolower (wchar_t c)
- {
- return std::towlower (c);
- }
-
- template <>
- inline char path_traits<char>::
- toupper (char c)
- {
- return ucase (c);
- }
-
- template <>
- inline wchar_t path_traits<wchar_t>::
- toupper (wchar_t c)
- {
- return std::towupper (c);
- }
-#endif
-
- template <class C, class K1, class K2>
- inline basic_path<C, K1>
- path_cast_impl (const basic_path<C, K2>& p, basic_path<C, K1>*)
- {
- typename basic_path<C, K1>::data_type d (
- typename basic_path<C, K1>::string_type (p.path_), p.tsep_);
- K1::cast (d);
- return basic_path<C, K1> (std::move (d));
- }
-
- template <class C, class K1, class K2>
- inline basic_path<C, K1>
- path_cast_impl (basic_path<C, K2>&& p, basic_path<C, K1>*)
- {
- typename basic_path<C, K1>::data_type d (std::move (p.path_), p.tsep_);
- K1::cast (d);
- return basic_path<C, K1> (std::move (d));
- }
-
- template <class P, class C, class K>
- inline P
- path_cast (const basic_path<C, K>& p)
- {
- return path_cast_impl (p, static_cast<P*> (nullptr));
- }
-
- template <class P, class C, class K>
- inline P
- path_cast (basic_path<C, K>&& p)
- {
- return path_cast_impl (std::move (p), static_cast<P*> (nullptr));
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- simple () const
- {
- return empty () ||
- traits::rfind_separator (this->path_, _size () - 1) == string_type::npos;
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- absolute () const
- {
- return traits::absolute (this->path_);
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- current () const
- {
- return traits::current (this->path_);
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- parent () const
- {
- return traits::parent (this->path_);
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- root () const
- {
- return traits::root (this->path_);
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- sub (const basic_path& p) const
- {
- // The thinking here is that we can use the full string representations
- // (including the trailing slash in "/").
- //
- const string_type& ps (p.path_);
- size_type pn (ps.size ());
-
- if (pn == 0)
- return true;
-
- const string_type& s (this->path_);
- size_type n (s.size ());
-
- // The second condition guards against the /foo-bar vs /foo case.
- //
- return n >= pn &&
- traits::compare (s.c_str (), pn, ps.c_str (), pn) == 0 &&
- (traits::is_separator (ps.back ()) || // p ends with a separator
- n == pn || // *this == p
- traits::is_separator (s[pn])); // next char is a separator
- }
-
- template <typename C, typename K>
- inline bool basic_path<C, K>::
- sup (const basic_path& p) const
- {
- // The thinking here is that we can use the full string representations
- // (including the trailing slash in "/").
- //
- const string_type& ps (p.path_);
- size_type pn (ps.size ());
-
- if (pn == 0)
- return true;
-
- const string_type& s (this->path_);
- size_type n (s.size ());
-
- // The second condition guards against the /foo-bar vs bar case.
- //
- return n >= pn &&
- traits::compare (s.c_str () + n - pn, pn, ps.c_str (), pn) == 0 &&
- (n == pn || // *this == p
- traits::is_separator (s[n - pn - 1])); // previous char is a separator
- }
-
- template <typename C, typename K>
- inline basic_path<C, K> basic_path<C, K>::
- leaf () const
- {
- const string_type& s (this->path_);
- size_type n (_size ());
-
- size_type p (n != 0
- ? traits::rfind_separator (s, n - 1)
- : string_type::npos);
-
- return p != string_type::npos
- ? basic_path (data_type (string_type (s, p + 1), this->tsep_))
- : *this;
- }
-
- template <typename C, typename K>
- inline typename basic_path<C, K>::dir_type basic_path<C, K>::
- directory () const
- {
- const string_type& s (this->path_);
- size_type n (_size ());
-
- size_type p (n != 0
- ? traits::rfind_separator (s, n - 1)
- : string_type::npos);
-
- return p != string_type::npos
- ? dir_type (data_type (string_type (s, 0, p + 1))) // Include slash.
- : dir_type ();
- }
-
- template <typename C, typename K>
- inline auto basic_path<C, K>::
- begin () const -> iterator
- {
- const string_type& s (this->path_);
-
- size_type b (s.empty () ? string_type::npos : 0);
- size_type e (b == 0 ? traits::find_separator (s) : b);
-
- return iterator (this, b, e);
- }
-
- template <typename C, typename K>
- inline auto basic_path<C, K>::
- end () const -> iterator
- {
- return iterator (this, string_type::npos, string_type::npos);
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>::
- basic_path (const iterator& b, const iterator& e)
- : base_type (
- b == e
- ? data_type ()
- // We need to include the trailing separator but it is implied if
- // e == end().
- //
- : (e.b_ != string_type::npos
- ? data_type (string_type (b.p_->path_, b.b_, e.b_ - b.b_))
- : data_type (string_type (b.p_->path_, b.b_), b.p_->tsep_)))
- {
- //assert (b.p_ == e.p_);
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- canonicalize ()
- {
- traits::canonicalize (this->path_);
-
- if (this->tsep_ > 1) // Non-canonical trailing separator.
- this->tsep_ = 1;
-
- return *this;
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- complete ()
- {
- if (relative ())
- *this = current_directory () / *this;
-
- return *this;
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- realize ()
- {
-#ifdef _WIN32
- // This is not exactly the semantics of realpath(3). In particular, we
- // don't fail if the path does not exist. But we could have seeing that
- // we actualize it.
- //
- complete ();
- normalize (true);
-#else
- traits::realize (this->path_); // Note: we retain the trailing slash.
-#endif
- return *this;
- }
-
- template <typename C, typename K>
- inline typename basic_path<C, K>::dir_type basic_path<C, K>::
- root_directory () const
- {
-#ifdef _WIN32
- // Note: on Windows we may have "c:" but still need to return "c:\".
- //
- const string_type& s (this->path_);
-
- return absolute ()
- ? dir_type (
- s.size () > 2
- ? data_type (string_type (s, 0, 3))
- : data_type (string_type (s), this->tsep_ != 0 ? this->tsep_ : 1))
- : dir_type ();
-#else
- return absolute ()
- ? dir_type (data_type ("/", -1))
- : dir_type ();
-#endif
-
- }
-
- template <typename C, typename K>
- inline basic_path<C, K> basic_path<C, K>::
- base () const
- {
- const string_type& s (this->path_);
- size_type p (traits::find_extension (s));
-
- return p != string_type::npos
- ? basic_path (data_type (string_type (s, 0, p), this->tsep_))
- : *this;
- }
-
- template <typename C, typename K>
- inline typename basic_path<C, K>::string_type basic_path<C, K>::
- extension () const
- {
- const string_type& s (this->path_);
- size_type p (traits::find_extension (s));
- return p != string_type::npos
- ? string_type (s.c_str () + p + 1)
- : string_type ();
- }
-
- template <typename C, typename K>
- inline const C* basic_path<C, K>::
- extension_cstring () const
- {
- const string_type& s (this->path_);
- size_type p (traits::find_extension (s));
- return p != string_type::npos ? s.c_str () + p + 1 : nullptr;
- }
-
-#ifndef _WIN32
- template <typename C, typename K>
- inline typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_string () const&
- {
- return string ();
- }
-
- template <typename C, typename K>
- inline typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_string () &&
- {
- return std::move (*this).string ();
- }
-
- template <typename C, typename K>
- inline typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_representation () const&
- {
- return representation ();
- }
-
- template <typename C, typename K>
- inline typename basic_path<C, K>::string_type basic_path<C, K>::
- posix_representation () &&
- {
- return std::move (*this).representation ();
- }
-#endif
-
- template <typename C, typename K>
- inline void basic_path<C, K>::
- combine (const C* r, size_type rn, difference_type rts)
- {
- //assert (rn != 0);
-
- string_type& l (this->path_);
- difference_type& ts (this->tsep_);
-
- // Handle the separator. LHS should be empty or already have one.
- //
- switch (ts)
- {
- case 0: if (!l.empty ()) throw invalid_basic_path<C> (l); break;
- case -1: break; // Already in the string.
- default: l += path_traits<C>::directory_separators[ts - 1];
- }
-
- l.append (r, rn);
- ts = rts; // New trailing separator from RHS.
- }
-
- template <typename C, typename K>
- inline void basic_path<C, K>::
- combine (const C* r, size_type rn)
- {
- // If we do (dir_path / path) then we will end up with path. What should
- // we end up if we do (dir_path / "foo") vs (dir_path / "foo/")? We cannot
- // choose at runtime what kind of path to return. One (elaborate) option
- // would be to handle the trailing slash but also call K::cast() so that
- // dir_path gets the canonical trailing slash if one wasn't there.
- //
- // For now we won't allow the slash and will always add the canonical one
- // for dir_path (via cast()).
- //
- if (traits::find_separator (r, rn) != nullptr)
- throw invalid_basic_path<C> (r);
-
- combine (r, rn, 0);
- K::cast (*this);
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- operator/= (basic_path<C, K> const& r)
- {
- if (r.absolute () && !empty ()) // Allow ('' / '/foo').
- throw invalid_basic_path<C> (r.path_);
-
- if (!r.empty ())
- combine (r.path_.c_str (), r.path_.size (), r.tsep_);
-
- return *this;
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- operator/= (string_type const& r)
- {
- if (size_type rn = r.size ())
- combine (r.c_str (), rn);
-
- return *this;
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- operator/= (const C* r)
- {
- if (size_type rn = string_type::traits_type::length (r))
- combine (r, rn);
-
- return *this;
- }
-
- template <typename C, typename K>
- inline void basic_path<C, K>::
- append (const C* r, size_type rn)
- {
- //assert (this->tsep_ != -1); // Append to root?
- this->path_.append (r, rn);
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- operator+= (string_type const& s)
- {
- append (s.c_str (), s.size ());
- return *this;
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- operator+= (const C* s)
- {
- append (s, string_type::traits_type::length (s));
- return *this;
- }
-
- template <typename C, typename K>
- inline basic_path<C, K>& basic_path<C, K>::
- operator+= (C c)
- {
- append (&c, 1);
- return *this;
- }
-
- template <typename C, typename K>
- inline auto basic_path<C, K>::
- representation () const& -> string_type
- {
- string_type r (this->path_);
-
- if (this->tsep_ > 0)
- r += path_traits<C>::directory_separators[this->tsep_ - 1];
-
- return r;
- }
-
- template <typename C, typename K>
- inline auto basic_path<C, K>::
- representation () && -> string_type
- {
- string_type r;
- r.swap (this->path_);
-
- if (this->tsep_ > 0)
- r += path_traits<C>::directory_separators[this->tsep_ - 1];
-
- return r;
- }
-
- template <typename C, typename K>
- inline C basic_path<C, K>::
- separator () const
- {
- return (this->tsep_ == 0 ? 0 :
- this->tsep_ == -1 ? this->path_[0] :
- path_traits<C>::directory_separators[this->tsep_ - 1]);
- }
-
- template <typename C, typename K>
- inline auto basic_path<C, K>::
- separator_string () const -> string_type
- {
- C c (separator ());
- return c == 0 ? string_type () : string_type (1, c);
- }
-
- template <typename C>
- inline void dir_path_kind<C>::
- cast (data_type& d)
- {
- // Add trailing slash if one isn't already there.
- //
- if (!d.path_.empty () && d.tsep_ == 0)
- d.tsep_ = 1; // Canonical separator is always first.
- }
-}