diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 1ea9ad627f62..24347bf977b2 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -762,15 +762,24 @@ inline std::chrono::duration get_milliseconds( return std::chrono::duration(static_cast(ms)); } -template +template ::value)> +OutputIt format_duration_value(OutputIt out, Rep val, int) { + static FMT_CONSTEXPR_DECL const Char format[] = {'{', '}', 0}; + return format_to(out, compile_string_to_view(format), val); +} + +template ::value)> OutputIt format_duration_value(OutputIt out, Rep val, int precision) { - const Char pr_f[] = {'{', ':', '.', '{', '}', 'f', '}', 0}; - if (precision >= 0) return format_to(out, pr_f, val, precision); - const Char fp_f[] = {'{', ':', 'g', '}', 0}; - const Char format[] = {'{', '}', 0}; - return format_to(out, std::is_floating_point::value ? fp_f : format, - val); + static FMT_CONSTEXPR_DECL const Char pr_f[] = {'{', ':', '.', '{', + '}', 'f', '}', 0}; + if (precision >= 0) + return format_to(out, compile_string_to_view(pr_f), val, precision); + static FMT_CONSTEXPR_DECL const Char fp_f[] = {'{', ':', 'g', '}', 0}; + return format_to(out, compile_string_to_view(fp_f), val); } + template OutputIt copy_unit(string_view unit, OutputIt out, Char) { return std::copy(unit.begin(), unit.end(), out); @@ -788,10 +797,13 @@ template OutputIt format_duration_unit(OutputIt out) { if (const char* unit = get_units()) return copy_unit(string_view(unit), out, Char()); - const Char num_f[] = {'[', '{', '}', ']', 's', 0}; - if (const_check(Period::den == 1)) return format_to(out, num_f, Period::num); - const Char num_def_f[] = {'[', '{', '}', '/', '{', '}', ']', 's', 0}; - return format_to(out, num_def_f, Period::num, Period::den); + static FMT_CONSTEXPR_DECL const Char num_f[] = {'[', '{', '}', ']', 's', 0}; + if (const_check(Period::den == 1)) + return format_to(out, compile_string_to_view(num_f), Period::num); + static FMT_CONSTEXPR_DECL const Char num_def_f[] = {'[', '{', '}', '/', '{', + '}', ']', 's', 0}; + return format_to(out, compile_string_to_view(num_def_f), Period::num, + Period::den); } template & out, int error_code, error_code_size += detail::to_unsigned(detail::count_digits(abs_value)); auto it = buffer_appender(out); if (message.size() <= inline_buffer_size - error_code_size) - format_to(it, "{}{}", message, SEP); - format_to(it, "{}{}", ERROR_STR, error_code); + format_to(it, FMT_STRING("{}{}"), message, SEP); + format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code); assert(out.size() <= inline_buffer_size); } @@ -2662,14 +2662,15 @@ template <> struct formatter { for (auto i = n.bigits_.size(); i > 0; --i) { auto value = n.bigits_[i - 1u]; if (first) { - out = format_to(out, "{:x}", value); + out = format_to(out, FMT_STRING("{:x}"), value); first = false; continue; } - out = format_to(out, "{:08x}", value); + out = format_to(out, FMT_STRING("{:08x}"), value); } if (n.exp_ > 0) - out = format_to(out, "p{}", n.exp_ * detail::bigint::bigit_bits); + out = format_to(out, FMT_STRING("p{}"), + n.exp_ * detail::bigint::bigit_bits); return out; } }; @@ -2715,8 +2716,8 @@ FMT_FUNC void format_system_error(detail::buffer& out, int error_code, int result = detail::safe_strerror(error_code, system_message, buf.size()); if (result == 0) { - format_to(detail::buffer_appender(out), "{}: {}", message, - system_message); + format_to(detail::buffer_appender(out), FMT_STRING("{}: {}"), + message, system_message); return; } if (result != ERANGE) diff --git a/test/format-test.cc b/test/format-test.cc index 77a6ded617ed..4b3d410cb8f1 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -355,22 +355,20 @@ TEST(MemoryBufferTest, ExceptionInDeallocate) { } template -class allocator_max_size: public Allocator { +class allocator_max_size : public Allocator { public: using typename Allocator::value_type; - size_t max_size() const FMT_NOEXCEPT { - return MaxSize; - } + size_t max_size() const FMT_NOEXCEPT { return MaxSize; } value_type* allocate(size_t n) { if (n > max_size()) { throw std::length_error("size > max_size"); } return std::allocator_traits::allocate( - *static_cast(this), n); + *static_cast(this), n); } void deallocate(value_type* p, size_t n) { - std::allocator_traits::deallocate( - *static_cast(this), p, n); + std::allocator_traits::deallocate(*static_cast(this), + p, n); } }; @@ -383,7 +381,7 @@ TEST(MemoryBufferTest, AllocatorMaxSize) { try { // new_capacity = 128 + 128/2 = 192 > 160 buffer.resize(160); - } catch (const std::exception &) { + } catch (const std::exception&) { throws_on_resize = true; } EXPECT_FALSE(throws_on_resize); @@ -395,7 +393,7 @@ TEST(MemoryBufferTest, AllocatorMaxSizeOverflow) { bool throws_on_resize = false; try { buffer.resize(161); - } catch (const std::exception &) { + } catch (const std::exception&) { throws_on_resize = true; } EXPECT_TRUE(throws_on_resize); @@ -1807,11 +1805,28 @@ fmt::string_view to_string_view(string_like) { return "foo"; } constexpr char with_null[3] = {'{', '}', '\0'}; constexpr char no_null[2] = {'{', '}'}; +static FMT_CONSTEXPR_DECL const char static_with_null[3] = {'{', '}', '\0'}; +static FMT_CONSTEXPR_DECL const wchar_t static_with_null_wide[3] = {'{', '}', + '\0'}; +static FMT_CONSTEXPR_DECL const char static_no_null[2] = {'{', '}'}; +static FMT_CONSTEXPR_DECL const wchar_t static_no_null_wide[2] = {'{', '}'}; TEST(FormatTest, CompileTimeString) { EXPECT_EQ("42", fmt::format(FMT_STRING("{}"), 42)); EXPECT_EQ(L"42", fmt::format(FMT_STRING(L"{}"), 42)); EXPECT_EQ("foo", fmt::format(FMT_STRING("{}"), string_like())); + + (void)static_with_null; + (void)static_with_null_wide; + (void)static_no_null; + (void)static_no_null_wide; +#if !defined(_MSC_VER) + EXPECT_EQ("42", fmt::format(FMT_STRING(static_with_null), 42)); + EXPECT_EQ(L"42", fmt::format(FMT_STRING(static_with_null_wide), 42)); + EXPECT_EQ("42", fmt::format(FMT_STRING(static_no_null), 42)); + EXPECT_EQ(L"42", fmt::format(FMT_STRING(static_no_null_wide), 42)); +#endif + (void)with_null; (void)no_null; #if __cplusplus >= 201703L