- format_to(some_char_array, ...) will now do the right thing for the most part, and also supports appending to existing ranges (using the same conceptual ideals as as std::ranges::to) - The API for format_to is a bit complicated since we do appending and also pass/support all the existing iterator-based use cases. - format_into is a cleaner API that accepts ranges and output iterators, and does not do appending for those ranges that it recognizes (just fills in the `[begin, end)`). This is necessary to avoid strange behaviors on whether or not a container may or may not meet the appending requirements (e.g., more consistent in generic code). - We lose a lot of compile-time performance with how we're checking things now, so not the best job we could be doing.... - Much of that compile-time performance can be gained back with more rigorous return-style enable_if and such, but that is beyond my work - Actual performance for the calls themselves are only marginally smaller for pointer-based iterators (fmt is, internally, lacking continguous iterator support. Counterpoint; buffers are the only case that matters! (this is a bit of a lie lmaoo))
193 lines
7.3 KiB
C++
193 lines
7.3 KiB
C++
// Formatting library for C++ - std::ostream support tests
|
|
//
|
|
// Copyright (c) 2012 - present, Victor Zverovich
|
|
// All rights reserved.
|
|
//
|
|
// For the license information refer to format.h.
|
|
|
|
#include "fmt/format.h"
|
|
|
|
#if FMT_OUTPUT_RANGES
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "gtest-extra.h"
|
|
#include "util.h"
|
|
|
|
#include <vector>
|
|
#include <list>
|
|
#include <deque>
|
|
#include <array>
|
|
#include <span>
|
|
|
|
TEST(output_range_c_array_char_test, format_into) {
|
|
char buffer[4];
|
|
buffer[3] = 'x';
|
|
auto result = fmt::format_into(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer + 3, result.begin());
|
|
EXPECT_EQ("abc", fmt::string_view(buffer, 3));
|
|
EXPECT_EQ("abcx", fmt::string_view(buffer, 4));
|
|
result = fmt::format_into(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer + 4, result.begin());
|
|
EXPECT_EQ("xabc", fmt::string_view(buffer, 4));
|
|
}
|
|
|
|
TEST(output_range_array_char_test, format_into) {
|
|
std::array<char, 4> buffer;
|
|
buffer[3] = 'x';
|
|
auto result = fmt::format_into(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer.begin() + 3, result.begin());
|
|
EXPECT_EQ("abc", fmt::string_view(buffer.data(), 3));
|
|
EXPECT_EQ("abcx", fmt::string_view(buffer.data(), 4));
|
|
result = fmt::format_into(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer.begin() + 4, result.begin());
|
|
EXPECT_EQ("xabc", fmt::string_view(buffer.data(), 4));
|
|
}
|
|
|
|
TEST(output_range_span_array_char_test, format_into) {
|
|
std::array<char, 4> storage;
|
|
std::span<char> buffer(storage);
|
|
buffer[3] = 'x';
|
|
auto result = fmt::format_into(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer.begin() + 3, result.begin());
|
|
EXPECT_EQ("abc", fmt::string_view(buffer.data(), 3));
|
|
EXPECT_EQ("abcx", fmt::string_view(buffer.data(), 4));
|
|
result = fmt::format_into(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer.begin() + 4, result.begin());
|
|
EXPECT_EQ("xabc", fmt::string_view(buffer.data(), 4));
|
|
}
|
|
|
|
TEST(output_range_vector_char_test, format_into) {
|
|
std::vector<char> buffer(4, '\0');
|
|
buffer[3] = 'x';
|
|
auto result = fmt::format_into(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer.begin() + 3, result.begin());
|
|
EXPECT_EQ("abc", fmt::string_view(buffer.data(), 3));
|
|
EXPECT_EQ("abcx", fmt::string_view(buffer.data(), 4));
|
|
result = fmt::format_into(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer.begin() + 4, result.begin());
|
|
EXPECT_EQ("xabc", fmt::string_view(buffer.data(), 4));
|
|
}
|
|
|
|
TEST(output_range_list_char_test, format_into) {
|
|
std::list<char> buffer(4, '\0');
|
|
using subrng = std::ranges::subrange<typename decltype(buffer)::iterator>;
|
|
auto fourth_it = std::ranges::next(buffer.begin(), 3);
|
|
auto end = buffer.end();
|
|
subrng first3_subrange(buffer.begin(), fourth_it);
|
|
*fourth_it = 'x';
|
|
auto result = fmt::format_into(buffer, "{}", "abc");
|
|
EXPECT_EQ(fourth_it, result.begin());
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("abc"), first3_subrange));
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("abcx"), buffer));
|
|
result = fmt::format_into(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(end, result.begin());
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("xabc"), buffer));
|
|
}
|
|
|
|
TEST(output_range_deque_char_test, format_into) {
|
|
std::deque<char> buffer(4, '\0');
|
|
using subrng = std::ranges::subrange<typename decltype(buffer)::iterator>;
|
|
auto fourth_it = std::ranges::next(buffer.begin(), 3);
|
|
auto end = buffer.end();
|
|
subrng first3_subrange(buffer.begin(), fourth_it);
|
|
*fourth_it = 'x';
|
|
auto result = fmt::format_into(buffer, "{}", "abc");
|
|
EXPECT_EQ(fourth_it, result.begin());
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("abc"), first3_subrange));
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("abcx"), buffer));
|
|
result = fmt::format_into(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(end, result.begin());
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("xabc"), buffer));
|
|
}
|
|
|
|
TEST(output_range_c_array_char_test, format_to) {
|
|
char buffer[4];
|
|
buffer[3] = 'x';
|
|
auto result = fmt::format_to(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer + 3, result.begin());
|
|
EXPECT_EQ("abc", fmt::string_view(buffer, 3));
|
|
EXPECT_EQ("abcx", fmt::string_view(buffer, 4));
|
|
result = fmt::format_to(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer + 4, result.begin());
|
|
EXPECT_EQ("xabc", fmt::string_view(buffer, 4));
|
|
}
|
|
|
|
TEST(output_range_array_char_test, format_to) {
|
|
std::array<char, 4> buffer;
|
|
buffer[3] = 'x';
|
|
auto result = fmt::format_to(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer.begin() + 3, result.begin());
|
|
EXPECT_EQ("abc", fmt::string_view(buffer.data(), 3));
|
|
EXPECT_EQ("abcx", fmt::string_view(buffer.data(), 4));
|
|
result = fmt::format_to(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer.begin() + 4, result.begin());
|
|
EXPECT_EQ("xabc", fmt::string_view(buffer.data(), 4));
|
|
}
|
|
|
|
TEST(output_range_span_array_char_test, format_to) {
|
|
std::array<char, 4> storage;
|
|
std::span<char> buffer(storage);
|
|
buffer[3] = 'x';
|
|
auto result = fmt::format_to(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer.begin() + 3, result.begin());
|
|
EXPECT_EQ("abc", fmt::string_view(buffer.data(), 3));
|
|
EXPECT_EQ("abcx", fmt::string_view(buffer.data(), 4));
|
|
result = fmt::format_to(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer.begin() + 4, result.begin());
|
|
EXPECT_EQ("xabc", fmt::string_view(buffer.data(), 4));
|
|
}
|
|
|
|
TEST(output_range_vector_char_test, format_to) {
|
|
std::vector<char> buffer{};
|
|
auto result = fmt::format_to(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer.begin() + 3, result.begin());
|
|
EXPECT_EQ("abc", fmt::string_view(buffer.data(), 3));
|
|
result = fmt::format_to(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer.begin() + 8, result.begin());
|
|
EXPECT_EQ(buffer.begin() + buffer.size(), result.begin());
|
|
EXPECT_EQ(buffer.end(), result.begin());
|
|
EXPECT_EQ("abcxabcy", fmt::string_view(buffer.data(), 8));
|
|
}
|
|
|
|
TEST(output_range_basic_string_char_test, format_to) {
|
|
std::string buffer{};
|
|
auto result = fmt::format_to(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer.begin() + 3, result.begin());
|
|
EXPECT_EQ("abc", buffer);
|
|
result = fmt::format_to(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer.begin() + 8, result.begin());
|
|
EXPECT_EQ(buffer.begin() + buffer.size(), result.begin());
|
|
EXPECT_EQ(buffer.end(), result.begin());
|
|
EXPECT_EQ("abcxabcy", buffer);
|
|
}
|
|
|
|
TEST(output_range_list_char_test, format_to) {
|
|
std::list<char> buffer{};
|
|
auto result = fmt::format_to(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer.end(), result.begin());
|
|
EXPECT_EQ(std::ranges::next(buffer.begin(), 3), result.begin());
|
|
EXPECT_EQ(std::ranges::next(buffer.begin(), buffer.size()), result.begin());
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("abc"), buffer));
|
|
result = fmt::format_to(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer.end(), result.begin());
|
|
EXPECT_EQ(std::ranges::next(buffer.begin(), 8), result.begin());
|
|
EXPECT_EQ(std::ranges::next(buffer.begin(), buffer.size()), result.begin());
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("abcxabcy"), buffer));
|
|
}
|
|
|
|
TEST(output_range_deque_char_test, format_to) {
|
|
std::deque<char> buffer{};
|
|
auto result = fmt::format_to(buffer, "{}", "abc");
|
|
EXPECT_EQ(buffer.end(), result.begin());
|
|
EXPECT_EQ(std::ranges::next(buffer.begin(), 3), result.begin());
|
|
EXPECT_EQ(std::ranges::next(buffer.begin(), buffer.size()), result.begin());
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("abc"), buffer));
|
|
result = fmt::format_to(buffer, "x{}y", "abc");
|
|
EXPECT_EQ(buffer.end(), result.begin());
|
|
EXPECT_EQ(std::ranges::next(buffer.begin(), 8), result.begin());
|
|
EXPECT_EQ(std::ranges::next(buffer.begin(), buffer.size()), result.begin());
|
|
EXPECT_TRUE(std::ranges::equal(fmt::string_view("abcxabcy"), buffer));
|
|
}
|
|
|
|
#endif
|