aboutsummaryrefslogtreecommitdiff
path: root/butl/path.ixx
diff options
context:
space:
mode:
Diffstat (limited to 'butl/path.ixx')
-rw-r--r--butl/path.ixx171
1 files changed, 171 insertions, 0 deletions
diff --git a/butl/path.ixx b/butl/path.ixx
new file mode 100644
index 0000000..0cbbeaf
--- /dev/null
+++ b/butl/path.ixx
@@ -0,0 +1,171 @@
+// file : butl/path.ixx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifdef _WIN32
+# include <cctype> // std::tolower
+# include <cwctype> // std::towlower
+#endif
+
+namespace butl
+{
+#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, typename K>
+ inline bool basic_path<C, K>::
+ absolute () const
+ {
+#ifdef _WIN32
+ return this->path_.size () > 1 && this->path_[1] == ':';
+#else
+ return !this->path_.empty () && traits::is_separator (this->path_[0]);
+#endif
+ }
+
+ template <typename C, typename K>
+ inline bool basic_path<C, K>::
+ root () const
+ {
+#ifdef _WIN32
+ return this->path_.size () == 2 && this->path_[1] == ':';
+#else
+ return this->path_.size () == 1 && traits::is_separator (this->path_[0]);
+#endif
+ }
+
+ template <typename C, typename K>
+ inline bool basic_path<C, K>::
+ sub (const basic_path& p) const
+ {
+ size_type n (p.path_.size ());
+
+ if (n == 0)
+ return true;
+
+ size_type m (this->path_.size ());
+
+ // The second condition guards against the /foo-bar vs /foo case.
+ //
+ return m >= n && this->path_.compare (0, n, p.path_) == 0 &&
+ (traits::is_separator (p.path_.back ()) || // p ends with a separator
+ m == n || // *this == p
+ traits::is_separator (this->path_[n])); // next char is a separator
+ }
+
+ template <typename C, typename K>
+ inline bool basic_path<C, K>::
+ sup (const basic_path& p) const
+ {
+ size_type n (p.path_.size ());
+
+ if (n == 0)
+ return true;
+
+ size_type m (this->path_.size ());
+
+ // The second condition guards against the /foo-bar vs bar case.
+ //
+ return m >= n && this->path_.compare (m - n, n, p.path_) == 0 &&
+ (m == n || // *this == p
+ traits::is_separator (this->path_[m - n - 1])); // prev char separator
+ }
+
+ template <typename C, typename K>
+ inline auto basic_path<C, K>::
+ begin () const -> iterator
+ {
+ size_type b, e;
+
+ if (this->path_.empty ())
+ b = e = string_type::npos;
+
+#ifndef _WIN32
+ else if (root ())
+ {
+ // We want to return a single empty component. Here we return
+ // the begin position one past the end. Not sure if this legal.
+ //
+ b = 1;
+ e = string_type::npos;
+ }
+#endif
+ else
+ {
+ b = 0;
+ e = traits::find_separator (this->path_);
+ }
+
+ return iterator (this->path_, b, e);
+ }
+
+ template <typename C, typename K>
+ inline auto basic_path<C, K>::
+ end () const -> iterator
+ {
+ return iterator (this->path_, string_type::npos, string_type::npos);
+ }
+
+ template <typename C, typename K>
+ inline basic_path<C, K>& basic_path<C, K>::
+ complete ()
+ {
+ if (relative ())
+ *this = current () / *this;
+
+ return *this;
+ }
+
+ template <typename C, typename K>
+ inline typename basic_path<C, K>::dir_type basic_path<C, K>::
+ root_directory () const
+ {
+ return absolute ()
+#ifdef _WIN32
+ ? dir_type (this->path_, 2)
+#else
+ ? dir_type ("/")
+#endif
+ : dir_type ();
+ }
+
+ template <typename C, typename K>
+ inline basic_path<C, K> basic_path<C, K>::
+ base () const
+ {
+ size_type p (traits::find_extension (this->path_));
+ return p != string_type::npos
+ ? basic_path (this->path_.c_str (), p)
+ : *this;
+ }
+
+ template <typename C, typename K>
+ inline const C* basic_path<C, K>::
+ extension () const
+ {
+ size_type p (traits::find_extension (this->path_));
+ return p != string_type::npos ? this->path_.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 ();
+ }
+#endif
+}