Consistent behavior of operator<<
The (templated) operator<< defined in ostream.h currently prevents efficient
handling of some basic types in BasicWriter. E.g.:
MemoryWriter w;
w << std::string("hello");
calls this operator (if visible). This will unneccessarily construct a
std::ostream object using a FormatBuf as its streambuf and insert the string
into the std::ostream object. (The same is true for float and some other
built-in types.) The write_str method in BasicWriter basically does the same
using a cheap memcpy.
Fix this performance problem by providing additional overloads of operator<<.
This commit is contained in:
parent
5d9a88f83a
commit
7458bb7fe0
314
fmt/format.h
314
fmt/format.h
@ -1155,6 +1155,9 @@ struct NamedArgWithType;
|
||||
template <typename T = void>
|
||||
struct Null {};
|
||||
|
||||
template <typename T = void>
|
||||
struct Incomplete; // never defined.
|
||||
|
||||
// A helper class template to enable or disable overloads taking wide
|
||||
// characters and strings in MakeValue.
|
||||
template <typename T, typename Char>
|
||||
@ -2590,10 +2593,6 @@ class BasicWriter : public BasicWriterBase {
|
||||
*/
|
||||
virtual ~BasicWriter() {}
|
||||
|
||||
void clear() FMT_NOEXCEPT { buffer_.clear(); }
|
||||
|
||||
Buffer<Char> &buffer() FMT_NOEXCEPT { return buffer_; }
|
||||
|
||||
/**
|
||||
Returns the total number of characters written.
|
||||
*/
|
||||
@ -2666,7 +2665,7 @@ class BasicWriter : public BasicWriterBase {
|
||||
write_int(spec.value(), spec);
|
||||
}
|
||||
|
||||
template <typename Float> // XXX: FloatFormatSpec?
|
||||
template <typename Float>
|
||||
void append_double(Float value) {
|
||||
write_double(value, FormatSpec());
|
||||
}
|
||||
@ -2689,6 +2688,14 @@ class BasicWriter : public BasicWriterBase {
|
||||
buffer_.push_back(ch);
|
||||
}
|
||||
|
||||
void append_char(
|
||||
typename internal::WCharHelper<wchar_t, Char>::Unsupported) {
|
||||
// Use an incomplete type to generate a compiler error if this function is
|
||||
// ever used. static_assert(false) does not work here.
|
||||
internal::Incomplete<Char>
|
||||
converting_wide_strings_to_narrow_strings_is_not_supported;
|
||||
}
|
||||
|
||||
void append_str(StringRef str) {
|
||||
buffer_.append(str.data(), str.data() + str.size());
|
||||
}
|
||||
@ -2698,6 +2705,12 @@ class BasicWriter : public BasicWriterBase {
|
||||
buffer_.append(str.data(), str.data() + str.size());
|
||||
}
|
||||
|
||||
void append_str(
|
||||
typename internal::WCharHelper<WStringRef, Char>::Unsupported) {
|
||||
internal::Incomplete<Char>
|
||||
converting_wide_strings_to_narrow_strings_is_not_supported;
|
||||
}
|
||||
|
||||
void append_str(const StrFormatSpec<char> &spec) {
|
||||
const char *s = spec.str();
|
||||
write_str(s, std::char_traits<char>::length(s), spec);
|
||||
@ -2710,110 +2723,139 @@ class BasicWriter : public BasicWriterBase {
|
||||
write_str(s, std::char_traits<wchar_t>::length(s), spec);
|
||||
}
|
||||
|
||||
private:
|
||||
// The following methods are private to disallow writing wide characters
|
||||
// and strings to a char stream. If you want to print a wide string as a
|
||||
// pointer as std::ostream does, cast it to const void*.
|
||||
// Do not implement!
|
||||
void append_char(
|
||||
typename internal::WCharHelper<wchar_t, Char>::Unsupported);
|
||||
void append_str(
|
||||
typename internal::WCharHelper<WStringRef, Char>::Unsupported);
|
||||
void append_str(
|
||||
typename internal::WCharHelper<
|
||||
const StrFormatSpec<wchar_t> &, Char>::Unsupported);
|
||||
};
|
||||
const StrFormatSpec<wchar_t> &, Char>::Unsupported) {
|
||||
internal::Incomplete<Char>
|
||||
converting_wide_strings_to_narrow_strings_is_not_supported;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, bool value) {
|
||||
// Note:
|
||||
// Uses the same format as ArgFormatterBase.
|
||||
w.append_str(value ? "true" : "false");
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(bool value) {
|
||||
append_str(value ? "true" : "false");
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, signed char value) {
|
||||
w.append_decimal(static_cast<int>(value));
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(signed char value) {
|
||||
append_decimal(static_cast<int>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, short value) {
|
||||
w.append_decimal(static_cast<int>(value));
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(short value) {
|
||||
append_decimal(static_cast<int>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, int value) {
|
||||
w.append_decimal(static_cast<int>(value));
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(int value) {
|
||||
append_decimal(static_cast<int>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, long value) {
|
||||
w.append_decimal(value);
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(long value) {
|
||||
append_decimal(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, LongLong value) {
|
||||
w.append_decimal(value);
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(LongLong value) {
|
||||
append_decimal(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if USHRT_MAX <= INT_MAX
|
||||
BasicWriter &operator<<(unsigned char value) {
|
||||
append_decimal(static_cast<int>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, unsigned char value) {
|
||||
w.append_decimal(static_cast<int>(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, unsigned short value) {
|
||||
w.append_decimal(static_cast<int>(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
#else // !( USHRT_MAX <= INT_MAX ) ---->
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, unsigned char value) {
|
||||
w.append_decimal(static_cast<unsigned int>(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, unsigned short value) {
|
||||
w.append_decimal(static_cast<unsigned int>(value));
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(unsigned short value) {
|
||||
append_decimal(static_cast<int>(value));
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
BasicWriter &operator<<(unsigned char value) {
|
||||
append_decimal(static_cast<unsigned int>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(unsigned short value) {
|
||||
append_decimal(static_cast<unsigned int>(value));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, unsigned int value) {
|
||||
w.append_decimal(value);
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(unsigned int value) {
|
||||
append_decimal(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, unsigned long value) {
|
||||
w.append_decimal(value);
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(unsigned long value) {
|
||||
append_decimal(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, ULongLong value) {
|
||||
w.append_decimal(value);
|
||||
return w;
|
||||
}
|
||||
BasicWriter &operator<<(ULongLong value) {
|
||||
append_decimal(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(float value) {
|
||||
append_double(static_cast<double>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(double value) {
|
||||
append_double(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(long double value) {
|
||||
append_double(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(char ch) {
|
||||
append_char(ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(wchar_t ch) {
|
||||
append_char(ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(const char *value) {
|
||||
append_str(fmt::StringRef(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(const wchar_t *value) {
|
||||
append_str(fmt::WStringRef(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(char *value) {
|
||||
append_str(fmt::StringRef(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(wchar_t *value) {
|
||||
append_str(fmt::WStringRef(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(const void *pointer) {
|
||||
append_pointer(pointer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasicWriter &operator<<(void *pointer) {
|
||||
append_pointer(pointer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void clear() FMT_NOEXCEPT { buffer_.clear(); }
|
||||
|
||||
Buffer<Char> &buffer() FMT_NOEXCEPT { return buffer_; }
|
||||
};
|
||||
|
||||
template <typename Char, typename Int, typename Spec, typename FillChar>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
@ -2822,76 +2864,6 @@ inline BasicWriter<Char> &operator<<(
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, float value) {
|
||||
w.append_double(static_cast<double>(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, double value) {
|
||||
w.append_double(value);
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, long double value) {
|
||||
w.append_double(value);
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, char ch) {
|
||||
w.append_char(ch);
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, wchar_t ch) {
|
||||
w.append_char(ch);
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, const char *value) {
|
||||
w.append_str(fmt::StringRef(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, const wchar_t *value) {
|
||||
w.append_str(fmt::WStringRef(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, char *value) {
|
||||
w.append_str(fmt::StringRef(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, wchar_t *value) {
|
||||
w.append_str(fmt::WStringRef(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char, typename Elem>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, fmt::BasicStringRef<Elem> s) {
|
||||
w.append_str(s);
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char, typename Elem, typename Alloc>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w,
|
||||
const std::basic_string<Elem, std::char_traits<Elem>, Alloc> &value) {
|
||||
w.append_str(fmt::BasicStringRef<Elem>(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char, typename Elem>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, const StrFormatSpec<Elem> &value) {
|
||||
@ -2899,16 +2871,17 @@ inline BasicWriter<Char> &operator<<(
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
template <typename Char, typename Elem>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, const void *pointer) {
|
||||
w.append_pointer(pointer);
|
||||
BasicWriter<Char> &w, const fmt::BasicStringRef<Elem> &s) {
|
||||
w.append_str(s);
|
||||
return w;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline BasicWriter<Char> &operator<<(BasicWriter<Char> &w, void *pointer) {
|
||||
w.append_pointer(pointer);
|
||||
template <typename Char, typename Elem, typename Traits, typename Alloc>
|
||||
inline BasicWriter<Char> &operator<<(
|
||||
BasicWriter<Char> &w, const std::basic_string<Elem, Traits, Alloc> &value) {
|
||||
w.append_str(fmt::BasicStringRef<Elem>(value));
|
||||
return w;
|
||||
}
|
||||
|
||||
@ -2923,8 +2896,7 @@ template <
|
||||
typename = typename std::enable_if<
|
||||
!std::is_lvalue_reference<WriterT>::value
|
||||
&& std::is_base_of<BasicWriterBase, WriterT>::value
|
||||
>::type,
|
||||
typename = decltype(std::declval<WriterT &>() << std::declval<const T&>())
|
||||
>::type
|
||||
>
|
||||
inline WriterT &&operator<<(WriterT &&w, const T &value) {
|
||||
w << value;
|
||||
|
||||
@ -119,13 +119,8 @@ void std_format(long double value, std::wstring &result) {
|
||||
// as writing it to std::basic_ostringstream<Char>.
|
||||
template <typename Char, typename T>
|
||||
::testing::AssertionResult check_write(const T &value, const char *type) {
|
||||
#if FMT_USE_OSTREAM_RVALUE
|
||||
std::basic_string<Char> actual =
|
||||
(fmt::BasicMemoryWriter<Char>() << value).str();
|
||||
#else
|
||||
fmt::BasicMemoryWriter<Char> w;
|
||||
std::basic_string<Char> actual = (w << value).str();
|
||||
#endif
|
||||
std::basic_string<Char> expected;
|
||||
std_format(value, expected);
|
||||
if (expected == actual)
|
||||
@ -369,28 +364,25 @@ TEST(WriterTest, WriteWideString) {
|
||||
|
||||
TEST(WriterTest, bin) {
|
||||
using fmt::bin;
|
||||
MemoryWriter w;
|
||||
w.clear(); EXPECT_EQ("1100101011111110", (w << bin(0xcafe)).str());
|
||||
w.clear(); EXPECT_EQ("1011101010111110", (w << bin(0xbabeu)).str());
|
||||
w.clear(); EXPECT_EQ("1101111010101101", (w << bin(0xdeadl)).str());
|
||||
w.clear(); EXPECT_EQ("1011111011101111", (w << bin(0xbeeful)).str());
|
||||
w.clear();
|
||||
EXPECT_EQ("11001010111111101011101010111110", (w << bin(0xcafebabell)).str());
|
||||
w.clear();
|
||||
EXPECT_EQ("1100101011111110", (MemoryWriter() << bin(0xcafe)).str());
|
||||
EXPECT_EQ("1011101010111110", (MemoryWriter() << bin(0xbabeu)).str());
|
||||
EXPECT_EQ("1101111010101101", (MemoryWriter() << bin(0xdeadl)).str());
|
||||
EXPECT_EQ("1011111011101111", (MemoryWriter() << bin(0xbeeful)).str());
|
||||
EXPECT_EQ("11001010111111101011101010111110",
|
||||
(MemoryWriter() << bin(0xcafebabell)).str());
|
||||
EXPECT_EQ("11011110101011011011111011101111",
|
||||
(w << bin(0xdeadbeefull)).str());
|
||||
(MemoryWriter() << bin(0xdeadbeefull)).str());
|
||||
}
|
||||
|
||||
TEST(WriterTest, oct) {
|
||||
using fmt::oct;
|
||||
MemoryWriter w;
|
||||
w.clear(); EXPECT_EQ("12", (w << oct(static_cast<short>(012))).str());
|
||||
w.clear(); EXPECT_EQ("12", (w << oct(012)).str());
|
||||
w.clear(); EXPECT_EQ("34", (w << oct(034u)).str());
|
||||
w.clear(); EXPECT_EQ("56", (w << oct(056l)).str());
|
||||
w.clear(); EXPECT_EQ("70", (w << oct(070ul)).str());
|
||||
w.clear(); EXPECT_EQ("1234", (w << oct(01234ll)).str());
|
||||
w.clear(); EXPECT_EQ("5670", (w << oct(05670ull)).str());
|
||||
EXPECT_EQ("12", (MemoryWriter() << oct(static_cast<short>(012))).str());
|
||||
EXPECT_EQ("12", (MemoryWriter() << oct(012)).str());
|
||||
EXPECT_EQ("34", (MemoryWriter() << oct(034u)).str());
|
||||
EXPECT_EQ("56", (MemoryWriter() << oct(056l)).str());
|
||||
EXPECT_EQ("70", (MemoryWriter() << oct(070ul)).str());
|
||||
EXPECT_EQ("1234", (MemoryWriter() << oct(01234ll)).str());
|
||||
EXPECT_EQ("5670", (MemoryWriter() << oct(05670ull)).str());
|
||||
}
|
||||
|
||||
TEST(WriterTest, hex) {
|
||||
@ -400,24 +392,22 @@ TEST(WriterTest, hex) {
|
||||
// This shouldn't compile:
|
||||
//fmt::IntFormatSpec<short, fmt::TypeSpec<'x'> > (*phex2)(short value) = hex;
|
||||
|
||||
MemoryWriter w;
|
||||
w.clear(); EXPECT_EQ("cafe", (w << hex(0xcafe)).str());
|
||||
w.clear(); EXPECT_EQ("babe", (w << hex(0xbabeu)).str());
|
||||
w.clear(); EXPECT_EQ("dead", (w << hex(0xdeadl)).str());
|
||||
w.clear(); EXPECT_EQ("beef", (w << hex(0xbeeful)).str());
|
||||
w.clear(); EXPECT_EQ("cafebabe", (w << hex(0xcafebabell)).str());
|
||||
w.clear(); EXPECT_EQ("deadbeef", (w << hex(0xdeadbeefull)).str());
|
||||
EXPECT_EQ("cafe", (MemoryWriter() << hex(0xcafe)).str());
|
||||
EXPECT_EQ("babe", (MemoryWriter() << hex(0xbabeu)).str());
|
||||
EXPECT_EQ("dead", (MemoryWriter() << hex(0xdeadl)).str());
|
||||
EXPECT_EQ("beef", (MemoryWriter() << hex(0xbeeful)).str());
|
||||
EXPECT_EQ("cafebabe", (MemoryWriter() << hex(0xcafebabell)).str());
|
||||
EXPECT_EQ("deadbeef", (MemoryWriter() << hex(0xdeadbeefull)).str());
|
||||
}
|
||||
|
||||
TEST(WriterTest, hexu) {
|
||||
using fmt::hexu;
|
||||
MemoryWriter w;
|
||||
w.clear(); EXPECT_EQ("CAFE", (w << hexu(0xcafe)).str());
|
||||
w.clear(); EXPECT_EQ("BABE", (w << hexu(0xbabeu)).str());
|
||||
w.clear(); EXPECT_EQ("DEAD", (w << hexu(0xdeadl)).str());
|
||||
w.clear(); EXPECT_EQ("BEEF", (w << hexu(0xbeeful)).str());
|
||||
w.clear(); EXPECT_EQ("CAFEBABE", (w << hexu(0xcafebabell)).str());
|
||||
w.clear(); EXPECT_EQ("DEADBEEF", (w << hexu(0xdeadbeefull)).str());
|
||||
EXPECT_EQ("CAFE", (MemoryWriter() << hexu(0xcafe)).str());
|
||||
EXPECT_EQ("BABE", (MemoryWriter() << hexu(0xbabeu)).str());
|
||||
EXPECT_EQ("DEAD", (MemoryWriter() << hexu(0xdeadl)).str());
|
||||
EXPECT_EQ("BEEF", (MemoryWriter() << hexu(0xbeeful)).str());
|
||||
EXPECT_EQ("CAFEBABE", (MemoryWriter() << hexu(0xcafebabell)).str());
|
||||
EXPECT_EQ("DEADBEEF", (MemoryWriter() << hexu(0xdeadbeefull)).str());
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
@ -442,22 +432,22 @@ public:
|
||||
ISO8601DateFormatter iso8601(const Date &d) { return ISO8601DateFormatter(d); }
|
||||
|
||||
TEST(WriterTest, pad) {
|
||||
MemoryWriter w;
|
||||
using fmt::hex;
|
||||
w.clear(); EXPECT_EQ(" cafe", (w << pad(hex(0xcafe), 8)).str());
|
||||
w.clear(); EXPECT_EQ(" babe", (w << pad(hex(0xbabeu), 8)).str());
|
||||
w.clear(); EXPECT_EQ(" dead", (w << pad(hex(0xdeadl), 8)).str());
|
||||
w.clear(); EXPECT_EQ(" beef", (w << pad(hex(0xbeeful), 8)).str());
|
||||
w.clear(); EXPECT_EQ(" dead", (w << pad(hex(0xdeadll), 8)).str());
|
||||
w.clear(); EXPECT_EQ(" beef", (w << pad(hex(0xbeefull), 8)).str());
|
||||
EXPECT_EQ(" cafe", (MemoryWriter() << pad(hex(0xcafe), 8)).str());
|
||||
EXPECT_EQ(" babe", (MemoryWriter() << pad(hex(0xbabeu), 8)).str());
|
||||
EXPECT_EQ(" dead", (MemoryWriter() << pad(hex(0xdeadl), 8)).str());
|
||||
EXPECT_EQ(" beef", (MemoryWriter() << pad(hex(0xbeeful), 8)).str());
|
||||
EXPECT_EQ(" dead", (MemoryWriter() << pad(hex(0xdeadll), 8)).str());
|
||||
EXPECT_EQ(" beef", (MemoryWriter() << pad(hex(0xbeefull), 8)).str());
|
||||
|
||||
w.clear(); EXPECT_EQ(" 11", (w << pad(11, 7)).str());
|
||||
w.clear(); EXPECT_EQ(" 22", (w << pad(22u, 7)).str());
|
||||
w.clear(); EXPECT_EQ(" 33", (w << pad(33l, 7)).str());
|
||||
w.clear(); EXPECT_EQ(" 44", (w << pad(44ul, 7)).str());
|
||||
w.clear(); EXPECT_EQ(" 33", (w << pad(33ll, 7)).str());
|
||||
w.clear(); EXPECT_EQ(" 44", (w << pad(44ull, 7)).str());
|
||||
EXPECT_EQ(" 11", (MemoryWriter() << pad(11, 7)).str());
|
||||
EXPECT_EQ(" 22", (MemoryWriter() << pad(22u, 7)).str());
|
||||
EXPECT_EQ(" 33", (MemoryWriter() << pad(33l, 7)).str());
|
||||
EXPECT_EQ(" 44", (MemoryWriter() << pad(44ul, 7)).str());
|
||||
EXPECT_EQ(" 33", (MemoryWriter() << pad(33ll, 7)).str());
|
||||
EXPECT_EQ(" 44", (MemoryWriter() << pad(44ull, 7)).str());
|
||||
|
||||
MemoryWriter w;
|
||||
w.clear();
|
||||
w << pad(42, 5, '0');
|
||||
EXPECT_EQ("00042", w.str());
|
||||
@ -470,24 +460,21 @@ TEST(WriterTest, pad) {
|
||||
}
|
||||
|
||||
TEST(WriterTest, PadString) {
|
||||
MemoryWriter w;
|
||||
w.clear(); EXPECT_EQ("test ", (w << pad("test", 8)).str());
|
||||
w.clear(); EXPECT_EQ("test******", (w << pad("test", 10, '*')).str());
|
||||
EXPECT_EQ("test ", (MemoryWriter() << pad("test", 8)).str());
|
||||
EXPECT_EQ("test******", (MemoryWriter() << pad("test", 10, '*')).str());
|
||||
}
|
||||
|
||||
TEST(WriterTest, PadWString) {
|
||||
WMemoryWriter w;
|
||||
w.clear(); EXPECT_EQ(L"test ", (w << pad(L"test", 8)).str());
|
||||
w.clear(); EXPECT_EQ(L"test******", (w << pad(L"test", 10, '*')).str());
|
||||
w.clear(); EXPECT_EQ(L"test******", (w << pad(L"test", 10, L'*')).str());
|
||||
EXPECT_EQ(L"test ", (WMemoryWriter() << pad(L"test", 8)).str());
|
||||
EXPECT_EQ(L"test******", (WMemoryWriter() << pad(L"test", 10, '*')).str());
|
||||
EXPECT_EQ(L"test******", (WMemoryWriter() << pad(L"test", 10, L'*')).str());
|
||||
}
|
||||
|
||||
TEST(WriterTest, NoConflictWithIOManip) {
|
||||
using namespace std;
|
||||
using namespace fmt;
|
||||
MemoryWriter w;
|
||||
w.clear(); EXPECT_EQ("cafe", (w << hex(0xcafe)).str());
|
||||
w.clear(); EXPECT_EQ("12", (w << oct(012)).str());
|
||||
EXPECT_EQ("cafe", (MemoryWriter() << hex(0xcafe)).str());
|
||||
EXPECT_EQ("12", (MemoryWriter() << oct(012)).str());
|
||||
}
|
||||
|
||||
TEST(WriterTest, Format) {
|
||||
@ -505,85 +492,94 @@ TEST(WriterTest, Format) {
|
||||
}
|
||||
|
||||
TEST(WriterTest, WWriter) {
|
||||
WMemoryWriter w;
|
||||
EXPECT_EQ(L"cafe", (w << fmt::hex(0xcafe)).str());
|
||||
EXPECT_EQ(L"cafe", (fmt::WMemoryWriter() << fmt::hex(0xcafe)).str());
|
||||
}
|
||||
|
||||
TEST(WriterTest, Stream) {
|
||||
MemoryWriter w;
|
||||
|
||||
const char *ncs = "ncs";
|
||||
|
||||
w.clear(); EXPECT_EQ("true", (w << true).str());
|
||||
w.clear(); EXPECT_EQ("false", (w << false).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (signed char)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (signed short)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (signed int)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (signed long)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (fmt::LongLong)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (unsigned char)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (unsigned short)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (unsigned int)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (unsigned long)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (fmt::ULongLong)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (float)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (double)0).str());
|
||||
w.clear(); EXPECT_EQ("0", (w << (long double)0).str());
|
||||
w.clear(); EXPECT_EQ("0x1234", (w << (const void *)0x1234).str());
|
||||
w.clear(); EXPECT_EQ("0x1234", (w << (void *)0x1234).str());
|
||||
w.clear(); EXPECT_EQ("x", (w << (char)'x').str());
|
||||
w.clear(); EXPECT_EQ("ncs", (w << (const char *)ncs).str());
|
||||
w.clear(); EXPECT_EQ("ncs", (w << (char *)ncs).str());
|
||||
w.clear(); EXPECT_EQ("ncs", (w << fmt::StringRef(ncs)).str());
|
||||
w.clear(); EXPECT_EQ("ncs", (w << std::string(ncs)).str());
|
||||
EXPECT_EQ("true", (MemoryWriter() << true).str());
|
||||
EXPECT_EQ("false", (MemoryWriter() << false).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (signed char)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (signed short)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (signed int)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (signed long)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (fmt::LongLong)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (unsigned char)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (unsigned short)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (unsigned int)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (unsigned long)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (fmt::ULongLong)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (float)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (double)0).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << (long double)0).str());
|
||||
EXPECT_EQ("0x1234", (MemoryWriter() << (const void *)0x1234).str());
|
||||
EXPECT_EQ("0x1234", (MemoryWriter() << (void *)0x1234).str());
|
||||
EXPECT_EQ("x", (MemoryWriter() << (char)'x').str());
|
||||
EXPECT_EQ("ncs", (MemoryWriter() << (const char *)ncs).str());
|
||||
EXPECT_EQ("ncs", (MemoryWriter() << (char *)ncs).str());
|
||||
EXPECT_EQ("ncs", (MemoryWriter() << fmt::StringRef(ncs)).str());
|
||||
EXPECT_EQ("ncs", (MemoryWriter() << std::string(ncs)).str());
|
||||
EXPECT_EQ("0", (MemoryWriter() << fmt::IntFormatSpec<int>(0)).str());
|
||||
EXPECT_EQ("ncs", (MemoryWriter() << fmt::StrFormatSpec<char>(ncs, 3, ' ')).str());
|
||||
|
||||
// This should not compile:
|
||||
#if 0
|
||||
const wchar_t *wcs = L"wcs";
|
||||
MemoryWriter w;
|
||||
//w << (wchar_t)'x';
|
||||
//w << (const wchar_t *)wcs;
|
||||
//w << (wchar_t *)wcs;
|
||||
//w << fmt::WStringRef(wcs);
|
||||
//w << std::wstring(wcs);
|
||||
w << fmt::StrFormatSpec<wchar_t>(wcs, 3, ' ');
|
||||
#endif
|
||||
|
||||
// w << (wchar_t)'x';
|
||||
// w << (const wchar_t *)wcs;
|
||||
// w << (wchar_t *)wcs;
|
||||
// w << fmt::WStringRef(wcs);
|
||||
// w << std::wstring(wcs);
|
||||
#if FMT_USE_OSTREAM_RVALUE
|
||||
EXPECT_EQ("i = 123", (MemoryWriter() << "i = " << 123).str());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(WWriterTest, Stream) {
|
||||
WMemoryWriter w;
|
||||
|
||||
const wchar_t *wcs = L"wcs";
|
||||
|
||||
w.clear(); EXPECT_EQ(L"true", (w << true).str());
|
||||
w.clear(); EXPECT_EQ(L"false", (w << false).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (signed char)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (signed short)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (signed int)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (signed long)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (fmt::LongLong)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (unsigned char)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (unsigned short)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (unsigned int)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (unsigned long)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (fmt::ULongLong)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (float)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (double)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0", (w << (long double)0).str());
|
||||
w.clear(); EXPECT_EQ(L"0x1234", (w << (const void*)0x1234).str());
|
||||
w.clear(); EXPECT_EQ(L"0x1234", (w << (void *)0x1234).str());
|
||||
w.clear(); EXPECT_EQ(L"x", (w << (wchar_t)'x').str());
|
||||
w.clear(); EXPECT_EQ(L"wcs", (w << (const wchar_t *)wcs).str());
|
||||
w.clear(); EXPECT_EQ(L"wcs", (w << (wchar_t *)wcs).str());
|
||||
w.clear(); EXPECT_EQ(L"wcs", (w << fmt::WStringRef(wcs)).str());
|
||||
w.clear(); EXPECT_EQ(L"wcs", (w << std::wstring(wcs)).str());
|
||||
EXPECT_EQ(L"true", (WMemoryWriter() << true).str());
|
||||
EXPECT_EQ(L"false", (WMemoryWriter() << false).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (signed char)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (signed short)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (signed int)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (signed long)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (fmt::LongLong)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (unsigned char)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (unsigned short)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (unsigned int)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (unsigned long)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (fmt::ULongLong)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (float)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (double)0).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << (long double)0).str());
|
||||
EXPECT_EQ(L"0x1234", (WMemoryWriter() << (const void*)0x1234).str());
|
||||
EXPECT_EQ(L"0x1234", (WMemoryWriter() << (void *)0x1234).str());
|
||||
EXPECT_EQ(L"x", (WMemoryWriter() << (wchar_t)'x').str());
|
||||
EXPECT_EQ(L"wcs", (WMemoryWriter() << (const wchar_t *)wcs).str());
|
||||
EXPECT_EQ(L"wcs", (WMemoryWriter() << (wchar_t *)wcs).str());
|
||||
EXPECT_EQ(L"wcs", (WMemoryWriter() << fmt::WStringRef(wcs)).str());
|
||||
EXPECT_EQ(L"wcs", (WMemoryWriter() << std::wstring(wcs)).str());
|
||||
EXPECT_EQ(L"0", (WMemoryWriter() << fmt::IntFormatSpec<int>(0)).str());
|
||||
EXPECT_EQ(L"wcs", (WMemoryWriter() << fmt::StrFormatSpec<wchar_t>(wcs, 3, ' ')).str());
|
||||
|
||||
const char *ncs = "ncs";
|
||||
|
||||
w.clear(); EXPECT_EQ(L"x", (w << (char)'x').str());
|
||||
w.clear(); EXPECT_EQ(L"ncs", (w << (const char *)ncs).str());
|
||||
w.clear(); EXPECT_EQ(L"ncs", (w << (char *)ncs).str());
|
||||
w.clear(); EXPECT_EQ(L"ncs", (w << fmt::StringRef(ncs)).str());
|
||||
w.clear(); EXPECT_EQ(L"ncs", (w << std::string(ncs)).str());
|
||||
EXPECT_EQ(L"x", (WMemoryWriter() << (char)'x').str());
|
||||
EXPECT_EQ(L"ncs", (WMemoryWriter() << (const char *)ncs).str());
|
||||
EXPECT_EQ(L"ncs", (WMemoryWriter() << (char *)ncs).str());
|
||||
EXPECT_EQ(L"ncs", (WMemoryWriter() << fmt::StringRef(ncs)).str());
|
||||
EXPECT_EQ(L"ncs", (WMemoryWriter() << std::string(ncs)).str());
|
||||
EXPECT_EQ(L"ncs", (WMemoryWriter() << fmt::StrFormatSpec<char>(ncs, 3, ' ')).str());
|
||||
|
||||
#if FMT_USE_OSTREAM_RVALUE
|
||||
EXPECT_EQ(L"i = 123", (WMemoryWriter() << L"i = " << 123).str());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(ArrayWriterTest, Ctor) {
|
||||
@ -1507,10 +1503,7 @@ TEST(FormatterTest, FormatStringFromSpeedTest) {
|
||||
|
||||
TEST(FormatterTest, FormatExamples) {
|
||||
using fmt::hex;
|
||||
{
|
||||
MemoryWriter w;
|
||||
EXPECT_EQ("0000cafe", (w << pad(hex(0xcafe), 8, '0')).str());
|
||||
}
|
||||
EXPECT_EQ("0000cafe", (MemoryWriter() << pad(hex(0xcafe), 8, '0')).str());
|
||||
|
||||
std::string message = format("The answer is {}", 42);
|
||||
EXPECT_EQ("The answer is 42", message);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user