diff --git a/doc/core.qbk b/doc/core.qbk index fd677c4..8e2d1a3 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -60,6 +60,7 @@ criteria for inclusion is that the utility component be: [include noinit_adaptor.qbk] [include noncopyable.qbk] [include null_deleter.qbk] +[include fclose_deleter.qbk] [include nvp.qbk] [include pointer_traits.qbk] [include quick_exit.qbk] diff --git a/doc/fclose_deleter.qbk b/doc/fclose_deleter.qbk new file mode 100644 index 0000000..30dd913 --- /dev/null +++ b/doc/fclose_deleter.qbk @@ -0,0 +1,34 @@ +[/ + / Copyright (c) 2022 Andrey Semashev + / + / Distributed under the Boost Software License, Version 1.0. (See accompanying + / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:fclose_deleter fclose_deleter] + +[simplesect Authors] + +* Andrey Semashev + +[endsimplesect] + +[section Header ] + +The header `` defines the `boost::fclose_deleter` function object, +which can be used as a deleter with smart pointers such as `unique_ptr` or `shared_ptr` pointing to `std::FILE`. +structures returned by `std::fopen` calls. The deleter calls `std::fclose` on the passed pointer, causing +the file stream to be flushed and closed. + +[section Example] +`` +std::unique_ptr< std::FILE, boost::fclose_deleter > make_file(const char* filename, const char* open_mode) +{ + return { std::fopen(filename, open_mode) }; +} +`` +[endsect] + +[endsect] + +[endsect] diff --git a/include/boost/core/fclose_deleter.hpp b/include/boost/core/fclose_deleter.hpp new file mode 100644 index 0000000..7a0d34a --- /dev/null +++ b/include/boost/core/fclose_deleter.hpp @@ -0,0 +1,45 @@ +/* + * Copyright Andrey Semashev 2022. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file fclose_deleter.hpp + * \author Andrey Semashev + * \date 21.09.2022 + * + * This header contains an \c fclose_deleter implementation. This is a deleter + * function object that invokes std::fclose on the passed pointer to + * a std::FILE structure. + */ + +#ifndef BOOST_CORE_FCLOSE_DELETER_HPP +#define BOOST_CORE_FCLOSE_DELETER_HPP + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +//! A function object that closes a file +struct fclose_deleter +{ + //! Function object result type + typedef void result_type; + /*! + * Closes the file handle + */ + void operator() (std::FILE* p) const BOOST_NOEXCEPT + { + std::fclose(p); + } +}; + +} // namespace boost + +#endif // BOOST_CORE_FCLOSE_DELETER_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 94b465e..a601332 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -186,6 +186,9 @@ compile-fail scoped_enum_compile_fail_conv_to_int.cpp run underlying_type.cpp ; +compile fclose_deleter_test.cpp + : windows:_CRT_SECURE_NO_WARNINGS windows:_CRT_SECURE_NO_DEPRECATE ; + run pointer_traits_pointer_test.cpp ; run pointer_traits_element_type_test.cpp ; run pointer_traits_difference_type_test.cpp ; diff --git a/test/fclose_deleter_test.cpp b/test/fclose_deleter_test.cpp new file mode 100644 index 0000000..dbe85a5 --- /dev/null +++ b/test/fclose_deleter_test.cpp @@ -0,0 +1,52 @@ +/* + * Copyright Andrey Semashev 2022. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file fclose_deleter_test.cpp + * \author Andrey Semashev + * \date 21.09.2022 + * + * This file contains tests for \c boost::fclose_deleter. + */ + +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#endif + +#if !defined(BOOST_NO_CXX11_SMART_PTR) +std::unique_ptr< std::FILE, boost::fclose_deleter > make_unique_file(const char* filename) +{ + return std::unique_ptr< std::FILE, boost::fclose_deleter >(std::fopen(filename, "w")); +} + +std::shared_ptr< std::FILE > make_shared_file(const char* filename) +{ + return std::shared_ptr< std::FILE >(std::fopen(filename, "w"), boost::fclose_deleter()); +} +#endif + +int main() +{ + const char* const filename = "fcd_test.txt"; + + std::FILE* file = std::fopen(filename, "w"); + if (file) + { + boost::fclose_deleter()(file); + file = NULL; + } + +#if !defined(BOOST_NO_CXX11_SMART_PTR) + make_unique_file(filename); + make_shared_file(filename); +#endif + + std::remove(filename); +} diff --git a/test/quick.cpp b/test/quick.cpp index f82d77b..fdfe983 100644 --- a/test/quick.cpp +++ b/test/quick.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include