86 lines
2.4 KiB
C++
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());
|
|
}
|
|
};
|