mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-08 12:20:06 +00:00
Purge basic_writer
This commit is contained in:
parent
2f05054dd3
commit
c06851456d
@ -1100,8 +1100,6 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
// is not specified.
|
||||
basic_memory_buffer<Char> buf;
|
||||
auto out = std::back_inserter(buf);
|
||||
using range = internal::output_range<decltype(ctx.out()), Char>;
|
||||
internal::basic_writer<range> w(range(ctx.out()));
|
||||
internal::handle_dynamic_spec<internal::width_checker>(specs.width,
|
||||
width_ref, ctx);
|
||||
internal::handle_dynamic_spec<internal::precision_checker>(
|
||||
@ -1115,8 +1113,8 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
f.precision = precision;
|
||||
parse_chrono_format(begin, end, f);
|
||||
}
|
||||
w.write(buf.data(), buf.size(), specs);
|
||||
return w.out();
|
||||
return internal::write(
|
||||
ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -383,9 +383,7 @@ OutputIt format_default(OutputIt out, T value) {
|
||||
|
||||
template <typename Char, typename OutputIt>
|
||||
OutputIt format_default(OutputIt out, double value) {
|
||||
basic_writer<buffer_range<char>> w(out);
|
||||
w.write(value);
|
||||
return w.out();
|
||||
return internal::write(out, value);
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt>
|
||||
|
@ -1561,6 +1561,16 @@ template <typename OutputIt, typename Char, typename UInt> struct int_writer {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename OutputIt>
|
||||
OutputIt write_bytes(OutputIt out, string_view bytes,
|
||||
const basic_format_specs<Char>& specs) {
|
||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
||||
return write_padded(out, specs, bytes.size(), [bytes](iterator it) {
|
||||
const char* data = bytes.data();
|
||||
return copy_str<Char>(data, data + bytes.size(), it);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt>
|
||||
OutputIt write_nonfinite(OutputIt out, bool isinf,
|
||||
const basic_format_specs<Char>& specs,
|
||||
@ -1577,6 +1587,71 @@ OutputIt write_nonfinite(OutputIt out, bool isinf,
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt, typename T,
|
||||
FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||
OutputIt write(OutputIt out, T value, basic_format_specs<Char> specs = {},
|
||||
locale_ref loc = {}) {
|
||||
if (const_check(!is_supported_floating_point(value))) return out;
|
||||
float_specs fspecs = parse_float_type_spec(specs);
|
||||
fspecs.sign = specs.sign;
|
||||
if (std::signbit(value)) { // value < 0 is false for NaN so use signbit.
|
||||
fspecs.sign = sign::minus;
|
||||
value = -value;
|
||||
} else if (fspecs.sign == sign::minus) {
|
||||
fspecs.sign = sign::none;
|
||||
}
|
||||
|
||||
if (!std::isfinite(value))
|
||||
return write_nonfinite(out, std::isinf(value), specs, fspecs);
|
||||
|
||||
if (specs.align == align::numeric && fspecs.sign) {
|
||||
auto it = reserve(out, 1);
|
||||
*it++ = static_cast<Char>(data::signs[fspecs.sign]);
|
||||
out = base_iterator(out, it);
|
||||
fspecs.sign = sign::none;
|
||||
if (specs.width != 0) --specs.width;
|
||||
}
|
||||
|
||||
memory_buffer buffer;
|
||||
if (fspecs.format == float_format::hex) {
|
||||
if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]);
|
||||
snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
|
||||
return write_bytes(out, {buffer.data(), buffer.size()}, specs);
|
||||
}
|
||||
int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6;
|
||||
if (fspecs.format == float_format::exp) {
|
||||
if (precision == max_value<int>())
|
||||
FMT_THROW(format_error("number is too big"));
|
||||
else
|
||||
++precision;
|
||||
}
|
||||
if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
|
||||
fspecs.use_grisu = use_grisu<T>();
|
||||
int exp = format_float(promote_float(value), precision, fspecs, buffer);
|
||||
fspecs.precision = precision;
|
||||
Char point =
|
||||
fspecs.locale ? decimal_point<Char>(loc) : static_cast<Char>('.');
|
||||
float_writer<Char> w(buffer.data(), static_cast<int>(buffer.size()), exp,
|
||||
fspecs, point);
|
||||
return write_padded<align::right>(out, specs, w.size(), w);
|
||||
}
|
||||
|
||||
template <typename StrChar, typename Char, typename OutputIt>
|
||||
OutputIt write(OutputIt out, basic_string_view<StrChar> s,
|
||||
const basic_format_specs<Char>& specs = {}) {
|
||||
auto data = s.data();
|
||||
auto size = s.size();
|
||||
if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
|
||||
size = code_point_index(s, to_unsigned(specs.precision));
|
||||
auto width = specs.width != 0
|
||||
? count_code_points(basic_string_view<StrChar>(data, size))
|
||||
: 0;
|
||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
||||
return write_padded(out, specs, size, width, [=](iterator it) {
|
||||
return copy_str<Char>(data, data + size, it);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt, typename UIntPtr>
|
||||
OutputIt write_ptr(OutputIt out, UIntPtr value,
|
||||
const basic_format_specs<Char>* specs) {
|
||||
@ -1592,27 +1667,21 @@ OutputIt write_ptr(OutputIt out, UIntPtr value,
|
||||
: base_iterator(out, write(reserve(out, size)));
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt>
|
||||
OutputIt write_bytes(OutputIt out, string_view bytes,
|
||||
const basic_format_specs<Char>& specs) {
|
||||
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
|
||||
return write_padded(out, specs, bytes.size(), [bytes](iterator it) {
|
||||
const char* data = bytes.data();
|
||||
return copy_str<Char>(data, data + bytes.size(), it);
|
||||
});
|
||||
}
|
||||
template <typename T> struct is_integral : std::is_integral<T> {};
|
||||
template <> struct is_integral<int128_t> : std::true_type {};
|
||||
template <> struct is_integral<uint128_t> : std::true_type {};
|
||||
|
||||
// This template provides operations for formatting and writing data into a
|
||||
// character range.
|
||||
template <typename Range> class basic_writer {
|
||||
template <typename Range, typename ErrorHandler = internal::error_handler>
|
||||
class arg_formatter_base {
|
||||
public:
|
||||
using char_type = typename Range::value_type;
|
||||
using iterator = typename Range::iterator;
|
||||
using format_specs = basic_format_specs<char_type>;
|
||||
|
||||
protected:
|
||||
private:
|
||||
iterator out_; // Output iterator.
|
||||
locale_ref locale_;
|
||||
format_specs* specs_;
|
||||
|
||||
// Attempts to reserve space for n extra characters in the output range.
|
||||
// Returns a pointer to the reserved range or a reference to out_.
|
||||
@ -1620,6 +1689,27 @@ template <typename Range> class basic_writer {
|
||||
return internal::reserve(out_, n);
|
||||
}
|
||||
|
||||
using reserve_iterator = remove_reference_t<decltype(
|
||||
internal::reserve(std::declval<iterator&>(), 0))>;
|
||||
|
||||
struct char_writer {
|
||||
char_type value;
|
||||
|
||||
size_t size() const { return 1; }
|
||||
|
||||
template <typename It> It operator()(It it) const {
|
||||
*it++ = value;
|
||||
return it;
|
||||
}
|
||||
};
|
||||
|
||||
void write_char(char_type value) {
|
||||
if (specs_)
|
||||
out_ = write_padded(out_, *specs_, 1, char_writer{value});
|
||||
else
|
||||
write(value);
|
||||
}
|
||||
|
||||
// Writes a decimal integer.
|
||||
template <typename Int> void write_decimal(Int value) {
|
||||
auto abs_value = static_cast<uint32_or_64_or_128_t<Int>>(value);
|
||||
@ -1632,15 +1722,6 @@ template <typename Range> class basic_writer {
|
||||
it = format_decimal<char_type>(it, abs_value, num_digits);
|
||||
}
|
||||
|
||||
using reserve_iterator = remove_reference_t<decltype(
|
||||
internal::reserve(std::declval<iterator&>(), 0))>;
|
||||
|
||||
public:
|
||||
explicit basic_writer(Range out, locale_ref loc = locale_ref())
|
||||
: out_(out.begin()), locale_(loc) {}
|
||||
|
||||
iterator& out() { return out_; }
|
||||
|
||||
void write(int value) { write_decimal(value); }
|
||||
void write(long value) { write_decimal(value); }
|
||||
void write(long long value) { write_decimal(value); }
|
||||
@ -1661,55 +1742,6 @@ template <typename Range> class basic_writer {
|
||||
out_ = w.out;
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||
void write(T value, format_specs specs = {}) {
|
||||
if (const_check(!is_supported_floating_point(value))) return;
|
||||
float_specs fspecs = parse_float_type_spec(specs);
|
||||
fspecs.sign = specs.sign;
|
||||
if (std::signbit(value)) { // value < 0 is false for NaN so use signbit.
|
||||
fspecs.sign = sign::minus;
|
||||
value = -value;
|
||||
} else if (fspecs.sign == sign::minus) {
|
||||
fspecs.sign = sign::none;
|
||||
}
|
||||
|
||||
if (!std::isfinite(value)) {
|
||||
out_ = write_nonfinite(out_, std::isinf(value), specs, fspecs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (specs.align == align::numeric && fspecs.sign) {
|
||||
auto&& it = reserve(1);
|
||||
*it++ = static_cast<char_type>(data::signs[fspecs.sign]);
|
||||
fspecs.sign = sign::none;
|
||||
if (specs.width != 0) --specs.width;
|
||||
}
|
||||
|
||||
memory_buffer buffer;
|
||||
if (fspecs.format == float_format::hex) {
|
||||
if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]);
|
||||
snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
|
||||
out_ = write_bytes(out_, {buffer.data(), buffer.size()}, specs);
|
||||
return;
|
||||
}
|
||||
int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6;
|
||||
if (fspecs.format == float_format::exp) {
|
||||
if (precision == max_value<int>())
|
||||
FMT_THROW(format_error("number is too big"));
|
||||
else
|
||||
++precision;
|
||||
}
|
||||
if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
|
||||
fspecs.use_grisu = use_grisu<T>();
|
||||
int exp = format_float(promote_float(value), precision, fspecs, buffer);
|
||||
fspecs.precision = precision;
|
||||
char_type point = fspecs.locale ? decimal_point<char_type>(locale_)
|
||||
: static_cast<char_type>('.');
|
||||
float_writer<char_type> w(buffer.data(), static_cast<int>(buffer.size()),
|
||||
exp, fspecs, point);
|
||||
out_ = write_padded<align::right>(out_, specs, w.size(), w);
|
||||
}
|
||||
|
||||
void write(char value) {
|
||||
auto&& it = reserve(1);
|
||||
*it++ = value;
|
||||
@ -1743,49 +1775,7 @@ template <typename Range> class basic_writer {
|
||||
|
||||
template <typename Char>
|
||||
void write(basic_string_view<Char> s, const format_specs& specs = {}) {
|
||||
const Char* data = s.data();
|
||||
std::size_t size = s.size();
|
||||
if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
|
||||
size = code_point_index(s, to_unsigned(specs.precision));
|
||||
write(data, size, specs);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct is_integral : std::is_integral<T> {};
|
||||
template <> struct is_integral<int128_t> : std::true_type {};
|
||||
template <> struct is_integral<uint128_t> : std::true_type {};
|
||||
|
||||
template <typename Range, typename ErrorHandler = internal::error_handler>
|
||||
class arg_formatter_base : private basic_writer<Range> {
|
||||
public:
|
||||
using char_type = typename Range::value_type;
|
||||
using iterator = typename Range::iterator;
|
||||
using format_specs = basic_format_specs<char_type>;
|
||||
|
||||
private:
|
||||
using writer_type = basic_writer<Range>;
|
||||
using writer_type::out_;
|
||||
format_specs* specs_;
|
||||
|
||||
using writer_type::write;
|
||||
using writer_type::write_int;
|
||||
|
||||
struct char_writer {
|
||||
char_type value;
|
||||
|
||||
size_t size() const { return 1; }
|
||||
|
||||
template <typename It> It operator()(It it) const {
|
||||
*it++ = value;
|
||||
return it;
|
||||
}
|
||||
};
|
||||
|
||||
void write_char(char_type value) {
|
||||
if (specs_)
|
||||
out() = write_padded(out(), *specs_, 1, char_writer{value});
|
||||
else
|
||||
write(value);
|
||||
out_ = internal::write(out_, s, specs);
|
||||
}
|
||||
|
||||
void write_pointer(const void* p) {
|
||||
@ -1793,8 +1783,7 @@ class arg_formatter_base : private basic_writer<Range> {
|
||||
}
|
||||
|
||||
protected:
|
||||
using writer_type::out;
|
||||
writer_type& writer() { return *this; }
|
||||
iterator out() { return out_; }
|
||||
format_specs* specs() { return specs_; }
|
||||
|
||||
void write(bool value) {
|
||||
@ -1814,7 +1803,7 @@ class arg_formatter_base : private basic_writer<Range> {
|
||||
|
||||
public:
|
||||
arg_formatter_base(Range r, format_specs* s, locale_ref loc)
|
||||
: basic_writer<Range>(r, loc), specs_(s) {}
|
||||
: out_(r.begin()), locale_(loc), specs_(s) {}
|
||||
|
||||
iterator operator()(monostate) {
|
||||
FMT_ASSERT(false, "invalid argument type");
|
||||
@ -1844,8 +1833,9 @@ class arg_formatter_base : private basic_writer<Range> {
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||
iterator operator()(T value) {
|
||||
auto specs = specs_ ? *specs_ : format_specs();
|
||||
if (const_check(is_supported_floating_point(value)))
|
||||
write(value, specs_ ? *specs_ : format_specs());
|
||||
out_ = internal::write(out_, value, specs, locale_);
|
||||
else
|
||||
FMT_ASSERT(false, "unsupported float argument type");
|
||||
return out();
|
||||
@ -2503,7 +2493,7 @@ template <typename Handler, typename Char> struct id_adapter {
|
||||
template <bool IS_CONSTEXPR, typename Char, typename Handler>
|
||||
FMT_CONSTEXPR void parse_format_string(basic_string_view<Char> format_str,
|
||||
Handler&& handler) {
|
||||
struct pfs_writer {
|
||||
struct writer {
|
||||
FMT_CONSTEXPR void operator()(const Char* begin, const Char* end) {
|
||||
if (begin == end) return;
|
||||
for (;;) {
|
||||
@ -3336,21 +3326,21 @@ extern template FMT_API char thousands_sep_impl<char>(locale_ref loc);
|
||||
extern template FMT_API wchar_t thousands_sep_impl<wchar_t>(locale_ref loc);
|
||||
extern template FMT_API char decimal_point_impl(locale_ref loc);
|
||||
extern template FMT_API wchar_t decimal_point_impl(locale_ref loc);
|
||||
extern template
|
||||
int format_float<double>(double value, int precision, float_specs specs,
|
||||
buffer<char>& buf);
|
||||
extern template
|
||||
int format_float<long double>(long double value, int precision,
|
||||
float_specs specs, buffer<char>& buf);
|
||||
extern template int format_float<double>(double value, int precision,
|
||||
float_specs specs, buffer<char>& buf);
|
||||
extern template int format_float<long double>(long double value, int precision,
|
||||
float_specs specs,
|
||||
buffer<char>& buf);
|
||||
int snprintf_float(float value, int precision, float_specs specs,
|
||||
buffer<char>& buf) = delete;
|
||||
extern template
|
||||
int snprintf_float<double>(double value, int precision, float_specs specs,
|
||||
buffer<char>& buf);
|
||||
extern template
|
||||
int snprintf_float<long double>(long double value, int precision,
|
||||
float_specs specs, buffer<char>& buf);
|
||||
}
|
||||
extern template int snprintf_float<double>(double value, int precision,
|
||||
float_specs specs,
|
||||
buffer<char>& buf);
|
||||
extern template int snprintf_float<long double>(long double value,
|
||||
int precision,
|
||||
float_specs specs,
|
||||
buffer<char>& buf);
|
||||
} // namespace internal
|
||||
#endif
|
||||
|
||||
template <typename S, typename Char = char_t<S>,
|
||||
|
@ -328,7 +328,9 @@ template <typename T> struct printf_formatter {
|
||||
}
|
||||
};
|
||||
|
||||
/** This template formats data and writes the output to a writer. */
|
||||
/**
|
||||
This template formats data and writes the output through an output iterator.
|
||||
*/
|
||||
template <typename OutputIt, typename Char> class basic_printf_context {
|
||||
public:
|
||||
/** The character type for the output. */
|
||||
@ -358,9 +360,8 @@ template <typename OutputIt, typename Char> class basic_printf_context {
|
||||
public:
|
||||
/**
|
||||
\rst
|
||||
Constructs a ``printf_context`` object. References to the arguments and
|
||||
the writer are stored in the context object so make sure they have
|
||||
appropriate lifetimes.
|
||||
Constructs a ``printf_context`` object. References to the arguments are
|
||||
stored in the context object so make sure they have appropriate lifetimes.
|
||||
\endrst
|
||||
*/
|
||||
basic_printf_context(OutputIt out, basic_string_view<char_type> format_str,
|
||||
|
@ -35,8 +35,6 @@
|
||||
#include "util.h"
|
||||
|
||||
#undef ERROR
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
using std::size_t;
|
||||
|
||||
@ -47,7 +45,6 @@ using fmt::memory_buffer;
|
||||
using fmt::string_view;
|
||||
using fmt::wmemory_buffer;
|
||||
using fmt::wstring_view;
|
||||
using fmt::internal::basic_writer;
|
||||
using fmt::internal::max_value;
|
||||
|
||||
using testing::Return;
|
||||
@ -102,47 +99,6 @@ void std_format(long double value, std::wstring& result) {
|
||||
result = buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Checks if writing value to BasicWriter<Char> produces the same result
|
||||
// as writing it to std::basic_ostringstream<Char>.
|
||||
template <typename Char, typename T>
|
||||
::testing::AssertionResult check_write(const T& value, const char* type) {
|
||||
fmt::basic_memory_buffer<Char> buffer;
|
||||
using range = fmt::buffer_range<Char>;
|
||||
basic_writer<range> writer(buffer);
|
||||
writer.write(value);
|
||||
std::basic_string<Char> actual = to_string(buffer);
|
||||
std::basic_string<Char> expected;
|
||||
std_format(value, expected);
|
||||
if (expected == actual) return ::testing::AssertionSuccess();
|
||||
return ::testing::AssertionFailure()
|
||||
<< "Value of: (Writer<" << type << ">() << value).str()\n"
|
||||
<< " Actual: " << actual << "\n"
|
||||
<< "Expected: " << expected << "\n";
|
||||
}
|
||||
|
||||
struct AnyWriteChecker {
|
||||
template <typename T>
|
||||
::testing::AssertionResult operator()(const char*, const T& value) const {
|
||||
::testing::AssertionResult result = check_write<char>(value, "char");
|
||||
return result ? check_write<wchar_t>(value, "wchar_t") : result;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char> struct WriteChecker {
|
||||
template <typename T>
|
||||
::testing::AssertionResult operator()(const char*, const T& value) const {
|
||||
return check_write<Char>(value, "char");
|
||||
}
|
||||
};
|
||||
|
||||
// Checks if writing value to BasicWriter produces the same result
|
||||
// as writing it to std::ostringstream both for char and wchar_t.
|
||||
#define CHECK_WRITE(value) EXPECT_PRED_FORMAT1(AnyWriteChecker(), value)
|
||||
|
||||
#define CHECK_WRITE_CHAR(value) EXPECT_PRED_FORMAT1(WriteChecker<char>(), value)
|
||||
#define CHECK_WRITE_WCHAR(value) \
|
||||
EXPECT_PRED_FORMAT1(WriteChecker<wchar_t>(), value)
|
||||
} // namespace
|
||||
|
||||
struct uint32_pair {
|
||||
@ -479,92 +435,6 @@ TEST(StringViewTest, Ctor) {
|
||||
EXPECT_EQ(4u, string_view(std::string("defg")).size());
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteInt) {
|
||||
CHECK_WRITE(42);
|
||||
CHECK_WRITE(-42);
|
||||
CHECK_WRITE(static_cast<short>(12));
|
||||
CHECK_WRITE(34u);
|
||||
CHECK_WRITE(std::numeric_limits<int>::min());
|
||||
CHECK_WRITE(max_value<int>());
|
||||
CHECK_WRITE(max_value<unsigned>());
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteLong) {
|
||||
CHECK_WRITE(56l);
|
||||
CHECK_WRITE(78ul);
|
||||
CHECK_WRITE(std::numeric_limits<long>::min());
|
||||
CHECK_WRITE(max_value<long>());
|
||||
CHECK_WRITE(max_value<unsigned long>());
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteLongLong) {
|
||||
CHECK_WRITE(56ll);
|
||||
CHECK_WRITE(78ull);
|
||||
CHECK_WRITE(std::numeric_limits<long long>::min());
|
||||
CHECK_WRITE(max_value<long long>());
|
||||
CHECK_WRITE(max_value<unsigned long long>());
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteDouble) {
|
||||
CHECK_WRITE(4.2);
|
||||
CHECK_WRITE(-4.2);
|
||||
auto min = std::numeric_limits<double>::min();
|
||||
auto max = max_value<double>();
|
||||
if (fmt::internal::use_grisu<double>()) {
|
||||
EXPECT_EQ("2.2250738585072014e-308", fmt::format("{}", min));
|
||||
EXPECT_EQ("1.7976931348623157e+308", fmt::format("{}", max));
|
||||
} else {
|
||||
CHECK_WRITE(min);
|
||||
CHECK_WRITE(max);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteLongDouble) {
|
||||
CHECK_WRITE(4.2l);
|
||||
CHECK_WRITE_CHAR(-4.2l);
|
||||
std::wstring str;
|
||||
std_format(4.2l, str);
|
||||
if (str[0] != '-')
|
||||
CHECK_WRITE_WCHAR(-4.2l);
|
||||
else
|
||||
fmt::print("warning: long double formatting with std::swprintf is broken");
|
||||
auto min = std::numeric_limits<long double>::min();
|
||||
auto max = max_value<long double>();
|
||||
if (fmt::internal::use_grisu<long double>()) {
|
||||
EXPECT_EQ("2.2250738585072014e-308", fmt::format("{}", min));
|
||||
EXPECT_EQ("1.7976931348623157e+308", fmt::format("{}", max));
|
||||
} else {
|
||||
CHECK_WRITE(min);
|
||||
CHECK_WRITE(max);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteDoubleAtBufferBoundary) {
|
||||
memory_buffer buf;
|
||||
for (int i = 0; i < 100; ++i) fmt::format_to(buf, "{}", 1.23456789);
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteDoubleWithFilledBuffer) {
|
||||
memory_buffer buf;
|
||||
// Fill the buffer.
|
||||
for (int i = 0; i < fmt::inline_buffer_size; ++i) fmt::format_to(buf, " ");
|
||||
fmt::format_to(buf, "{}", 1.2);
|
||||
fmt::string_view sv(buf.data(), buf.size());
|
||||
sv.remove_prefix(fmt::inline_buffer_size);
|
||||
EXPECT_EQ("1.2", sv);
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteChar) { CHECK_WRITE('a'); }
|
||||
|
||||
TEST(WriterTest, WriteWideChar) { CHECK_WRITE_WCHAR(L'a'); }
|
||||
|
||||
TEST(WriterTest, WriteString) {
|
||||
CHECK_WRITE_CHAR("abc");
|
||||
CHECK_WRITE_WCHAR("abc");
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteWideString) { CHECK_WRITE_WCHAR(L"abc"); }
|
||||
|
||||
TEST(FormatToTest, FormatWithoutArgs) {
|
||||
std::string s;
|
||||
fmt::format_to(std::back_inserter(s), "test");
|
||||
|
Loading…
Reference in New Issue
Block a user