From 6a8b78cdd79ec4c8f35c2327b91c6b1143e8f08e Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 17 Nov 2016 18:36:53 +1100 Subject: [PATCH] fixup: add minimal filesystem implementation Implement the minimum possible surface of std::experimental::filesystem in terms of POSIX APIs so that we can compile under mingw --- Makefile.am | 7 ++ configure.ac | 3 + fixup/experimental/filesystem | 1 + fixup/experimental/filesystem.cpp | 121 ++++++++++++++++++++++++++++++ fixup/experimental/filesystem.hpp | 74 ++++++++++++++++++ 5 files changed, 206 insertions(+) create mode 100644 fixup/experimental/filesystem create mode 100644 fixup/experimental/filesystem.cpp create mode 100644 fixup/experimental/filesystem.hpp diff --git a/Makefile.am b/Makefile.am index d2f27e29..adc14edc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -344,6 +344,13 @@ if HAVE_CAPTURESTACKBACKTRACE __BACKTRACE_FILES += backtrace_stackwalk.cpp backtrace_win32.cpp endif +if !HAVE_STD_EXPERIMENTAL_FILESYSTEM +AM_CXXFLAGS += -isystem ${top_srcdir}/fixup +UTIL_FILES += \ + fixup/experimental/filesystem.hpp \ + fixup/experimental/filesystem.cpp +endif + BACKTRACE_FILES=$(firstword $(__BACKTRACE_FILES) backtrace_null.cpp) diff --git a/configure.ac b/configure.ac index b1528b56..96d9abce 100644 --- a/configure.ac +++ b/configure.ac @@ -52,6 +52,9 @@ AS_IF([test "x${host_os}" != "xmingw32"],[ AC_FUNC_MMAP +AC_CHECK_HEADERS([experimental/filesystem]) +AM_CONDITIONAL([HAVE_STD_EXPERIMENTAL_FILESYSTEM], [test "x$ac_cv_header_experimental_filesystem" == "xyes"]) + AC_SEARCH_LIBS([backtrace], [execinfo]) AC_CHECK_FUNC([backtrace]) AM_CONDITIONAL([HAVE_EXECINFO], [test "x$ac_cv_func_backtrace" == "xyes"]) diff --git a/fixup/experimental/filesystem b/fixup/experimental/filesystem new file mode 100644 index 00000000..375196f7 --- /dev/null +++ b/fixup/experimental/filesystem @@ -0,0 +1 @@ +#include "./filesystem.hpp" diff --git a/fixup/experimental/filesystem.cpp b/fixup/experimental/filesystem.cpp new file mode 100644 index 00000000..4ad7156f --- /dev/null +++ b/fixup/experimental/filesystem.cpp @@ -0,0 +1,121 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2016 Danny Robson + */ + +#include "./filesystem.hpp" + +#include "../../except.hpp" + +#include +#include +#include +#include + +namespace ns = std::experimental::filesystem; + + +/////////////////////////////////////////////////////////////////////////////// +ns::path::path () +{ ; } + + +//----------------------------------------------------------------------------- +ns::path::path (const path &p): + m_path (p.m_path) +{ ; } + + +/////////////////////////////////////////////////////////////////////////////// +std::string +ns::path::string (void) const +{ + return m_path; +} + + +/////////////////////////////////////////////////////////////////////////////// +const ns::path::string_type& +ns::path::native (void) const +{ + return m_path; +} + + +//----------------------------------------------------------------------------- +const ns::path::value_type* +ns::path::c_str (void) const +{ + return m_path.c_str (); +} + + +/////////////////////////////////////////////////////////////////////////////// +ns::path +ns::path::filename (void) const +{ + auto slash = m_path.find_last_of (preferred_separator); + if (slash == decltype(m_path)::npos) + return m_path; + return ns::path (m_path.cbegin () + slash, m_path.cend ()); +} + +//----------------------------------------------------------------------------- +ns::path +ns::path::stem (void) const +{ + auto name = filename (); + + auto first = name.m_path.cbegin (); + auto last = std::find_if (first, name.m_path.cend (), [] (auto c) { return c == '.'; }); + return path (first, last); +} + + +/////////////////////////////////////////////////////////////////////////////// +ns::path +ns::operator/ (const ns::path &a, const ns::path &b) +{ + return ns::path (a) /= b; +} + + +//----------------------------------------------------------------------------- +ns::path& +ns::path::operator/= (const path &rhs) +{ + m_path += preferred_separator + rhs.m_path; + return *this; +} + + +/////////////////////////////////////////////////////////////////////////////// +bool +ns::operator== (const path &a, const path &b) +{ + return a == b; +} + + +/////////////////////////////////////////////////////////////////////////////// +bool +ns::is_directory (const path &p) +{ + struct stat buf; + + if (stat (p.c_str (), &buf)) + ::util::errno_error::throw_code (); + + return S_ISDIR (buf.st_mode); +} diff --git a/fixup/experimental/filesystem.hpp b/fixup/experimental/filesystem.hpp new file mode 100644 index 00000000..541ddf09 --- /dev/null +++ b/fixup/experimental/filesystem.hpp @@ -0,0 +1,74 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2016 Danny Robson + */ + +#ifndef CRUFT_UTIL_FIXUP_EXPERIMENTAL_FILESYSTEM_HPP +#define CRUFT_UTIL_FIXUP_EXPERIMENTAL_FILESYSTEM_HPP + +#include + +/////////////////////////////////////////////////////////////////////////////// +namespace std::experimental::filesystem { + class path { + public: + using value_type = char; + using string_type = std::basic_string; + + static constexpr value_type preferred_separator = '/'; + + path (); + path (const path&); + + template + path (const Source &s): + m_path (s) + { ; } + + template + path (InputT first, InputT last): + m_path (first, last) + { ; } + + std::string string (void) const; + + const string_type& native (void) const; + const value_type* c_str (void) const; + + path filename (void) const; + path stem (void) const; + + path& operator/= (const path&); + + private: + string_type m_path; + }; + + path operator/ (const path&, const path&); + + bool operator== (const path&, const path&); + + //bool is_directory (file_status); + bool is_directory (const path&); + //bool is_directory (const path&, error_code&); + + template + std::basic_ostream& + operator<< (std::basic_ostream &os, const path &p) + { return os << p.native (); } +} + + +#endif +