aboutsummaryrefslogtreecommitdiff
path: root/cutl/fs/path.hxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-09-13 14:29:04 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-09-13 14:29:04 +0200
commit6aeb2e06e9fa137a8e26f8605ec63f7567e65280 (patch)
treef31e1a8abd880376dc35c0bcf1d57a39050c3fdb /cutl/fs/path.hxx
parent90377830e06d58a2dbe116ec002741181c9a1915 (diff)
Rework fs::path
Use platform-canonical slashes. Add path_traits. Add the notion of an empty path.
Diffstat (limited to 'cutl/fs/path.hxx')
-rw-r--r--cutl/fs/path.hxx123
1 files changed, 113 insertions, 10 deletions
diff --git a/cutl/fs/path.hxx b/cutl/fs/path.hxx
index aee91b9..fbf179e 100644
--- a/cutl/fs/path.hxx
+++ b/cutl/fs/path.hxx
@@ -19,6 +19,63 @@ namespace cutl
class basic_path;
template <typename C>
+ struct path_traits
+ {
+ typedef std::basic_string<C> string_type;
+ typedef typename string_type::size_type size_type;
+
+ // Canonical directory and path seperators.
+ //
+#ifdef _WIN32
+ static char const directory_separator = '\\';
+ static char const path_separator = ';';
+#else
+ static char const directory_separator = '/';
+ static char const path_separator = ':';
+#endif
+
+ // Directory separator tests. On some platforms there
+ // could be multiple seperators. For example, on Windows
+ // we check for both '/' and '\'.
+ //
+
+ static bool
+ is_separator (C c)
+ {
+#ifdef _WIN32
+ return c == '\\' || c == '/';
+#else
+ return c == '/';
+#endif
+ }
+
+ static size_type
+ find_separator (string_type const& s)
+ {
+ for (size_type i (0), n (s.size ()); i < n; ++i)
+ {
+ if (is_separator (s[i]))
+ return i;
+ }
+
+ return string_type::npos;
+ }
+
+ static size_type
+ rfind_separator (string_type const& s)
+ {
+ for (size_type i (s.size ()) ; i > 0; --i)
+ {
+ if (is_separator (s[i - 1]))
+ return i - 1;
+ }
+
+ return string_type::npos;
+ }
+ };
+
+
+ template <typename C>
class invalid_basic_path;
typedef basic_path<char> path;
@@ -63,33 +120,75 @@ namespace cutl
typedef std::basic_string<C> string_type;
typedef typename string_type::size_type size_type;
+ typedef path_traits<C> traits;
+
+ // Construct special empty path.
+ //
+ basic_path ()
+ {
+ }
+
explicit
basic_path (C const* s)
: path_ (s)
{
- init (false);
+ init ();
+ }
+
+ basic_path (C const* s, size_type n)
+ : path_ (s, n)
+ {
+ init ();
}
explicit
basic_path (string_type const& s)
: path_ (s)
{
- init (false);
+ init ();
}
public:
+ // Return the path without the directory part.
+ //
basic_path
leaf () const;
+ // Return the directory part of the path or empty path if
+ // there is no directory.
+ //
basic_path
directory () const;
+ // Return the path without the extension, if any.
+ //
basic_path
base () const;
public:
basic_path
- operator/ (basic_path const&);
+ operator/ (basic_path const& x)
+ {
+ basic_path r (*this);
+ r /= x;
+ return r;
+ }
+
+ basic_path&
+ operator/= (basic_path const&);
+
+ basic_path
+ operator+ (string_type const& s)
+ {
+ return basic_path (path_ + s);
+ }
+
+ basic_path&
+ operator+= (string_type const& s)
+ {
+ path_ += s;
+ return *this;
+ }
bool
operator== (basic_path const& x) const
@@ -104,22 +203,26 @@ namespace cutl
}
public:
+ bool
+ empty () const
+ {
+ return path_.empty ();
+ }
+
string_type
string () const
{
- return path_.empty () ? string_type (1, '/') : path_;
+ return path_;
}
private:
void
- init (bool internal);
+ init ();
- // Assume internal format.
- //
- basic_path (C const* s, size_type n)
- : path_ (s, n)
+ bool
+ root () const
{
- init (true);
+ return path_.size () == 1 && traits::is_separator (path_[0]);
}
private: