forked from fmtlib/fmt
Fix handling of output iterator in ranges
This commit is contained in:
@@ -55,21 +55,22 @@ struct formatting_tuple : formatting_base<Char> {
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename RangeT, typename OutputIterator>
|
template <typename RangeT, typename OutputIterator>
|
||||||
void copy(const RangeT& range, OutputIterator out) {
|
OutputIterator copy(const RangeT& range, OutputIterator out) {
|
||||||
for (auto it = range.begin(), end = range.end(); it != end; ++it)
|
for (auto it = range.begin(), end = range.end(); it != end; ++it)
|
||||||
*out++ = *it;
|
*out++ = *it;
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIterator>
|
template <typename OutputIterator>
|
||||||
void copy(const char* str, OutputIterator out) {
|
OutputIterator copy(const char* str, OutputIterator out) {
|
||||||
const char* p_curr = str;
|
while (*str) *out++ = *str++;
|
||||||
while (*p_curr) {
|
return out;
|
||||||
*out++ = *p_curr++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIterator> void copy(char ch, OutputIterator out) {
|
template <typename OutputIterator>
|
||||||
|
OutputIterator copy(char ch, OutputIterator out) {
|
||||||
*out++ = ch;
|
*out++ = ch;
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true value if T has std::string interface, like std::string_view.
|
/// Return true value if T has std::string interface, like std::string_view.
|
||||||
@@ -211,9 +212,9 @@ struct formatter<
|
|||||||
if (formatting.add_prepostfix_space) {
|
if (formatting.add_prepostfix_space) {
|
||||||
*out++ = ' ';
|
*out++ = ' ';
|
||||||
}
|
}
|
||||||
internal::copy(formatting.delimiter, out);
|
out = internal::copy(formatting.delimiter, out);
|
||||||
}
|
}
|
||||||
format_to(out,
|
out = format_to(out,
|
||||||
internal::format_str_quoted(
|
internal::format_str_quoted(
|
||||||
(formatting.add_delimiter_spaces && i > 0), v),
|
(formatting.add_delimiter_spaces && i > 0), v),
|
||||||
v);
|
v);
|
||||||
@@ -268,30 +269,24 @@ struct formatter<RangeT, Char,
|
|||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
typename FormatContext::iterator format(const RangeT& values,
|
typename FormatContext::iterator format(const RangeT& values,
|
||||||
FormatContext& ctx) {
|
FormatContext& ctx) {
|
||||||
auto out = ctx.out();
|
auto out = internal::copy(formatting.prefix, ctx.out());
|
||||||
internal::copy(formatting.prefix, out);
|
|
||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
for (auto it = values.begin(), end = values.end(); it != end; ++it) {
|
for (auto it = values.begin(), end = values.end(); it != end; ++it) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
if (formatting.add_prepostfix_space) {
|
if (formatting.add_prepostfix_space) *out++ = ' ';
|
||||||
*out++ = ' ';
|
out = internal::copy(formatting.delimiter, out);
|
||||||
}
|
}
|
||||||
internal::copy(formatting.delimiter, out);
|
out = format_to(out,
|
||||||
}
|
|
||||||
format_to(out,
|
|
||||||
internal::format_str_quoted(
|
internal::format_str_quoted(
|
||||||
(formatting.add_delimiter_spaces && i > 0), *it),
|
(formatting.add_delimiter_spaces && i > 0), *it),
|
||||||
*it);
|
*it);
|
||||||
if (++i > formatting.range_length_limit) {
|
if (++i > formatting.range_length_limit) {
|
||||||
format_to(out, " ... <other elements>");
|
out = format_to(out, " ... <other elements>");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (formatting.add_prepostfix_space) {
|
if (formatting.add_prepostfix_space) *out++ = ' ';
|
||||||
*out++ = ' ';
|
return internal::copy(formatting.postfix, out);
|
||||||
}
|
|
||||||
internal::copy(formatting.postfix, out);
|
|
||||||
return ctx.out();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -39,14 +39,14 @@ TEST(RangesTest, FormatMap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(RangesTest, FormatPair) {
|
TEST(RangesTest, FormatPair) {
|
||||||
std::pair<int64_t, float> pa1{42, 3.14159265358979f};
|
std::pair<int64_t, float> pa1{42, 1.5f};
|
||||||
EXPECT_EQ("(42, 3.14159)", fmt::format("{}", pa1));
|
EXPECT_EQ("(42, 1.5)", fmt::format("{}", pa1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RangesTest, FormatTuple) {
|
TEST(RangesTest, FormatTuple) {
|
||||||
std::tuple<int64_t, float, std::string, char> tu1{42, 3.14159265358979f,
|
std::tuple<int64_t, float, std::string, char> tu1{42, 1.5f,
|
||||||
"this is tuple", 'i'};
|
"this is tuple", 'i'};
|
||||||
EXPECT_EQ("(42, 3.14159, \"this is tuple\", 'i')", fmt::format("{}", tu1));
|
EXPECT_EQ("(42, 1.5, \"this is tuple\", 'i')", fmt::format("{}", tu1));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct my_struct {
|
struct my_struct {
|
||||||
@@ -80,5 +80,12 @@ TEST(RangesTest, FormatStruct) {
|
|||||||
EXPECT_EQ("(13, \"my struct\")", fmt::format("{}", mst));
|
EXPECT_EQ("(13, \"my struct\")", fmt::format("{}", mst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(RangesTest, FormatTo) {
|
||||||
|
char buf[10];
|
||||||
|
auto end = fmt::format_to(buf, "{}", std::vector{1, 2, 3});
|
||||||
|
*end = '\0';
|
||||||
|
EXPECT_STREQ(buf, "{1, 2, 3}");
|
||||||
|
}
|
||||||
|
|
||||||
#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >
|
#endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >
|
||||||
// 201402L && _MSC_VER >= 1910)
|
// 201402L && _MSC_VER >= 1910)
|
||||||
|
Reference in New Issue
Block a user