mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2024-12-28 09:29:57 +00:00
850 lines
20 KiB
C++
850 lines
20 KiB
C++
#ifndef __filesystem_h__
|
|
#define __filesystem_h__
|
|
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <locale>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <system_error>
|
|
#include <memory>
|
|
|
|
#include <dirent.h>
|
|
|
|
/*
|
|
*
|
|
* light-weight implementation of n3803
|
|
*
|
|
*
|
|
*/
|
|
|
|
namespace filesystem {
|
|
|
|
class path;
|
|
class filesystem_error;
|
|
|
|
using std::error_code;
|
|
using std::system_error;
|
|
|
|
class path {
|
|
|
|
public:
|
|
|
|
typedef char value_type;
|
|
typedef std::basic_string<value_type> string_type;
|
|
static constexpr value_type preferred_separator = '/';
|
|
|
|
|
|
// constructors and destructor
|
|
path() = default;
|
|
path(const path& p) = default;
|
|
path(path&& p) noexcept :
|
|
_path(std::move(p._path)) {
|
|
p.invalidate();
|
|
}
|
|
|
|
template<class Source>
|
|
path(Source const& source) :
|
|
_path(source) {}
|
|
|
|
template <class InputIterator>
|
|
path(InputIterator begin, InputIterator end) :
|
|
_path(begin, end) {}
|
|
|
|
template <class Source>
|
|
path(Source const& source, const std::locale& loc);
|
|
|
|
template <class InputIterator>
|
|
path(InputIterator begin, InputIterator end, const std::locale& loc);
|
|
|
|
~path() = default;
|
|
|
|
// assignments
|
|
path& operator=(const path& p) {
|
|
if (this != &p) {
|
|
_path = p._path;
|
|
_info = p._info;
|
|
}
|
|
return *this;
|
|
}
|
|
path& operator=(path&& p) noexcept {
|
|
if (this != &p) {
|
|
_path = std::move(p._path);
|
|
_info = p._info;
|
|
p.invalidate();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class Source>
|
|
path& operator=(Source const& source) {
|
|
invalidate();
|
|
_path = source;
|
|
return *this;
|
|
}
|
|
|
|
path& assign(const path &p) {
|
|
return (*this = p);
|
|
}
|
|
|
|
template <class Source>
|
|
path& assign(Source const& source) {
|
|
invalidate();
|
|
_path.assign(source);
|
|
return *this;
|
|
}
|
|
|
|
template <class InputIterator>
|
|
path& assign(InputIterator begin, InputIterator end) {
|
|
invalidate();
|
|
_path.assign(begin, end);
|
|
return *this;
|
|
}
|
|
|
|
|
|
// appends
|
|
path& operator/=(const path& p) {
|
|
return append(p);
|
|
}
|
|
|
|
|
|
|
|
template <class Source>
|
|
path& operator/=(Source const& source) {
|
|
return append(source);
|
|
}
|
|
|
|
|
|
|
|
// consider this a specialization of append.
|
|
path& append(const path &p);
|
|
|
|
path& append(const string_type &s);
|
|
|
|
|
|
template <class Source>
|
|
path& append(Source const& source) {
|
|
return append(path(source));
|
|
}
|
|
|
|
template <class InputIterator>
|
|
path& append(InputIterator begin, InputIterator end) {
|
|
return append(path(begin, end));
|
|
}
|
|
|
|
|
|
// concatenation
|
|
path& operator+=(const path& x) {
|
|
invalidate();
|
|
_path += x._path;
|
|
return *this;
|
|
}
|
|
|
|
path& operator+=(const string_type& x) {
|
|
invalidate();
|
|
_path += x;
|
|
return *this;
|
|
}
|
|
|
|
path& operator+=(const value_type* x) {
|
|
invalidate();
|
|
_path += x;
|
|
return *this;
|
|
}
|
|
|
|
path& operator+=(value_type x) {
|
|
invalidate();
|
|
_path += x;
|
|
return *this;
|
|
}
|
|
|
|
template <class Source>
|
|
path& operator+=(Source const& x) {
|
|
invalidate();
|
|
_path += x;
|
|
return *this;
|
|
}
|
|
|
|
template <class charT>
|
|
path& operator+=(charT x){
|
|
invalidate();
|
|
_path += x;
|
|
return *this;
|
|
}
|
|
|
|
template <class Source>
|
|
path& concat(Source const& x) {
|
|
invalidate();
|
|
_path += x;
|
|
return *this;
|
|
}
|
|
|
|
template <class InputIterator>
|
|
path& concat(InputIterator begin, InputIterator end) {
|
|
invalidate();
|
|
_path.append(begin, end);
|
|
return *this;
|
|
}
|
|
|
|
|
|
// modifiers
|
|
void clear() noexcept {
|
|
invalidate();
|
|
_path.clear();
|
|
}
|
|
|
|
path& make_preferred() {
|
|
return *this;
|
|
}
|
|
path& remove_filename();
|
|
path& replace_filename(const path& replacement);
|
|
path& replace_extension(/* const path& replacement = path() */);
|
|
path& replace_extension(const path& replacement);
|
|
|
|
void swap(path& rhs) noexcept {
|
|
std::swap(_path, rhs._path);
|
|
std::swap(_info, rhs._info);
|
|
}
|
|
|
|
// native format observers
|
|
const string_type& native() const noexcept {
|
|
return _path;
|
|
}
|
|
|
|
const value_type* c_str() const noexcept {
|
|
return _path.c_str();
|
|
}
|
|
|
|
operator string_type() const {
|
|
return _path;
|
|
}
|
|
|
|
template <class charT, class traits = std::char_traits<charT>,
|
|
class Allocator = std::allocator<charT> >
|
|
std::basic_string<charT, traits, Allocator> string(const Allocator& a = Allocator()) const;
|
|
|
|
std::string string() const {
|
|
return _path;
|
|
}
|
|
|
|
std::wstring wstring() const;
|
|
std::string u8string() const;
|
|
std::u16string u16string() const;
|
|
std::u32string u32string() const;
|
|
|
|
// generic format observers
|
|
template <class charT, class traits = std::char_traits<charT>,
|
|
class Allocator = std::allocator<charT> >
|
|
std::basic_string<charT, traits, Allocator>
|
|
generic_string(const Allocator& a = Allocator()) const;
|
|
std::string generic_string() const {
|
|
return _path;
|
|
}
|
|
std::wstring generic_wstring() const;
|
|
std::string generic_u8string() const;
|
|
std::u16string generic_u16string() const;
|
|
std::u32string generic_u32string() const;
|
|
|
|
// compare
|
|
int compare(const path& p) const noexcept;
|
|
int compare(const std::string& s) const;
|
|
int compare(const value_type* s) const;
|
|
|
|
// decomposition
|
|
path root_name() const;
|
|
path root_directory() const;
|
|
path root_path() const;
|
|
path relative_path() const;
|
|
path parent_path() const;
|
|
path filename() const;
|
|
path stem() const;
|
|
path extension() const;
|
|
|
|
// query
|
|
bool empty() const noexcept {
|
|
return _path.empty();
|
|
}
|
|
|
|
bool has_root_name() const;
|
|
bool has_root_directory() const;
|
|
bool has_root_path() const;
|
|
bool has_relative_path() const;
|
|
bool has_parent_path() const;
|
|
bool has_filename() const;
|
|
bool has_stem() const;
|
|
bool has_extension() const;
|
|
|
|
bool is_absolute() const {
|
|
return !empty() && _path[0] == '/';
|
|
}
|
|
|
|
bool is_relative() const {
|
|
return empty() || _path[0] != '/';
|
|
}
|
|
|
|
// iterators
|
|
class iterator;
|
|
typedef iterator const_iterator;
|
|
iterator begin() const;
|
|
iterator end() const;
|
|
|
|
private:
|
|
|
|
void invalidate() const {
|
|
_info.valid = false;
|
|
}
|
|
|
|
void study() const;
|
|
path &append_common(const std::string &s);
|
|
|
|
|
|
|
|
|
|
string_type _path;
|
|
|
|
mutable struct {
|
|
bool valid = false;
|
|
value_type special;
|
|
int stem;
|
|
int extension;
|
|
} _info;
|
|
|
|
};
|
|
|
|
|
|
inline void swap(path& lhs, path& rhs) noexcept {
|
|
lhs.swap(rhs);
|
|
}
|
|
|
|
/*
|
|
// ugh, this is boost, not stl.
|
|
inline std::size_t hash_value(const path& p) noexcept {
|
|
return std::hash_value(p._path);
|
|
}
|
|
*/
|
|
inline bool operator==(const path& lhs, const path& rhs) noexcept {
|
|
return lhs.compare(rhs) == 0;
|
|
}
|
|
|
|
inline bool operator!=(const path& lhs, const path& rhs) noexcept {
|
|
return lhs.compare(rhs) != 0;
|
|
}
|
|
|
|
inline bool operator< (const path& lhs, const path& rhs) noexcept {
|
|
return lhs.compare(rhs) < 0;
|
|
}
|
|
inline bool operator<=(const path& lhs, const path& rhs) noexcept {
|
|
return lhs.compare(rhs) <= 0;
|
|
}
|
|
inline bool operator> (const path& lhs, const path& rhs) noexcept {
|
|
return lhs.compare(rhs) > 0;
|
|
}
|
|
inline bool operator>=(const path& lhs, const path& rhs) noexcept {
|
|
return lhs.compare(rhs) >= 0;
|
|
}
|
|
inline path operator/ (const path& lhs, const path& rhs) {
|
|
path tmp = lhs;
|
|
return tmp.append(rhs);
|
|
}
|
|
|
|
//template <class charT, class traits>
|
|
//basic_ostream<charT, traits>&
|
|
//operator<<(basic_ostream<charT, traits>& os, const path& p);
|
|
//template <class charT, class traits>
|
|
//basic_istream<charT, traits>&
|
|
///operator>>(basic_istream<charT, traits>& is, path& p);
|
|
template <class Source>
|
|
path u8path(Source const& source);
|
|
template <class InputIterator>
|
|
path u8path(InputIterator begin, InputIterator end);
|
|
|
|
|
|
class filesystem_error : public system_error
|
|
{
|
|
public:
|
|
filesystem_error(const std::string& what_arg, error_code ec) :
|
|
system_error(ec, what_arg)
|
|
{}
|
|
|
|
filesystem_error(const std::string& what_arg, const path& p1, error_code ec) :
|
|
system_error(ec, what_arg), _p1(p1)
|
|
{}
|
|
|
|
filesystem_error(const std::string& what_arg, const path& p1, const path& p2, error_code ec) :
|
|
system_error(ec, what_arg), _p1(p1), _p2(p2)
|
|
{}
|
|
|
|
const path& path1() const noexcept {
|
|
return _p1;
|
|
}
|
|
const path& path2() const noexcept {
|
|
return _p2;
|
|
}
|
|
|
|
//const char* what() const noexcept;
|
|
|
|
private:
|
|
path _p1;
|
|
path _p2;
|
|
};
|
|
|
|
|
|
|
|
enum class file_type {
|
|
|
|
none = 0,
|
|
not_found = -1,
|
|
regular = 1,
|
|
directory = 2,
|
|
symlink = 3,
|
|
block = 4,
|
|
character = 5,
|
|
fifo = 6,
|
|
socket = 7,
|
|
unknown = 8
|
|
};
|
|
|
|
enum perms {
|
|
|
|
none = 0,
|
|
owner_read = 0400,
|
|
owner_write = 0200,
|
|
owner_exec = 0100,
|
|
owner_all = 0700,
|
|
|
|
group_read = 040,
|
|
group_write = 020,
|
|
group_exec = 010,
|
|
group_all = 070,
|
|
|
|
others_read = 04,
|
|
others_write = 02,
|
|
others_exec = 01,
|
|
others_all = 07,
|
|
|
|
all = 0777,
|
|
set_uid = 04000,
|
|
set_gid = 02000,
|
|
sticky_bit = 01000,
|
|
mask = 07777,
|
|
|
|
unknown = 0xffff,
|
|
|
|
add_perms = 0x10000,
|
|
remove_perms = 0x20000,
|
|
resolve_symlinks = 0x40000,
|
|
|
|
};
|
|
|
|
|
|
class file_status
|
|
{
|
|
public:
|
|
// constructors
|
|
explicit file_status(file_type ft = file_type::none, perms prms = perms::unknown) noexcept:
|
|
_ft(ft), _prms(prms) {}
|
|
|
|
file_status(const file_status&) noexcept = default;
|
|
file_status(file_status&&) noexcept = default;
|
|
~file_status() = default;
|
|
|
|
file_status& operator=(const file_status&) noexcept = default;
|
|
file_status& operator=(file_status&&) noexcept = default;
|
|
|
|
// observers
|
|
file_type type() const noexcept {
|
|
return _ft;
|
|
}
|
|
|
|
perms permissions() const noexcept {
|
|
return _prms;
|
|
}
|
|
|
|
// modifiers
|
|
void type(file_type ft) noexcept {
|
|
_ft = ft;
|
|
}
|
|
void permissions(perms prms) noexcept {
|
|
_prms = prms;
|
|
}
|
|
|
|
private:
|
|
file_type _ft = file_type::none;
|
|
perms _prms = perms::unknown;
|
|
};
|
|
|
|
|
|
struct space_info // returned by space function
|
|
{
|
|
uintmax_t capacity;
|
|
uintmax_t free;
|
|
uintmax_t available; // free space available to a non-privileged process
|
|
};
|
|
|
|
enum class directory_options
|
|
{
|
|
none,
|
|
follow_directory_symlink,
|
|
skip_permission_denied
|
|
};
|
|
|
|
//typedef std::chrono::time_point<trivial-clock> file_time_type;
|
|
typedef std::chrono::time_point<std::chrono::system_clock> file_time_type;
|
|
|
|
enum class copy_options
|
|
{
|
|
none = 0,
|
|
skip_existing = 1,
|
|
overwrite_existing = 2,
|
|
update_existing = 4,
|
|
recurive = 8,
|
|
copy_symlinks = 16,
|
|
skip_symlinks = 32,
|
|
directories_only = 64,
|
|
create_symlinks = 128,
|
|
create_hard_links = 256
|
|
};
|
|
|
|
path current_path();
|
|
path current_path(error_code& ec);
|
|
void current_path(const path& p);
|
|
void current_path(const path& p, error_code& ec) noexcept;
|
|
|
|
path absolute(const path& p, const path& base=current_path());
|
|
|
|
path canonical(const path& p, const path& base = current_path());
|
|
path canonical(const path& p, error_code& ec);
|
|
path canonical(const path& p, const path& base, error_code& ec);
|
|
|
|
void copy(const path& from, const path& to);
|
|
void copy(const path& from, const path& to, error_code& ec) noexcept;
|
|
void copy(const path& from, const path& to, copy_options options);
|
|
void copy(const path& from, const path& to, copy_options options, error_code& ec) noexcept;
|
|
|
|
bool copy_file(const path& from, const path& to);
|
|
bool copy_file(const path& from, const path& to, error_code& ec) noexcept;
|
|
bool copy_file(const path& from, const path& to, copy_options option);
|
|
bool copy_file(const path& from, const path& to, copy_options option, error_code& ec) noexcept;
|
|
void copy_symlink(const path& existing_symlink, const path& new_symlink);
|
|
|
|
void copy_symlink(const path& existing_symlink, const path& new_symlink, error_code& ec) noexcept;
|
|
|
|
bool create_directories(const path& p);
|
|
bool create_directories(const path& p, error_code& ec) noexcept;
|
|
|
|
bool create_directory(const path& p);
|
|
bool create_directory(const path& p, error_code& ec) noexcept;
|
|
bool create_directory(const path& p, const path& attributes);
|
|
bool create_directory(const path& p, const path& attributes, error_code& ec) noexcept;
|
|
|
|
void create_directory_symlink(const path& to, const path& new_symlink);
|
|
void create_directory_symlink(const path& to, const path& new_symlink, error_code& ec) noexcept;
|
|
|
|
void create_hard_link(const path& to, const path& new_hard_link);
|
|
void create_hard_link(const path& to, const path& new_hard_link, error_code& ec) noexcept;
|
|
|
|
void create_symlink(const path& to, const path& new_symlink);
|
|
void create_symlink(const path& to, const path& new_symlink, error_code& ec) noexcept;
|
|
|
|
|
|
|
|
|
|
file_status status(const path& p);
|
|
file_status status(const path& p, error_code& ec) noexcept;
|
|
|
|
file_status symlink_status(const path& p);
|
|
file_status symlink_status(const path& p, error_code& ec) noexcept;
|
|
|
|
inline bool status_known(file_status s) noexcept {
|
|
return s.type() != file_type::none;
|
|
}
|
|
|
|
inline bool exists(file_status s) noexcept {
|
|
return status_known(s) && s.type() != file_type::not_found;
|
|
}
|
|
|
|
inline bool exists(const path& p) {
|
|
return exists(status(p));
|
|
}
|
|
inline bool exists(const path& p, error_code& ec) noexcept {
|
|
return exists(status(p, ec));
|
|
}
|
|
|
|
|
|
bool equivalent(const path& p1, const path& p2);
|
|
bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
|
|
|
|
uintmax_t file_size(const path& p);
|
|
uintmax_t file_size(const path& p, error_code& ec) noexcept;
|
|
|
|
uintmax_t hard_link_count(const path& p);
|
|
uintmax_t hard_link_count(const path& p, error_code& ec) noexcept;
|
|
|
|
inline bool is_block_file(file_status s) noexcept {
|
|
return s.type() == file_type::block;
|
|
}
|
|
inline bool is_block_file(const path& p) {
|
|
return is_block_file(status(p));
|
|
}
|
|
inline bool is_block_file(const path& p, error_code& ec) noexcept {
|
|
return is_block_file(status(p, ec));
|
|
}
|
|
|
|
inline bool is_character_file(file_status s) noexcept {
|
|
return s.type() == file_type::character;
|
|
}
|
|
inline bool is_character_file(const path& p) {
|
|
return is_character_file(status(p));
|
|
}
|
|
inline bool is_character_file(const path& p, error_code& ec) noexcept {
|
|
return is_character_file(status(p, ec));
|
|
}
|
|
|
|
inline bool is_directory(file_status s) noexcept {
|
|
return s.type() == file_type::directory;
|
|
}
|
|
inline bool is_directory(const path& p) {
|
|
return is_directory(status(p));
|
|
}
|
|
inline bool is_directory(const path& p, error_code& ec) noexcept {
|
|
return is_directory(status(p, ec));
|
|
}
|
|
|
|
bool is_empty(const path& p);
|
|
bool is_empty(const path& p, error_code& ec) noexcept;
|
|
|
|
|
|
inline bool is_fifo(file_status s) noexcept {
|
|
return s.type() == file_type::fifo;
|
|
}
|
|
inline bool is_fifo(const path& p) {
|
|
return is_fifo(status(p));
|
|
}
|
|
inline bool is_fifo(const path& p, error_code& ec) noexcept {
|
|
return is_fifo(status(p, ec));
|
|
}
|
|
|
|
inline bool is_socket(file_status s) noexcept {
|
|
return s.type() == file_type::socket;
|
|
}
|
|
inline bool is_socket(const path& p) {
|
|
return is_socket(status(p));
|
|
}
|
|
inline bool is_socket(const path& p, error_code& ec) noexcept {
|
|
return is_socket(status(p, ec));
|
|
}
|
|
|
|
|
|
inline bool is_symlink(file_status s) noexcept {
|
|
return s.type() == file_type::symlink;
|
|
}
|
|
inline bool is_symlink(const path& p) {
|
|
return is_symlink(status(p));
|
|
}
|
|
inline bool is_symlink(const path& p, error_code& ec) noexcept {
|
|
return is_symlink(status(p, ec));
|
|
}
|
|
|
|
|
|
inline bool is_regular_file(file_status s) noexcept {
|
|
return s.type() == file_type::regular;
|
|
}
|
|
|
|
inline bool is_regular_file(const path& p) {
|
|
return is_regular_file(status(p));
|
|
}
|
|
|
|
inline bool is_regular_file(const path& p, error_code& ec) noexcept {
|
|
return is_regular_file(status(p, ec));
|
|
}
|
|
|
|
inline bool is_other(file_status s) noexcept {
|
|
return exists(s) && !is_regular_file(s) && ! is_directory(s) && !is_symlink(s);
|
|
}
|
|
|
|
inline bool is_other(const path& p) {
|
|
return is_other(status(p));
|
|
}
|
|
|
|
inline bool is_other(const path& p, error_code& ec) noexcept {
|
|
return is_other(status(p, ec));
|
|
}
|
|
|
|
|
|
|
|
|
|
file_time_type last_write_time(const path& p);
|
|
file_time_type last_write_time(const path& p, error_code& ec) noexcept;
|
|
void last_write_time(const path& p, file_time_type new_time);
|
|
void last_write_time(const path& p, file_time_type new_time, error_code& ec) noexcept;
|
|
|
|
void permissions(const path& p, perms prms);
|
|
void permissions(const path& p, perms prms, error_code& ec) noexcept;
|
|
|
|
path read_symlink(const path& p);
|
|
path read_symlink(const path& p, error_code& ec);
|
|
bool remove(const path& p);
|
|
bool remove(const path& p, error_code& ec) noexcept;
|
|
uintmax_t remove_all(const path& p);
|
|
uintmax_t remove_all(const path& p, error_code& ec) noexcept;
|
|
void rename(const path& from, const path& to);
|
|
void rename(const path& from, const path& to, error_code& ec) noexcept;
|
|
void resize_file(const path& p, uintmax_t size);
|
|
void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept;
|
|
space_info space(const path& p);
|
|
space_info space(const path& p, error_code& ec) noexcept;
|
|
file_status status(const path& p);
|
|
file_status status(const path& p, error_code& ec) noexcept;
|
|
bool status_known(file_status s) noexcept;
|
|
file_status symlink_status(const path& p);
|
|
file_status symlink_status(const path& p, error_code& ec) noexcept;
|
|
path system_complete(const path& p);
|
|
path system_complete(const path& p, error_code& ec);
|
|
path temp_directory_path();
|
|
path temp_directory_path(error_code& ec);
|
|
|
|
|
|
|
|
|
|
class directory_entry {
|
|
|
|
public:
|
|
|
|
// constructors and destructor
|
|
directory_entry() = default;
|
|
directory_entry(const directory_entry&) = default;
|
|
directory_entry(directory_entry&&) noexcept = default;
|
|
explicit directory_entry(const path& p, file_status st=file_status(), file_status symlink_st=file_status());
|
|
|
|
~directory_entry() = default;
|
|
|
|
// modifiers
|
|
directory_entry& operator=(const directory_entry&) = default;
|
|
directory_entry& operator=(directory_entry&&) noexcept = default;
|
|
void assign(const path& p, file_status st=file_status(),
|
|
file_status symlink_st=file_status());
|
|
void replace_filename(const path& p, file_status st=file_status(),
|
|
file_status symlink_st=file_status());
|
|
|
|
|
|
// observers
|
|
const filesystem::path& path() const noexcept {
|
|
return _path;
|
|
}
|
|
|
|
file_status status() const;
|
|
file_status status(error_code& ec) const noexcept;
|
|
file_status symlink_status() const;
|
|
file_status symlink_status(error_code& ec) const noexcept;
|
|
|
|
|
|
bool operator< (const directory_entry& rhs) const noexcept;
|
|
bool operator==(const directory_entry& rhs) const noexcept;
|
|
bool operator!=(const directory_entry& rhs) const noexcept;
|
|
bool operator<=(const directory_entry& rhs) const noexcept;
|
|
bool operator> (const directory_entry& rhs) const noexcept;
|
|
bool operator>=(const directory_entry& rhs) const noexcept;
|
|
|
|
|
|
private:
|
|
class path _path;
|
|
mutable file_status _st;
|
|
mutable file_status _lst;
|
|
};
|
|
|
|
|
|
class directory_iterator : public std::iterator<std::input_iterator_tag, directory_entry>
|
|
{
|
|
public:
|
|
// member functions
|
|
directory_iterator() noexcept = default;
|
|
explicit directory_iterator(const path& p);
|
|
directory_iterator(const path& p, error_code& ec) noexcept;
|
|
|
|
directory_iterator(const directory_iterator&) = default;
|
|
|
|
directory_iterator(directory_iterator&&) = default;
|
|
~directory_iterator() = default;
|
|
|
|
directory_iterator& operator=(const directory_iterator&) = default;
|
|
directory_iterator& operator=(directory_iterator&&) = default;
|
|
|
|
const directory_entry& operator*() const {
|
|
return _imp->_entry;
|
|
}
|
|
const directory_entry* operator->() const {
|
|
return &_imp->_entry;
|
|
}
|
|
directory_iterator& operator++();
|
|
directory_iterator& increment(error_code& ec) noexcept;
|
|
|
|
bool operator == (const directory_iterator &rhs) const noexcept {
|
|
return _imp == rhs._imp;
|
|
}
|
|
bool operator != (const directory_iterator &rhs) const noexcept {
|
|
return _imp != rhs._imp;
|
|
}
|
|
|
|
// other members as required by
|
|
// C++ Std, 24.1.1 Input iterators [input.iterators]
|
|
|
|
|
|
|
|
private:
|
|
|
|
void open_dir(const path &p, error_code &ec) noexcept;
|
|
|
|
struct imp {
|
|
path _path;
|
|
directory_entry _entry;
|
|
DIR *_dp = nullptr;
|
|
|
|
imp() = default;
|
|
imp(const path &p, DIR *dp) : _path(p), _dp(dp)
|
|
{}
|
|
|
|
~imp() {
|
|
if (_dp) closedir(_dp);
|
|
}
|
|
};
|
|
|
|
std::shared_ptr<imp> _imp;
|
|
};
|
|
|
|
|
|
/*
|
|
directory_iterator non-member functions
|
|
*/
|
|
inline const directory_iterator& begin(const directory_iterator& iter) noexcept {
|
|
return iter;
|
|
}
|
|
|
|
inline directory_iterator end(const directory_iterator&) noexcept {
|
|
return directory_iterator();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
namespace std
|
|
{
|
|
|
|
inline void swap(filesystem::path& lhs, filesystem::path& rhs) noexcept {
|
|
lhs.swap(rhs);
|
|
}
|
|
|
|
template<>
|
|
struct hash<filesystem::path>
|
|
{
|
|
std::size_t operator()(const filesystem::path &p) const
|
|
{
|
|
std::hash<filesystem::path::string_type> hasher;
|
|
return hasher(p.native());
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
#endif
|