Files
astyle-port/filesystem.h
T
2025-12-11 22:37:14 +03:00

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__