271 lines
6.9 KiB
C++
271 lines
6.9 KiB
C++
#ifndef __FILESYSTEM_H__
|
|
#define __FILESYSTEM_H__
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <cstring>
|
|
#include <list>
|
|
#include <sys/stat.h>
|
|
|
|
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<char, '/', '/', '.'>
|
|
{
|
|
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<class Char>
|
|
path(const std::basic_string<Char>& 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<path>& 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__
|