From 4408f34cfe5edc76faa1ea974a0225316cfbc702 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Sun, 21 Jun 2020 14:27:46 +0200 Subject: STL Support: Add function cm::quoted in --- Help/dev/source.rst | 3 + Utilities/std/cm/iomanip | 183 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 Utilities/std/cm/iomanip diff --git a/Help/dev/source.rst b/Help/dev/source.rst index 0ccb8f4..5fbc9fa 100644 --- a/Help/dev/source.rst +++ b/Help/dev/source.rst @@ -35,6 +35,9 @@ Available features are: * From ``C++14``: + * ````: + ``cm::quoted`` + * ````: ``cm::make_reverse_iterator``, ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, ``cm::crbegin``, ``cm::crend`` diff --git a/Utilities/std/cm/iomanip b/Utilities/std/cm/iomanip new file mode 100644 index 0000000..6f68530 --- /dev/null +++ b/Utilities/std/cm/iomanip @@ -0,0 +1,183 @@ +// -*-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. */ +#ifndef cm_iomanip +#define cm_iomanip + +#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 + +#endif -- cgit v0.12