From 8a79e9a86b5e23d2a5f23b7e7969fd3c8771d766 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Sun, 4 Dec 2022 19:07:55 +0800 Subject: [PATCH] fix: [imp] long string formatting output --- benchmark/benchmark_fmt.cpp | 40 ++++++++++++++--------------- include/libimp/fmt_cpo.h | 5 ++-- src/libimp/fmt.cpp | 51 +++++++++++++++++-------------------- test/imp/test_imp_fmt.cpp | 14 ++++++++++ 4 files changed, 59 insertions(+), 51 deletions(-) diff --git a/benchmark/benchmark_fmt.cpp b/benchmark/benchmark_fmt.cpp index be39e1a..8017544 100644 --- a/benchmark/benchmark_fmt.cpp +++ b/benchmark/benchmark_fmt.cpp @@ -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) { 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) { 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) { std::ignore = fmt::format("{}{}{}{}{}", "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) { 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) { std::ignore = fmt::format("{}", 654321); } } -void fmt_format_multi_int(benchmark::State &state) { +void fmt_multi_fmt_int(benchmark::State &state) { for (auto _ : state) { 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) { 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) { 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) { 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) { std::ignore = fmt::format("{}", std::chrono::system_clock::now()); } @@ -97,18 +97,18 @@ void fmt_format_chrono(benchmark::State &state) { } // namespace BENCHMARK(imp_fmt_string); -BENCHMARK(fmt_format_string); +BENCHMARK(fmt_fmt_string); BENCHMARK(imp_fmt_int); -BENCHMARK(fmt_format_int); +BENCHMARK(fmt_fmt_int); BENCHMARK(imp_fmt_float); -BENCHMARK(fmt_format_float); +BENCHMARK(fmt_fmt_float); -BENCHMARK(imp_fmt_multi_string); -BENCHMARK(fmt_format_multi_string); -BENCHMARK(imp_fmt_multi_int); -BENCHMARK(fmt_format_multi_int); -BENCHMARK(imp_fmt_multi_float); -BENCHMARK(fmt_format_multi_float); +BENCHMARK(imp_multi_fmt_string); +BENCHMARK(fmt_multi_fmt_string); +BENCHMARK(imp_multi_fmt_int); +BENCHMARK(fmt_multi_fmt_int); +BENCHMARK(imp_multi_fmt_float); +BENCHMARK(fmt_multi_fmt_float); BENCHMARK(imp_fmt_chrono); -BENCHMARK(fmt_format_chrono); +BENCHMARK(fmt_fmt_chrono); diff --git a/include/libimp/fmt_cpo.h b/include/libimp/fmt_cpo.h index 48437f5..3d94ec5 100644 --- a/include/libimp/fmt_cpo.h +++ b/include/libimp/fmt_cpo.h @@ -35,9 +35,8 @@ public: std::size_t capacity() noexcept; void reset() noexcept; bool finish() noexcept; - bool resize(std::size_t sz) noexcept; - span buffer() noexcept; - bool expend(std::size_t sz) noexcept; + span buffer(std::size_t sz) noexcept; + void expend(std::size_t sz) noexcept; bool append(std::string const &str) noexcept; }; diff --git a/src/libimp/fmt.cpp b/src/libimp/fmt.cpp index c2ba502..587b99b 100644 --- a/src/libimp/fmt.cpp +++ b/src/libimp/fmt.cpp @@ -111,17 +111,15 @@ span fmt_of_float(span fstr, span const &l) { template int sprintf(fmt_context &ctx, span const &sfmt, A a) { - for (;;) { - auto sbuf = ctx.buffer(); - auto sz = std::snprintf(sbuf.data(), sbuf.size(), sfmt.data(), a); + for (int sz = -1;;) { + auto sbuf = ctx.buffer(sz + 1); + sz = std::snprintf(sbuf.data(), sbuf.size(), sfmt.data(), a); if (sz <= 0) { return sz; } if (sz < sbuf.size()) { - return ctx.expend(sz) ? sz : -1; - } - if (!ctx.resize(sz + 1)) { - return -1; + ctx.expend(sz); + return sz; } } } @@ -165,38 +163,35 @@ bool fmt_context::finish() noexcept { } } -bool fmt_context::resize(std::size_t sz) noexcept { +span fmt_context::buffer(std::size_t sz) noexcept { LIBIMP_TRY { - if (sz < sbuf_.size()) { - return true; + if (offset_ < sbuf_.size()) { + 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 fmt_context::buffer() noexcept { - if (offset_ < sbuf_.size()) { - return make_span(sbuf_).subspan(offset_); - } else { return {&joined_[offset_], joined_.size() - offset_}; + } LIBIMP_CATCH(...) { + return {}; } } -bool fmt_context::expend(std::size_t sz) noexcept { - if ((offset_ += sz) < sbuf_.size()) { - return true; - } - return (offset_ < joined_.size()) || resize(offset_); +void fmt_context::expend(std::size_t sz) noexcept { + offset_ += sz; } 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; } - std::memcpy(buffer().data(), str.data(), str.size()); + std::memcpy(sbuf.data(), str.data(), str.size()); offset_ += str.size(); return true; } diff --git a/test/imp/test_imp_fmt.cpp b/test/imp/test_imp_fmt.cpp index 235ebff..3e0e39c 100644 --- a/test/imp/test_imp_fmt.cpp +++ b/test/imp/test_imp_fmt.cpp @@ -92,9 +92,23 @@ TEST(fmt, to_string) { } TEST(fmt, fmt) { + /// @brief hello world auto s = imp::fmt("hello", " ", "world", "."); EXPECT_EQ(s, "hello world."); + + /// @brief chrono 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 {