#ifndef __FILESYSTEM_H__ #define __FILESYSTEM_H__ #include #include #include #include #include namespace std { namespace filesystem { class path; namespace path_detail { template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > struct path_constants { typedef path_constants< Char, Separator, PreferredSeparator, Dot > path_constants_base; typedef Char value_type; static constexpr value_type separator = Separator; static constexpr value_type preferred_separator = PreferredSeparator; static constexpr value_type dot = Dot; }; template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > constexpr typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type path_constants< Char, Separator, PreferredSeparator, Dot >::separator; template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > constexpr typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type path_constants< Char, Separator, PreferredSeparator, Dot >::preferred_separator; template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > constexpr typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type path_constants< Char, Separator, PreferredSeparator, Dot >::dot; } // namespace path_detail class path : public filesystem::path_detail::path_constants { public: using string_type = std::basic_string< value_type >; constexpr static size_t max_path = 256u; constexpr static const value_type* const root_path = "/"; inline constexpr static bool is_directory_separator(path::value_type c) noexcept { return c == preferred_separator; } template path(const std::basic_string& s) : m_pathname(s) {}; path() noexcept : m_pathname() {} path(path const& p) : m_pathname(p.m_pathname) {} path(const value_type* s) : m_pathname(s) {} path(path&& p) noexcept : m_pathname(static_cast< string_type&& >(p.m_pathname)) { } path& operator=(path&& p) noexcept { m_pathname = static_cast< string_type&& >(p.m_pathname); return *this; } path& assign(path&& p) noexcept { m_pathname = static_cast< string_type&& >(p.m_pathname); return *this; } path(string_type&& s) noexcept : m_pathname(static_cast< string_type&& >(s)) { } path& operator=(string_type&& p) noexcept { m_pathname = static_cast< string_type&& >(p); return *this; } path& assign(string_type&& p) noexcept { m_pathname = static_cast< string_type&& >(p); return *this; } path(const value_type* begin, const value_type* end) : m_pathname(begin, end) {} path& assign(path const& p) { m_pathname = p.m_pathname; return *this; } path& assign(const value_type* begin, const value_type* end) { m_pathname.assign(begin, end); return *this; } path& operator+=(value_type c) { m_pathname.push_back(c); return *this; } path& operator+=(const string_type& s) { m_pathname.append(s); return *this; } path& concat(path const& p) { m_pathname.append(p.m_pathname); return *this; } path& concat(const value_type* begin, const value_type* end) { m_pathname.append(begin, end); return *this; } static string_type quoted(const string_type& s, value_type q = '"') { return string_type{}.append(1,q).append(s).append(1,q); } string_type string() const { return m_pathname; } path& operator/= (const path& p) { if(empty()) { if(p.string().find_first_of(preferred_separator) == 0) { assign(p); } else { m_pathname = preferred_separator + p.m_pathname; } } else { const bool leftHasTrailingSeparator = m_pathname.at(m_pathname.size() - 1u) == preferred_separator; const bool rightStartsWithSeparator = p.string().find_first_of(preferred_separator) == 0; if(leftHasTrailingSeparator && rightStartsWithSeparator) { const string_type& right = p.string(); m_pathname.append(right.cbegin() + 1u, right.cend()); } else if (!leftHasTrailingSeparator && !rightStartsWithSeparator) { m_pathname += (preferred_separator + p.m_pathname); } else { m_pathname += p.m_pathname; } } return *this; } path filename() const { if(empty() || m_pathname == "/") { return {}; } const auto pos = m_pathname.find_last_of(preferred_separator); if(pos == string_type::npos) { return *this; } return (pos == m_pathname.size() - 1) ? path{} : m_pathname.substr(pos + 1u); } bool empty() const noexcept { return m_pathname.empty(); } const value_type* c_str() const noexcept { return m_pathname.c_str(); } private: string_type m_pathname; }; template< typename Char, typename Traits > inline std::basic_ostream< Char, Traits >& operator<<(std::basic_ostream< Char, Traits >& os, path const& p) { return os << path::quoted(p.string()); } template< typename Char, typename Traits > inline std::basic_istream< Char, Traits >& operator>>(std::basic_istream< Char, Traits >& is, path& p) { std::basic_string< Char > str; is >> path::quoted(p.string()); p = str; return is; } path current_path(); path operator/(path lhs, path const& rhs); inline bool is_directory(path const& p); inline bool is_regular_file(path const& p); bool exists(path const& p); path absolute(path const& p); inline bool is_absolute(path const& p); void scan_directory (path const& directory, std::list& paths); inline bool is_directory(path const& p) { if(p.empty()) { return false; } struct stat sb; if (stat(p.string().c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) { return true; } return false; } inline bool is_regular_file(path const& p) { if(p.empty()) { return false; } struct stat sb; if (stat(p.string().c_str(), &sb) == 0 && S_ISREG(sb.st_mode)) { return true; } return false; } inline bool exists(path const& p) { return (is_regular_file(p) || is_directory(p)); } inline bool is_absolute(path const& p) { if(p.empty()) { return false; } const auto strPath(p.string()); const auto pos = strPath.find_first_of(path::root_path); if(pos == std::string::npos) { return false; } return pos == 0; } } // namespace filesystem } // namespace std #endif // !__FILESYSTEM_H__