libcruft-util/format/quoted.hpp

86 lines
2.4 KiB
C++

#pragma once
#include <fmt/format.h>
namespace cruft::format {
namespace detail {
/// A utility string container that is rendered enclosed in quotes when formatted.
template <typename string_type = std::string_view>
struct escaped_string {
/// The string that needs to be escaped
string_type source;
/// The character marking the beginning and end of the string that needs to be escaped
typename string_type::value_type delim;
/// The character that escapes other characters
typename string_type::value_type escape;
constexpr bool
escaped_character (char c) const
{
return delim == c or escape == c;
}
/// Copies the string characters to an output iterator, inserting
/// delim and escape characters as required.
template <typename OutputT>
constexpr
OutputT
copy (OutputT dst) const
{
*dst++ = delim;
for (const auto& c : source) {
if (escaped_character (c))
*dst++ = escape;
*dst++ = c;
}
*dst++ = delim;
return dst;
}
};
}
/// Returns an object that will be enclosed between delimiters. All
/// occurrences of this delimiter will be escaped with the supplied
/// character (as will occurences of this escape character).
constexpr
auto
quoted (
std::string_view source,
char delim = '"',
char escape = '\\'
) {
return cruft::format::detail::escaped_string<
std::string_view
> {
.source = source,
.delim = delim,
.escape = escape,
};
}
}
///////////////////////////////////////////////////////////////////////////////
template <typename string_type>
struct fmt::formatter<cruft::format::detail::escaped_string<string_type>> {
constexpr
format_parse_context::iterator
parse (fmt::format_parse_context ctx) const
{
return ctx.begin();
}
constexpr
format_context::iterator
format(
cruft::format::detail::escaped_string<string_type> const& val,
format_context & ctx
) const {
return val.copy (ctx.out());
}
};