diff options
Diffstat (limited to 'Utilities/std')
-rw-r--r-- | Utilities/std/cm/iomanip | 183 |
1 files changed, 183 insertions, 0 deletions
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 <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 + +#endif |