| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- // -*-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 <iomanip> // IWYU pragma: export
- #if __cplusplus < 201402L || defined(_MSVC_LANG) && _MSVC_LANG < 201402L
- # include <ios>
- # include <iostream>
- # include <sstream>
- # include <string>
- # include <type_traits>
- #endif
- #if __cplusplus < 201703L || defined(_MSVC_LANG) && _MSVC_LANG < 201703L
- # include <cm/string_view>
- #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<std::string>(str), delim, escape);
- }
- # endif
- #else
- namespace internals {
- // Struct for delimited strings.
- template <typename String, typename Char>
- struct quoted_string
- {
- static_assert(std::is_reference<String>::value ||
- std::is_pointer<String>::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<cm::string_view, char>
- {
- 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 <typename Char, typename Traits>
- std::basic_ostream<Char, Traits>& operator<<(
- std::basic_ostream<Char, Traits>& os,
- const quoted_string<const Char*, Char>& str)
- {
- std::basic_ostringstream<Char, Traits> 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 <typename Char, typename Traits, typename String>
- std::basic_ostream<Char, Traits>& operator<<(
- std::basic_ostream<Char, Traits>& os, const quoted_string<String, Char>& str)
- {
- std::basic_ostringstream<Char, Traits> 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 <typename Char, typename Traits, typename Alloc>
- std::basic_istream<Char, Traits>& operator>>(
- std::basic_istream<Char, Traits>& is,
- const quoted_string<std::basic_string<Char, Traits, Alloc>&, 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 <typename Char>
- inline internals::quoted_string<const Char*, Char> quoted(
- const Char* str, Char delim = Char('"'), Char escape = Char('\\'))
- {
- return internals::quoted_string<const Char*, Char>(str, delim, escape);
- }
- template <typename Char, typename Traits, typename Alloc>
- inline internals::quoted_string<const std::basic_string<Char, Traits, Alloc>&,
- Char>
- quoted(const std::basic_string<Char, Traits, Alloc>& str,
- Char delim = Char('"'), Char escape = Char('\\'))
- {
- return internals::quoted_string<
- const std::basic_string<Char, Traits, Alloc>&, Char>(str, delim, escape);
- }
- template <typename Char, typename Traits, typename Alloc>
- inline internals::quoted_string<std::basic_string<Char, Traits, Alloc>&, Char>
- quoted(std::basic_string<Char, Traits, Alloc>& str, Char delim = Char('"'),
- Char escape = Char('\\'))
- {
- return internals::quoted_string<std::basic_string<Char, Traits, Alloc>&,
- Char>(str, delim, escape);
- }
- inline internals::quoted_string<cm::string_view, char> quoted(
- cm::string_view str, char delim = '"', char escape = '\\')
- {
- return internals::quoted_string<cm::string_view, char>(str, delim, escape);
- }
- #endif
- } // namespace cm
|