Boost.Nowide
quoted.hpp
1 //
2 // Copyright (c) 2023 Alexander Grund
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // https://www.boost.org/LICENSE_1_0.txt
6 
7 #ifndef BOOST_NOWIDE_QUOTED_HPP_INCLUDED
8 #define BOOST_NOWIDE_QUOTED_HPP_INCLUDED
9 
10 #include <boost/nowide/config.hpp>
11 #include <boost/nowide/detail/is_path.hpp>
12 #include <boost/nowide/utf/convert.hpp>
13 #include <iomanip>
14 #include <istream>
15 #include <ostream>
16 #include <type_traits>
17 
18 #if defined(__cpp_lib_quoted_string_io) && __cpp_lib_quoted_string_io >= 201304
19 
20 namespace boost {
21 namespace nowide {
23  namespace detail {
24  template<class Path>
25  struct quoted;
26  template<typename T>
27  using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
28 
29  } // namespace detail
31 
42  template<class Path>
43 #ifdef BOOST_NOWIDE_DOXYGEN
44  unspecified_type
45 #else
46  detail::enable_if_path_t<detail::remove_cvref_t<Path>, detail::quoted<Path&>>
47 #endif
48  quoted(Path& path)
49  {
50  return {path};
51  }
52 
54  // Same but for const-refs and r-values
55  template<class Path>
56  detail::enable_if_path_t<detail::remove_cvref_t<Path>, detail::quoted<const Path&>> quoted(const Path& path)
57  {
58  return {path};
59  }
60 
61  namespace detail {
62  template<typename CharOut,
63  typename CharIn,
64  typename = typename std::enable_if<!std::is_same<CharOut, CharIn>::value>::type>
65  std::basic_string<CharOut> maybe_convert_string(const std::basic_string<CharIn>& s)
66  {
67  return utf::convert_string<CharOut>(s);
68  }
69  template<typename Char>
70  const std::basic_string<Char>& maybe_convert_string(const std::basic_string<Char>& s)
71  {
72  return s;
73  }
74 
75  template<typename T>
76  using requires_non_const =
77  typename std::enable_if<!std::is_const<typename std::remove_reference<T>::type>::value>::type;
78 
79  template<class Path>
80  struct quoted
81  {
82  Path value;
83  template<typename CharType>
84  friend std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& out, const quoted& path)
85  {
86  return out << std::quoted(maybe_convert_string<CharType>(path.value.native()));
87  }
88 
89  template<typename CharType, class Path2 = Path, typename = requires_non_const<Path2>>
90  friend std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& in, const quoted& path)
91  {
92  std::basic_string<CharType> value;
93  using PlainPath = remove_cvref_t<Path>;
94  if(in >> std::quoted(value))
95  path.value = PlainPath(maybe_convert_string<typename PlainPath::value_type>(value));
96  return in;
97  }
98  };
99 
100  } // namespace detail
102 } // namespace nowide
103 } // namespace boost
104 
105 #elif defined(BOOST_PRAGMA_MESSAGE)
106 BOOST_PRAGMA_MESSAGE("To use boost::nowide::quoted at least C++14 is required.")
107 #endif
108 
109 #endif