From 8286ac511144e4f17d34eac9affb97e50646344a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 23 Jul 2014 15:25:44 +0200 Subject: Imported Upstream version 4.0.0 --- libcutl/cutl/fs/auto-remove.cxx | 37 +++++ libcutl/cutl/fs/auto-remove.hxx | 83 +++++++++++ libcutl/cutl/fs/exception.cxx | 17 +++ libcutl/cutl/fs/exception.hxx | 35 +++++ libcutl/cutl/fs/path.cxx | 115 +++++++++++++++ libcutl/cutl/fs/path.hxx | 311 ++++++++++++++++++++++++++++++++++++++++ libcutl/cutl/fs/path.ixx | 71 +++++++++ libcutl/cutl/fs/path.txx | 216 ++++++++++++++++++++++++++++ 8 files changed, 885 insertions(+) create mode 100644 libcutl/cutl/fs/auto-remove.cxx create mode 100644 libcutl/cutl/fs/auto-remove.hxx create mode 100644 libcutl/cutl/fs/exception.cxx create mode 100644 libcutl/cutl/fs/exception.hxx create mode 100644 libcutl/cutl/fs/path.cxx create mode 100644 libcutl/cutl/fs/path.hxx create mode 100644 libcutl/cutl/fs/path.ixx create mode 100644 libcutl/cutl/fs/path.txx (limited to 'libcutl/cutl/fs') diff --git a/libcutl/cutl/fs/auto-remove.cxx b/libcutl/cutl/fs/auto-remove.cxx new file mode 100644 index 0000000..c790c29 --- /dev/null +++ b/libcutl/cutl/fs/auto-remove.cxx @@ -0,0 +1,37 @@ +// file : cutl/fs/auto-remove.cxx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include // std::remove +#include + +#include + +namespace cutl +{ + namespace fs + { + auto_remove:: + ~auto_remove () + { + if (!canceled_) + { + if (std::remove (path_.string ().c_str ()) == -1) + throw error (errno); + } + } + + auto_removes:: + ~auto_removes () + { + if (!canceled_) + { + for (paths::iterator i (paths_.begin ()); i != paths_.end (); ++i) + { + if (std::remove (i->string ().c_str ()) == -1) + throw error (errno); + } + } + } + } +} diff --git a/libcutl/cutl/fs/auto-remove.hxx b/libcutl/cutl/fs/auto-remove.hxx new file mode 100644 index 0000000..c0319e8 --- /dev/null +++ b/libcutl/cutl/fs/auto-remove.hxx @@ -0,0 +1,83 @@ +// file : cutl/fs/auto-remove.hxx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifndef CUTL_FS_AUTO_REMOVE_HXX +#define CUTL_FS_AUTO_REMOVE_HXX + +#include + +#include +#include + +#include + +namespace cutl +{ + namespace fs + { + // Remove a file or an empty directory on destruction unless canceled. + // + struct LIBCUTL_EXPORT auto_remove + { + explicit + auto_remove (path const& p) + : path_ (p), canceled_ (false) + { + } + + ~auto_remove (); + + void + cancel () + { + canceled_ = true; + } + + private: + auto_remove (auto_remove const&); + + auto_remove& + operator= (auto_remove const&); + + private: + path path_; + bool canceled_; + }; + + // Remove a list of file or aempty directories on destruction unless + // canceled. + // + struct LIBCUTL_EXPORT auto_removes + { + auto_removes (): canceled_ (false) {} + ~auto_removes (); + + void + add (path const& p) + { + paths_.push_back (p); + } + + void + cancel () + { + canceled_ = true; + } + + private: + auto_removes (auto_removes const&); + + auto_removes& + operator= (auto_removes const&); + + private: + typedef std::vector paths; + + paths paths_; + bool canceled_; + }; + } +} + +#endif // CUTL_FS_AUTO_REMOVE_HXX diff --git a/libcutl/cutl/fs/exception.cxx b/libcutl/cutl/fs/exception.cxx new file mode 100644 index 0000000..3fbd26b --- /dev/null +++ b/libcutl/cutl/fs/exception.cxx @@ -0,0 +1,17 @@ +// file : cutl/fs/exception.cxx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include + +namespace cutl +{ + namespace fs + { + char const* error:: + what () const throw () + { + return "filesystem error"; + } + } +} diff --git a/libcutl/cutl/fs/exception.hxx b/libcutl/cutl/fs/exception.hxx new file mode 100644 index 0000000..d6c9601 --- /dev/null +++ b/libcutl/cutl/fs/exception.hxx @@ -0,0 +1,35 @@ +// file : cutl/fs/exception.hxx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifndef CUTL_FS_EXCEPTION_HXX +#define CUTL_FS_EXCEPTION_HXX + +#include + +namespace cutl +{ + namespace fs + { + struct LIBCUTL_EXPORT error: exception + { + error (int code): code_ (code) {} + + // Error code (errno). + // + int + code () const + { + return code_; + } + + virtual char const* + what () const throw (); + + private: + int code_; + }; + } +} + +#endif // CUTL_FS_EXCEPTION_HXX diff --git a/libcutl/cutl/fs/path.cxx b/libcutl/cutl/fs/path.cxx new file mode 100644 index 0000000..87b7f5f --- /dev/null +++ b/libcutl/cutl/fs/path.cxx @@ -0,0 +1,115 @@ +// file : cutl/fs/path.cxx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifdef _WIN32 +# include // _MAX_PATH +# include // _[w]getcwd, _[w]chdir +#else +# include // mbstowcs, wcstombs +# include // PATH_MAX +# include // getcwd, chdir +#endif + +#include + +namespace cutl +{ + namespace fs + { + char const* invalid_path_base:: + what () const throw () + { + return "invalid filesystem path"; + } + + // + // char + // + + template <> + basic_path basic_path:: + current () + { +#ifdef _WIN32 + char cwd[_MAX_PATH]; + if(_getcwd(cwd, _MAX_PATH) == 0) + throw invalid_basic_path ("."); +#else + char cwd[PATH_MAX]; + if (getcwd (cwd, PATH_MAX) == 0) + throw invalid_basic_path ("."); +#endif + + return basic_path (cwd); + } + + template <> + void basic_path:: + current (basic_path const& p) + { + string_type const& s (p.string ()); + + if (p.empty ()) + throw invalid_basic_path (s); + +#ifdef _WIN32 + if(_chdir(s.c_str ()) != 0) + throw invalid_basic_path (s); +#else + if (chdir (s.c_str ()) != 0) + throw invalid_basic_path (s); +#endif + } + + // + // wchar_t + // + + template <> + basic_path basic_path:: + current () + { +#ifdef _WIN32 + wchar_t wcwd[_MAX_PATH]; + if(_wgetcwd(wcwd, _MAX_PATH) == 0) + throw invalid_basic_path (L"."); +#else + char cwd[PATH_MAX]; + if (getcwd (cwd, PATH_MAX) == 0) + throw invalid_basic_path (L"."); + + wchar_t wcwd[PATH_MAX]; + if (mbstowcs (wcwd, cwd, PATH_MAX) == size_type (-1)) + throw invalid_basic_path (L"."); +#endif + + return basic_path (wcwd); + } + + template <> + void basic_path:: + current (basic_path const& p) + { + string_type const& s (p.string ()); + + if (p.empty ()) + throw invalid_basic_path (s); + +#ifdef _WIN32 + if(_wchdir(s.c_str ()) != 0) + throw invalid_basic_path (s); +#else + char ns[PATH_MAX + 1]; + + if (wcstombs (ns, s.c_str (), PATH_MAX) == size_type (-1)) + throw invalid_basic_path (s); + + ns[PATH_MAX] = '\0'; + + if (chdir (ns) != 0) + throw invalid_basic_path (s); +#endif + } + } +} diff --git a/libcutl/cutl/fs/path.hxx b/libcutl/cutl/fs/path.hxx new file mode 100644 index 0000000..cbe71a6 --- /dev/null +++ b/libcutl/cutl/fs/path.hxx @@ -0,0 +1,311 @@ +// file : cutl/fs/path.hxx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifndef CUTL_FS_PATH_HXX +#define CUTL_FS_PATH_HXX + +#include +#include + +#include + +#include + +namespace cutl +{ + namespace fs + { + template + class basic_path; + + template + struct path_traits + { + typedef std::basic_string string_type; + typedef typename string_type::size_type size_type; + + // Canonical directory and path seperators. + // +#ifdef _WIN32 + static C const directory_separator = '\\'; + static C const path_separator = ';'; +#else + static C const directory_separator = '/'; + static C 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, size_type pos = 0) + { + for (size_type n (s.size ()); pos < n; ++pos) + { + if (is_separator (s[pos])) + return pos; + } + + return string_type::npos; + } + + static size_type + rfind_separator (string_type const& s, size_type pos = string_type::npos) + { + if (pos == string_type::npos) + pos = s.size (); + else + pos++; + + for (; pos > 0; --pos) + { + if (is_separator (s[pos - 1])) + return pos - 1; + } + + return string_type::npos; + } + }; + + template + class invalid_basic_path; + + typedef basic_path path; + typedef invalid_basic_path invalid_path; + + typedef basic_path wpath; + typedef invalid_basic_path invalid_wpath; + + // + // + class LIBCUTL_EXPORT invalid_path_base: exception + { + public: + virtual char const* + what () const throw (); + }; + + template + class invalid_basic_path: public invalid_path_base + { + public: + typedef std::basic_string string_type; + + invalid_basic_path (C const* p): path_ (p) {} + invalid_basic_path (string_type const& p): path_ (p) {} + ~invalid_basic_path () throw () {} + + string_type const& + path () const + { + return path_; + } + + private: + string_type path_; + }; + + template + class basic_path + { + public: + typedef std::basic_string string_type; + typedef typename string_type::size_type size_type; + + typedef path_traits traits; + + // Construct special empty path. + // + basic_path () + { + } + + explicit + basic_path (C const* s) + : path_ (s) + { + init (); + } + + basic_path (C const* s, size_type n) + : path_ (s, n) + { + init (); + } + + explicit + basic_path (string_type const& s) + : path_ (s) + { + init (); + } + + void + swap (basic_path& p) + { + path_.swap (p.path_); + } + + void + clear () + { + path_.clear (); + } + + static basic_path + current (); + + static void + current (basic_path const&); + + public: + bool + empty () const + { + return path_.empty (); + } + + bool + absolute () const; + + bool + relative () const + { + return !absolute (); + } + + bool + root () const; + + 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: + // Normalize the path. This includes collapsing the '.' and '..' + // directories if possible, collapsing multiple directory + // separators, converting all directory separators to the + // canonical form, and making the path lower-case if the + // filesystem is not case-sensitive (e.g., Windows). Returns + // *this. + // + basic_path& + normalize (); + + // Make the path absolute using the current directory unless + // it is already absolute. + // + basic_path& + complete (); + + public: + basic_path + operator/ (basic_path const& x) const + { + basic_path r (*this); + r /= x; + return r; + } + + basic_path& + operator/= (basic_path const&); + + basic_path + operator+ (string_type const& s) const + { + return basic_path (path_ + s); + } + + basic_path& + operator+= (string_type const& s) + { + path_ += s; + return *this; + } + + bool + operator== (basic_path const& x) const + { + return path_ == x.path_; + } + + bool + operator!= (basic_path const& x) const + { + return !(*this == x); + } + + bool + operator< (basic_path const& x) const + { + return path_ < x.path_; + } + + public: + string_type + string () const + { + return path_; + } + + // If possible, return a POSIX representation of the path. For example, + // for a Windows path in the form foo\bar this function will return + // foo/bar. If it is not possible to create a POSIX representation for + // this path (e.g., c:\foo), this function will throw the invalid_path + // exception. + // + string_type + posix_string () const; + + private: + void + init (); + +#ifdef _WIN32 + static C + tolower (C); +#endif + + private: + string_type path_; + }; + + template + inline std::basic_ostream& + operator<< (std::basic_ostream& os, basic_path const& p) + { + return os << p.string (); + } + } +} + +#include +#include + +#endif // CUTL_FS_PATH_HXX diff --git a/libcutl/cutl/fs/path.ixx b/libcutl/cutl/fs/path.ixx new file mode 100644 index 0000000..80d3bb3 --- /dev/null +++ b/libcutl/cutl/fs/path.ixx @@ -0,0 +1,71 @@ +// file : cutl/fs/path.ixx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#ifdef _WIN32 +# include // std::tolower +# include // std::towlower +#endif + +namespace cutl +{ + namespace fs + { + template + inline bool basic_path:: + absolute () const + { +#ifdef _WIN32 + return path_.size () > 1 && path_[1] == ':'; +#else + return !path_.empty () && traits::is_separator (path_[0]); +#endif + } + + template + inline bool basic_path:: + root () const + { +#ifdef _WIN32 + return path_.size () == 2 && path_[1] == ':'; +#else + return path_.size () == 1 && traits::is_separator (path_[0]); +#endif + } + + template + inline basic_path& basic_path:: + complete () + { + if (relative ()) + *this = current () / *this; + + return *this; + } + +#ifndef _WIN32 + template + inline typename basic_path::string_type basic_path:: + posix_string () const + { + return string (); + } +#endif + +#ifdef _WIN32 + template <> + inline char basic_path:: + tolower (char c) + { + return std::tolower (c); + } + + template <> + inline wchar_t basic_path:: + tolower (wchar_t c) + { + return std::towlower (c); + } +#endif + } +} diff --git a/libcutl/cutl/fs/path.txx b/libcutl/cutl/fs/path.txx new file mode 100644 index 0000000..e95c890 --- /dev/null +++ b/libcutl/cutl/fs/path.txx @@ -0,0 +1,216 @@ +// file : cutl/fs/path.txx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include + +namespace cutl +{ + namespace fs + { + template + basic_path basic_path:: + leaf () const + { + size_type p (traits::rfind_separator (path_)); + + return p != string_type::npos + ? basic_path (path_.c_str () + p + 1, path_.size () - p - 1) + : *this; + } + + template + basic_path basic_path:: + directory () const + { + if (root ()) + return basic_path (); + + size_type p (traits::rfind_separator (path_)); + + // Include the trailing slash so that we get correct behavior + // if directory is root. + // + return p != string_type::npos + ? basic_path (path_.c_str (), p + 1) + : basic_path (); + } + + template + basic_path basic_path:: + base () const + { + size_type i (path_.size ()); + + for (; i > 0; --i) + { + if (path_[i - 1] == '.') + break; + + if (traits::is_separator (path_[i - 1])) + { + i = 0; + break; + } + } + + // Weed out paths like ".txt" and "/.txt" + // + if (i > 1 && !traits::is_separator (path_[i - 2])) + { + return basic_path (path_.c_str (), i - 1); + } + else + return *this; + } + +#ifdef _WIN32 + template + typename basic_path::string_type basic_path:: + posix_string () const + { + if (absolute ()) + throw invalid_basic_path (path_); + + string_type r (path_); + + // Translate Windows-style separators to the POSIX ones. + // + for (size_type i (0), n (r.size ()); i != n; ++i) + if (r[i] == '\\') + r[i] = '/'; + + return r; + } +#endif + + template + basic_path& basic_path:: + operator/= (basic_path const& r) + { + if (r.absolute ()) + throw invalid_basic_path (r.path_); + + if (path_.empty () || r.path_.empty ()) + { + path_ += r.path_; + return *this; + } + + if (!traits::is_separator (path_[path_.size () - 1])) + path_ += traits::directory_separator; + + path_ += r.path_; + + return *this; + } + + template + basic_path& basic_path:: + normalize () + { + if (empty ()) + return *this; + + bool abs (absolute ()); + + typedef std::vector paths; + paths ps; + + for (size_type b (0), e (traits::find_separator (path_)), + n (path_.size ());; + e = traits::find_separator (path_, b)) + { + string_type s (path_, b, e == string_type::npos ? e : e - b); + ps.push_back (s); + + if (e == string_type::npos) + break; + + ++e; + + while (e < n && traits::is_separator (path_[e])) + ++e; + + if (e == n) + break; + + b = e; + } + + // First collapse '.' and '..'. + // + paths r; + + for (typename paths::const_iterator i (ps.begin ()), e (ps.end ()); + i != e; ++i) + { + string_type const& s (*i); + size_type n (s.size ()); + + if (n == 1 && s[0] == '.') + continue; + + if (n == 2 && s[0] == '.' && s[1] == '.') + { + // Pop the last directory from r unless it is '..'. + // + if (!r.empty ()) + { + string_type const& s1 (r.back ()); + + if (!(s1.size () == 2 && s1[0] == '.' && s1[1] == '.')) + { + // Cannot go past the root directory. + // + if (abs && r.size () == 1) + throw invalid_basic_path (path_); + + r.pop_back (); + continue; + } + } + } + + r.push_back (s); + } + + // Reassemble the path. + // + string_type p; + + for (typename paths::const_iterator i (r.begin ()), e (r.end ()); + i != e;) + { +#ifdef _WIN32 + for (size_type j (0), n (i->size ()); j < n; ++j) + p += tolower ((*i)[j]); +#else + p += *i; +#endif + ++i; + + if (i != e) + p += traits::directory_separator; + } + + if (p.empty () && !r.empty ()) + p += traits::directory_separator; // Root directory. + + path_.swap (p); + return *this; + } + + template + void basic_path:: + init () + { + // Strip trailing slashes except for the case where the single + // slash represents the root directory. + // + size_type n (path_.size ()); + for (; n > 1 && traits::is_separator (path_[n - 1]); --n) ; + path_.resize (n); + } + } +} -- cgit v1.2.3