mirror of
https://github.com/shadps4-emu/ext-fmt.git
synced 2024-11-27 03:30:32 +00:00
Move ostream support to ostream.{h,cc}
This commit is contained in:
parent
041725e9d0
commit
90730e706b
@ -1,12 +1,12 @@
|
||||
# Define the fmt library, its includes and the needed defines.
|
||||
# format.cc is added to FMT_HEADERS for the header-only configuration.
|
||||
set(FMT_HEADERS format.h format.cc time.h)
|
||||
set(FMT_HEADERS format.h format.cc ostream.h ostream.cc time.h)
|
||||
if (HAVE_OPEN)
|
||||
set(FMT_HEADERS ${FMT_HEADERS} posix.h)
|
||||
set(FMT_SOURCES ${FMT_SOURCES} posix.cc)
|
||||
endif ()
|
||||
|
||||
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS})
|
||||
add_library(fmt ${FMT_SOURCES} ${FMT_HEADERS} ../ChangeLog.rst)
|
||||
|
||||
option(FMT_CPPFORMAT "Build cppformat library for backward compatibility." OFF)
|
||||
if (FMT_CPPFORMAT)
|
||||
|
@ -60,12 +60,6 @@ using fmt::internal::Arg;
|
||||
# define FMT_CATCH(x) if (false)
|
||||
#endif
|
||||
|
||||
#ifdef FMT_HEADER_ONLY
|
||||
# define FMT_FUNC inline
|
||||
#else
|
||||
# define FMT_FUNC
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
@ -361,21 +355,6 @@ class CharConverter : public ArgVisitor<CharConverter, void> {
|
||||
arg_.int_value = static_cast<char>(value);
|
||||
}
|
||||
};
|
||||
|
||||
// Write the content of w to os.
|
||||
void write(std::ostream &os, Writer &w) {
|
||||
const char *data = w.data();
|
||||
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
|
||||
UnsignedStreamSize size = w.size();
|
||||
UnsignedStreamSize max_size =
|
||||
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
|
||||
do {
|
||||
UnsignedStreamSize n = size <= max_size ? size : max_size;
|
||||
os.write(data, static_cast<std::streamsize>(n));
|
||||
data += n;
|
||||
size -= n;
|
||||
} while (size != 0);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace internal {
|
||||
@ -896,13 +875,6 @@ FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
|
||||
print(stdout, format_str, args);
|
||||
}
|
||||
|
||||
FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str,
|
||||
ArgList args) {
|
||||
MemoryWriter w;
|
||||
w.write(format_str, args);
|
||||
write(os, w);
|
||||
}
|
||||
|
||||
FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
|
||||
char escape[] = "\x1b[30m";
|
||||
escape[3] = static_cast<char>('0' + c);
|
||||
@ -918,13 +890,6 @@ FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
|
||||
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
|
||||
}
|
||||
|
||||
FMT_FUNC int fmt::fprintf(std::ostream &os, CStringRef format, ArgList args) {
|
||||
MemoryWriter w;
|
||||
printf(w, format, args);
|
||||
write(os, w);
|
||||
return static_cast<int>(w.size());
|
||||
}
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
|
||||
template struct fmt::internal::BasicData<void>;
|
||||
|
113
fmt/format.h
113
fmt/format.h
@ -40,14 +40,6 @@
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#ifndef FMT_USE_IOSTREAMS
|
||||
# define FMT_USE_IOSTREAMS 1
|
||||
#endif
|
||||
|
||||
#if FMT_USE_IOSTREAMS
|
||||
# include <ostream>
|
||||
#endif
|
||||
|
||||
#ifdef _SECURE_SCL
|
||||
# define FMT_SECURE_SCL _SECURE_SCL
|
||||
#else
|
||||
@ -387,10 +379,6 @@ template <typename CharType,
|
||||
typename ArgFormatter = fmt::ArgFormatter<CharType> >
|
||||
class BasicFormatter;
|
||||
|
||||
template <typename Char, typename ArgFormatter, typename T>
|
||||
void format(BasicFormatter<Char, ArgFormatter> &f,
|
||||
const Char *&format_str, const T &value);
|
||||
|
||||
/**
|
||||
\rst
|
||||
A string reference. It can be constructed from a C string or ``std::string``.
|
||||
@ -1057,33 +1045,16 @@ struct WCharHelper<T, wchar_t> {
|
||||
typedef char Yes[1];
|
||||
typedef char No[2];
|
||||
|
||||
// These are non-members to workaround an overload resolution bug in bcc32.
|
||||
Yes &convert(fmt::ULongLong);
|
||||
Yes &convert(std::ostream &);
|
||||
No &convert(...);
|
||||
|
||||
template <typename T>
|
||||
T &get();
|
||||
|
||||
struct DummyStream : std::ostream {
|
||||
DummyStream(); // Suppress a bogus warning in MSVC.
|
||||
// Hide all operator<< overloads from std::ostream.
|
||||
void operator<<(Null<>);
|
||||
};
|
||||
|
||||
No &operator<<(std::ostream &, int);
|
||||
// These are non-members to workaround an overload resolution bug in bcc32.
|
||||
Yes &convert(fmt::ULongLong);
|
||||
No &convert(...);
|
||||
|
||||
template<typename T, bool ENABLE_CONVERSION>
|
||||
struct ConvertToIntImpl {
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToIntImpl<T, true> {
|
||||
// Convert to int only if T doesn't have an overloaded operator<<.
|
||||
enum {
|
||||
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
|
||||
};
|
||||
enum { value = ENABLE_CONVERSION };
|
||||
};
|
||||
|
||||
template<typename T, bool ENABLE_CONVERSION>
|
||||
@ -2140,38 +2111,6 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
|
||||
(t12.type << 48) | (t13.type << 52) | (t14.type << 56);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Char>
|
||||
class FormatBuf : public std::basic_streambuf<Char> {
|
||||
private:
|
||||
typedef typename std::basic_streambuf<Char>::int_type int_type;
|
||||
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
|
||||
|
||||
Buffer<Char> &buffer_;
|
||||
Char *start_;
|
||||
|
||||
public:
|
||||
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) {
|
||||
this->setp(start_, start_ + buffer_.capacity());
|
||||
}
|
||||
|
||||
int_type overflow(int_type ch = traits_type::eof()) {
|
||||
if (!traits_type::eq_int_type(ch, traits_type::eof())) {
|
||||
size_t size = this->size();
|
||||
buffer_.resize(size);
|
||||
buffer_.reserve(size * 2);
|
||||
|
||||
start_ = &buffer_[0];
|
||||
start_[size] = traits_type::to_char_type(ch);
|
||||
this->setp(start_+ size + 1, start_ + size * 2);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return to_unsigned(this->pptr() - start_);
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
|
||||
@ -3100,21 +3039,6 @@ class BasicArrayWriter : public BasicWriter<Char> {
|
||||
typedef BasicArrayWriter<char> ArrayWriter;
|
||||
typedef BasicArrayWriter<wchar_t> WArrayWriter;
|
||||
|
||||
// Formats a value.
|
||||
template <typename Char, typename ArgFormatter, typename T>
|
||||
void format(BasicFormatter<Char, ArgFormatter> &f,
|
||||
const Char *&format_str, const T &value) {
|
||||
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||
|
||||
internal::FormatBuf<Char> format_buf(buffer);
|
||||
std::basic_ostream<Char> output(&format_buf);
|
||||
output << value;
|
||||
|
||||
BasicStringRef<Char> str(&buffer[0], format_buf.size());
|
||||
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
|
||||
format_str = f.format(format_str, MakeArg(str));
|
||||
}
|
||||
|
||||
// Reports a system error without throwing an exception.
|
||||
// Can be used to report errors from destructors.
|
||||
FMT_API void report_system_error(int error_code,
|
||||
@ -3544,32 +3468,6 @@ FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
|
||||
FMT_VARIADIC(int, printf, CStringRef)
|
||||
FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
|
||||
|
||||
#if FMT_USE_IOSTREAMS
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
print(cerr, "Don't {}!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
|
||||
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
fprintf(cerr, "Don't %s!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args);
|
||||
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
template <typename Char>
|
||||
inline bool is_name_start(Char c) {
|
||||
@ -3924,7 +3822,10 @@ operator"" _a(const wchar_t *s, std::size_t) { return {s}; }
|
||||
#endif
|
||||
|
||||
#ifdef FMT_HEADER_ONLY
|
||||
# define FMT_FUNC inline
|
||||
# include "format.cc"
|
||||
#else
|
||||
# define FMT_FUNC
|
||||
#endif
|
||||
|
||||
#endif // FMT_FORMAT_H_
|
||||
|
61
fmt/ostream.cc
Normal file
61
fmt/ostream.cc
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
Formatting library for C++ - std::ostream support
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ostream.h"
|
||||
|
||||
namespace fmt {
|
||||
|
||||
namespace {
|
||||
// Write the content of w to os.
|
||||
void write(std::ostream &os, Writer &w) {
|
||||
const char *data = w.data();
|
||||
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
|
||||
UnsignedStreamSize size = w.size();
|
||||
UnsignedStreamSize max_size =
|
||||
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
|
||||
do {
|
||||
UnsignedStreamSize n = size <= max_size ? size : max_size;
|
||||
os.write(data, static_cast<std::streamsize>(n));
|
||||
data += n;
|
||||
size -= n;
|
||||
} while (size != 0);
|
||||
}
|
||||
}
|
||||
|
||||
FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) {
|
||||
MemoryWriter w;
|
||||
w.write(format_str, args);
|
||||
write(os, w);
|
||||
}
|
||||
|
||||
FMT_FUNC int fprintf(std::ostream &os, CStringRef format, ArgList args) {
|
||||
MemoryWriter w;
|
||||
printf(w, format, args);
|
||||
write(os, w);
|
||||
return static_cast<int>(w.size());
|
||||
}
|
||||
} // namespace fmt
|
133
fmt/ostream.h
Normal file
133
fmt/ostream.h
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
Formatting library for C++ - std::ostream support
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FMT_OSTREAM_H_
|
||||
#define FMT_OSTREAM_H_
|
||||
|
||||
#include "format.h"
|
||||
#include <ostream>
|
||||
|
||||
namespace fmt {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class Char>
|
||||
class FormatBuf : public std::basic_streambuf<Char> {
|
||||
private:
|
||||
typedef typename std::basic_streambuf<Char>::int_type int_type;
|
||||
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
|
||||
|
||||
Buffer<Char> &buffer_;
|
||||
Char *start_;
|
||||
|
||||
public:
|
||||
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0]) {
|
||||
this->setp(start_, start_ + buffer_.capacity());
|
||||
}
|
||||
|
||||
int_type overflow(int_type ch = traits_type::eof()) {
|
||||
if (!traits_type::eq_int_type(ch, traits_type::eof())) {
|
||||
size_t size = this->size();
|
||||
buffer_.resize(size);
|
||||
buffer_.reserve(size * 2);
|
||||
|
||||
start_ = &buffer_[0];
|
||||
start_[size] = traits_type::to_char_type(ch);
|
||||
this->setp(start_+ size + 1, start_ + size * 2);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return to_unsigned(this->pptr() - start_);
|
||||
}
|
||||
};
|
||||
|
||||
Yes &convert(std::ostream &);
|
||||
|
||||
struct DummyStream : std::ostream {
|
||||
DummyStream(); // Suppress a bogus warning in MSVC.
|
||||
// Hide all operator<< overloads from std::ostream.
|
||||
void operator<<(Null<>);
|
||||
};
|
||||
|
||||
No &operator<<(std::ostream &, int);
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToIntImpl<T, true> {
|
||||
// Convert to int only if T doesn't have an overloaded operator<<.
|
||||
enum {
|
||||
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
|
||||
};
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
// Formats a value.
|
||||
template <typename Char, typename ArgFormatter, typename T>
|
||||
void format(BasicFormatter<Char, ArgFormatter> &f,
|
||||
const Char *&format_str, const T &value) {
|
||||
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||
|
||||
internal::FormatBuf<Char> format_buf(buffer);
|
||||
std::basic_ostream<Char> output(&format_buf);
|
||||
output << value;
|
||||
|
||||
BasicStringRef<Char> str(&buffer[0], format_buf.size());
|
||||
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
|
||||
format_str = f.format(format_str, MakeArg(str));
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
print(cerr, "Don't {}!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
|
||||
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
fprintf(cerr, "Don't %s!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
FMT_API int fprintf(std::ostream &os, CStringRef format_str, ArgList args);
|
||||
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
|
||||
} // namespace fmt
|
||||
|
||||
#ifdef FMT_HEADER_ONLY
|
||||
# include "ostream.cc"
|
||||
#endif
|
||||
|
||||
#endif // FMT_OSTREAM_H_
|
@ -75,6 +75,7 @@ add_fmt_test(assert-test)
|
||||
add_fmt_test(gtest-extra-test)
|
||||
add_fmt_test(format-test)
|
||||
add_fmt_test(format-impl-test)
|
||||
add_fmt_test(ostream-test)
|
||||
add_fmt_test(printf-test)
|
||||
add_fmt_test(util-test mock-allocator.h)
|
||||
add_fmt_test(macro-test)
|
||||
|
@ -123,55 +123,3 @@ TEST(FormatTest, FormatErrorCode) {
|
||||
EXPECT_EQ(msg, w.str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FormatTest, WriteToOStream) {
|
||||
std::ostringstream os;
|
||||
fmt::MemoryWriter w;
|
||||
w << "foo";
|
||||
fmt::write(os, w);
|
||||
EXPECT_EQ("foo", os.str());
|
||||
}
|
||||
|
||||
TEST(FormatTest, WriteToOStreamMaxSize) {
|
||||
std::size_t max_size = std::numeric_limits<std::size_t>::max();
|
||||
std::streamsize max_streamsize = std::numeric_limits<std::streamsize>::max();
|
||||
if (max_size <= fmt::internal::to_unsigned(max_streamsize))
|
||||
return;
|
||||
|
||||
class TestWriter : public fmt::BasicWriter<char> {
|
||||
private:
|
||||
struct TestBuffer : fmt::Buffer<char> {
|
||||
explicit TestBuffer(std::size_t size) { size_ = size; }
|
||||
void grow(std::size_t) {}
|
||||
} buffer_;
|
||||
public:
|
||||
explicit TestWriter(std::size_t size)
|
||||
: fmt::BasicWriter<char>(buffer_), buffer_(size) {}
|
||||
} w(max_size);
|
||||
|
||||
struct MockStreamBuf : std::streambuf {
|
||||
MOCK_METHOD2(xsputn, std::streamsize (const void *s, std::streamsize n));
|
||||
std::streamsize xsputn(const char *s, std::streamsize n) {
|
||||
const void *v = s;
|
||||
return xsputn(v, n);
|
||||
}
|
||||
} buffer;
|
||||
|
||||
struct TestOStream : std::ostream {
|
||||
explicit TestOStream(MockStreamBuf &buffer) : std::ostream(&buffer) {}
|
||||
} os(buffer);
|
||||
|
||||
testing::InSequence sequence;
|
||||
const char *data = 0;
|
||||
std::size_t size = max_size;
|
||||
do {
|
||||
typedef fmt::internal::MakeUnsigned<std::streamsize>::Type UStreamSize;
|
||||
UStreamSize n = std::min<UStreamSize>(
|
||||
size, fmt::internal::to_unsigned(max_streamsize));
|
||||
EXPECT_CALL(buffer, xsputn(data, static_cast<std::streamsize>(n)))
|
||||
.WillOnce(testing::Return(max_streamsize));
|
||||
data += n;
|
||||
size -= static_cast<std::size_t>(n);
|
||||
} while (size != 0);
|
||||
fmt::write(os, w);
|
||||
}
|
||||
|
@ -31,10 +31,7 @@
|
||||
#include <clocale>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdint.h>
|
||||
|
||||
#if FMT_USE_TYPE_TRAITS
|
||||
@ -386,30 +383,10 @@ TEST(WriterTest, hexu) {
|
||||
EXPECT_EQ("DEADBEEF", (MemoryWriter() << hexu(0xdeadbeefull)).str());
|
||||
}
|
||||
|
||||
class Date {
|
||||
int year_, month_, day_;
|
||||
public:
|
||||
Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
|
||||
|
||||
int year() const { return year_; }
|
||||
int month() const { return month_; }
|
||||
int day() const { return day_; }
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const Date &d) {
|
||||
os << d.year_ << '-' << d.month_ << '-' << d.day_;
|
||||
return os;
|
||||
}
|
||||
|
||||
friend std::wostream &operator<<(std::wostream &os, const Date &d) {
|
||||
os << d.year_ << L'-' << d.month_ << L'-' << d.day_;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
friend BasicWriter<Char> &operator<<(BasicWriter<Char> &f, const Date &d) {
|
||||
return f << d.year_ << '-' << d.month_ << '-' << d.day_;
|
||||
}
|
||||
};
|
||||
template <typename Char>
|
||||
BasicWriter<Char> &operator<<(BasicWriter<Char> &f, const Date &d) {
|
||||
return f << d.year() << '-' << d.month() << '-' << d.day();
|
||||
}
|
||||
|
||||
class ISO8601DateFormatter {
|
||||
const Date *date_;
|
||||
@ -665,7 +642,6 @@ TEST(FormatterTest, LeftAlign) {
|
||||
EXPECT_EQ("c ", format("{0:<5}", 'c'));
|
||||
EXPECT_EQ("abc ", format("{0:<5}", "abc"));
|
||||
EXPECT_EQ("0xface ", format("{0:<8}", reinterpret_cast<void*>(0xface)));
|
||||
EXPECT_EQ("def ", format("{0:<5}", TestString("def")));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, RightAlign) {
|
||||
@ -683,7 +659,6 @@ TEST(FormatterTest, RightAlign) {
|
||||
EXPECT_EQ(" c", format("{0:>5}", 'c'));
|
||||
EXPECT_EQ(" abc", format("{0:>5}", "abc"));
|
||||
EXPECT_EQ(" 0xface", format("{0:>8}", reinterpret_cast<void*>(0xface)));
|
||||
EXPECT_EQ(" def", format("{0:>5}", TestString("def")));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, NumericAlign) {
|
||||
@ -709,8 +684,6 @@ TEST(FormatterTest, NumericAlign) {
|
||||
FormatError, "format specifier '=' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:=8}", reinterpret_cast<void*>(0xface)),
|
||||
FormatError, "format specifier '=' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:=5}", TestString("def")),
|
||||
FormatError, "format specifier '=' requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, CenterAlign) {
|
||||
@ -728,7 +701,6 @@ TEST(FormatterTest, CenterAlign) {
|
||||
EXPECT_EQ(" c ", format("{0:^5}", 'c'));
|
||||
EXPECT_EQ(" abc ", format("{0:^6}", "abc"));
|
||||
EXPECT_EQ(" 0xface ", format("{0:^8}", reinterpret_cast<void*>(0xface)));
|
||||
EXPECT_EQ(" def ", format("{0:^5}", TestString("def")));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, Fill) {
|
||||
@ -748,7 +720,6 @@ TEST(FormatterTest, Fill) {
|
||||
EXPECT_EQ("c****", format("{0:*<5}", 'c'));
|
||||
EXPECT_EQ("abc**", format("{0:*<5}", "abc"));
|
||||
EXPECT_EQ("**0xface", format("{0:*>8}", reinterpret_cast<void*>(0xface)));
|
||||
EXPECT_EQ("def**", format("{0:*<5}", TestString("def")));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, PlusSign) {
|
||||
@ -773,8 +744,6 @@ TEST(FormatterTest, PlusSign) {
|
||||
FormatError, "format specifier '+' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:+}", reinterpret_cast<void*>(0x42)),
|
||||
FormatError, "format specifier '+' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:+}", TestString()),
|
||||
FormatError, "format specifier '+' requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, MinusSign) {
|
||||
@ -799,8 +768,6 @@ TEST(FormatterTest, MinusSign) {
|
||||
FormatError, "format specifier '-' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:-}", reinterpret_cast<void*>(0x42)),
|
||||
FormatError, "format specifier '-' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:-}", TestString()),
|
||||
FormatError, "format specifier '-' requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, SpaceSign) {
|
||||
@ -825,8 +792,6 @@ TEST(FormatterTest, SpaceSign) {
|
||||
FormatError, "format specifier ' ' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0: }", reinterpret_cast<void*>(0x42)),
|
||||
FormatError, "format specifier ' ' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0: }", TestString()),
|
||||
FormatError, "format specifier ' ' requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, HashFlag) {
|
||||
@ -872,8 +837,6 @@ TEST(FormatterTest, HashFlag) {
|
||||
FormatError, "format specifier '#' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:#}", reinterpret_cast<void*>(0x42)),
|
||||
FormatError, "format specifier '#' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:#}", TestString()),
|
||||
FormatError, "format specifier '#' requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, ZeroFlag) {
|
||||
@ -894,8 +857,6 @@ TEST(FormatterTest, ZeroFlag) {
|
||||
FormatError, "format specifier '0' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:05}", reinterpret_cast<void*>(0x42)),
|
||||
FormatError, "format specifier '0' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:05}", TestString()),
|
||||
FormatError, "format specifier '0' requires numeric argument");
|
||||
}
|
||||
|
||||
TEST(FormatterTest, Width) {
|
||||
@ -923,7 +884,6 @@ TEST(FormatterTest, Width) {
|
||||
EXPECT_EQ(" 0xcafe", format("{0:10}", reinterpret_cast<void*>(0xcafe)));
|
||||
EXPECT_EQ("x ", format("{0:11}", 'x'));
|
||||
EXPECT_EQ("str ", format("{0:12}", "str"));
|
||||
EXPECT_EQ("test ", format("{0:13}", TestString("test")));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, RuntimeWidth) {
|
||||
@ -982,7 +942,6 @@ TEST(FormatterTest, RuntimeWidth) {
|
||||
format("{0:{1}}", reinterpret_cast<void*>(0xcafe), 10));
|
||||
EXPECT_EQ("x ", format("{0:{1}}", 'x', 11));
|
||||
EXPECT_EQ("str ", format("{0:{1}}", "str", 12));
|
||||
EXPECT_EQ("test ", format("{0:{1}}", TestString("test"), 13));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, Precision) {
|
||||
@ -1042,7 +1001,6 @@ TEST(FormatterTest, Precision) {
|
||||
FormatError, "precision not allowed in pointer format specifier");
|
||||
|
||||
EXPECT_EQ("st", format("{0:.2}", "str"));
|
||||
EXPECT_EQ("te", format("{0:.2}", TestString("test")));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, RuntimePrecision) {
|
||||
@ -1126,7 +1084,6 @@ TEST(FormatterTest, RuntimePrecision) {
|
||||
FormatError, "precision not allowed in pointer format specifier");
|
||||
|
||||
EXPECT_EQ("st", format("{0:.{1}}", "str", 2));
|
||||
EXPECT_EQ("te", format("{0:.{1}}", TestString("test"), 2));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -1393,14 +1350,14 @@ TEST(FormatterTest, FormatCStringRef) {
|
||||
EXPECT_EQ("test", format("{0}", CStringRef("test")));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatUsingIOStreams) {
|
||||
EXPECT_EQ("a string", format("{0}", TestString("a string")));
|
||||
std::string s = format("The date is {0}", Date(2012, 12, 9));
|
||||
EXPECT_EQ("The date is 2012-12-9", s);
|
||||
void format(fmt::BasicFormatter<char> &f, const char *, const Date &d) {
|
||||
f.writer() << d.year() << '-' << d.month() << '-' << d.day();
|
||||
}
|
||||
|
||||
TEST(FormatterTest, FormatCustom) {
|
||||
Date date(2012, 12, 9);
|
||||
check_unknown_types(date, "s", "string");
|
||||
EXPECT_EQ(L"The date is 2012-12-9",
|
||||
format(L"The date is {0}", Date(2012, 12, 9)));
|
||||
EXPECT_THROW_MSG(fmt::format("{:s}", date), FormatError,
|
||||
"unmatched '}' in format string");
|
||||
}
|
||||
|
||||
class Answer {};
|
||||
@ -1563,9 +1520,6 @@ TEST(FormatTest, Print) {
|
||||
EXPECT_WRITE(stderr,
|
||||
fmt::print(stderr, "Don't {}!", "panic"), "Don't panic!");
|
||||
#endif
|
||||
std::ostringstream os;
|
||||
fmt::print(os, "Don't {}!", "panic");
|
||||
EXPECT_EQ("Don't panic!", os.str());
|
||||
}
|
||||
|
||||
#if FMT_USE_FILE_DESCRIPTORS
|
||||
@ -1660,27 +1614,12 @@ TEST(LiteralsTest, NamedArg) {
|
||||
}
|
||||
#endif // FMT_USE_USER_DEFINED_LITERALS
|
||||
|
||||
enum TestEnum {};
|
||||
std::ostream &operator<<(std::ostream &os, TestEnum) {
|
||||
return os << "TestEnum";
|
||||
}
|
||||
|
||||
enum TestEnum2 { A };
|
||||
enum TestEnum { A };
|
||||
|
||||
TEST(FormatTest, Enum) {
|
||||
EXPECT_EQ("TestEnum", fmt::format("{}", TestEnum()));
|
||||
EXPECT_EQ("0", fmt::format("{}", A));
|
||||
}
|
||||
|
||||
struct EmptyTest {};
|
||||
std::ostream &operator<<(std::ostream &os, EmptyTest) {
|
||||
return os << "";
|
||||
}
|
||||
|
||||
TEST(FormatTest, EmptyCustomOutput) {
|
||||
EXPECT_EQ("", fmt::format("{}", EmptyTest()));
|
||||
}
|
||||
|
||||
class MockArgFormatter :
|
||||
public fmt::internal::ArgFormatterBase<MockArgFormatter, char> {
|
||||
public:
|
||||
@ -1705,19 +1644,3 @@ FMT_VARIADIC(void, custom_format, const char *)
|
||||
TEST(FormatTest, CustomArgFormatter) {
|
||||
custom_format("{}", 42);
|
||||
}
|
||||
|
||||
struct TestArgFormatter : fmt::BasicArgFormatter<TestArgFormatter, char> {
|
||||
TestArgFormatter(fmt::BasicFormatter<char, TestArgFormatter> &f,
|
||||
fmt::FormatSpec &s, const char *fmt)
|
||||
: fmt::BasicArgFormatter<TestArgFormatter, char>(f, s, fmt) {}
|
||||
};
|
||||
|
||||
TEST(ArgFormatterTest, CustomArg) {
|
||||
fmt::MemoryWriter writer;
|
||||
typedef fmt::BasicFormatter<char, TestArgFormatter> Formatter;
|
||||
Formatter formatter(fmt::ArgList(), writer);
|
||||
fmt::FormatSpec spec;
|
||||
TestArgFormatter af(formatter, spec, "}");
|
||||
af.visit(fmt::internal::MakeArg<Formatter>(TestEnum()));
|
||||
EXPECT_EQ("TestEnum", writer.str());
|
||||
}
|
||||
|
192
test/ostream-test.cc
Normal file
192
test/ostream-test.cc
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
std::ostream support tests
|
||||
|
||||
Copyright (c) 2012-2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fmt/ostream.cc"
|
||||
|
||||
#include <sstream>
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest-extra.h"
|
||||
#include "util.h"
|
||||
|
||||
using fmt::format;
|
||||
using fmt::FormatError;
|
||||
|
||||
template <typename Char>
|
||||
std::basic_ostream<Char> &operator<<(
|
||||
std::basic_ostream<Char> &os, const BasicTestString<Char> &s) {
|
||||
os << s.value();
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Date &d) {
|
||||
os << d.year() << '-' << d.month() << '-' << d.day();
|
||||
return os;
|
||||
}
|
||||
|
||||
std::wostream &operator<<(std::wostream &os, const Date &d) {
|
||||
os << d.year() << L'-' << d.month() << L'-' << d.day();
|
||||
return os;
|
||||
}
|
||||
|
||||
enum TestEnum {};
|
||||
std::ostream &operator<<(std::ostream &os, TestEnum) {
|
||||
return os << "TestEnum";
|
||||
}
|
||||
|
||||
enum TestEnum2 {A};
|
||||
|
||||
TEST(OStreamTest, Enum) {
|
||||
EXPECT_FALSE(fmt::internal::ConvertToInt<TestEnum>::value);
|
||||
EXPECT_EQ("TestEnum", fmt::format("{}", TestEnum()));
|
||||
EXPECT_EQ("0", fmt::format("{}", A));
|
||||
}
|
||||
|
||||
struct TestArgFormatter : fmt::BasicArgFormatter<TestArgFormatter, char> {
|
||||
TestArgFormatter(fmt::BasicFormatter<char, TestArgFormatter> &f,
|
||||
fmt::FormatSpec &s, const char *fmt)
|
||||
: fmt::BasicArgFormatter<TestArgFormatter, char>(f, s, fmt) {}
|
||||
};
|
||||
|
||||
TEST(OStreamTest, CustomArg) {
|
||||
fmt::MemoryWriter writer;
|
||||
typedef fmt::BasicFormatter<char, TestArgFormatter> Formatter;
|
||||
Formatter formatter(fmt::ArgList(), writer);
|
||||
fmt::FormatSpec spec;
|
||||
TestArgFormatter af(formatter, spec, "}");
|
||||
af.visit(fmt::internal::MakeArg<Formatter>(TestEnum()));
|
||||
EXPECT_EQ("TestEnum", writer.str());
|
||||
}
|
||||
|
||||
TEST(OStreamTest, Format) {
|
||||
EXPECT_EQ("a string", format("{0}", TestString("a string")));
|
||||
std::string s = format("The date is {0}", Date(2012, 12, 9));
|
||||
EXPECT_EQ("The date is 2012-12-9", s);
|
||||
Date date(2012, 12, 9);
|
||||
EXPECT_EQ(L"The date is 2012-12-9",
|
||||
format(L"The date is {0}", Date(2012, 12, 9)));
|
||||
}
|
||||
|
||||
TEST(OStreamTest, FormatSpecs) {
|
||||
EXPECT_EQ("def ", format("{0:<5}", TestString("def")));
|
||||
EXPECT_EQ(" def", format("{0:>5}", TestString("def")));
|
||||
EXPECT_THROW_MSG(format("{0:=5}", TestString("def")),
|
||||
FormatError, "format specifier '=' requires numeric argument");
|
||||
EXPECT_EQ(" def ", format("{0:^5}", TestString("def")));
|
||||
EXPECT_EQ("def**", format("{0:*<5}", TestString("def")));
|
||||
EXPECT_THROW_MSG(format("{0:+}", TestString()),
|
||||
FormatError, "format specifier '+' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:-}", TestString()),
|
||||
FormatError, "format specifier '-' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0: }", TestString()),
|
||||
FormatError, "format specifier ' ' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:#}", TestString()),
|
||||
FormatError, "format specifier '#' requires numeric argument");
|
||||
EXPECT_THROW_MSG(format("{0:05}", TestString()),
|
||||
FormatError, "format specifier '0' requires numeric argument");
|
||||
EXPECT_EQ("test ", format("{0:13}", TestString("test")));
|
||||
EXPECT_EQ("test ", format("{0:{1}}", TestString("test"), 13));
|
||||
EXPECT_EQ("te", format("{0:.2}", TestString("test")));
|
||||
EXPECT_EQ("te", format("{0:.{1}}", TestString("test"), 2));
|
||||
}
|
||||
|
||||
struct EmptyTest {};
|
||||
std::ostream &operator<<(std::ostream &os, EmptyTest) {
|
||||
return os << "";
|
||||
}
|
||||
|
||||
TEST(OStreamTest, EmptyCustomOutput) {
|
||||
EXPECT_EQ("", fmt::format("{}", EmptyTest()));
|
||||
}
|
||||
|
||||
TEST(OStreamTest, Print) {
|
||||
std::ostringstream os;
|
||||
fmt::print(os, "Don't {}!", "panic");
|
||||
EXPECT_EQ("Don't panic!", os.str());
|
||||
}
|
||||
|
||||
TEST(OStreamTest, PrintfCustom) {
|
||||
EXPECT_EQ("abc", fmt::sprintf("%s", TestString("abc")));
|
||||
}
|
||||
|
||||
TEST(OStreamTest, FPrintf) {
|
||||
std::ostringstream os;
|
||||
int ret = fmt::fprintf(os, "Don't %s!", "panic");
|
||||
EXPECT_EQ("Don't panic!", os.str());
|
||||
EXPECT_EQ(12, ret);
|
||||
}
|
||||
|
||||
TEST(OStreamTest, WriteToOStream) {
|
||||
std::ostringstream os;
|
||||
fmt::MemoryWriter w;
|
||||
w << "foo";
|
||||
fmt::write(os, w);
|
||||
EXPECT_EQ("foo", os.str());
|
||||
}
|
||||
|
||||
TEST(OStreamTest, WriteToOStreamMaxSize) {
|
||||
std::size_t max_size = std::numeric_limits<std::size_t>::max();
|
||||
std::streamsize max_streamsize = std::numeric_limits<std::streamsize>::max();
|
||||
if (max_size <= fmt::internal::to_unsigned(max_streamsize))
|
||||
return;
|
||||
|
||||
class TestWriter : public fmt::BasicWriter<char> {
|
||||
private:
|
||||
struct TestBuffer : fmt::Buffer<char> {
|
||||
explicit TestBuffer(std::size_t size) { size_ = size; }
|
||||
void grow(std::size_t) {}
|
||||
} buffer_;
|
||||
public:
|
||||
explicit TestWriter(std::size_t size)
|
||||
: fmt::BasicWriter<char>(buffer_), buffer_(size) {}
|
||||
} w(max_size);
|
||||
|
||||
struct MockStreamBuf : std::streambuf {
|
||||
MOCK_METHOD2(xsputn, std::streamsize (const void *s, std::streamsize n));
|
||||
std::streamsize xsputn(const char *s, std::streamsize n) {
|
||||
const void *v = s;
|
||||
return xsputn(v, n);
|
||||
}
|
||||
} buffer;
|
||||
|
||||
struct TestOStream : std::ostream {
|
||||
explicit TestOStream(MockStreamBuf &buffer) : std::ostream(&buffer) {}
|
||||
} os(buffer);
|
||||
|
||||
testing::InSequence sequence;
|
||||
const char *data = 0;
|
||||
std::size_t size = max_size;
|
||||
do {
|
||||
typedef fmt::internal::MakeUnsigned<std::streamsize>::Type UStreamSize;
|
||||
UStreamSize n = std::min<UStreamSize>(
|
||||
size, fmt::internal::to_unsigned(max_streamsize));
|
||||
EXPECT_CALL(buffer, xsputn(data, static_cast<std::streamsize>(n)))
|
||||
.WillOnce(testing::Return(max_streamsize));
|
||||
data += n;
|
||||
size -= static_cast<std::size_t>(n);
|
||||
} while (size != 0);
|
||||
fmt::write(os, w);
|
||||
}
|
@ -447,10 +447,6 @@ TEST(PrintfTest, Pointer) {
|
||||
EXPECT_PRINTF("(nil)", "%p", null_str);
|
||||
}
|
||||
|
||||
TEST(PrintfTest, Custom) {
|
||||
EXPECT_PRINTF("abc", "%s", TestString("abc"));
|
||||
}
|
||||
|
||||
TEST(PrintfTest, Location) {
|
||||
// TODO: test %n
|
||||
}
|
||||
@ -479,12 +475,5 @@ TEST(PrintfTest, PrintfError) {
|
||||
#endif
|
||||
|
||||
TEST(PrintfTest, WideString) {
|
||||
EXPECT_EQ(L"abc", fmt::sprintf(L"%s", TestWString(L"abc")));
|
||||
}
|
||||
|
||||
TEST(PrintfTest, Iostream) {
|
||||
std::ostringstream os;
|
||||
int ret = fmt::fprintf(os, "Don't %s!", "panic");
|
||||
EXPECT_EQ("Don't panic!", os.str());
|
||||
EXPECT_EQ(12, ret);
|
||||
EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc"));
|
||||
}
|
||||
|
@ -62,9 +62,10 @@ using testing::StrictMock;
|
||||
namespace {
|
||||
|
||||
struct Test {};
|
||||
|
||||
template <typename Char>
|
||||
std::basic_ostream<Char> &operator<<(std::basic_ostream<Char> &os, Test) {
|
||||
return os << "test";
|
||||
void format(fmt::BasicFormatter<Char> &f, const Char *, Test) {
|
||||
f.writer() << "test";
|
||||
}
|
||||
|
||||
template <typename Char, typename T>
|
||||
@ -914,14 +915,11 @@ TEST(UtilTest, ReportWindowsError) {
|
||||
#endif // _WIN32
|
||||
|
||||
enum TestEnum2 {};
|
||||
enum TestEnum3 {};
|
||||
std::ostream &operator<<(std::ostream &, TestEnum3);
|
||||
|
||||
TEST(UtilTest, ConvertToInt) {
|
||||
EXPECT_TRUE(fmt::internal::ConvertToInt<char>::enable_conversion);
|
||||
EXPECT_FALSE(fmt::internal::ConvertToInt<const char *>::enable_conversion);
|
||||
EXPECT_TRUE(fmt::internal::ConvertToInt<TestEnum2>::value);
|
||||
EXPECT_FALSE(fmt::internal::ConvertToInt<TestEnum3>::value);
|
||||
}
|
||||
|
||||
#if FMT_USE_ENUM_BASE
|
||||
|
16
test/util.h
16
test/util.h
@ -78,11 +78,7 @@ class BasicTestString {
|
||||
public:
|
||||
explicit BasicTestString(const Char *value = EMPTY) : value_(value) {}
|
||||
|
||||
friend std::basic_ostream<Char> &operator<<(
|
||||
std::basic_ostream<Char> &os, const BasicTestString &s) {
|
||||
os << s.value_;
|
||||
return os;
|
||||
}
|
||||
const std::basic_string<Char> &value() const { return value_; }
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
@ -90,3 +86,13 @@ const Char BasicTestString<Char>::EMPTY[] = {0};
|
||||
|
||||
typedef BasicTestString<char> TestString;
|
||||
typedef BasicTestString<wchar_t> TestWString;
|
||||
|
||||
class Date {
|
||||
int year_, month_, day_;
|
||||
public:
|
||||
Date(int year, int month, int day) : year_(year), month_(month), day_(day) {}
|
||||
|
||||
int year() const { return year_; }
|
||||
int month() const { return month_; }
|
||||
int day() const { return day_; }
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user