fix: [imp] long string formatting output

This commit is contained in:
mutouyun 2022-12-04 19:07:55 +08:00
parent 80c8d112b1
commit 46a6228c34
4 changed files with 59 additions and 51 deletions

View File

@ -15,19 +15,19 @@ void imp_fmt_string(benchmark::State &state) {
} }
} }
void imp_fmt_multi_string(benchmark::State &state) { void imp_multi_fmt_string(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = imp::fmt("hello world.", "hello world.", "hello world.", "hello world.", "hello world."); std::ignore = imp::fmt("hello world.", "hello world.", "hello world.", "hello world.", "hello world.");
} }
} }
void fmt_format_string(benchmark::State &state) { void fmt_fmt_string(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = fmt::format("hello world.hello world.hello world.hello world.hello world."); std::ignore = fmt::format("hello world.hello world.hello world.hello world.hello world.");
} }
} }
void fmt_format_multi_string(benchmark::State &state) { void fmt_multi_fmt_string(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = fmt::format("{}{}{}{}{}", std::ignore = fmt::format("{}{}{}{}{}",
"hello world.", " hello world.", " hello world.", " hello world.", " hello world."); "hello world.", " hello world.", " hello world.", " hello world.", " hello world.");
@ -40,19 +40,19 @@ void imp_fmt_int(benchmark::State &state) {
} }
} }
void imp_fmt_multi_int(benchmark::State &state) { void imp_multi_fmt_int(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = imp::fmt(654321, 654321, 654321, 654321, 654321); std::ignore = imp::fmt(654321, 654321, 654321, 654321, 654321);
} }
} }
void fmt_format_int(benchmark::State &state) { void fmt_fmt_int(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = fmt::format("{}", 654321); std::ignore = fmt::format("{}", 654321);
} }
} }
void fmt_format_multi_int(benchmark::State &state) { void fmt_multi_fmt_int(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = fmt::format("{}{}{}{}{}", 654321, 654321, 654321, 654321, 654321); std::ignore = fmt::format("{}{}{}{}{}", 654321, 654321, 654321, 654321, 654321);
} }
@ -64,19 +64,19 @@ void imp_fmt_float(benchmark::State &state) {
} }
} }
void imp_fmt_multi_float(benchmark::State &state) { void imp_multi_fmt_float(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = imp::fmt(654.321, 654.321, 654.321, 654.321, 654.321); std::ignore = imp::fmt(654.321, 654.321, 654.321, 654.321, 654.321);
} }
} }
void fmt_format_float(benchmark::State &state) { void fmt_fmt_float(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = fmt::format("{}", 654.321); std::ignore = fmt::format("{}", 654.321);
} }
} }
void fmt_format_multi_float(benchmark::State &state) { void fmt_multi_fmt_float(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = fmt::format("{}{}{}{}{}", 654.321, 654.321, 654.321, 654.321, 654.321); std::ignore = fmt::format("{}{}{}{}{}", 654.321, 654.321, 654.321, 654.321, 654.321);
} }
@ -88,7 +88,7 @@ void imp_fmt_chrono(benchmark::State &state) {
} }
} }
void fmt_format_chrono(benchmark::State &state) { void fmt_fmt_chrono(benchmark::State &state) {
for (auto _ : state) { for (auto _ : state) {
std::ignore = fmt::format("{}", std::chrono::system_clock::now()); std::ignore = fmt::format("{}", std::chrono::system_clock::now());
} }
@ -97,18 +97,18 @@ void fmt_format_chrono(benchmark::State &state) {
} // namespace } // namespace
BENCHMARK(imp_fmt_string); BENCHMARK(imp_fmt_string);
BENCHMARK(fmt_format_string); BENCHMARK(fmt_fmt_string);
BENCHMARK(imp_fmt_int); BENCHMARK(imp_fmt_int);
BENCHMARK(fmt_format_int); BENCHMARK(fmt_fmt_int);
BENCHMARK(imp_fmt_float); BENCHMARK(imp_fmt_float);
BENCHMARK(fmt_format_float); BENCHMARK(fmt_fmt_float);
BENCHMARK(imp_fmt_multi_string); BENCHMARK(imp_multi_fmt_string);
BENCHMARK(fmt_format_multi_string); BENCHMARK(fmt_multi_fmt_string);
BENCHMARK(imp_fmt_multi_int); BENCHMARK(imp_multi_fmt_int);
BENCHMARK(fmt_format_multi_int); BENCHMARK(fmt_multi_fmt_int);
BENCHMARK(imp_fmt_multi_float); BENCHMARK(imp_multi_fmt_float);
BENCHMARK(fmt_format_multi_float); BENCHMARK(fmt_multi_fmt_float);
BENCHMARK(imp_fmt_chrono); BENCHMARK(imp_fmt_chrono);
BENCHMARK(fmt_format_chrono); BENCHMARK(fmt_fmt_chrono);

View File

@ -35,9 +35,8 @@ public:
std::size_t capacity() noexcept; std::size_t capacity() noexcept;
void reset() noexcept; void reset() noexcept;
bool finish() noexcept; bool finish() noexcept;
bool resize(std::size_t sz) noexcept; span<char> buffer(std::size_t sz) noexcept;
span<char> buffer() noexcept; void expend(std::size_t sz) noexcept;
bool expend(std::size_t sz) noexcept;
bool append(std::string const &str) noexcept; bool append(std::string const &str) noexcept;
}; };

View File

@ -111,17 +111,15 @@ span<char> fmt_of_float(span<char const> fstr, span<char const> const &l) {
template <typename A /*a fundamental or pointer type*/> template <typename A /*a fundamental or pointer type*/>
int sprintf(fmt_context &ctx, span<char const> const &sfmt, A a) { int sprintf(fmt_context &ctx, span<char const> const &sfmt, A a) {
for (;;) { for (int sz = -1;;) {
auto sbuf = ctx.buffer(); auto sbuf = ctx.buffer(sz + 1);
auto sz = std::snprintf(sbuf.data(), sbuf.size(), sfmt.data(), a); sz = std::snprintf(sbuf.data(), sbuf.size(), sfmt.data(), a);
if (sz <= 0) { if (sz <= 0) {
return sz; return sz;
} }
if (sz < sbuf.size()) { if (sz < sbuf.size()) {
return ctx.expend(sz) ? sz : -1; ctx.expend(sz);
} return sz;
if (!ctx.resize(sz + 1)) {
return -1;
} }
} }
} }
@ -165,38 +163,35 @@ bool fmt_context::finish() noexcept {
} }
} }
bool fmt_context::resize(std::size_t sz) noexcept { span<char> fmt_context::buffer(std::size_t sz) noexcept {
LIBIMP_TRY { LIBIMP_TRY {
if (sz < sbuf_.size()) { if (offset_ < sbuf_.size()) {
return true; if ((offset_ + sz) < sbuf_.size()) {
return make_span(sbuf_).subspan(offset_);
} else {
/// @remark switch the cache to std::string
joined_.assign(sbuf_.data(), offset_);
joined_.resize(roundup(offset_ + sz));
}
} else if ((offset_ + sz) >= joined_.size()) {
joined_.resize(roundup(offset_ + sz));
} }
joined_.resize(roundup(sz));
return true;
} LIBIMP_CATCH(...) {
return false;
}
}
span<char> fmt_context::buffer() noexcept {
if (offset_ < sbuf_.size()) {
return make_span(sbuf_).subspan(offset_);
} else {
return {&joined_[offset_], joined_.size() - offset_}; return {&joined_[offset_], joined_.size() - offset_};
} LIBIMP_CATCH(...) {
return {};
} }
} }
bool fmt_context::expend(std::size_t sz) noexcept { void fmt_context::expend(std::size_t sz) noexcept {
if ((offset_ += sz) < sbuf_.size()) { offset_ += sz;
return true;
}
return (offset_ < joined_.size()) || resize(offset_);
} }
bool fmt_context::append(std::string const &str) noexcept { bool fmt_context::append(std::string const &str) noexcept {
if ((buffer().size() < str.size()) && !resize(offset_ + str.size())) { auto sbuf = buffer(str.size());
if (sbuf.size() < str.size()) {
return false; return false;
} }
std::memcpy(buffer().data(), str.data(), str.size()); std::memcpy(sbuf.data(), str.data(), str.size());
offset_ += str.size(); offset_ += str.size();
return true; return true;
} }

View File

@ -92,9 +92,23 @@ TEST(fmt, to_string) {
} }
TEST(fmt, fmt) { TEST(fmt, fmt) {
/// @brief hello world
auto s = imp::fmt("hello", " ", "world", "."); auto s = imp::fmt("hello", " ", "world", ".");
EXPECT_EQ(s, "hello world."); EXPECT_EQ(s, "hello world.");
/// @brief chrono
std::cout << imp::fmt('[', std::chrono::system_clock::now(), "] ", s) << "\n"; std::cout << imp::fmt('[', std::chrono::system_clock::now(), "] ", s) << "\n";
/// @brief long string
s = imp::fmt(imp::spec("1024")("hello world."));
EXPECT_EQ(s, " "
" "
" "
" "
" "
" "
" "
" hello world.");
} }
namespace { namespace {