diff --git a/cmake/asyncpp-options.cmake b/cmake/asyncpp-options.cmake index 5e406d4..99b9a77 100644 --- a/cmake/asyncpp-options.cmake +++ b/cmake/asyncpp-options.cmake @@ -9,6 +9,9 @@ Option ( ASYNCPP_INSTALL_PACKAGE Option ( ASYNCPP_USE_GIT_VERSION "Read the git tags to get the version of asyncpp" ON ) -Option ( ASYNCPP_FEATURE_TIMING_ENABLED +Option ( ASYNCPP_ENABLE_FEATURE_FS + "Enable the file system features of asyncpp" + ON ) +Option ( ASYNCPP_ENABLE_FEATURE_TIMING "Enable the timing features of asyncpp" ON ) diff --git a/cmake/config.h.in b/cmake/config.h.in index 85fe7b8..3794232 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -1,3 +1,4 @@ #pragma once -#cmakedefine ASYNCPP_FEATURE_TIMING_ENABLED +#cmakedefine ASYNCPP_ENABLE_FEATURE_FS +#cmakedefine ASYNCPP_ENABLE_FEATURE_TIMING diff --git a/include/asyncpp.h b/include/asyncpp.h index 3e57fa6..c31bfef 100644 --- a/include/asyncpp.h +++ b/include/asyncpp.h @@ -4,6 +4,10 @@ #include -#ifdef ASYNCPP_FEATURE_TIMING_ENABLED +#ifdef ASYNCPP_ENABLE_FEATURE_FS + #include +#endif + +#ifdef ASYNCPP_ENABLE_FEATURE_TIMING #include #endif diff --git a/include/asyncpp/core/future.h b/include/asyncpp/core/future.h index 706ef96..053e11e 100644 --- a/include/asyncpp/core/future.h +++ b/include/asyncpp/core/future.h @@ -6,6 +6,6 @@ #include "future/lazy.inl" #include "future/and_then.inl" -#ifdef ASYNCPP_FEATURE_TIMING_ENABLED +#ifdef ASYNCPP_ENABLE_FEATURE_TIMING #include "future/timeout.inl" #endif diff --git a/include/asyncpp/core/future/future.h b/include/asyncpp/core/future/future.h index 18ca90c..b9dc196 100644 --- a/include/asyncpp/core/future/future.h +++ b/include/asyncpp/core/future/future.h @@ -57,7 +57,7 @@ namespace asyncpp typename X_lambda> inline auto and_then(X_lambda&& p_lambda) &&; - #ifdef ASYNCPP_FEATURE_TIMING_ENABLED + #ifdef ASYNCPP_ENABLE_FEATURE_TIMING public: /** * @brief Throw an execption if the timeout has passed. diff --git a/include/asyncpp/core/stream.h b/include/asyncpp/core/stream.h index e120ad9..74df535 100644 --- a/include/asyncpp/core/stream.h +++ b/include/asyncpp/core/stream.h @@ -6,6 +6,6 @@ #include "stream/flatten.inl" #include "stream/for_each.inl" -#ifdef ASYNCPP_FEATURE_TIMING_ENABLED +#ifdef ASYNCPP_ENABLE_FEATURE_TIMING #include "stream/timeout.inl" #endif diff --git a/include/asyncpp/core/stream/stream.h b/include/asyncpp/core/stream/stream.h index 9b13b62..e013a0d 100644 --- a/include/asyncpp/core/stream/stream.h +++ b/include/asyncpp/core/stream/stream.h @@ -75,7 +75,7 @@ namespace asyncpp chaining_mode X_mode = move> inline auto flatten() &&; - #ifdef ASYNCPP_FEATURE_TIMING_ENABLED + #ifdef ASYNCPP_ENABLE_FEATURE_TIMING public: /** * @brief Throw an execption if the timeout has passed. diff --git a/include/asyncpp/fs.h b/include/asyncpp/fs.h index 5d95a8e..b66a439 100644 --- a/include/asyncpp/fs.h +++ b/include/asyncpp/fs.h @@ -1,5 +1,3 @@ #pragma once #include "fs/directory.h" - -#include "fs/directory.inl" diff --git a/include/asyncpp/fs/directory.h b/include/asyncpp/fs/directory.h index 7749920..095ee6a 100644 --- a/include/asyncpp/fs/directory.h +++ b/include/asyncpp/fs/directory.h @@ -1,42 +1,11 @@ #pragma once -#include - -#include - -#include - -namespace asyncpp { -namespace fs { - - /** - * @brief Create future to read the content of a directory. - */ - inline auto read_dir(const cppfs::path& p_path); - - /** - * @brief Create future to read the content of a directory including the subdirectories. - */ - inline auto read_dir_all(const cppfs::path& p_path); - - /** - * @brief Create a new future to create a directory. - */ - inline auto create_dir(const cppfs::path& p_path); - - /** - * @brief Create a new future to create a directory and all it's parent directories. - */ - inline auto create_dir_all(const cppfs::path& p_path); - - /** - * @brief Create a new future to remove an empty directory. - */ - inline auto remove_dir(const cppfs::path& p_path); - - /** - * @brief Create a new future to remove a directory and all it's content. - */ - inline auto remove_dir_all(const cppfs::path& p_path); - -} } +#include "directory/directory.h" + +#include "directory/directory.inl" +#include "directory/create.inl" +#include "directory/create_all.inl" +#include "directory/read.inl" +#include "directory/read_all.inl" +#include "directory/remove.inl" +#include "directory/remove_all.inl" diff --git a/include/asyncpp/fs/directory.inl b/include/asyncpp/fs/directory.inl deleted file mode 100644 index 975f4e3..0000000 --- a/include/asyncpp/fs/directory.inl +++ /dev/null @@ -1,167 +0,0 @@ -#pragma once - -#include - -#include - -#include "directory.h" - -namespace asyncpp { -namespace fs { - - namespace __impl - { - - struct read_dir_impl - : public base_stream< - cppfs::directory::entry, - read_dir_impl> - { - public: - using value_type = cppfs::directory::entry; - using this_type = read_dir_impl; - using base_future_type = base_stream; - using result_type = typename base_future_type::result_type; - - private: - cppfs::directory::iterator _it; - cppfs::directory::iterator _end; - - public: - inline read_dir_impl( - const cppfs::path& p_path) - { - cppfs::directory d(p_path); - if (d.exists()) - { - _it = d.begin(); - _end = d.end(); - } - } - - public: - inline result_type poll() - { - if (_it == _end) - return result_type::done(); - - auto ret = result_type::ready(*_it); - ++_it; - return ret; - } - }; - - struct read_dir_all_impl - : public base_stream< - cppfs::directory::entry, - read_dir_all_impl> - { - public: - using value_type = cppfs::directory::entry; - using this_type = read_dir_impl; - using base_future_type = base_stream; - using result_type = typename base_future_type::result_type; - - private: - struct entry - { - cppfs::directory::iterator it; - cppfs::directory::iterator end; - }; - - using entry_stack = std::vector; - - entry_stack _stack; - - public: - inline read_dir_all_impl( - const cppfs::path& p_path) - { - cppfs::directory d(p_path); - if (d.exists()) - { - _stack.emplace_back(entry { - d.begin(), - d.end() - }); - } - } - - public: - inline result_type poll() - { - while (true) - { - if (_stack.empty()) - return result_type::done(); - - auto& e = _stack.back(); - if (e.it == e.end) - { - _stack.pop_back(); - continue; - } - - auto ret = result_type::ready(std::move(*e.it)); - cppfs::directory d(e.it->path); - - ++e.it; - - if (d.exists()) - { - _stack.emplace_back(entry { - d.begin(), - d.end(), - }); - } - - return ret; - } - } - }; - - } - - auto read_dir(const cppfs::path& p_path) - { - return __impl::read_dir_impl(p_path); - } - - auto read_dir_all(const cppfs::path& p_path) - { - return __impl::read_dir_all_impl(p_path); - } - - auto create_dir(const cppfs::path& p_path) - { - return lazy([d = cppfs::directory(p_path)]{ - if (!d.exists()) - d.create(false); - }); - } - - auto create_dir_all(const cppfs::path& p_path) - { - return lazy([d = cppfs::directory(p_path)]{ - if (!d.exists()) - d.create(true); - }); - } - - auto remove_dir(const cppfs::path& p_path) - { - return lazy([d = cppfs::directory(p_path)]{ - if (d.exists()) - d.remove(false); - }); - } - - auto remove_dir_all(const cppfs::path& p_path) - { - return lazy([d = cppfs::directory(p_path)]{ - if (d.exists()) - d.remove(true); - }); - } - -} } diff --git a/include/asyncpp/fs/directory/create.inl b/include/asyncpp/fs/directory/create.inl new file mode 100644 index 0000000..725ef81 --- /dev/null +++ b/include/asyncpp/fs/directory/create.inl @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include "directory.h" + +namespace asyncpp { +namespace fs { +namespace __directory { + + template< + chaining_mode X_mode, + typename X_self> + inline auto create_impl(X_self&& p_self) + { + return lazy([self = std::forward(p_self)] { + if (!self.handle.exists()) + self.handle.create(false); + + return self; // TODO: use std::forward + }); + } + +} } } + +namespace asyncpp { +namespace fs { + + /* directory::create */ + + template + auto directory + ::create() & + { + return __directory::create_impl(*this); + } + + template + auto directory + ::create() && + { + static_assert( + X_mode != ref, + "Can not store rvalue reference as lvalue reference!"); + + return __directory::create_impl(std::move(*this)); + } + +} } diff --git a/include/asyncpp/fs/directory/create_all.inl b/include/asyncpp/fs/directory/create_all.inl new file mode 100644 index 0000000..bef3069 --- /dev/null +++ b/include/asyncpp/fs/directory/create_all.inl @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include "directory.h" + +namespace asyncpp { +namespace fs { +namespace __directory { + + template< + chaining_mode X_mode, + typename X_self> + inline auto create_all_impl(X_self&& p_self) + { + return lazy([self = std::forward(p_self)] { + if (!self.handle.exists()) + self.handle.create(true); + + return self; // TODO: use std::forward + }); + } + +} } } + +namespace asyncpp { +namespace fs { + + /* directory::create */ + + template + auto directory + ::create_all() & + { + return __directory::create_all_impl(*this); + } + + template + auto directory + ::create_all() && + { + static_assert( + X_mode != ref, + "Can not store rvalue reference as lvalue reference!"); + + return __directory::create_all_impl(std::move(*this)); + } + +} } diff --git a/include/asyncpp/fs/directory/directory.h b/include/asyncpp/fs/directory/directory.h new file mode 100644 index 0000000..f5798d6 --- /dev/null +++ b/include/asyncpp/fs/directory/directory.h @@ -0,0 +1,100 @@ +#pragma once + +#include + +#include + +namespace asyncpp { +namespace fs { + + struct directory + { + public: + cppfs::directory handle; + + public: + /** + * @brief Constructor. + */ + inline directory(const cppfs::path& p_path); + + public: + /** + * @brief Create a new future to create a directory. + */ + template + inline auto create() &; + + /** + * @brief Create a new future to create a directory. + */ + template + inline auto create() &&; + + public: + /** + * @brief Create a new future to create a directory and all it's parent directories. + */ + template + inline auto create_all() &; + + /** + * @brief Create a new future to create a directory and all it's parent directories. + */ + template + inline auto create_all() &&; + + public: + /** + * @brief Create future to read the content of a directory. + */ + template + inline auto read() &; + + /** + * @brief Create future to read the content of a directory. + */ + template + inline auto read() &&; + + public: + /** + * @brief Create future to read the content of a directory including the subdirectories. + */ + template + inline auto read_all() &; + + /** + * @brief Create future to read the content of a directory including the subdirectories. + */ + template + inline auto read_all() &&; + + public: + /** + * @brief Create a new future to remove an empty directory. + */ + template + inline auto remove() &; + + /** + * @brief Create a new future to remove an empty directory. + */ + template + inline auto remove() &&; + + public: + /** + * @brief Create a new future to remove a directory and all it's content. + */ + template + inline auto remove_all() &; + + /** + * @brief Create a new future to remove a directory and all it's content. + */ + template + inline auto remove_all() &&; + }; + +} } diff --git a/include/asyncpp/fs/directory/directory.inl b/include/asyncpp/fs/directory/directory.inl new file mode 100644 index 0000000..e444c6e --- /dev/null +++ b/include/asyncpp/fs/directory/directory.inl @@ -0,0 +1,14 @@ +#pragma once + +#include "directory.h" + +namespace asyncpp { +namespace fs { + + /* directory */ + + inline directory::directory(const cppfs::path& p_path) + : handle(p_path) + { } + +} } diff --git a/include/asyncpp/fs/directory/read.inl b/include/asyncpp/fs/directory/read.inl new file mode 100644 index 0000000..18cb5b4 --- /dev/null +++ b/include/asyncpp/fs/directory/read.inl @@ -0,0 +1,80 @@ +#pragma once + +#include + +#include "directory.h" + +namespace asyncpp { +namespace fs { +namespace __directory { + + struct read_stream + : public base_stream< + cppfs::directory::entry, + read_stream> + { + public: + using value_type = cppfs::directory::entry; + using this_type = read_stream; + using base_future_type = base_stream; + using result_type = typename base_future_type::result_type; + + private: + cppfs::directory::iterator _it; + cppfs::directory::iterator _end; + + public: + inline read_stream( + const fs::directory& p_directory) + { + auto& d = p_directory.handle; + if (d.exists()) + { + _it = d.begin(); + _end = d.end(); + } + } + + public: + inline result_type poll() + { + if (_it == _end) + return result_type::done(); + + auto ret = result_type::ready(*_it); + ++_it; + + return ret; + } + }; + + template< + chaining_mode X_mode, + typename X_self> + inline auto read_impl(X_self&& p_self) + { return read_stream(std::forward(p_self)); } + +} } } + +namespace asyncpp { +namespace fs { + + template + auto directory + ::read() & + { + return __directory::read_impl(*this); + } + + template + auto directory + ::read() && + { + static_assert( + X_mode != ref, + "Can not store rvalue reference as lvalue reference!"); + + return __directory::read_impl(std::move(*this)); + } + +} } diff --git a/include/asyncpp/fs/directory/read_all.inl b/include/asyncpp/fs/directory/read_all.inl new file mode 100644 index 0000000..56a69bb --- /dev/null +++ b/include/asyncpp/fs/directory/read_all.inl @@ -0,0 +1,111 @@ +#pragma once + +#include + +#include + +#include "directory.h" + +namespace asyncpp { +namespace fs { +namespace __directory { + + struct read_all_stream + : public base_stream< + cppfs::directory::entry, + read_all_stream> + { + public: + using value_type = cppfs::directory::entry; + using this_type = read_all_stream; + using base_future_type = base_stream; + using result_type = typename base_future_type::result_type; + + private: + struct entry + { + cppfs::directory::iterator it; + cppfs::directory::iterator end; + }; + + using entry_stack = std::vector; + + entry_stack _stack; + + public: + inline read_all_stream( + const fs::directory& p_directory) + { + auto& d = p_directory.handle; + if (d.exists()) + { + _stack.emplace_back(entry { + d.begin(), + d.end() + }); + } + } + + public: + inline result_type poll() + { + while (true) + { + if (_stack.empty()) + return result_type::done(); + + auto& e = _stack.back(); + if (e.it == e.end) + { + _stack.pop_back(); + continue; + } + + auto ret = result_type::ready(std::move(*e.it)); + cppfs::directory d(e.it->path); + + ++e.it; + + if (d.exists()) + { + _stack.emplace_back(entry { + d.begin(), + d.end(), + }); + } + + return ret; + } + } + }; + + template< + chaining_mode X_mode, + typename X_self> + inline auto read_all_impl(X_self&& p_self) + { return read_all_stream(std::forward(p_self)); } + +} } } + +namespace asyncpp { +namespace fs { + + template + auto directory + ::read_all() & + { + return __directory::read_all_impl(*this); + } + + template + auto directory + ::read_all() && + { + static_assert( + X_mode != ref, + "Can not store rvalue reference as lvalue reference!"); + + return __directory::read_all_impl(std::move(*this)); + } + +} } diff --git a/include/asyncpp/fs/directory/remove.inl b/include/asyncpp/fs/directory/remove.inl new file mode 100644 index 0000000..bf28805 --- /dev/null +++ b/include/asyncpp/fs/directory/remove.inl @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include "directory.h" + +namespace asyncpp { +namespace fs { +namespace __directory { + + template< + chaining_mode X_mode, + typename X_self> + inline auto remove_impl(X_self&& p_self) + { + return lazy([self = std::forward(p_self)] { + if (self.handle.exists()) + self.handle.remove(false); + + return self; // TODO: use std::forward + }); + } + +} } } + +namespace asyncpp { +namespace fs { + + /* directory::remove */ + + template + auto directory + ::remove() & + { + return __directory::remove_impl(*this); + } + + template + auto directory + ::remove() && + { + static_assert( + X_mode != ref, + "Can not store rvalue reference as lvalue reference!"); + + return __directory::remove_impl(std::move(*this)); + } + +} } diff --git a/include/asyncpp/fs/directory/remove_all.inl b/include/asyncpp/fs/directory/remove_all.inl new file mode 100644 index 0000000..f121f4a --- /dev/null +++ b/include/asyncpp/fs/directory/remove_all.inl @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include "directory.h" + +namespace asyncpp { +namespace fs { +namespace __directory { + + template< + chaining_mode X_mode, + typename X_self> + inline auto remove_all_impl(X_self&& p_self) + { + return lazy([self = std::forward(p_self)] { + if (self.handle.exists()) + self.handle.remove(true); + + return self; // TODO: use std::forward + }); + } + +} } } + +namespace asyncpp { +namespace fs { + + /* directory::create */ + + template + auto directory + ::remove_all() & + { + return __directory::remove_all_impl(*this); + } + + template + auto directory + ::remove_all() && + { + static_assert( + X_mode != ref, + "Can not store rvalue reference as lvalue reference!"); + + return __directory::remove_all_impl(std::move(*this)); + } + +} } diff --git a/include/asyncpp/timing.h b/include/asyncpp/timing.h index 7472958..95f5f74 100644 --- a/include/asyncpp/timing.h +++ b/include/asyncpp/timing.h @@ -1,6 +1,6 @@ #pragma once -#define ASYNCPP_FEATURE_TIMING_ENABLED +#define ASYNCPP_ENABLE_FEATURE_TIMING #include "timing/delay.h" #include "timing/interval.h" diff --git a/test/asyncpp/fs/directory_tests.cpp b/test/asyncpp/fs/directory_tests.cpp index 679bfe4..0bf0488 100644 --- a/test/asyncpp/fs/directory_tests.cpp +++ b/test/asyncpp/fs/directory_tests.cpp @@ -67,7 +67,7 @@ TEST_F(directory_tests, read_dir) using namespace cppfs; using namespace std::string_literals; - auto s = fs::read_dir("."s); + auto s = fs::directory("."s).read(); auto v = std::vector(); auto r = decltype(s)::result_type::not_ready(); @@ -89,7 +89,7 @@ TEST_F(directory_tests, read_dir_all) using namespace cppfs; using namespace std::string_literals; - auto s = fs::read_dir_all("."s); + auto s = fs::directory("."s).read_all(); auto r = decltype(s)::result_type::not_ready(); auto entries = std::vector(); @@ -137,11 +137,8 @@ TEST_F(directory_tests, read_dir_all) TEST_F(directory_tests, create_dir) { - auto f = - lazy([path=path_test_dir_single()]{ - return path; - }) - .and_then(fs::create_dir); + auto f = fs::directory(path_test_dir_single()) + .create(); auto_remove_dir d(path_test_dir_single()); @@ -155,11 +152,8 @@ TEST_F(directory_tests, create_dir) TEST_F(directory_tests, create_dir_all) { - auto f = - lazy([path=path_test_dir_child()]{ - return path; - }) - .and_then(fs::create_dir_all); + auto f = fs::directory(path_test_dir_child()) + .create_all(); auto_remove_dir d(path_test_dir_child()); @@ -173,11 +167,8 @@ TEST_F(directory_tests, create_dir_all) TEST_F(directory_tests, remove_dir) { - auto f = - lazy([path=path_test_dir_single()]{ - return path; - }) - .and_then(fs::remove_dir); + auto f = fs::directory(path_test_dir_single()) + .remove(); auto_remove_dir d(path_test_dir_single()); d.create(true); @@ -192,11 +183,8 @@ TEST_F(directory_tests, remove_dir) TEST_F(directory_tests, remove_dir_all) { - auto f = - lazy([path=path_test_dir_parent()]{ - return path; - }) - .and_then(fs::remove_dir_all); + auto f = fs::directory(path_test_dir_child()) + .remove_all(); auto_remove_dir d(path_test_dir_child()); d.create(true);