diff --git a/build.cc b/build.cc index 0efe88a..445fcc7 100644 --- a/build.cc +++ b/build.cc @@ -66,8 +66,8 @@ static fs::path OSTD_SHARED_LIB = "libostd.so"; static fs::path OSTD_STATIC_LIB = "libostd.a"; static std::string DEFAULT_CXXFLAGS = "-std=c++1z -I. -O2 -Wall -Wextra " - "-Wshadow -Wold-style-cast -fPIC "; - "-D_FILE_OFFSET_BITS=64" + "-Wshadow -Wold-style-cast -fPIC " + "-D_FILE_OFFSET_BITS=64"; static std::string DEFAULT_LDFLAGS = "-pthread"; static std::string DEFAULT_ASFLAGS = "-fPIC"; diff --git a/ostd/path.hh b/ostd/path.hh index 5f93485..4d63cd6 100644 --- a/ostd/path.hh +++ b/ostd/path.hh @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -724,6 +725,51 @@ private: }; namespace detail { + struct OSTD_EXPORT dir_range_impl { + void open(path const &p); + void close() noexcept; + void read_next(); + + bool empty() const noexcept { + return p_current.path().empty(); + } + + directory_entry const &front() const noexcept { + return p_current; + } + + ~dir_range_impl() { + close(); + } + + directory_entry p_current{}; + path p_dir{}; + void *p_handle = nullptr; + }; + + struct OSTD_EXPORT rdir_range_impl { + using hstack = std::stack>; + + void open(path const &p); + void close() noexcept; + void read_next(); + + bool empty() const noexcept { + return p_current.path().empty(); + } + + directory_entry const &front() const noexcept { + return p_current; + } + + ~rdir_range_impl() { + close(); + } + + directory_entry p_current{}; + path p_dir{}; + hstack p_handles{}; + }; } struct directory_range: input_range { @@ -733,47 +779,26 @@ struct directory_range: input_range { using size_type = std::size_t; directory_range() = delete; - directory_range(path const &p) { - open(p); - } - - directory_range(directory_range const &r): - p_current(r.p_current), p_dir(r.p_dir), - p_handle(r.p_handle), p_owned(false) - {} - - ~directory_range() { - close(); - } - - directory_range &operator=(directory_range const &r) noexcept { - close(); - p_handle = r.p_handle; - p_owned = false; - return *this; + directory_range(path const &p): + p_impl{std::make_shared()} + { + p_impl->open(p); } bool empty() const noexcept { - return p_current.path().empty(); + return p_impl->empty(); } void pop_front() { - read_next(); + p_impl->read_next(); } reference front() const noexcept { - return p_current; + return p_impl->front(); } private: - OSTD_EXPORT void open(path const &p); - OSTD_EXPORT void close() noexcept; - OSTD_EXPORT void read_next(); - - directory_entry p_current{}; - path p_dir{}; - void *p_handle = nullptr; - bool p_owned = false; + std::shared_ptr p_impl; }; struct recursive_directory_range: input_range { @@ -783,52 +808,26 @@ struct recursive_directory_range: input_range { using size_type = std::size_t; recursive_directory_range() = delete; - recursive_directory_range(path const &p) { - open(p); - } - - recursive_directory_range(recursive_directory_range const &r): - p_current(r.p_current), p_dir(r.p_dir), - p_stack(r.p_stack), p_owned(false) - {} - - ~recursive_directory_range() { - close(); - } - - recursive_directory_range &operator=( - recursive_directory_range const &r - ) noexcept { - close(); - p_stack = r.p_stack; - p_owned = false; - return *this; + recursive_directory_range(path const &p): + p_impl{std::make_shared()} + { + p_impl->open(p); } bool empty() const noexcept { - return p_current.path().empty(); + return p_impl->empty(); } void pop_front() { - read_next(); + p_impl->read_next(); } reference front() const noexcept { - return p_current; + return p_impl->front(); } private: - using hstack = std::stack>; - - OSTD_EXPORT void open(path const &p); - OSTD_EXPORT void close() noexcept; - OSTD_EXPORT void read_next(); - - directory_entry p_current{}; - path p_dir{}; - hstack p_handles{}; - hstack *p_stack = nullptr; - bool p_owned = false; + std::shared_ptr p_impl; }; OSTD_EXPORT path cwd(); diff --git a/src/posix/path.cc b/src/posix/path.cc index e0d43c7..810b7c5 100644 --- a/src/posix/path.cc +++ b/src/posix/path.cc @@ -11,6 +11,7 @@ namespace ostd { namespace fs { +namespace detail { static void dir_read_next(DIR *dh, directory_entry &cur, path const &base) { struct dirent d; @@ -37,7 +38,7 @@ static void dir_read_next(DIR *dh, directory_entry &cur, path const &base) { /* dir range */ -OSTD_EXPORT void directory_range::open(path const &p) { +OSTD_EXPORT void dir_range_impl::open(path const &p) { DIR *d = opendir(p.string().data()); if (!d) { /* FIXME: throw */ @@ -45,50 +46,39 @@ OSTD_EXPORT void directory_range::open(path const &p) { } p_dir = p; p_handle = d; - p_owned = true; read_next(); } -OSTD_EXPORT void directory_range::close() noexcept { - if (!p_owned) { - return; - } +OSTD_EXPORT void dir_range_impl::close() noexcept { closedir(static_cast(p_handle)); - p_owned = false; } -OSTD_EXPORT void directory_range::read_next() { +OSTD_EXPORT void dir_range_impl::read_next() { dir_read_next(static_cast(p_handle), p_current, p_dir); } /* recursive dir range */ -OSTD_EXPORT void recursive_directory_range::open(path const &p) { +OSTD_EXPORT void rdir_range_impl::open(path const &p) { DIR *d = opendir(p.string().data()); if (!d) { /* FIXME: throw */ abort(); } p_dir = p; - p_stack = &p_handles; - p_stack->push(d); - p_owned = true; + p_handles.push(d); read_next(); } -OSTD_EXPORT void recursive_directory_range::close() noexcept { - if (!p_owned) { - return; - } +OSTD_EXPORT void rdir_range_impl::close() noexcept { while (!p_handles.empty()) { closedir(static_cast(p_handles.top())); p_handles.pop(); } - p_owned = false; } -OSTD_EXPORT void recursive_directory_range::read_next() { - if (p_stack->empty()) { +OSTD_EXPORT void rdir_range_impl::read_next() { + if (p_handles.empty()) { return; } struct stat sb; @@ -106,7 +96,7 @@ OSTD_EXPORT void recursive_directory_range::read_next() { dir_read_next(nd, curd, based); if (!curd.path().empty()) { p_dir = based; - p_stack->push(nd); + p_handles.push(nd); p_current = curd; return; } else { @@ -114,20 +104,21 @@ OSTD_EXPORT void recursive_directory_range::read_next() { } } /* didn't recurse into a directory, go to next file */ - dir_read_next(static_cast(p_stack->top()), p_current, p_dir); + dir_read_next(static_cast(p_handles.top()), p_current, p_dir); /* end of dir, pop while at it */ if (p_current.path().empty()) { - closedir(static_cast(p_stack->top())); - p_stack->pop(); - if (!p_stack->empty()) { + closedir(static_cast(p_handles.top())); + p_handles.pop(); + if (!p_handles.empty()) { /* got back to another dir, read next so it's valid */ p_dir.remove_name(); - dir_read_next(static_cast(p_stack->top()), p_current, p_dir); + dir_read_next(static_cast(p_handles.top()), p_current, p_dir); } else { p_current.clear(); } } } +} /* namespace detail */ } /* namesapce fs */ } /* namespace ostd */