mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-25 19:50: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
|
#ifndef FMT_IMPORT_STD
|
||||||
# include <initializer_list>
|
# include <initializer_list>
|
||||||
# include <iterator>
|
# include <iterator>
|
||||||
|
# include <string>
|
||||||
# include <tuple>
|
# include <tuple>
|
||||||
# include <type_traits>
|
# include <type_traits>
|
||||||
# include <utility>
|
# include <utility>
|
||||||
|
# ifdef __cpp_lib_ranges
|
||||||
|
# include <ranges>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
@ -516,9 +520,11 @@ template <typename R, typename Char>
|
|||||||
struct formatter<
|
struct formatter<
|
||||||
R, Char,
|
R, Char,
|
||||||
enable_if_t<conjunction<
|
enable_if_t<conjunction<
|
||||||
bool_constant<range_format_kind<R, Char>::value !=
|
bool_constant<
|
||||||
range_format::disabled &&
|
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::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.
|
// Workaround a bug in MSVC 2015 and earlier.
|
||||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
|
#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>
|
template <typename It, typename Sentinel, typename Char = char>
|
||||||
struct join_view : detail::view {
|
struct join_view : detail::view {
|
||||||
It begin;
|
It begin;
|
||||||
|
@ -268,6 +268,33 @@ TEST(ranges_test, disabled_range_formatting_of_path) {
|
|||||||
fmt::range_format::disabled);
|
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
|
// A range that provides non-const only begin()/end() to test fmt::join
|
||||||
// handles that.
|
// handles that.
|
||||||
//
|
//
|
||||||
|
Loading…
Reference in New Issue
Block a user