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
|
fixed_string.hpp
|
||||||
float.cpp
|
float.cpp
|
||||||
float.hpp
|
float.hpp
|
||||||
|
format/quoted.hpp
|
||||||
fourcc.cpp
|
fourcc.cpp
|
||||||
fourcc.hpp
|
fourcc.hpp
|
||||||
fs/scoped.cpp
|
fs/scoped.cpp
|
||||||
@ -730,6 +731,7 @@ if (TESTS)
|
|||||||
extent
|
extent
|
||||||
fixed
|
fixed
|
||||||
float
|
float
|
||||||
|
format/quoted
|
||||||
fs/scoped
|
fs/scoped
|
||||||
fs/tmp
|
fs/tmp
|
||||||
geom/aabb
|
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