From: Enblend <enb...@li...> - 2019-11-23 13:00:12
|
branch: details: http://enblend.hg.sourceforge.net/hgweb/enblend/enblend/hg/p/enblend/code/rev/2a3eed753859 changeset: 1535:2a3eed753859 user: Chris <cs...@us...> date: Sat Nov 23 13:45:09 2019 +0100 description: Update "filenameparse.cc" module to reflect the C++17 Standard. Path manipulation is vastly simplified, however some compilers need an additional library to support <filesystem>, for example "stdc++fs" for g++-8.3.0. diffstat: VERSION | 2 +- configure.ac | 13 +- src/filenameparse.cc | 303 +++++++++----------------------------------------- 3 files changed, 66 insertions(+), 252 deletions(-) diffs (445 lines): diff -r affc3d4dcc67 -r 2a3eed753859 VERSION --- a/VERSION Sat Nov 23 13:41:24 2019 +0100 +++ b/VERSION Sat Nov 23 13:45:09 2019 +0100 @@ -1,1 +1,1 @@ -4.3-51a1e6b03cc6 +4.3-affc3d4dcc67 diff -r affc3d4dcc67 -r 2a3eed753859 configure.ac --- a/configure.ac Sat Nov 23 13:41:24 2019 +0100 +++ b/configure.ac Sat Nov 23 13:45:09 2019 +0100 @@ -46,8 +46,8 @@ AC_MSG_CHECKING([for on-demand dynamic linking]) save_ldflags="$LDFLAGS" LDFLAGS="-Wl,--as-needed -Wl,--no-copy-dt-needed-entries ${LDFLAGS}" - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <string.h>]], - [[strlen("foo")]])], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <cstring>]], + [[std::strlen("foo")]])], [AC_MSG_RESULT(yes); have_on_demand_dynamic_linking=yes], AC_MSG_RESULT(no)) @@ -60,6 +60,15 @@ # Checks for libraries. +STDCXX_FILESYSTEM_LIBRARY='-lstdc++fs' +AC_MSG_CHECKING([whether we must link with an extra library to get C++17 filesystem support]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <filesystem>]], + [[std::filesystem::path p; + p.parent_path()]])], + [AC_MSG_RESULT(no)], + [AC_MSG_RESULT(yes) + LIBS="$LIBS $STDCXX_FILESYSTEM_LIBRARY"]) + # We check for TCMalloc so early to make it the last user library on # the linker command line. It will then gobble all undefined # references to malloc(3) and free(3) and thus relieve the O/S even diff -r affc3d4dcc67 -r 2a3eed753859 src/filenameparse.cc --- a/src/filenameparse.cc Sat Nov 23 13:41:24 2019 +0100 +++ b/src/filenameparse.cc Sat Nov 23 13:45:09 2019 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2017 Dr. Christoph L. Spiel + * Copyright (C) 2009-2019 Dr. Christoph L. Spiel * * This file is part of Enblend. * @@ -22,12 +22,11 @@ // Life is tough and then you die. -- Jack Dempsey -#include <list> +#include <filesystem> +#include <numeric> #include <string> +#include <vector> -#if _WIN32 -#include <ctype.h> // isalpha -#endif #ifdef HAVE_CONFIG_H #include <config.h> @@ -35,332 +34,138 @@ #include "filenameparse.h" -#if defined(_MSC_VER) || defined(HAVE_WINDOWS_H) -#define PATH_SEPARATOR "\\" -#else -#define PATH_SEPARATOR "/" -#endif -#define DOT "." -#define DOTDOT ".." +#define CURRENT_DIRECTORY "." +#define PARENT_DIRECTORY ".." -#ifdef HAVE_STD_FILESYSTEM -#include <filesystem> -#if defined _MSC_VER && _MSC_VER>=1912 -typedef std::experimental::filesystem::path basic_path; -#else -typedef std::tr2::sys::path basic_path; -#endif -#endif + +typedef std::filesystem::path basic_path; + namespace enblend { bool isRelativePath(const std::string& aFilename) { -#if defined(HAVE_STD_FILESYSTEM) - const basic_path path(aFilename); - return !path.has_root_directory(); -#else - const std::string::size_type separator = aFilename.find(PATH_SEPARATOR); -#if defined(_MSC_VER) || defined(HAVE_WINDOWS_H) - return !(aFilename.size() >= 3 && - isalpha(aFilename[0]) && - aFilename[1] == ':' && - separator == 2); -#else - return separator != 0; -#endif -#endif + const basic_path path {aFilename}; + + return path.is_relative(); } std::string extractDirname(const std::string& aFilename) { -#if defined(HAVE_STD_FILESYSTEM) - const basic_path path(aFilename); - const std::string directory(path.parent_path().string()); - return directory.empty() ? DOT : directory; -#else - const std::string::size_type separator = aFilename.rfind(PATH_SEPARATOR); - return (separator == std::string::npos) ? DOT : aFilename.substr(0, separator); -#endif + const basic_path path {aFilename}; + const std::string directory {path.parent_path().string()}; + + return directory.empty() ? CURRENT_DIRECTORY : directory; } std::string extractBasename(const std::string& aFilename) { -#if defined(HAVE_STD_FILESYSTEM) - const basic_path path(aFilename); + const basic_path path {aFilename}; + return path.filename().string(); -#else - const std::string::size_type separator = aFilename.rfind(PATH_SEPARATOR); - return - (separator == std::string::npos) ? - aFilename : - aFilename.substr(separator + 1, aFilename.length() - separator - 1); -#endif } std::string extractFilename(const std::string& aFilename) { -#if defined(HAVE_STD_FILESYSTEM) - const basic_path path(aFilename); + const basic_path path {aFilename}; + return path.stem().string(); -#else - const std::string::size_type separator = aFilename.rfind(PATH_SEPARATOR); - const std::string::size_type dot = aFilename.rfind(DOT); - if (separator == std::string::npos) - { - return (dot == std::string::npos) ? aFilename : aFilename.substr(0, dot); - } - else - { - return - (dot == std::string::npos) ? - aFilename.substr(separator + 1, aFilename.length() - separator - 1) : - aFilename.substr(separator + 1, dot - separator - 1); - } -#endif } std::string extractExtension(const std::string& aFilename) { -#if defined(HAVE_STD_FILESYSTEM) - const basic_path path(aFilename); + const basic_path path {aFilename}; + return path.extension().string(); -#else - const std::string::size_type dot = aFilename.rfind(DOT); - return - (dot == std::string::npos) ? - "" : - aFilename.substr(dot, aFilename.length() - dot); -#endif } -typedef std::list<std::string> list_t; - - -#if defined(HAVE_STD_FILESYSTEM) - -inline basic_path -removeDotsBoost(const basic_path& aPath) +static +basic_path +removeDotsInPath(const basic_path& aPath) { basic_path result; - for (basic_path::const_iterator p = aPath.begin(); p != aPath.end(); ++p) + + for (const auto& p : aPath) { - if (*p != DOT) + if (p != CURRENT_DIRECTORY) { - result /= *p; + result /= p; } } + return result; } -inline basic_path -removeDotDotsBoost(const basic_path& aPath) +static +basic_path +removeDotDotsInPath(const basic_path& aPath) { - list_t directories; - for (basic_path::const_iterator p = aPath.begin(); p != aPath.end(); ++p) + std::vector<std::string> directories; + + for (const auto& p : aPath) { - if (*p == DOTDOT && - !directories.empty() && directories.back() != DOTDOT) + if (p == PARENT_DIRECTORY && + !directories.empty() && directories.back() != PARENT_DIRECTORY) { directories.pop_back(); } else { - directories.push_back(p->string()); + directories.push_back(p.string()); } } - basic_path result; - for (list_t::const_iterator p = directories.begin(); p != directories.end(); ++p) - { - result /= *p; - } - return result; + + return std::accumulate(directories.begin(), directories.end(), + basic_path {}, + [](const basic_path& parent, const basic_path& leaf) + { + return basic_path {parent} /= leaf; + }); } -#else - -inline -std::string -removeDotsCxx(const std::string& aPathname) -{ - std::string path(aPathname); - std::string::size_type predecessor = std::string::npos; - std::string::size_type separator = path.find(PATH_SEPARATOR); - while (separator != std::string::npos) - { - const std::string::size_type begin = - predecessor == std::string::npos ? 0 : predecessor + 1; - const std::string component = - path.substr(begin, separator - predecessor - 1); - if (component == DOT) - { - path.erase(begin, 2); - } - else - { - predecessor = separator; - } - separator = path.find(PATH_SEPARATOR, predecessor + 1); - } - if (predecessor == std::string::npos) - { - if (path == DOT) - { - path.clear(); - } - } - else - { - const std::string component = path.substr(predecessor + 1); - if (component == DOT) - { - path.erase(predecessor); - } - } - return path; -} - - -inline std::string -removeDotDotsCxx(const std::string& aPathname) -{ - std::string path(aPathname); - list_t directories; - std::string::size_type predecessor = std::string::npos; - std::string::size_type separator = path.find(PATH_SEPARATOR); - while (separator != std::string::npos) - { - const std::string::size_type begin = - predecessor == std::string::npos ? 0 : predecessor + 1; - const std::string component = - path.substr(begin, separator - predecessor - 1); - if (component == DOTDOT && - !directories.empty() && directories.back() != DOTDOT) - { - directories.pop_back(); - } - else - { - directories.push_back(component); - } - - predecessor = separator; - separator = path.find(PATH_SEPARATOR, predecessor + 1); - } - if (predecessor == std::string::npos) - { - directories.push_back(path); - } - else - { - const std::string component = path.substr(predecessor + 1); - if (component == DOTDOT && - !directories.empty() && directories.back() != DOTDOT) - { - directories.pop_back(); - } - else - { - directories.push_back(component); - } - } - std::string result; - for (list_t::const_iterator p = directories.begin(); p != directories.end(); ++p) - { - if (p != directories.begin()) - { - result.append(PATH_SEPARATOR); - } - result.append(*p); - } - return result; -} -#endif - std::string canonicalizePath(const std::string& aPathname, bool keepDot) { -#if defined(HAVE_STD_FILESYSTEM) - const basic_path result = removeDotDotsBoost(removeDotsBoost(basic_path(aPathname))); + const basic_path result {removeDotDotsInPath(removeDotsInPath(basic_path(aPathname)))}; + if (keepDot && result.empty()) { - return std::string(DOT); + return CURRENT_DIRECTORY; } else { return result.string(); } -#else - std::string result = removeDotDotsCxx(removeDotsCxx(aPathname)); - - // For compatibility with the Boost implementation: Remove a - // trailing PATH_SEPARATOR unless we reference the root directory. - const size_t size = result.size(); - if (size >= 2 && result.substr(size - 1, 1) == PATH_SEPARATOR) - { - result.erase(size - 1, 1); - } - if (keepDot && result.empty()) - { - return std::string(DOT); - } - else - { - return result; - } -#endif } std::string concatPath(const std::string& aPathname, const std::string& anotherPathname) { -#if defined(HAVE_STD_FILESYSTEM) - basic_path path(aPathname); - basic_path leaf(anotherPathname); + basic_path path {aPathname}; + basic_path leaf {anotherPathname}; + path /= leaf; + return path.string(); -#else - if (aPathname.empty()) - { - return anotherPathname; - } - else if (anotherPathname.empty()) - { - return aPathname; - } - else - { - const std::string::size_type end = aPathname.find_last_not_of(PATH_SEPARATOR); - const std::string path = - (end == std::string::npos) ? - aPathname : - aPathname.substr(0, end + 1); - const std::string::size_type begin = anotherPathname.find_first_not_of(PATH_SEPARATOR); - const std::string leaf = - (begin == std::string::npos) ? - anotherPathname : - anotherPathname.substr(begin); - return path + PATH_SEPARATOR + leaf; - } -#endif } } // namespace enblend + // Local Variables: // mode: c++ // End: |