Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:46

0001 //
0002 // Copyright (c) 2012 Artyom Beilis (Tonkikh)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // https://www.boost.org/LICENSE_1_0.txt
0006 
0007 #ifndef BOOST_NOWIDE_FSTREAM_HPP_INCLUDED
0008 #define BOOST_NOWIDE_FSTREAM_HPP_INCLUDED
0009 
0010 #include <boost/nowide/config.hpp>
0011 #include <boost/nowide/detail/is_path.hpp>
0012 #include <boost/nowide/filebuf.hpp>
0013 #include <istream>
0014 #include <ostream>
0015 #include <utility>
0016 
0017 namespace boost {
0018 namespace nowide {
0019     /// \cond INTERNAL
0020     namespace detail {
0021         // clang-format off
0022         struct StreamTypeIn
0023         {
0024             static std::ios_base::openmode mode() { return std::ios_base::in; }
0025             static std::ios_base::openmode mode_modifier() { return mode(); }
0026             template<typename CharType, typename Traits>
0027             struct stream_base{
0028                 using type = std::basic_istream<CharType, Traits>;
0029             };
0030         };
0031         struct StreamTypeOut
0032         {
0033             static std::ios_base::openmode mode() { return std::ios_base::out; }
0034             static std::ios_base::openmode mode_modifier() { return mode(); }
0035             template<typename CharType, typename Traits>
0036             struct stream_base{
0037                 using type = std::basic_ostream<CharType, Traits>;
0038             };
0039         };
0040         struct StreamTypeInOut
0041         {
0042             static std::ios_base::openmode mode() { return std::ios_base::in | std::ios_base::out; }
0043             static std::ios_base::openmode mode_modifier() { return std::ios_base::openmode(); }
0044             template<typename CharType, typename Traits>
0045             struct stream_base{
0046                 using type = std::basic_iostream<CharType, Traits>;
0047             };
0048         };
0049         // clang-format on
0050 
0051         /// Base class for all basic_*fstream classes
0052         /// Contains basic_filebuf instance so its pointer can be used to construct basic_*stream
0053         /// Provides common functions to reduce boilerplate code including inheriting from
0054         /// the correct std::basic_[io]stream class and initializing it
0055         /// \tparam T_StreamType One of StreamType* above.
0056         ///         Class used instead of value, because openmode::operator| may not be constexpr
0057         /// \tparam FileBufType Discriminator to force a differing ABI if depending on the contained filebuf
0058         template<typename CharType,
0059                  typename Traits,
0060                  typename T_StreamType,
0061                  int FileBufType = BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT>
0062         class fstream_impl;
0063 
0064     } // namespace detail
0065     /// \endcond
0066 
0067     ///
0068     /// \brief Same as std::basic_ifstream<char> but accepts UTF-8 strings under Windows
0069     ///
0070     /// Affected by #BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT and #BOOST_NOWIDE_USE_WCHAR_OVERLOADS
0071     template<typename CharType, typename Traits = std::char_traits<CharType>>
0072     class basic_ifstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeIn>
0073     {
0074         using fstream_impl = detail::fstream_impl<CharType, Traits, detail::StreamTypeIn>;
0075 
0076     public:
0077         basic_ifstream()
0078         {}
0079 
0080         explicit basic_ifstream(const char* file_name, std::ios_base::openmode mode = std::ios_base::in)
0081         {
0082             open(file_name, mode);
0083         }
0084 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
0085         explicit basic_ifstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::in)
0086         {
0087             open(file_name, mode);
0088         }
0089 #endif
0090 
0091         explicit basic_ifstream(const std::string& file_name, std::ios_base::openmode mode = std::ios_base::in)
0092         {
0093             open(file_name, mode);
0094         }
0095 
0096         template<typename Path>
0097         explicit basic_ifstream(const Path& file_name,
0098                                 detail::enable_if_path_t<Path, std::ios_base::openmode> mode = std::ios_base::in)
0099         {
0100             open(file_name, mode);
0101         }
0102         using fstream_impl::open;
0103         using fstream_impl::is_open;
0104         using fstream_impl::close;
0105         using fstream_impl::rdbuf;
0106         using fstream_impl::swap;
0107         basic_ifstream(const basic_ifstream&) = delete;
0108         basic_ifstream& operator=(const basic_ifstream&) = delete;
0109         basic_ifstream(basic_ifstream&& other) noexcept : fstream_impl(std::move(other))
0110         {}
0111         basic_ifstream& operator=(basic_ifstream&& rhs) noexcept
0112         {
0113             fstream_impl::operator=(std::move(rhs));
0114             return *this;
0115         }
0116     };
0117 
0118     ///
0119     /// \brief Same as std::basic_ofstream<char> but accepts UTF-8 strings under Windows
0120     ///
0121     /// Affected by #BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT and #BOOST_NOWIDE_USE_WCHAR_OVERLOADS
0122     template<typename CharType, typename Traits = std::char_traits<CharType>>
0123     class basic_ofstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeOut>
0124     {
0125         using fstream_impl = detail::fstream_impl<CharType, Traits, detail::StreamTypeOut>;
0126 
0127     public:
0128         basic_ofstream()
0129         {}
0130         explicit basic_ofstream(const char* file_name, std::ios_base::openmode mode = std::ios_base::out)
0131         {
0132             open(file_name, mode);
0133         }
0134 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
0135         explicit basic_ofstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::out)
0136         {
0137             open(file_name, mode);
0138         }
0139 #endif
0140         explicit basic_ofstream(const std::string& file_name, std::ios_base::openmode mode = std::ios_base::out)
0141         {
0142             open(file_name, mode);
0143         }
0144         template<typename Path>
0145         explicit basic_ofstream(const Path& file_name,
0146                                 detail::enable_if_path_t<Path, std::ios_base::openmode> mode = std::ios_base::out)
0147         {
0148             open(file_name, mode);
0149         }
0150 
0151         using fstream_impl::open;
0152         using fstream_impl::is_open;
0153         using fstream_impl::close;
0154         using fstream_impl::rdbuf;
0155         using fstream_impl::swap;
0156         basic_ofstream(const basic_ofstream&) = delete;
0157         basic_ofstream& operator=(const basic_ofstream&) = delete;
0158         basic_ofstream(basic_ofstream&& other) noexcept : fstream_impl(std::move(other))
0159         {}
0160         basic_ofstream& operator=(basic_ofstream&& rhs)
0161         {
0162             fstream_impl::operator=(std::move(rhs));
0163             return *this;
0164         }
0165     };
0166 
0167 #ifdef BOOST_MSVC
0168 #pragma warning(push)
0169 #pragma warning(disable : 4250) // <class> : inherits <method> via dominance
0170 #endif
0171     ///
0172     /// \brief Same as std::basic_fstream<char> but accepts UTF-8 strings under Windows
0173     ///
0174     /// Affected by #BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT and #BOOST_NOWIDE_USE_WCHAR_OVERLOADS
0175     template<typename CharType, typename Traits = std::char_traits<CharType>>
0176     class basic_fstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeInOut>
0177     {
0178         using fstream_impl = detail::fstream_impl<CharType, Traits, detail::StreamTypeInOut>;
0179 
0180     public:
0181         basic_fstream()
0182         {}
0183         explicit basic_fstream(const char* file_name,
0184                                std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
0185         {
0186             open(file_name, mode);
0187         }
0188 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
0189         explicit basic_fstream(const wchar_t* file_name,
0190                                std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
0191         {
0192             open(file_name, mode);
0193         }
0194 #endif
0195         explicit basic_fstream(const std::string& file_name,
0196                                std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
0197         {
0198             open(file_name, mode);
0199         }
0200         template<typename Path>
0201         explicit basic_fstream(const Path& file_name,
0202                                detail::enable_if_path_t<Path, std::ios_base::openmode> mode = std::ios_base::in
0203                                                                                               | std::ios_base::out)
0204         {
0205             open(file_name, mode);
0206         }
0207 
0208         using fstream_impl::open;
0209         using fstream_impl::is_open;
0210         using fstream_impl::close;
0211         using fstream_impl::rdbuf;
0212         using fstream_impl::swap;
0213         basic_fstream(const basic_fstream&) = delete;
0214         basic_fstream& operator=(const basic_fstream&) = delete;
0215         basic_fstream(basic_fstream&& other) noexcept : fstream_impl(std::move(other))
0216         {}
0217         basic_fstream& operator=(basic_fstream&& rhs)
0218         {
0219             fstream_impl::operator=(std::move(rhs));
0220             return *this;
0221         }
0222     };
0223 
0224     template<typename CharType, typename Traits>
0225     void swap(basic_ifstream<CharType, Traits>& lhs, basic_ifstream<CharType, Traits>& rhs)
0226     {
0227         lhs.swap(rhs);
0228     }
0229     template<typename CharType, typename Traits>
0230     void swap(basic_ofstream<CharType, Traits>& lhs, basic_ofstream<CharType, Traits>& rhs)
0231     {
0232         lhs.swap(rhs);
0233     }
0234     template<typename CharType, typename Traits>
0235     void swap(basic_fstream<CharType, Traits>& lhs, basic_fstream<CharType, Traits>& rhs)
0236     {
0237         lhs.swap(rhs);
0238     }
0239 
0240     ///
0241     /// Same as std::filebuf but accepts UTF-8 strings under Windows
0242     ///
0243     using filebuf = basic_filebuf<char>;
0244     ///
0245     /// Same as std::ifstream but accepts UTF-8 strings under Windows
0246     /// and *\::filesystem::path on all systems
0247     ///
0248     using ifstream = basic_ifstream<char>;
0249     ///
0250     /// Same as std::ofstream but accepts UTF-8 strings under Windows
0251     /// and *\::filesystem::path on all systems
0252     ///
0253     using ofstream = basic_ofstream<char>;
0254     ///
0255     /// Same as std::fstream but accepts UTF-8 strings under Windows
0256     /// and *\::filesystem::path on all systems
0257     ///
0258     using fstream = basic_fstream<char>;
0259 
0260     // Implementation
0261     namespace detail {
0262         /// Holds an instance of T
0263         /// Required to make sure this is constructed first before passing it to sibling classes
0264         template<typename T>
0265         struct buf_holder
0266         {
0267             T buf_;
0268         };
0269         template<typename CharType, typename Traits, typename T_StreamType, int>
0270         class fstream_impl : private buf_holder<basic_filebuf<CharType, Traits>>, // must be first due to init order
0271                              public T_StreamType::template stream_base<CharType, Traits>::type
0272         {
0273             using internal_buffer_type = basic_filebuf<CharType, Traits>;
0274             using base_buf_holder = buf_holder<internal_buffer_type>;
0275             using stream_base = typename T_StreamType::template stream_base<CharType, Traits>::type;
0276 
0277         public:
0278             using stream_base::setstate;
0279             using stream_base::clear;
0280 
0281         protected:
0282             using base_buf_holder::buf_;
0283 
0284             fstream_impl() : stream_base(&buf_)
0285             {}
0286             fstream_impl(const fstream_impl&) = delete;
0287             fstream_impl& operator=(const fstream_impl&) = delete;
0288 
0289             // coverity[exn_spec_violation]
0290             fstream_impl(fstream_impl&& other) noexcept :
0291                 base_buf_holder(std::move(other)), stream_base(std::move(other))
0292             {
0293                 this->set_rdbuf(rdbuf());
0294             }
0295             fstream_impl& operator=(fstream_impl&& rhs) noexcept
0296             {
0297                 base_buf_holder::operator=(std::move(rhs));
0298                 stream_base::operator=(std::move(rhs));
0299                 return *this;
0300             }
0301             void swap(fstream_impl& other)
0302             {
0303                 stream_base::swap(other);
0304                 rdbuf()->swap(*other.rdbuf());
0305             }
0306 
0307             void open(const std::string& file_name, std::ios_base::openmode mode = T_StreamType::mode())
0308             {
0309                 open(file_name.c_str(), mode);
0310             }
0311             template<typename Path>
0312             detail::enable_if_path_t<Path, void> open(const Path& file_name,
0313                                                       std::ios_base::openmode mode = T_StreamType::mode())
0314             {
0315                 open(file_name.c_str(), mode);
0316             }
0317             void open(const char* file_name, std::ios_base::openmode mode = T_StreamType::mode())
0318             {
0319                 if(!rdbuf()->open(file_name, mode | T_StreamType::mode_modifier()))
0320                     setstate(std::ios_base::failbit);
0321                 else
0322                     clear();
0323             }
0324 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
0325             void open(const wchar_t* file_name, std::ios_base::openmode mode = T_StreamType::mode())
0326             {
0327                 if(!rdbuf()->open(file_name, mode | T_StreamType::mode_modifier()))
0328                     setstate(std::ios_base::failbit);
0329                 else
0330                     clear();
0331             }
0332 #endif
0333             bool is_open()
0334             {
0335                 return rdbuf()->is_open();
0336             }
0337             bool is_open() const
0338             {
0339                 return rdbuf()->is_open();
0340             }
0341             void close()
0342             {
0343                 if(!rdbuf()->close())
0344                     setstate(std::ios_base::failbit);
0345             }
0346 
0347             internal_buffer_type* rdbuf() const
0348             {
0349                 return const_cast<internal_buffer_type*>(&buf_);
0350             }
0351         };
0352 #ifdef BOOST_MSVC
0353 #pragma warning(pop)
0354 #endif
0355     } // namespace detail
0356 } // namespace nowide
0357 } // namespace boost
0358 
0359 #endif