diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-06-18 14:41:45 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-06-18 14:41:45 +0200 |
commit | 63e7a4a77cb8ceed7b42561fe3202b0b48d86db6 (patch) | |
tree | bde5a79522225f32ec188ba46d0834486c30f00f | |
parent | 28c82c861e38fe05a25e916563e0551ed8fce91e (diff) |
Move path and filesystem from build2 to libbutl
47 files changed, 95 insertions, 1858 deletions
diff --git a/build/algorithm b/build/algorithm index c21457e..5138dfa 100644 --- a/build/algorithm +++ b/build/algorithm @@ -5,9 +5,9 @@ #ifndef BUILD_ALGORITHM #define BUILD_ALGORITHM +#include <build/types> #include <build/target> #include <build/operation> -#include <build/timestamp> namespace build { diff --git a/build/algorithm.cxx b/build/algorithm.cxx index fe85c4e..2529e13 100644 --- a/build/algorithm.cxx +++ b/build/algorithm.cxx @@ -11,7 +11,6 @@ #include <butl/utility> // reverse_iterate -#include <build/path> #include <build/scope> #include <build/target> #include <build/prerequisite> diff --git a/build/b.cxx b/build/b.cxx index 24f4266..8e75c14 100644 --- a/build/b.cxx +++ b/build/b.cxx @@ -16,8 +16,9 @@ #include <iostream> #include <system_error> -#include <build/path> -#include <build/name> +#include <butl/filesystem> + +#include <build/types> #include <build/spec> #include <build/operation> #include <build/scope> @@ -30,7 +31,6 @@ #include <build/diagnostics> #include <build/context> #include <build/utility> -#include <build/filesystem> #include <build/token> #include <build/lexer> diff --git a/build/bin/module b/build/bin/module index 749ce3f..e09e742 100644 --- a/build/bin/module +++ b/build/bin/module @@ -5,7 +5,7 @@ #ifndef BUILD_BIN_MODULE #define BUILD_BIN_MODULE -#include <build/path> +#include <build/types> #include <build/module> namespace build diff --git a/build/buildfile b/build/buildfile index 8b4cb84..4cb9c59 100644 --- a/build/buildfile +++ b/build/buildfile @@ -5,9 +5,8 @@ bin = bin/{target rule module} cxx = cxx/{target rule module} exe{b}: cxx{b algorithm name operation spec scope variable target \ - prerequisite rule file module context search diagnostics token \ - lexer parser timestamp path path-io utility filesystem dump options \ - $config $bin $cxx} $libs + prerequisite rule file module context search diagnostics token \ + lexer parser path-io utility dump options $config $bin $cxx} $libs #@@ TODO # diff --git a/build/config/module b/build/config/module index 317b25a..4ab3e7e 100644 --- a/build/config/module +++ b/build/config/module @@ -5,6 +5,7 @@ #ifndef BUILD_CONFIG_MODULE #define BUILD_CONFIG_MODULE +#include <build/types> #include <build/module> namespace build diff --git a/build/config/module.cxx b/build/config/module.cxx index ab7ed4e..7ac9071 100644 --- a/build/config/module.cxx +++ b/build/config/module.cxx @@ -4,15 +4,16 @@ #include <build/config/module> -#include <build/path> +#include <butl/filesystem> + #include <build/scope> #include <build/file> -#include <build/filesystem> #include <build/diagnostics> #include <build/config/operation> using namespace std; +using namespace butl; namespace build { diff --git a/build/config/operation.cxx b/build/config/operation.cxx index 567e636..89bef61 100644 --- a/build/config/operation.cxx +++ b/build/config/operation.cxx @@ -6,13 +6,15 @@ #include <fstream> +#include <butl/filesystem> + #include <build/scope> #include <build/file> #include <build/context> -#include <build/filesystem> #include <build/diagnostics> using namespace std; +using namespace butl; namespace build { diff --git a/build/context b/build/context index 3a99014..dc865d2 100644 --- a/build/context +++ b/build/context @@ -8,10 +8,11 @@ #include <string> #include <ostream> -#include <build/path> +#include <butl/filesystem> + +#include <build/types> #include <build/rule> #include <build/operation> -#include <build/filesystem> namespace build { @@ -37,7 +38,7 @@ namespace build // The dual interface wrapper for the {mk,rm}{file,dir}() functions // below that allows you to use it as a true/false return or a more - // detailed enum from <filesystem> + // detailed enum from <butl/filesystem> // template <typename T> struct fs_status @@ -53,7 +54,7 @@ namespace build // directory will exist in the majority of case and performance is // important. See the fsdir{} rule for details. // - fs_status<mkdir_status> + fs_status<butl::mkdir_status> mkdir (const dir_path&); // Remove the file and print the standard diagnostics. The second @@ -62,19 +63,19 @@ namespace build // being printed. // template <typename T> - fs_status<rmfile_status> + fs_status<butl::rmfile_status> rmfile (const path&, const T& target); - inline fs_status<rmfile_status> + inline fs_status<butl::rmfile_status> rmfile (const path& f) {return rmfile (f, f);} // Similar to rmfile() but for directories. // template <typename T> - fs_status<rmdir_status> + fs_status<butl::rmdir_status> rmdir (const dir_path&, const T& target); - inline fs_status<rmdir_status> + inline fs_status<butl::rmdir_status> rmdir (const dir_path& d) {return rmdir (d, d);} // Return the src/out directory corresponding to the given out/src. The diff --git a/build/context.cxx b/build/context.cxx index 7769c94..22b6f53 100644 --- a/build/context.cxx +++ b/build/context.cxx @@ -12,6 +12,7 @@ #include <build/diagnostics> using namespace std; +using namespace butl; namespace build { diff --git a/build/context.txx b/build/context.txx index 286d460..b9004e0 100644 --- a/build/context.txx +++ b/build/context.txx @@ -9,9 +9,11 @@ namespace build { template <typename T> - fs_status<rmfile_status> + fs_status<butl::rmfile_status> rmfile (const path& f, const T& t) { + using namespace butl; + // We don't want to print the command if we couldn't remove the // file because it does not exist (just like we don't print the // update command if the file is up to date). This makes the @@ -45,9 +47,11 @@ namespace build } template <typename T> - fs_status<rmdir_status> + fs_status<butl::rmdir_status> rmdir (const dir_path& d, const T& t) { + using namespace butl; + bool w (d == work); // Don't try to remove working directory. rmdir_status rs; diff --git a/build/cxx/module b/build/cxx/module index 11cd7bc..2d50f59 100644 --- a/build/cxx/module +++ b/build/cxx/module @@ -5,6 +5,7 @@ #ifndef BUILD_CXX_MODULE #define BUILD_CXX_MODULE +#include <build/types> #include <build/module> namespace build diff --git a/build/cxx/module.cxx b/build/cxx/module.cxx index 4193104..21f1b85 100644 --- a/build/cxx/module.cxx +++ b/build/cxx/module.cxx @@ -7,7 +7,6 @@ #include <butl/process> #include <butl/fdstream> -#include <build/path> #include <build/scope> #include <build/diagnostics> diff --git a/build/cxx/rule b/build/cxx/rule index 686d5ae..8c575fe 100644 --- a/build/cxx/rule +++ b/build/cxx/rule @@ -5,6 +5,7 @@ #ifndef BUILD_CXX_RULE #define BUILD_CXX_RULE +#include <build/types> #include <build/rule> namespace build diff --git a/build/cxx/rule.cxx b/build/cxx/rule.cxx index c0e6550..58d8e88 100644 --- a/build/cxx/rule.cxx +++ b/build/cxx/rule.cxx @@ -18,7 +18,6 @@ #include <build/scope> #include <build/variable> #include <build/algorithm> -#include <build/timestamp> #include <build/diagnostics> #include <build/context> diff --git a/build/diagnostics b/build/diagnostics index 05401b9..6c528f2 100644 --- a/build/diagnostics +++ b/build/diagnostics @@ -14,11 +14,15 @@ #include <exception> #include <type_traits> -#include <build/path> +#include <butl/path> + #include <build/path-io> namespace build { + using butl::path; + using butl::dir_path; + // Throw this exception to terminate the build. The handler should // assume that the diagnostics has already been issued. // @@ -5,8 +5,7 @@ #ifndef BUILD_FILE #define BUILD_FILE -#include <build/path> -#include <build/name> +#include <build/types> #include <build/variable> // list_value namespace build diff --git a/build/file.cxx b/build/file.cxx index 6f10391..5f899de 100644 --- a/build/file.cxx +++ b/build/file.cxx @@ -6,13 +6,15 @@ #include <fstream> +#include <butl/filesystem> + #include <build/scope> #include <build/context> #include <build/parser> -#include <build/filesystem> #include <build/diagnostics> using namespace std; +using namespace butl; namespace build { diff --git a/build/filesystem b/build/filesystem deleted file mode 100644 index fbade4f..0000000 --- a/build/filesystem +++ /dev/null @@ -1,61 +0,0 @@ -// file : build/filesystem -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD_FILESYSTEM -#define BUILD_FILESYSTEM - -#include <sys/types.h> // mode_t - -#include <build/path> - -namespace build -{ - // Return true if the path is to an existing directory. Note that - // this function resolves symlinks. - // - bool - dir_exists (const path&); - - // Return true if the path is to an existing regular file. Note that - // this function resolves symlinks. - // - bool - file_exists (const path&); - - // Try to create a directory unless it already exists. If you expect - // the directory to exist and performance is important, then you - // should first call dir_exists() above since that's what this - // implementation will do to make sure the path is actually a - // directory. - // - // You should also probably use the default mode 0777 and let the - // umask mechanism adjust it to the user's preferences. - // - // Errors are reported by throwing std::system_error. - // - enum class mkdir_status {success, already_exists}; - - mkdir_status - try_mkdir (const path&, mode_t = 0777); - - // Try to remove the directory returning not_exist if it does not - // exist and not_empty if it is not empty. All other errors are - // reported by throwing std::system_error. - // - enum class rmdir_status {success, not_exist, not_empty}; - - rmdir_status - try_rmdir (const path&); - - // Try to remove the file (or symbolic link) returning not_exist if - // it does not exist. All other errors are reported by throwing - // std::system_error. - // - enum class rmfile_status {success, not_exist}; - - rmfile_status - try_rmfile (const path&); -} - -#endif // BUILD_FILESYSTEM diff --git a/build/filesystem.cxx b/build/filesystem.cxx deleted file mode 100644 index 6485f34..0000000 --- a/build/filesystem.cxx +++ /dev/null @@ -1,101 +0,0 @@ -// file : build/filesystem.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <build/filesystem> - -#include <unistd.h> // rmdir(), unlink() -#include <sys/types.h> // stat -#include <sys/stat.h> // stat, lstat(), S_IS*, mkdir() - -#include <system_error> - -using namespace std; - -namespace build -{ - bool - dir_exists (const path& p) - { - struct stat s; - if (::lstat (p.string ().c_str (), &s) != 0) - { - if (errno == ENOENT || errno == ENOTDIR) - return false; - else - throw system_error (errno, system_category ()); - } - - return S_ISDIR (s.st_mode); - } - - bool - file_exists (const path& p) - { - struct stat s; - if (::lstat (p.string ().c_str (), &s) != 0) - { - if (errno == ENOENT || errno == ENOTDIR) - return false; - else - throw system_error (errno, system_category ()); - } - - return S_ISREG (s.st_mode); - } - - mkdir_status - try_mkdir (const path& p, mode_t m) - { - mkdir_status r (mkdir_status::success); - - if (::mkdir (p.string ().c_str (), m) != 0) - { - int e (errno); - - // EEXIST means the path already exists but not necessarily as - // a directory. - // - if (e == EEXIST && dir_exists (p)) - return mkdir_status::already_exists; - else - throw system_error (e, system_category ()); - } - - return r; - } - - rmdir_status - try_rmdir (const path& p) - { - rmdir_status r (rmdir_status::success); - - if (::rmdir (p.string ().c_str ()) != 0) - { - if (errno == ENOENT) - r = rmdir_status::not_exist; - else if (errno == ENOTEMPTY || errno == EEXIST) - r = rmdir_status::not_empty; - else - throw system_error (errno, system_category ()); - } - - return r; - } - - rmfile_status - try_rmfile (const path& p) - { - rmfile_status r (rmfile_status::success); - - if (::unlink (p.string ().c_str ()) != 0) - { - if (errno == ENOENT || errno == ENOTDIR) - r = rmfile_status::not_exist; - else - throw system_error (errno, system_category ()); - } - - return r; - } -} @@ -10,10 +10,14 @@ #include <iosfwd> #include <utility> // move() -#include <build/path> +#include <butl/path> +// Note: include <build/types> instead of this file directly. +// namespace build { + using butl::dir_path; + // A name is what we operate on by default. Depending on the context, // it can be interpreted as a target or prerequisite name. A name // without a type and directory can be used to represent any text. diff --git a/build/operation b/build/operation index 7492050..51c9f88 100644 --- a/build/operation +++ b/build/operation @@ -11,7 +11,7 @@ #include <cstdint> #include <functional> // reference_wrapper -#include <build/path> +#include <build/types> #include <build/string-table> namespace build diff --git a/build/parser b/build/parser index 35b2f32..403fbaf 100644 --- a/build/parser +++ b/build/parser @@ -9,9 +9,8 @@ #include <iosfwd> #include <utility> // move() -#include <build/path> +#include <build/types> #include <build/token> -#include <build/name> #include <build/spec> #include <build/variable> // list_value #include <build/diagnostics> diff --git a/build/path b/build/path deleted file mode 100644 index f107391..0000000 --- a/build/path +++ /dev/null @@ -1,553 +0,0 @@ -// file : build/path -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD_PATH -#define BUILD_PATH - -#include <string> -#include <cstddef> // ptrdiff_t -#include <ostream> -#include <utility> // move -#include <iterator> -#include <exception> -#include <functional> // hash - -namespace build -{ - 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 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; - } - - // Return the position of '.' or npos if there is no extension. - // - static size_type - find_extension (string_type const& s) - { - size_type i (s.size ()); - - for (; i > 0; --i) - { - C c (s[i - 1]); - - if (c == '.') - break; - - if (is_separator (c)) - { - i = 0; - break; - } - } - - // Weed out paths like ".txt" (and "/.txt") and "txt.". - // - if (i > 1 && !is_separator (s[i - 2]) && i != s.size ()) - return i - 1; - else - return string_type::npos; - } - - static int - compare (string_type const& l, string_type const& r) - { - size_type ln (l.size ()), rn (r.size ()), n (ln < rn ? ln : rn); - for (size_type i (0); i != n; ++i) - { -#ifdef _WIN32 - C lc (tolower (l[i])), rc (tolower (r[i])); -#else - C lc (l[i]), rc (r[i]); -#endif - if (is_separator (lc) && is_separator (rc)) - continue; - - if (lc < rc) return -1; - if (lc > rc) return 1; - } - - return ln < rn ? -1 : (ln > rn ? 1 : 0); - } - - // Get/set current working directory. Throw std::system_error - // to report the underlying OS errors. - // - static string_type - current (); - - static void - current (string_type const&); - - private: -#ifdef _WIN32 - static C - tolower (C); -#endif - }; - - template <typename C> - class invalid_basic_path; - - template <typename C, typename K> - class basic_path; - - template <typename C> - class path_data; - - template <typename C> - struct dir_path_kind; - - template <typename C> - struct any_path_kind - { - typedef path_data<C> base_type; - typedef basic_path<C, dir_path_kind<C>> dir_type; - }; - - template <typename C> - struct dir_path_kind - { - typedef basic_path<C, any_path_kind<C>> base_type; - typedef basic_path<C, dir_path_kind<C>> dir_type; - }; - - typedef basic_path<char, any_path_kind<char>> path; - typedef basic_path<char, dir_path_kind<char>> dir_path; - typedef invalid_basic_path<char> invalid_path; - - typedef basic_path<wchar_t, any_path_kind<wchar_t>> wpath; - typedef basic_path<wchar_t, dir_path_kind<wchar_t>> dir_wpath; - typedef invalid_basic_path<wchar_t> invalid_wpath; - - // - // - class invalid_path_base: std::exception - { - public: - virtual char const* - what () const throw (); - }; - - template <typename C> - class invalid_basic_path: public invalid_path_base - { - public: - typedef std::basic_string<C> 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 <typename C> - class path_data - { - public: - typedef std::basic_string<C> string_type; - - path_data () = default; - - explicit - path_data (string_type s): path_ (std::move (s)) {} - - protected: - string_type path_; - }; - - template <typename C, typename K> - class basic_path: public K::base_type - { - public: - typedef std::basic_string<C> string_type; - typedef typename string_type::size_type size_type; - - typedef typename K::base_type base_type; - typedef typename K::dir_type dir_type; - - typedef path_traits<C> traits; - - // Construct special empty path. Note that we have to provide our - // own implementation rather than using '=default' to make clang - // allow default-initialized const instances of this type. - // - basic_path () {}; - - explicit - basic_path (C const* s): base_type (s) {init ();} - - basic_path (C const* s, size_type n) - : base_type (string_type (s, n)) {init ();} - - explicit - basic_path (string_type s): base_type (std::move (s)) {init ();} - - basic_path (const string_type& s, size_type n) - : base_type (string_type (s, 0, n)) {init ();} - - basic_path (const string_type& s, size_type p, size_type n) - : base_type (string_type (s, p, n)) {init ();} - - void - swap (basic_path& p) - { - this->path_.swap (p.path_); - } - - void - clear () - { - this->path_.clear (); - } - - // Get/set current working directory. Throw std::system_error - // to report the underlying OS errors. - // - static dir_type - current () {return dir_type (traits::current ());} - - static void - current (basic_path const&); - - public: - bool - empty () const - { - return this->path_.empty (); - } - - bool - absolute () const; - - bool - relative () const - { - return !absolute (); - } - - bool - root () const; - - // Return true if *this is a sub-path of the specified path (i.e., - // the specified path is a prefix). Expects both paths to be - // normalized. Note that this function returns true if the paths - // are equal. Empty path is considered a prefix of any path. - // - bool - sub (const basic_path&) const; - - // Return true if *this is a super-path of the specified path (i.e., - // the specified path is a suffix). Expects both paths to be - // normalized. Note that this function returns true if the paths - // are equal. Empty path is considered a suffix of any path. - // - bool - sup (const basic_path&) const; - - public: - // Return the path without the directory part. - // - basic_path - leaf () const; - - // Return the path without the specified directory part. Throws - // invalid_path if the directory is not a prefix of *this. Expects - // both paths to be normalized. - // - basic_path - leaf (basic_path const&) const; - - // Return the directory part of the path or empty path if - // there is no directory. - // - dir_type - directory () const; - - // Return the directory part of the path without the specified - // leaf part. Throws invalid_path if the leaf is not a suffix of - // *this. Expects both paths to be normalized. - // - dir_type - directory (basic_path const&) const; - - // Return the root directory of the path or empty path if - // the directory is not absolute. - // - dir_type - root_directory () const; - - // Return the path without the extension, if any. - // - basic_path - base () const; - - // Return the extension or NULL if not present. - // - const C* - extension () const; - - // Return a path relative to the specified path that is equivalent - // to *this. Throws invalid_path if a relative path cannot be derived - // (e.g., paths are on different drives on Windows). - // - basic_path - relative (basic_path) const; - - // Iteration over path components. - // - public: - struct iterator - { - typedef string_type value_type; - typedef string_type* pointer; - typedef string_type& reference; - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - typedef typename string_type::size_type size_type; - - iterator (): p_ (nullptr) {} - iterator (const string_type& p, size_type b, size_type e) - : p_ (&p), b_ (b), e_ (e) {} - - iterator& - operator++ () - { - b_ = e_; - - if (b_ != string_type::npos) - e_ = traits::find_separator (*p_, ++b_); - - return *this; - } - - iterator - operator++ (int) {iterator r (*this); return ++r;} - - string_type operator* () const - { - return string_type (*p_, b_, (e_ != string_type::npos ? e_ - b_ : e_)); - } - - friend bool - operator== (const iterator& x, const iterator& y) - { - return x.p_ == y.p_ && x.b_ == y.b_ && x.e_ == y.e_; - } - - friend bool - operator!= (const iterator& x, const iterator& y) {return !(x == y);} - - private: - // b != npos && e == npos - last component - // b == npos && e == npos - one past last component (end) - // - const string_type* p_; - size_type b_; - size_type e_; - }; - - iterator begin () const; - iterator end () const; - - public: - // Normalize the path. This includes collapsing the '.' and '..' - // directories if possible, collapsing multiple directory - // separators, and converting all directory separators to the - // canonical form. 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&); - - basic_path - operator+ (string_type const& s) const - { - return basic_path (this->path_ + s); - } - - basic_path - operator+ (C c) const - { - return basic_path (this->path_ + c); - } - - basic_path& - operator+= (string_type const& s) - { - this->path_ += s; - return *this; - } - - basic_path& - operator+= (C c) - { - this->path_ += c; - return *this; - } - - // Note that comparison is case-insensitive if the filesystem is - // not case-sensitive (e.g., Windows). - // - bool - operator== (basic_path const& x) const - { - return traits::compare (this->path_, x.path_) == 0; - } - - bool - operator!= (basic_path const& x) const - { - return !(*this == x); - } - - bool - operator< (basic_path const& x) const - { - return traits::compare (this->path_, x.path_) < 0; - } - - public: - const string_type& - string () const - { - return this->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 (); - }; - - template <typename C, typename K> - inline basic_path<C, K> - operator/ (basic_path<C, K> const& x, basic_path<C, K> const& y) - { - basic_path<C, K> r (x); - r /= y; - return r; - } - - // Additional operators for certain path kind combinations. - // - template <typename C> - inline basic_path<C, any_path_kind<C>> - operator/ (basic_path<C, dir_path_kind<C>> const& x, - basic_path<C, any_path_kind<C>> const& y) - { - basic_path<C, any_path_kind<C>> r (x); - r /= y; - return r; - } - - // IO - // - - /* - template <typename C, typename K> - inline std::basic_ostream<C>& - operator<< (std::basic_ostream<C>& os, basic_path<C, K> const& p) - { - return os << p.string (); - } - */ -} - -namespace std -{ - template <typename C, typename K> - struct hash<build::basic_path<C, K>>: hash<basic_string<C>> - { - size_t - operator() (const build::basic_path<C, K>& p) const noexcept - { - return hash<basic_string<C>>::operator() (p.string ()); - } - }; -} - -#include <build/path.ixx> -#include <build/path.txx> - -#endif // BUILD_PATH diff --git a/build/path-io b/build/path-io index c2130da..888a8b4 100644 --- a/build/path-io +++ b/build/path-io @@ -7,10 +7,15 @@ #include <iosfwd> -#include <build/path> +#include <butl/path> +// Custom path IO. +// namespace build { + using butl::path; + using butl::dir_path; + std::ostream& operator<< (std::ostream&, const path&); diff --git a/build/path-map b/build/path-map deleted file mode 100644 index 8355ccc..0000000 --- a/build/path-map +++ /dev/null @@ -1,88 +0,0 @@ -// file : build/path-map -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD_PATH_MAP -#define BUILD_PATH_MAP - -#include <butl/prefix-map> - -#include <build/path> - -namespace butl -{ - - // @@ Remove butl:: when move to libbutl. - - // prefix_map for paths - // - // The paths should be normalized. - // - // Note that the path's representation of POSIX root ('/') is - // inconsistent in that we have a trailing delimiter at the end of - // the path (its "proper" representation would have been an empty - // string but that would have clashed with empty paths). To work - // around this snag, this implementation, during key comparison, - // detects '/' and treats it as empty. Note that the map will - // still store the key as you have first inserted it. So if you - // want a particular representation, pre-populate the map with - // it. - // - template <typename C, typename K> - struct compare_prefix<build::basic_path<C, K>>: compare_prefix<std::basic_string<C>> - { - typedef build::basic_path<C, K> key_type; - - typedef C delimiter_type; - typedef std::basic_string<C> string_type; - typedef compare_prefix<std::basic_string<C>> base; - - explicit - compare_prefix (delimiter_type d): base (d) {} - - bool - operator() (const key_type& x, const key_type& y) const - { - const auto& xs (x.string ()); - const auto& ys (y.string ()); - -#ifdef _WIN32 - return base::compare (xs.c_str (), - xs.size (), - ys.c_str (), - ys.size ()) < 0; -#else - return base::compare (xs.c_str (), - x.root () ? 0 : xs.size (), - ys.c_str (), - y.root () ? 0 : ys.size ()) < 0; -#endif - } - - bool - prefix (const key_type& p, const key_type& k) const - { - const auto& ps (p.string ()); - const auto& ks (k.string ()); - -#ifdef _WIN32 - return base::prefix (ps, ks); -#else - return base::prefix (p.root () ? string_type () : ps, - k.root () ? string_type () : ks); -#endif - } - }; -} - -namespace build -{ - template <typename T> - using path_map = butl::prefix_map<path, T, path::traits::directory_separator>; - - template <typename T> - using dir_path_map = - butl::prefix_map<dir_path, T, dir_path::traits::directory_separator>; -} - -#endif // BUILD_PATH_MAP diff --git a/build/path.cxx b/build/path.cxx deleted file mode 100644 index 3a3ea3d..0000000 --- a/build/path.cxx +++ /dev/null @@ -1,109 +0,0 @@ -// file : build/path.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <build/path> - -#ifdef _WIN32 -# include <stdlib.h> // _MAX_PATH -# include <direct.h> // _[w]getcwd, _[w]chdir -#else -# include <errno.h> // EINVAL -# include <stdlib.h> // mbstowcs, wcstombs -# include <limits.h> // PATH_MAX -# include <unistd.h> // getcwd, chdir -#endif - -#include <system_error> - -using namespace std; - -namespace build -{ - char const* invalid_path_base:: - what () const throw () - { - return "invalid filesystem path"; - } - - // - // char - // - - template <> - path_traits<char>::string_type path_traits<char>:: - current () - { - // @@ throw system_error (and in the other current() versions). - -#ifdef _WIN32 - char cwd[_MAX_PATH]; - if(_getcwd(cwd, _MAX_PATH) == 0) - throw system_error (errno, system_category ()); -#else - char cwd[PATH_MAX]; - if (getcwd (cwd, PATH_MAX) == 0) - throw system_error (errno, system_category ()); -#endif - - return string_type (cwd); - } - - template <> - void path_traits<char>:: - current (string_type const& s) - { -#ifdef _WIN32 - if(_chdir(s.c_str ()) != 0) - throw system_error (errno, system_category ()); -#else - if (chdir (s.c_str ()) != 0) - throw system_error (errno, system_category ()); -#endif - } - - // - // wchar_t - // - - template <> - path_traits<wchar_t>::string_type path_traits<wchar_t>:: - current () - { -#ifdef _WIN32 - wchar_t wcwd[_MAX_PATH]; - if(_wgetcwd(wcwd, _MAX_PATH) == 0) - throw system_error (errno, system_category ()); -#else - char cwd[PATH_MAX]; - if (getcwd (cwd, PATH_MAX) == 0) - throw system_error (errno, system_category ()); - - wchar_t wcwd[PATH_MAX]; - if (mbstowcs (wcwd, cwd, PATH_MAX) == size_type (-1)) - throw system_error (EINVAL, system_category ()); -#endif - - return string_type (wcwd); - } - - template <> - void path_traits<wchar_t>:: - current (string_type const& s) - { -#ifdef _WIN32 - if(_wchdir(s.c_str ()) != 0) - throw system_error (errno, system_category ()); -#else - char ns[PATH_MAX + 1]; - - if (wcstombs (ns, s.c_str (), PATH_MAX) == size_type (-1)) - throw system_error (EINVAL, system_category ()); - - ns[PATH_MAX] = '\0'; - - if (chdir (ns) != 0) - throw system_error (errno, system_category ()); -#endif - } -} diff --git a/build/path.ixx b/build/path.ixx deleted file mode 100644 index 9193fba..0000000 --- a/build/path.ixx +++ /dev/null @@ -1,171 +0,0 @@ -// file : build/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 build -{ -#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 -} diff --git a/build/path.txx b/build/path.txx deleted file mode 100644 index c664eaf..0000000 --- a/build/path.txx +++ /dev/null @@ -1,256 +0,0 @@ -// file : build/path.txx -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <vector> - -namespace build -{ - template <typename C, typename K> - basic_path<C, K> basic_path<C, K>:: - leaf () const - { - size_type p (traits::rfind_separator (this->path_)); - - return p != string_type::npos - ? basic_path (this->path_.c_str () + p + 1, this->path_.size () - p - 1) - : *this; - } - - template <typename C, typename K> - typename basic_path<C, K>::dir_type basic_path<C, K>:: - directory () const - { - if (root ()) - return dir_type (); - - size_type p (traits::rfind_separator (this->path_)); - - // Include the trailing slash so that we get correct behavior - // if directory is root. - // - return p != string_type::npos - ? dir_type (this->path_.c_str (), p + 1) - : dir_type (); - } - -#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 (this->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 <typename C, typename K> - basic_path<C, K>& basic_path<C, K>:: - operator/= (basic_path<C, K> const& r) - { - if (r.absolute () && !this->path_.empty ()) // Allow ('' / '/foo'). - throw invalid_basic_path<C> (r.path_); - - if (this->path_.empty () || r.path_.empty ()) - { - this->path_ += r.path_; - return *this; - } - - if (!traits::is_separator (this->path_[this->path_.size () - 1])) - this->path_ += traits::directory_separator; - - this->path_ += r.path_; - return *this; - } - - template <typename C, typename K> - basic_path<C, K> basic_path<C, K>:: - leaf (basic_path<C, K> const& d) const - { - size_type n (d.path_.size ()); - - if (n == 0) - return *this; - - if (!sub (d)) - throw invalid_basic_path<C> (this->path_); - - size_type m (this->path_.size ()); - - if (n != m -#ifndef _WIN32 - && !d.root () -#endif - ) - n++; // Skip the directory separator (unless it is POSIX root). - - return basic_path (this->path_.c_str () + n, m - n); - } - - 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 n (l.path_.size ()); - - if (n == 0) - return dir_type (this->path_); - - if (!sup (l)) - throw invalid_basic_path<C> (this->path_); - - size_type m (this->path_.size ()); - - if (n != m) - n++; // Skip the directory separator. - - return dir_type (this->path_.c_str (), m - n); - } - - template <typename C, typename K> - basic_path<C, K> basic_path<C, K>:: - relative (basic_path<C, K> d) const - { - basic_path r; - - for (;; d = d.directory ()) - { - if (sub (d)) - break; - - r /= basic_path (".."); - - // Roots of the paths do not match. - // - if (d.root ()) - throw invalid_basic_path<C> (this->path_); - } - - return r / leaf (d); - } - - template <typename C, typename K> - basic_path<C, K>& basic_path<C, K>:: - normalize () - { - if (empty ()) - return *this; - - bool abs (absolute ()); - - typedef std::vector<string_type> paths; - paths ps; - - for (size_type b (0), e (traits::find_separator (this->path_)), - n (this->path_.size ());; - e = traits::find_separator (this->path_, b)) - { - string_type s (this->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 (this->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<C> (this->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;) - { - p += *i; - - if (++i != e) - p += traits::directory_separator; - } - - if (p.empty () && !r.empty ()) - p += traits::directory_separator; // Root directory. - - this->path_.swap (p); - return *this; - } - - template <typename C, typename K> - void basic_path<C, K>:: - current (basic_path const& p) - { - const string_type& s (p.string ()); - - if (s.empty ()) - throw invalid_basic_path<char> (s); - - traits::current (s); - } - - template <typename C, typename K> - void basic_path<C, K>:: - init () - { - // Strip trailing slashes except for the case where the single - // slash represents the root directory. - // - size_type n (this->path_.size ()); - for (; n > 1 && traits::is_separator (this->path_[n - 1]); --n) ; - this->path_.resize (n); - } -} diff --git a/build/prerequisite b/build/prerequisite index ba850ec..0d3428f 100644 --- a/build/prerequisite +++ b/build/prerequisite @@ -13,7 +13,7 @@ #include <typeindex> #include <functional> // reference_wrapper -#include <build/path> +#include <build/types> #include <build/target-key> #include <build/utility> // extension_pool #include <build/diagnostics> @@ -12,6 +12,7 @@ #include <butl/prefix-map> +#include <build/types> #include <build/target> #include <build/operation> diff --git a/build/rule.cxx b/build/rule.cxx index a99611b..b3dfaeb 100644 --- a/build/rule.cxx +++ b/build/rule.cxx @@ -7,14 +7,15 @@ #include <utility> // move() #include <system_error> +#include <butl/filesystem> + #include <build/scope> #include <build/algorithm> #include <build/diagnostics> -#include <build/timestamp> -#include <build/filesystem> #include <build/context> using namespace std; +using namespace butl; namespace build { diff --git a/build/scope b/build/scope index 7dec7a2..5266370 100644 --- a/build/scope +++ b/build/scope @@ -9,8 +9,9 @@ #include <unordered_set> #include <unordered_map> -#include <build/path> -#include <build/path-map> +#include <butl/path-map> + +#include <build/types> #include <build/variable> #include <build/prerequisite> #include <build/operation> @@ -133,7 +134,8 @@ namespace build temp_scope (scope& p) {path_ = p.path_; parent_ = &p; root_ = p.root_;} }; - class scope_map: public dir_path_map<scope> + using scope_map_base = butl::dir_path_map<scope>; + class scope_map: public scope_map_base { public: // Note that we assume the first insertion into the map is that @@ -160,9 +162,6 @@ namespace build // return find (dir_path (p.string ())); } - - private: - typedef dir_path_map<scope> base; }; extern scope_map scopes; diff --git a/build/scope.cxx b/build/scope.cxx index 2b24702..5bd2b62 100644 --- a/build/scope.cxx +++ b/build/scope.cxx @@ -119,14 +119,14 @@ namespace build // Normally we would have a scope for the full path so try // that before making any copies. // - auto i (base::find (k)); + auto i (scope_map_base::find (k)); if (i != end ()) return i->second; for (dir_path d (k.directory ());; d = d.directory ()) { - auto i (base::find (d)); + auto i (scope_map_base::find (d)); if (i != end ()) return i->second; diff --git a/build/search.cxx b/build/search.cxx index dc59a9b..ee6e20f 100644 --- a/build/search.cxx +++ b/build/search.cxx @@ -4,17 +4,16 @@ #include <build/search> -#include <utility> // move +#include <utility> // move() #include <cassert> -#include <build/path> #include <build/scope> #include <build/target> #include <build/prerequisite> -#include <build/timestamp> #include <build/diagnostics> using namespace std; +using namespace butl; namespace build { @@ -10,8 +10,7 @@ #include <iosfwd> #include <utility> // move() -#include <build/path> -#include <build/name> +#include <build/types> namespace build { diff --git a/build/target b/build/target index d12a8e5..9388065 100644 --- a/build/target +++ b/build/target @@ -19,9 +19,7 @@ #include <butl/utility> // compare_c_string #include <butl/multi-index> // map_iterator_adapter -#include <build/path> -#include <build/timestamp> -#include <build/name> +#include <build/types> #include <build/variable> #include <build/operation> #include <build/target-key> diff --git a/build/target-key b/build/target-key index 2fa2186..9e74c27 100644 --- a/build/target-key +++ b/build/target-key @@ -9,7 +9,7 @@ #include <typeindex> #include <ostream> -#include <build/path> +#include <build/types> namespace build { diff --git a/build/timestamp b/build/timestamp deleted file mode 100644 index 3479a77..0000000 --- a/build/timestamp +++ /dev/null @@ -1,54 +0,0 @@ -// file : build/timestamp -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD_TIMESTAMP -#define BUILD_TIMESTAMP - -#include <chrono> -#include <string> -#include <iosfwd> - -#include <build/path> - -namespace build -{ - // On all three main platforms that we target (GNU/Linux, Windows (both - // VC++ and GCC/MinGW64), and MacOS X) with recent C++ runtimes, - // system_clock has nanoseconds resolution and counts from the UNIX - // epoch. The latter is important since struct stat also returns times - // based on UNIX epoch. - // - // The underlying type for nanoseconds duration is signed integer type - // of at least 64 bits (currently int64_t). Because it is signed, we - // will overflow in year 2262 but by then the underlying type will - // most likely have changed to something larger than 64-bit. - // - // So to support other platforms that could possibly use a different - // system_clock resolutions (e.g., microseconds), we actually not going - // to assume anywhere (except perhaps timestamp.cxx) that we are dealing - // with nanoseconds or the 64-bit underlying type. - // - using std::chrono::system_clock; - - using timestamp = system_clock::time_point; - using duration = system_clock::duration; - - const timestamp timestamp_unknown {duration {-1}}; - const timestamp timestamp_nonexistent {duration {0}}; - - std::ostream& - operator<< (std::ostream&, const timestamp&); - - std::ostream& - operator<< (std::ostream&, const duration&); - - // Returns timestamp_nonexistent if the entry at the specified path - // does not exist. All other errors are reported by throwing - // std::system_error. - // - timestamp - path_mtime (const path&); -}; - -#endif // BUILD_TIMESTAMP diff --git a/build/timestamp.cxx b/build/timestamp.cxx deleted file mode 100644 index 9d6e70c..0000000 --- a/build/timestamp.cxx +++ /dev/null @@ -1,177 +0,0 @@ -// file : build/timestamp.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <build/timestamp> - -#include <unistd.h> // stat -#include <sys/types.h> // stat -#include <sys/stat.h> // stat - -#include <time.h> // localtime, gmtime, strftime - -#include <ostream> -#include <system_error> - -using namespace std; - -namespace build -{ - // Figuring out whether we have the nanoseconds in some form. - // - template <typename S> - constexpr auto nsec (const S* s) -> decltype(s->st_mtim.tv_nsec) - { - return s->st_mtim.tv_nsec; // POSIX (GNU/Linux, Solaris). - } - - template <typename S> - constexpr auto nsec (const S* s) -> decltype(s->st_mtimespec.tv_nsec) - { - return s->st_mtimespec.tv_nsec; // MacOS X. - } - - template <typename S> - constexpr auto nsec (const S* s) -> decltype(s->st_mtime_n) - { - return s->st_mtime_n; // AIX 5.2 and later. - } - - template <typename S> - constexpr int nsec (...) {return 0;} - - timestamp - path_mtime (const path& p) - { - struct stat s; - if (stat (p.string ().c_str (), &s) != 0) - { - if (errno == ENOENT || errno == ENOTDIR) - return timestamp_nonexistent; - else - throw system_error (errno, system_category ()); - } - - return system_clock::from_time_t (s.st_mtime) + - chrono::duration_cast<duration> ( - chrono::nanoseconds (nsec<struct stat> (&s))); - } - - ostream& - operator<< (ostream& os, const timestamp& ts) - { - // @@ replace with put_time() - // - - time_t t (system_clock::to_time_t (ts)); - - if (t == 0) - return os << "<nonexistent>"; - - std::tm tm; - if (localtime_r (&t, &tm) == nullptr) - throw system_error (errno, system_category ()); - - // If year is greater than 9999, we will overflow. - // - char buf[20]; // YYYY-MM-DD HH:MM:SS\0 - if (strftime (buf, sizeof (buf), "%Y-%m-%d %H:%M:%S", &tm) == 0) - return os << "<beyond year 9999>"; - - os << buf; - - using namespace chrono; - - timestamp sec (system_clock::from_time_t (t)); - nanoseconds ns (duration_cast<nanoseconds> (ts - sec)); - - if (ns != nanoseconds::zero ()) - { - os << '.'; - os.width (9); - os.fill ('0'); - os << ns.count (); - } - - return os; - } - - ostream& - operator<< (ostream& os, const duration& d) - { - // @@ replace with put_time() - // - - timestamp ts; // Epoch. - ts += d; - - time_t t (system_clock::to_time_t (ts)); - - const char* fmt (nullptr); - const char* unt ("nanoseconds"); - if (t >= 365 * 12 * 24 * 60 * 60) - { - fmt = "%Y-%m-%d %H:%M:%S"; - unt = "years"; - } - else if (t >= 12 * 24 * 60* 60) - { - fmt = "%m-%d %H:%M:%S"; - unt = "months"; - } - else if (t >= 24 * 60* 60) - { - fmt = "%d %H:%M:%S"; - unt = "days"; - } - else if (t >= 60 * 60) - { - fmt = "%H:%M:%S"; - unt = "hours"; - } - else if (t >= 60) - { - fmt = "%M:%S"; - unt = "minutes"; - } - else if (t >= 1) - { - fmt = "%S"; - unt = "seconds"; - } - - if (fmt != nullptr) - { - std::tm tm; - if (gmtime_r (&t, &tm) == nullptr) - throw system_error (errno, system_category ()); - - char buf[20]; // YYYY-MM-DD HH:MM:SS\0 - if (strftime (buf, sizeof (buf), fmt, &tm) == 0) - return os << "<beyond 9999>"; - - os << buf; - } - - using namespace chrono; - - timestamp sec (system_clock::from_time_t (t)); - nanoseconds ns (duration_cast<nanoseconds> (ts - sec)); - - if (ns != nanoseconds::zero ()) - { - if (fmt != nullptr) - { - os << '.'; - os.width (9); - os.fill ('0'); - } - - os << ns.count () << ' ' << unt; - } - else if (fmt == 0) - os << '0'; - - return os; - } -} diff --git a/build/types b/build/types index c29890a..5f6b3de 100644 --- a/build/types +++ b/build/types @@ -7,13 +7,32 @@ #include <vector> -#include <build/path> +#include <butl/path> +#include <butl/timestamp> + +#include <build/name> namespace build { // Commonly-used types. // + // <butl/path> + // + using butl::path; + using butl::dir_path; + using butl::basic_path; + using butl::invalid_path; + + // <butl/timestamp> + // + using butl::system_clock; + using butl::timestamp; + using butl::duration; + using butl::timestamp_unknown; + using butl::timestamp_nonexistent; + using butl::operator<<; + typedef std::vector<path> paths; typedef std::vector<dir_path> dir_paths; } diff --git a/build/utility b/build/utility index 717a9ed..4135b37 100644 --- a/build/utility +++ b/build/utility @@ -11,7 +11,7 @@ #include <exception> #include <unordered_set> -#include <build/path> +#include <build/types> namespace build { diff --git a/build/variable b/build/variable index 42f0787..2164f92 100644 --- a/build/variable +++ b/build/variable @@ -16,8 +16,7 @@ #include <butl/prefix-map> -#include <build/path> -#include <build/name> +#include <build/types> namespace build { diff --git a/tests/build/buildfile b/tests/build/buildfile index 19ea46e..8d7e692 100644 --- a/tests/build/buildfile +++ b/tests/build/buildfile @@ -1,4 +1,3 @@ -d=path/ - +d= .: $d include $d diff --git a/tests/build/parser/driver.cxx b/tests/build/parser/driver.cxx index 57d9267..fef2f41 100644 --- a/tests/build/parser/driver.cxx +++ b/tests/build/parser/driver.cxx @@ -6,7 +6,7 @@ #include <sstream> #include <iostream> -#include <build/path> +#include <build/types> #include <build/scope> #include <build/target> #include <build/native> diff --git a/tests/build/path/buildfile b/tests/build/path/buildfile deleted file mode 100644 index c2756b7..0000000 --- a/tests/build/path/buildfile +++ /dev/null @@ -1 +0,0 @@ -exe{driver}: cxx{driver ../../../build/path} diff --git a/tests/build/path/driver.cxx b/tests/build/path/driver.cxx deleted file mode 100644 index 58839d4..0000000 --- a/tests/build/path/driver.cxx +++ /dev/null @@ -1,227 +0,0 @@ -// file : tests/build/path/driver.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <cassert> -#include <iostream> - -#include <build/path> - -using namespace std; -using namespace build; - -int -main () -{ - assert (path ("/").string () == "/"); - assert (path ("//").string () == "/"); - assert (path ("/tmp/foo/").string () == "/tmp/foo"); -#ifdef _WIN32 - assert (path ("\\\\").string () == "\\"); - assert (path ("/\\").string () == "/"); - assert (path ("C:").string () == "C:"); - assert (path ("C:\\").string () == "C:"); - assert (path ("C:\\tmp\\foo\\").string () == "C:\\tmp\\foo"); -#endif - - // abslote/relative/root - // -#ifndef _WIN32 - assert (path ("/").root ()); - assert (path ("//").root ()); - assert (path ("/").absolute ()); - assert (path ("/foo/bar").absolute ()); - assert (path ("bar/baz").relative ()); -#else - assert (path ("C:").root ()); - assert (path ("C:\\").root ()); - assert (path ("C:\\").absolute ()); - assert (path ("C:\\foo\\bar").absolute ()); - assert (path ("bar\\baz").relative ()); -#endif - - - // leaf - // -#ifndef _WIN32 - assert (path ("/").leaf ().string () == ""); - assert (path ("/tmp").leaf ().string () == "tmp"); - assert (path ("//tmp").leaf ().string () == "tmp"); -#else - assert (path ("C:").leaf ().string () == "C:"); - assert (path ("C:\\tmp").leaf ().string () == "tmp"); - assert (path ("C:\\\\tmp").leaf ().string () == "tmp"); -#endif - - // directory - // -#ifndef _WIN32 - assert (path ("/").directory ().string () == ""); - assert (path ("/tmp").directory ().string () == "/"); - assert (path ("//tmp").directory ().string () == "/"); -#else - assert (path ("C:").directory ().string () == ""); - assert (path ("C:\\tmp").directory ().string () == "C:"); - assert (path ("C:\\\\tmp").directory ().string () == "C:"); -#endif - - // base - // - assert (path ("/").base ().string () == "/"); - assert (path ("/foo.txt").base ().string () == "/foo"); - assert (path (".txt").base ().string () == ".txt"); - assert (path ("/.txt").base ().string () == "/.txt"); - assert (path ("foo.txt.orig").base ().string () == "foo.txt"); -#ifdef _WIN32 - assert (path ("C:").base ().string () == "C:"); - assert (path ("C:\\foo.txt").base ().string () == "C:\\foo"); -#endif - - // iteration - // - { - path p; - assert (p.begin () == p.end ()); - } - { - path p ("foo"); - path::iterator i (p.begin ()); - assert (i != p.end () && *i == "foo"); - assert (++i == p.end ()); - } - { - path p ("foo/bar"); - path::iterator i (p.begin ()); - assert (i != p.end () && *i == "foo"); - assert (++i != p.end () && *i == "bar"); - assert (++i == p.end ()); - } - { - path p ("/foo/bar"); - path::iterator i (p.begin ()); - assert (i != p.end () && *i == ""); - assert (++i != p.end () && *i == "foo"); - assert (++i != p.end () && *i == "bar"); - assert (++i == p.end ()); - } - { - path p ("/"); - path::iterator i (p.begin ()); - assert (i != p.end () && *i == ""); - assert (++i == p.end ()); - } - - // operator/ - // -#ifndef _WIN32 - assert ((path ("/") / path ("tmp")).string () == "/tmp"); - assert ((path ("foo") / path ("bar")).string () == "foo/bar"); -#else - assert ((path ("\\") / path ("tmp")).string () == "\\tmp"); - assert ((path ("C:\\") / path ("tmp")).string () == "C:\\tmp"); - assert ((path ("foo") / path ("bar")).string () == "foo\\bar"); -#endif - - // normalize - // -#ifndef _WIN32 - assert (path ("../foo").normalize ().string () == "../foo"); - assert (path ("..///foo").normalize ().string () == "../foo"); - assert (path ("../../foo").normalize ().string () == "../../foo"); - assert (path (".././foo").normalize ().string () == "../foo"); - assert (path (".").normalize ().string () == ""); - assert (path ("./..").normalize ().string () == ".."); - assert (path ("../.").normalize ().string () == ".."); - assert (path ("foo/./..").normalize ().string () == ""); - assert (path ("/foo/./..").normalize ().string () == "/"); - assert (path ("./foo").normalize ().string () == "foo"); -#else - assert (path ("../foo").normalize ().string () == "..\\foo"); - assert (path ("..///foo").normalize ().string () == "..\\foo"); - assert (path ("..\\../foo").normalize ().string () == "..\\..\\foo"); - assert (path (".././foo").normalize ().string () == "..\\foo"); - assert (path (".").normalize ().string () == ""); - assert (path ("./..").normalize ().string () == ".."); - assert (path ("../.").normalize ().string () == ".."); - assert (path ("foo/./..").normalize ().string () == ""); - assert (path ("C:/foo/./..").normalize ().string () == "C:"); - assert (path ("./foo").normalize ().string () == "foo"); - - assert (path ("C:").normalize ().string () == "C:"); - assert (path ("C:\\Foo12//Bar").normalize ().string () == "C:\\Foo12\\Bar"); -#endif - - // comparison - // - assert (path ("./foo") == path("./foo")); - assert (path ("./boo") < path("./foo")); -#ifdef _WIN32 - assert (path (".\\foo") == path("./FoO")); - assert (path (".\\boo") < path(".\\Foo")); -#endif - - // posix_string - // - assert (path ("foo/bar/../baz").posix_string () == "foo/bar/../baz"); -#ifdef _WIN32 - assert (path ("foo\\bar\\..\\baz").posix_string () == "foo/bar/../baz"); - try - { - path ("c:\\foo\\bar\\..\\baz").posix_string (); - assert (false); - } - catch (const invalid_path&) {} -#endif - - // sub - // - assert (path ("foo").sub (path ("foo"))); - assert (path ("foo/bar").sub (path ("foo/bar"))); - assert (path ("foo/bar").sub (path ("foo"))); - assert (!path ("foo/bar").sub (path ("bar"))); - assert (path ("/foo/bar").sub (path ("/foo"))); - assert (path ("/foo/bar/baz").sub (path ("/foo/bar"))); - assert (!path ("/foo/bar/baz").sub (path ("/foo/baz"))); -#ifdef _WIN32 - assert (path ("c:").sub (path ("c:"))); - assert (!path ("c:").sub (path ("d:"))); - assert (path ("c:\\foo").sub (path ("c:"))); -#else - assert (path ("/foo/bar/baz").sub (path ("/"))); -#endif - - // relative - // - assert (path ("foo").relative (path ("foo")) == path ()); - assert (path ("foo/bar").relative (path ("foo/bar")) == path ()); - assert (path ("foo/bar/baz").relative (path ("foo/bar")) == path ("baz")); - assert (path ("foo/bar/baz").relative (path ("foo/bar/buz")). - posix_string () == "../baz"); - assert (path ("foo/bar/baz").relative (path ("foo/biz/baz")). - posix_string () == "../../bar/baz"); - assert (path ("foo/bar/baz").relative (path ("fox/bar/baz")). - posix_string () == "../../../foo/bar/baz"); -#ifdef _WIN32 - assert (path ("c:\\foo\\bar").relative (path ("c:\\fox\\bar")) == - path ("..\\..\\foo\\bar")); - try - { - path ("c:\\foo\\bar").relative (path ("d:\\fox\\bar")); - assert (false); - } - catch (const invalid_path&) {} -#else - assert (path ("/foo/bar/baz").relative (path ("/")) == - path ("foo/bar/baz")); -#endif - - /* - path p ("../foo"); - p.complete (); - - cerr << path::current () << endl; - cerr << p << endl; - p.normalize (); - cerr << p << endl; - */ -} |