Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:49:04

0001 //
0002 // Copyright (c) 2023 Alexander Grund
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_QUOTED_HPP_INCLUDED
0008 #define BOOST_NOWIDE_QUOTED_HPP_INCLUDED
0009 
0010 #include <boost/nowide/config.hpp>
0011 #include <boost/nowide/detail/is_path.hpp>
0012 #include <boost/nowide/utf/convert.hpp>
0013 #include <iomanip>
0014 #include <istream>
0015 #include <ostream>
0016 #include <type_traits>
0017 
0018 #if defined(__cpp_lib_quoted_string_io) && __cpp_lib_quoted_string_io >= 201304
0019 
0020 namespace boost {
0021 namespace nowide {
0022     /// \cond INTERNAL
0023     namespace detail {
0024         template<class Path>
0025         struct quoted;
0026         template<typename T>
0027         using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
0028 
0029     } // namespace detail
0030     /// \endcond
0031 
0032     /// \brief Allows insertion and extraction of `filesystem::path` into/from streams.
0033     ///
0034     /// When used in an expression such as `out << quoted(path)`, where `out` is an output stream,
0035     /// has the effect as-if `out << std::quoted(path.native())` was used.
0036     ///
0037     /// When used in an expression like `in >> quoted(path)`, where `in` is an input stream,
0038     /// has the effect as-if `in >> std::quoted(path.native())` was used if that would be valid.
0039     /// To that effect a temporary string is used, which on success is assigned to `path`.
0040     ///
0041     /// Will automatically convert between the streams `char_type` and `path::value_type` if neccessary.
0042     template<class Path>
0043 #ifdef BOOST_NOWIDE_DOXYGEN
0044     unspecified_type
0045 #else
0046     detail::enable_if_path_t<detail::remove_cvref_t<Path>, detail::quoted<Path&>>
0047 #endif
0048     quoted(Path& path)
0049     {
0050         return {path};
0051     }
0052 
0053     /// \cond INTERNAL
0054     // Same but for const-refs and r-values
0055     template<class Path>
0056     detail::enable_if_path_t<detail::remove_cvref_t<Path>, detail::quoted<const Path&>> quoted(const Path& path)
0057     {
0058         return {path};
0059     }
0060 
0061     namespace detail {
0062         template<typename CharOut,
0063                  typename CharIn,
0064                  typename = typename std::enable_if<!std::is_same<CharOut, CharIn>::value>::type>
0065         std::basic_string<CharOut> maybe_convert_string(const std::basic_string<CharIn>& s)
0066         {
0067             return utf::convert_string<CharOut>(s);
0068         }
0069         template<typename Char>
0070         const std::basic_string<Char>& maybe_convert_string(const std::basic_string<Char>& s)
0071         {
0072             return s;
0073         }
0074 
0075         template<typename T>
0076         using requires_non_const =
0077           typename std::enable_if<!std::is_const<typename std::remove_reference<T>::type>::value>::type;
0078 
0079         template<class Path>
0080         struct quoted
0081         {
0082             Path value;
0083             template<typename CharType>
0084             friend std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& out, const quoted& path)
0085             {
0086                 return out << std::quoted(maybe_convert_string<CharType>(path.value.native()));
0087             }
0088 
0089             template<typename CharType, class Path2 = Path, typename = requires_non_const<Path2>>
0090             friend std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& in, const quoted& path)
0091             {
0092                 std::basic_string<CharType> value;
0093                 using PlainPath = remove_cvref_t<Path>;
0094                 if(in >> std::quoted(value))
0095                     path.value = PlainPath(maybe_convert_string<typename PlainPath::value_type>(value));
0096                 return in;
0097             }
0098         };
0099 
0100     } // namespace detail
0101     /// \endcond
0102 } // namespace nowide
0103 } // namespace boost
0104 
0105 #elif defined(BOOST_PRAGMA_MESSAGE)
0106 BOOST_PRAGMA_MESSAGE("To use boost::nowide::quoted at least C++14 is required.")
0107 #endif
0108 
0109 #endif