format: add 'quoted' helper function that emulates std::quoted
This commit is contained in:
parent
fffd584c93
commit
aaa00bc989
@ -352,6 +352,7 @@ list (
|
||||
fixed_string.hpp
|
||||
float.cpp
|
||||
float.hpp
|
||||
format/quoted.hpp
|
||||
fourcc.cpp
|
||||
fourcc.hpp
|
||||
fs/scoped.cpp
|
||||
@ -730,6 +731,7 @@ if (TESTS)
|
||||
extent
|
||||
fixed
|
||||
float
|
||||
format/quoted
|
||||
fs/scoped
|
||||
fs/tmp
|
||||
geom/aabb
|
||||
|
85
format/quoted.hpp
Normal file
85
format/quoted.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
#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());
|
||||
}
|
||||
};
|
32
test/format/quoted.cpp
Normal file
32
test/format/quoted.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include <cruft/util/format/quoted.hpp>
|
||||
|
||||
#include <cruft/util/tap.hpp>
|
||||
|
||||
|
||||
int main ()
|
||||
{
|
||||
static constexpr struct {
|
||||
std::string_view format;
|
||||
std::string_view inner;
|
||||
std::string_view result;
|
||||
std::string_view message;
|
||||
} TESTS[] = {
|
||||
{ "{}", "Foo", R"("Foo")", "Simple word" },
|
||||
{ "{}", "F\"oo", R"("F\"oo")", "Embedded delim" },
|
||||
{ "{}", "F\\oo", R"("F\\oo")", "Embedded escape" },
|
||||
};
|
||||
|
||||
cruft::TAP::logger tap;
|
||||
|
||||
for (auto const &t: TESTS) {
|
||||
auto const result = fmt::vformat (
|
||||
t.format,
|
||||
fmt::make_format_args (
|
||||
cruft::format::quoted (t.inner)
|
||||
)
|
||||
);
|
||||
tap.expect_eq (result, t.result, "quoted format: {}", t.message);
|
||||
}
|
||||
|
||||
return tap.status ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user