From 63e7a4a77cb8ceed7b42561fe3202b0b48d86db6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 18 Jun 2015 14:41:45 +0200 Subject: Move path and filesystem from build2 to libbutl --- build/algorithm | 2 +- build/algorithm.cxx | 1 - build/b.cxx | 6 +- build/bin/module | 2 +- build/buildfile | 5 +- build/config/module | 1 + build/config/module.cxx | 5 +- build/config/operation.cxx | 4 +- build/context | 17 +- build/context.cxx | 1 + build/context.txx | 8 +- build/cxx/module | 1 + build/cxx/module.cxx | 1 - build/cxx/rule | 1 + build/cxx/rule.cxx | 1 - build/diagnostics | 6 +- build/file | 3 +- build/file.cxx | 4 +- build/filesystem | 61 ----- build/filesystem.cxx | 101 --------- build/name | 6 +- build/operation | 2 +- build/parser | 3 +- build/path | 553 --------------------------------------------- build/path-io | 7 +- build/path-map | 88 -------- build/path.cxx | 109 --------- build/path.ixx | 171 -------------- build/path.txx | 256 --------------------- build/prerequisite | 2 +- build/rule | 1 + build/rule.cxx | 5 +- build/scope | 11 +- build/scope.cxx | 4 +- build/search.cxx | 5 +- build/spec | 3 +- build/target | 4 +- build/target-key | 2 +- build/timestamp | 54 ----- build/timestamp.cxx | 177 --------------- build/types | 21 +- build/utility | 2 +- build/variable | 3 +- 43 files changed, 93 insertions(+), 1627 deletions(-) delete mode 100644 build/filesystem delete mode 100644 build/filesystem.cxx delete mode 100644 build/path delete mode 100644 build/path-map delete mode 100644 build/path.cxx delete mode 100644 build/path.ixx delete mode 100644 build/path.txx delete mode 100644 build/timestamp delete mode 100644 build/timestamp.cxx (limited to 'build') 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 #include #include -#include 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 // reverse_iterate -#include #include #include #include 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 #include -#include -#include +#include + +#include #include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #include #include 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 +#include #include 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 #include 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 -#include +#include + #include #include -#include #include #include 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 +#include + #include #include #include -#include #include 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 #include -#include +#include + +#include #include #include -#include 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 + // detailed enum from // template 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 + fs_status mkdir (const dir_path&); // Remove the file and print the standard diagnostics. The second @@ -62,19 +63,19 @@ namespace build // being printed. // template - fs_status + fs_status rmfile (const path&, const T& target); - inline fs_status + inline fs_status rmfile (const path& f) {return rmfile (f, f);} // Similar to rmfile() but for directories. // template - fs_status + fs_status rmdir (const dir_path&, const T& target); - inline fs_status + inline fs_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 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 - fs_status + fs_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 - fs_status + fs_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 #include 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 #include -#include #include #include 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 #include 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 #include #include -#include #include #include diff --git a/build/diagnostics b/build/diagnostics index 05401b9..6c528f2 100644 --- a/build/diagnostics +++ b/build/diagnostics @@ -14,11 +14,15 @@ #include #include -#include +#include + #include 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. // diff --git a/build/file b/build/file index 7f72282..7ac4d4d 100644 --- a/build/file +++ b/build/file @@ -5,8 +5,7 @@ #ifndef BUILD_FILE #define BUILD_FILE -#include -#include +#include #include // 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 +#include + #include #include #include -#include #include 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 // mode_t - -#include - -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 - -#include // rmdir(), unlink() -#include // stat -#include // stat, lstat(), S_IS*, mkdir() - -#include - -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; - } -} diff --git a/build/name b/build/name index 412abad..924c123 100644 --- a/build/name +++ b/build/name @@ -10,10 +10,14 @@ #include #include // move() -#include +#include +// Note: include 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 #include // reference_wrapper -#include +#include #include 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 #include // move() -#include +#include #include -#include #include #include // list_value #include 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 -#include // ptrdiff_t -#include -#include // move -#include -#include -#include // hash - -namespace build -{ - 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; - } - - // 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 - class invalid_basic_path; - - template - class basic_path; - - template - class path_data; - - template - struct dir_path_kind; - - template - struct any_path_kind - { - typedef path_data base_type; - typedef basic_path> dir_type; - }; - - template - struct dir_path_kind - { - typedef basic_path> base_type; - typedef basic_path> dir_type; - }; - - typedef basic_path> path; - typedef basic_path> dir_path; - typedef invalid_basic_path invalid_path; - - typedef basic_path> wpath; - typedef basic_path> dir_wpath; - typedef invalid_basic_path invalid_wpath; - - // - // - class invalid_path_base: std::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 path_data - { - public: - typedef std::basic_string string_type; - - path_data () = default; - - explicit - path_data (string_type s): path_ (std::move (s)) {} - - protected: - string_type path_; - }; - - template - class basic_path: public K::base_type - { - public: - typedef std::basic_string 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 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 - inline basic_path - operator/ (basic_path const& x, basic_path const& y) - { - basic_path r (x); - r /= y; - return r; - } - - // Additional operators for certain path kind combinations. - // - template - inline basic_path> - operator/ (basic_path> const& x, - basic_path> const& y) - { - basic_path> r (x); - r /= y; - return r; - } - - // IO - // - - /* - template - inline std::basic_ostream& - operator<< (std::basic_ostream& os, basic_path const& p) - { - return os << p.string (); - } - */ -} - -namespace std -{ - template - struct hash>: hash> - { - size_t - operator() (const build::basic_path& p) const noexcept - { - return hash>::operator() (p.string ()); - } - }; -} - -#include -#include - -#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 -#include +#include +// 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 - -#include - -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 - struct compare_prefix>: compare_prefix> - { - typedef build::basic_path key_type; - - typedef C delimiter_type; - typedef std::basic_string string_type; - typedef compare_prefix> 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 - using path_map = butl::prefix_map; - - template - using dir_path_map = - butl::prefix_map; -} - -#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 - -#ifdef _WIN32 -# include // _MAX_PATH -# include // _[w]getcwd, _[w]chdir -#else -# include // EINVAL -# include // mbstowcs, wcstombs -# include // PATH_MAX -# include // getcwd, chdir -#endif - -#include - -using namespace std; - -namespace build -{ - char const* invalid_path_base:: - what () const throw () - { - return "invalid filesystem path"; - } - - // - // char - // - - template <> - path_traits::string_type path_traits:: - 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:: - 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::string_type path_traits:: - 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:: - 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 // std::tolower -# include // std::towlower -#endif - -namespace build -{ -#ifdef _WIN32 - template <> - inline char path_traits:: - tolower (char c) - { - return std::tolower (c); - } - - template <> - inline wchar_t path_traits:: - tolower (wchar_t c) - { - return std::towlower (c); - } -#endif - - template - inline bool basic_path:: - 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 - inline bool basic_path:: - 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 - inline bool basic_path:: - 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 - inline bool basic_path:: - 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 - inline auto basic_path:: - 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 - inline auto basic_path:: - end () const -> iterator - { - return iterator (this->path_, string_type::npos, string_type::npos); - } - - template - inline basic_path& basic_path:: - complete () - { - if (relative ()) - *this = current () / *this; - - return *this; - } - - template - inline typename basic_path::dir_type basic_path:: - root_directory () const - { - return absolute () -#ifdef _WIN32 - ? dir_type (this->path_, 2) -#else - ? dir_type ("/") -#endif - : dir_type (); - } - - template - inline basic_path basic_path:: - base () const - { - size_type p (traits::find_extension (this->path_)); - return p != string_type::npos - ? basic_path (this->path_.c_str (), p) - : *this; - } - - template - inline const C* basic_path:: - 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 - inline typename basic_path::string_type basic_path:: - 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 - -namespace build -{ - template - basic_path basic_path:: - 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 basic_path::dir_type basic_path:: - 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 basic_path::string_type basic_path:: - posix_string () const - { - if (absolute ()) - throw invalid_basic_path (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 - basic_path& basic_path:: - operator/= (basic_path const& r) - { - if (r.absolute () && !this->path_.empty ()) // Allow ('' / '/foo'). - throw invalid_basic_path (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 - basic_path basic_path:: - leaf (basic_path const& d) const - { - size_type n (d.path_.size ()); - - if (n == 0) - return *this; - - if (!sub (d)) - throw invalid_basic_path (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 basic_path::dir_type basic_path:: - directory (basic_path const& l) const - { - size_type n (l.path_.size ()); - - if (n == 0) - return dir_type (this->path_); - - if (!sup (l)) - throw invalid_basic_path (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 - basic_path basic_path:: - relative (basic_path 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 (this->path_); - } - - return r / leaf (d); - } - - 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 (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 (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 - void basic_path:: - current (basic_path const& p) - { - const string_type& s (p.string ()); - - if (s.empty ()) - throw invalid_basic_path (s); - - traits::current (s); - } - - template - void basic_path:: - 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 #include // reference_wrapper -#include +#include #include #include // extension_pool #include diff --git a/build/rule b/build/rule index 04d3650..c7134e1 100644 --- a/build/rule +++ b/build/rule @@ -12,6 +12,7 @@ #include +#include #include #include 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 // move() #include +#include + #include #include #include -#include -#include #include 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 #include -#include -#include +#include + +#include #include #include #include @@ -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 + using scope_map_base = butl::dir_path_map; + 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 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 -#include // move +#include // move() #include -#include #include #include #include -#include #include using namespace std; +using namespace butl; namespace build { diff --git a/build/spec b/build/spec index bdfda4c..f50110b 100644 --- a/build/spec +++ b/build/spec @@ -10,8 +10,7 @@ #include #include // move() -#include -#include +#include 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 // compare_c_string #include // map_iterator_adapter -#include -#include -#include +#include #include #include #include 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 #include -#include +#include 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 -#include -#include - -#include - -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 - -#include // stat -#include // stat -#include // stat - -#include // localtime, gmtime, strftime - -#include -#include - -using namespace std; - -namespace build -{ - // Figuring out whether we have the nanoseconds in some form. - // - template - constexpr auto nsec (const S* s) -> decltype(s->st_mtim.tv_nsec) - { - return s->st_mtim.tv_nsec; // POSIX (GNU/Linux, Solaris). - } - - template - constexpr auto nsec (const S* s) -> decltype(s->st_mtimespec.tv_nsec) - { - return s->st_mtimespec.tv_nsec; // MacOS X. - } - - template - constexpr auto nsec (const S* s) -> decltype(s->st_mtime_n) - { - return s->st_mtime_n; // AIX 5.2 and later. - } - - template - 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 ( - chrono::nanoseconds (nsec (&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 << ""; - - 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 << ""; - - os << buf; - - using namespace chrono; - - timestamp sec (system_clock::from_time_t (t)); - nanoseconds ns (duration_cast (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 << ""; - - os << buf; - } - - using namespace chrono; - - timestamp sec (system_clock::from_time_t (t)); - nanoseconds ns (duration_cast (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 -#include +#include +#include + +#include namespace build { // Commonly-used types. // + // + // + using butl::path; + using butl::dir_path; + using butl::basic_path; + using butl::invalid_path; + + // + // + using butl::system_clock; + using butl::timestamp; + using butl::duration; + using butl::timestamp_unknown; + using butl::timestamp_nonexistent; + using butl::operator<<; + typedef std::vector paths; typedef std::vector 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 #include -#include +#include 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 -#include -#include +#include namespace build { -- cgit v1.1