diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b039498..e5af6fc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -344,6 +344,8 @@ list ( float.hpp fourcc.cpp fourcc.hpp + fs/scoped.cpp + fs/scoped.hpp fs/tmp_posix.cpp fs/tmp.hpp functor.hpp diff --git a/fs/scoped.cpp b/fs/scoped.cpp new file mode 100644 index 00000000..f4f12c36 --- /dev/null +++ b/fs/scoped.cpp @@ -0,0 +1,51 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2022, Danny Robson + */ + +#include "./scoped.hpp" + +#include + +using cruft::fs::scoped_dir; + + +/////////////////////////////////////////////////////////////////////////////// +scoped_dir::scoped_dir (std::filesystem::path const &_path) + : scoped_dir (std::filesystem::path (_path)) +{} + + +//----------------------------------------------------------------------------- +scoped_dir::scoped_dir (std::filesystem::path &&_path) + : m_path (std::move (_path)) +{ + CHECK (std::filesystem::is_directory (*m_path)); +} + + +/////////////////////////////////////////////////////////////////////////////// +scoped_dir::~scoped_dir () +{ + if (m_path) + std::filesystem::remove_all (*m_path); +} + + +/////////////////////////////////////////////////////////////////////////////// +std::filesystem::path const & +scoped_dir::operator* () const & +{ + return *m_path; +} + + +//----------------------------------------------------------------------------- +std::filesystem::path const* +scoped_dir::operator-> () const & +{ + return &*m_path; +} diff --git a/fs/scoped.hpp b/fs/scoped.hpp new file mode 100644 index 00000000..dcccad2c --- /dev/null +++ b/fs/scoped.hpp @@ -0,0 +1,37 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2022, Danny Robson + */ + +#include +#include + + +/////////////////////////////////////////////////////////////////////////////// +namespace cruft::fs { + ///------------------------------------------------------------------------ + /// Holds the path to a directory that will be deleted (along with all + /// contents) when the object goes out of scope. + class scoped_dir { + public: + explicit scoped_dir (std::filesystem::path const&); + explicit scoped_dir (std::filesystem::path &&); + + scoped_dir (scoped_dir const&) = delete; + scoped_dir& operator= (scoped_dir const&) = delete; + + scoped_dir (scoped_dir&&) noexcept = default; + scoped_dir& operator= (scoped_dir&&) noexcept = default; + + ~scoped_dir (); + + std::filesystem::path const& operator* () const&; + std::filesystem::path const* operator-> () const&; + + private: + std::optional m_path; + }; +} \ No newline at end of file diff --git a/test/fs/scoped.cpp b/test/fs/scoped.cpp new file mode 100644 index 00000000..35f6a16c --- /dev/null +++ b/test/fs/scoped.cpp @@ -0,0 +1,26 @@ +#include +#include +#include + + +int +main (int, char**) +{ + cruft::TAP::logger tap; + + { + bool success = true; + auto const path = cruft::fs::mktmpdir (); + + { + cruft::fs::scoped_dir dir (path); + success = success && std::filesystem::is_directory (path); + } + + success = success && !exists(path); + + tap.expect (success, "scoped_dir removes directory after scope"); + } + + return tap.status (); +} \ No newline at end of file