mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-22 10:30:05 +00:00
Added range_format::(debug_)string formatter (#3973)
This commit is contained in:
parent
1d9df9ce1c
commit
794df69c8c
@ -11,9 +11,13 @@
|
||||
#ifndef FMT_IMPORT_STD
|
||||
# include <initializer_list>
|
||||
# include <iterator>
|
||||
# include <string>
|
||||
# include <tuple>
|
||||
# include <type_traits>
|
||||
# include <utility>
|
||||
# ifdef __cpp_lib_ranges
|
||||
# include <ranges>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "format.h"
|
||||
@ -516,9 +520,11 @@ template <typename R, typename Char>
|
||||
struct formatter<
|
||||
R, Char,
|
||||
enable_if_t<conjunction<
|
||||
bool_constant<range_format_kind<R, Char>::value !=
|
||||
range_format::disabled &&
|
||||
range_format_kind<R, Char>::value != range_format::map>
|
||||
bool_constant<
|
||||
range_format_kind<R, Char>::value != range_format::disabled &&
|
||||
range_format_kind<R, Char>::value != range_format::map &&
|
||||
range_format_kind<R, Char>::value != range_format::string &&
|
||||
range_format_kind<R, Char>::value != range_format::debug_string>
|
||||
// Workaround a bug in MSVC 2015 and earlier.
|
||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
|
||||
,
|
||||
@ -607,6 +613,49 @@ struct formatter<
|
||||
}
|
||||
};
|
||||
|
||||
// A (debug_)string formatter.
|
||||
template <typename R, typename Char>
|
||||
struct formatter<
|
||||
R, Char,
|
||||
enable_if_t<range_format_kind<R, Char>::value == range_format::string ||
|
||||
range_format_kind<R, Char>::value ==
|
||||
range_format::debug_string>> {
|
||||
private:
|
||||
using range_type = detail::maybe_const_range<R>;
|
||||
#ifdef __cpp_lib_ranges
|
||||
using string_type = conditional_t<
|
||||
std::is_constructible_v<std::basic_string_view<Char>,
|
||||
std::ranges::iterator_t<range_type>,
|
||||
std::ranges::sentinel_t<range_type>>,
|
||||
std::basic_string_view<Char>, std::basic_string<Char>>;
|
||||
#else
|
||||
using string_type = std::basic_string<Char>;
|
||||
#endif
|
||||
|
||||
formatter<string_type, Char> underlying_;
|
||||
|
||||
public:
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return underlying_.parse(ctx);
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(range_type& range, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
if (detail::const_check(range_format_kind<R, Char>::value ==
|
||||
range_format::debug_string))
|
||||
*out++ = '"';
|
||||
out = underlying_.format(
|
||||
string_type{detail::range_begin(range), detail::range_end(range)}, ctx);
|
||||
if (detail::const_check(range_format_kind<R, Char>::value ==
|
||||
range_format::debug_string))
|
||||
*out++ = '"';
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename It, typename Sentinel, typename Char = char>
|
||||
struct join_view : detail::view {
|
||||
It begin;
|
||||
|
@ -268,6 +268,33 @@ TEST(ranges_test, disabled_range_formatting_of_path) {
|
||||
fmt::range_format::disabled);
|
||||
}
|
||||
|
||||
struct vector_string : std::vector<char> {
|
||||
using base = std::vector<char>;
|
||||
using base::base;
|
||||
};
|
||||
struct vector_debug_string : std::vector<char> {
|
||||
using base = std::vector<char>;
|
||||
using base::base;
|
||||
};
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <>
|
||||
struct range_format_kind<vector_string, char>
|
||||
: std::integral_constant<range_format, range_format::string> {};
|
||||
template <>
|
||||
struct range_format_kind<vector_debug_string, char>
|
||||
: std::integral_constant<range_format, range_format::debug_string> {};
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
TEST(ranges_test, range_format_string) {
|
||||
const vector_string v{'f', 'o', 'o'};
|
||||
EXPECT_EQ(fmt::format("{}", v), "foo");
|
||||
}
|
||||
|
||||
TEST(ranges_test, range_format_debug_string) {
|
||||
const vector_debug_string v{'f', 'o', 'o'};
|
||||
EXPECT_EQ(fmt::format("{}", v), "\"foo\"");
|
||||
}
|
||||
|
||||
// A range that provides non-const only begin()/end() to test fmt::join
|
||||
// handles that.
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user