diff --git a/format.cc b/format.cc index 38f899c8..ac4535d8 100644 --- a/format.cc +++ b/format.cc @@ -138,7 +138,6 @@ const char RESET_COLOR[] = "\x1b[0m"; typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef); -// TODO: test void format_error_code(fmt::Writer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) { // Report error code making sure that the output fits into @@ -147,12 +146,11 @@ void format_error_code(fmt::Writer &out, int error_code, out.clear(); static const char SEP[] = ": "; static const char ERROR[] = "error "; - // SEP and ERROR add two terminating null characters, so subtract 1 as - // we need only one. fmt::internal::IntTraits::MainType ec_value = error_code; + // Subtract 2 to account for terminating null characters in SEP and ERROR. std::size_t error_code_size = - sizeof(SEP) + sizeof(ERROR) + fmt::internal::count_digits(ec_value) - 1; - if (message.size() < fmt::internal::INLINE_BUFFER_SIZE - error_code_size) + sizeof(SEP) + sizeof(ERROR) + fmt::internal::count_digits(ec_value) - 2; + if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size) out << message << SEP; out << ERROR << error_code; assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE); @@ -160,12 +158,12 @@ void format_error_code(fmt::Writer &out, int error_code, void report_error(FormatFunc func, int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) { - try { - fmt::Writer full_message; - func(full_message, error_code, message); - std::fwrite(full_message.c_str(), full_message.size(), 1, stderr); - std::fputc('\n', stderr); - } catch (...) {} + fmt::Writer full_message; + func(full_message, error_code, message); + // Use Writer::data instead of Writer::c_str to avoid potential memory + // allocation. + std::fwrite(full_message.data(), full_message.size(), 1, stderr); + std::fputc('\n', stderr); } // IsZeroInt::visit(arg) returns true iff arg is a zero integer. diff --git a/format.h b/format.h index abc6db7f..ceb0d85a 100644 --- a/format.h +++ b/format.h @@ -1395,7 +1395,7 @@ class BasicWriter { Returns a pointer to the output buffer content. No terminating null character is appended. */ - const Char *data() const { return &buffer_[0]; } + const Char *data() const FMT_NOEXCEPT(true) { return &buffer_[0]; } /** Returns a pointer to the output buffer content with terminating null diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index 6fc4a330..c4ed2480 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -38,10 +38,35 @@ TEST(FormatTest, ArgConverter) { EXPECT_EQ(Arg::LONG_LONG, arg.type); } -TEST(FormatterTest, FormatNegativeNaN) { +TEST(FormatTest, FormatNegativeNaN) { double nan = std::numeric_limits::quiet_NaN(); if (getsign(-nan)) EXPECT_EQ("-nan", fmt::format("{}", -nan)); else fmt::print("Warning: compiler doesn't handle negative NaN correctly"); } + +TEST(FormatTest, FormatErrorCode) { + std::string msg = "error 42", sep = ": "; + { + fmt::Writer w; + w << "garbage"; + format_error_code(w, 42, "test"); + EXPECT_EQ("test: " + msg, w.str()); + } + { + fmt::Writer w; + std::string prefix( + fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size() + 1, 'x'); + format_error_code(w, 42, prefix); + EXPECT_EQ(msg, w.str()); + } + { + fmt::Writer w; + std::string prefix( + fmt::internal::INLINE_BUFFER_SIZE - msg.size() - sep.size(), 'x'); + format_error_code(w, 42, prefix); + EXPECT_EQ(prefix + sep + msg, w.str()); + EXPECT_EQ(fmt::internal::INLINE_BUFFER_SIZE, w.size()); + } +}