// // Copyright (c) 2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_NOWIDE_QUOTED_HPP_INCLUDED #define BOOST_NOWIDE_QUOTED_HPP_INCLUDED #include #include #include #include #include #include #include #if defined(__cpp_lib_quoted_string_io) && __cpp_lib_quoted_string_io >= 201304 namespace boost { namespace nowide { /// \cond INTERNAL namespace detail { template struct quoted; template using remove_cvref_t = typename std::remove_cv::type>::type; } // namespace detail /// \endcond /// \brief Allows insertion and extraction of `filesystem::path` into/from streams. /// /// When used in an expression such as `out << quoted(path)`, where `out` is an output stream, /// has the effect as-if `out << std::quoted(path.native())` was used. /// /// When used in an expression like `in >> quoted(path)`, where `in` is an input stream, /// has the effect as-if `in >> std::quoted(path.native())` was used if that would be valid. /// To that effect a temporary string is used, which on success is assigned to `path`. /// /// Will automatically convert between the streams `char_type` and `path::value_type` if neccessary. template #ifdef BOOST_NOWIDE_DOXYGEN unspecified_type #else detail::enable_if_path_t, detail::quoted> #endif quoted(Path& path) { return {path}; } /// \cond INTERNAL // Same but for const-refs and r-values template detail::enable_if_path_t, detail::quoted> quoted(const Path& path) { return {path}; } namespace detail { template::value>::type> std::basic_string maybe_convert_string(const std::basic_string& s) { return utf::convert_string(s); } template const std::basic_string& maybe_convert_string(const std::basic_string& s) { return s; } template using requires_non_const = typename std::enable_if::type>::value>::type; template struct quoted { Path value; template friend std::basic_ostream& operator<<(std::basic_ostream& out, const quoted& path) { return out << std::quoted(maybe_convert_string(path.value.native())); } template> friend std::basic_istream& operator>>(std::basic_istream& in, const quoted& path) { std::basic_string value; using PlainPath = remove_cvref_t; if(in >> std::quoted(value)) path.value = PlainPath(maybe_convert_string(value)); return in; } }; } // namespace detail /// \endcond } // namespace nowide } // namespace boost #elif defined(BOOST_PRAGMA_MESSAGE) BOOST_PRAGMA_MESSAGE("To use boost::nowide::quoted at least C++14 is required.") #endif #endif