// -*-c++-*- // vim: set ft=cpp: /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once #include // IWYU pragma: export #if __cplusplus < 201402L || defined(_MSVC_LANG) && _MSVC_LANG < 201402L # include # include # include # include # include #endif #if __cplusplus < 201703L || defined(_MSVC_LANG) && _MSVC_LANG < 201703L # include #endif namespace cm { #if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L using std::quoted; # if __cplusplus < 201703L || defined(_MSVC_LANG) && _MSVC_LANG < 201703L inline auto quoted(cm::string_view str, char delim = '"', char escape = '\\') { return std::quoted(static_cast(str), delim, escape); } # endif #else namespace internals { // Struct for delimited strings. template struct quoted_string { static_assert(std::is_reference::value || std::is_pointer::value, "String type must be pointer or reference"); quoted_string(String str, Char del, Char esc) : string_(str) , delim_{ del } , escape_{ esc } { } quoted_string& operator=(quoted_string&) = delete; String string_; Char delim_; Char escape_; }; template <> struct quoted_string { quoted_string(cm::string_view str, char del, char esc) : string_(str) , delim_{ del } , escape_{ esc } { } quoted_string& operator=(quoted_string&) = delete; cm::string_view string_; char delim_; char escape_; }; template std::basic_ostream& operator<<( std::basic_ostream& os, const quoted_string& str) { std::basic_ostringstream ostr; ostr << str.delim_; for (const Char* c = str.string_; *c; ++c) { if (*c == str.delim_ || *c == str.escape_) ostr << str.escape_; ostr << *c; } ostr << str.delim_; return os << ostr.str(); } template std::basic_ostream& operator<<( std::basic_ostream& os, const quoted_string& str) { std::basic_ostringstream ostr; ostr << str.delim_; for (auto c : str.string_) { if (c == str.delim_ || c == str.escape_) ostr << str.escape_; ostr << c; } ostr << str.delim_; return os << ostr.str(); } template std::basic_istream& operator>>( std::basic_istream& is, const quoted_string&, Char>& str) { Char c; is >> c; if (!is.good()) return is; if (c != str.delim_) { is.unget(); is >> str.string_; return is; } str.string_.clear(); std::ios_base::fmtflags flags = is.flags(is.flags() & ~std::ios_base::skipws); do { is >> c; if (!is.good()) break; if (c == str.escape_) { is >> c; if (!is.good()) break; } else if (c == str.delim_) break; str.string_ += c; } while (true); is.setf(flags); return is; } } template inline internals::quoted_string quoted( const Char* str, Char delim = Char('"'), Char escape = Char('\\')) { return internals::quoted_string(str, delim, escape); } template inline internals::quoted_string&, Char> quoted(const std::basic_string& str, Char delim = Char('"'), Char escape = Char('\\')) { return internals::quoted_string< const std::basic_string&, Char>(str, delim, escape); } template inline internals::quoted_string&, Char> quoted(std::basic_string& str, Char delim = Char('"'), Char escape = Char('\\')) { return internals::quoted_string&, Char>(str, delim, escape); } inline internals::quoted_string quoted( cm::string_view str, char delim = '"', char escape = '\\') { return internals::quoted_string(str, delim, escape); } #endif } // namespace cm