diff --git a/include/dwarfs/cached_value.h b/include/dwarfs/cached_value.h
new file mode 100644
index 00000000..5b1a743e
--- /dev/null
+++ b/include/dwarfs/cached_value.h
@@ -0,0 +1,50 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/**
+ * \author Marcus Holland-Moritz (github@mhxnet.de)
+ * \copyright Copyright (c) Marcus Holland-Moritz
+ *
+ * This file is part of dwarfs.
+ *
+ * dwarfs is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * dwarfs is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with dwarfs. If not, see .
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace dwarfs {
+
+template
+class cached_value {
+ public:
+ using function_type = std::function;
+
+ cached_value(function_type f)
+ : v_{f} {}
+
+ T const& get() {
+ if (std::holds_alternative(v_)) [[unlikely]] {
+ v_ = std::get(v_)();
+ }
+ return std::get(v_);
+ }
+
+ T const& operator()() { return get(); }
+
+ private:
+ std::variant v_;
+};
+
+} // namespace dwarfs
diff --git a/include/dwarfs/console_writer.h b/include/dwarfs/console_writer.h
index 23704ee3..3c789880 100644
--- a/include/dwarfs/console_writer.h
+++ b/include/dwarfs/console_writer.h
@@ -23,6 +23,7 @@
#include
#include
+#include
#include
#include
#include
@@ -36,12 +37,14 @@ class progress;
class console_writer : public logger {
public:
+ using get_term_width_type = std::function;
+
enum display_mode { NORMAL, REWRITE };
enum progress_mode { NONE, SIMPLE, ASCII, UNICODE };
- console_writer(std::ostream& os, progress_mode pg_mode, size_t width,
- level_type threshold, display_mode mode = NORMAL,
- bool verbose = false);
+ console_writer(std::ostream& os, progress_mode pg_mode,
+ get_term_width_type get_term_width, level_type threshold,
+ display_mode mode = NORMAL, bool verbose = false);
void write(level_type level, const std::string& output, char const* file,
int line) override;
@@ -58,7 +61,7 @@ class console_writer : public logger {
double frac_;
std::atomic counter_{0};
progress_mode const pg_mode_;
- size_t const width_;
+ get_term_width_type get_term_width_;
display_mode const mode_;
bool const color_;
bool const with_context_;
diff --git a/src/dwarfs/console_writer.cpp b/src/dwarfs/console_writer.cpp
index d8fdb264..57f671da 100644
--- a/src/dwarfs/console_writer.cpp
+++ b/src/dwarfs/console_writer.cpp
@@ -27,6 +27,7 @@
#include
+#include "dwarfs/cached_value.h"
#include "dwarfs/console_writer.h"
#include "dwarfs/entry.h"
#include "dwarfs/entry_interface.h"
@@ -78,13 +79,14 @@ std::string progress_bar(size_t width, double frac, bool unicode) {
} // namespace
console_writer::console_writer(std::ostream& os, progress_mode pg_mode,
- size_t width, level_type threshold,
- display_mode mode, bool with_context)
+ get_term_width_type get_term_width,
+ level_type threshold, display_mode mode,
+ bool with_context)
: os_(os)
, threshold_(threshold)
, frac_(0.0)
, pg_mode_(pg_mode)
- , width_(width)
+ , get_term_width_(get_term_width)
, mode_(mode)
, color_(stream_is_fancy_terminal(os))
, with_context_(with_context)
@@ -180,12 +182,13 @@ void console_writer::update(const progress& p, bool last) {
const char* newline = pg_mode_ != NONE ? "\x1b[K\n" : "\n";
std::ostringstream oss;
+ cached_value width(get_term_width_);
bool fancy = pg_mode_ == ASCII || pg_mode_ == UNICODE;
if (last || fancy) {
if (fancy) {
- for (size_t i = 0; i < width_; ++i) {
+ for (size_t i = 0; i < width.get(); ++i) {
oss << (pg_mode_ == UNICODE ? "⎯" : "-");
}
oss << "\n";
@@ -205,7 +208,8 @@ void console_writer::update(const progress& p, bool last) {
}
if (fancy) {
- oss << terminal_colored(p.status(width_), termcolor::BOLD_CYAN, color_)
+ oss << terminal_colored(p.status(width.get()), termcolor::BOLD_CYAN,
+ color_)
<< newline;
}
@@ -305,7 +309,7 @@ void console_writer::update(const progress& p, bool last) {
os_ << oss.str();
}
} else {
- oss << progress_bar(width_ - 6, frac_, pg_mode_ == UNICODE)
+ oss << progress_bar(width.get() - 6, frac_, pg_mode_ == UNICODE)
<< fmt::format("{:3.0f}% ", 100 * frac_) << "-\\|/"[counter_ % 4]
<< '\n';
diff --git a/src/mkdwarfs_main.cpp b/src/mkdwarfs_main.cpp
index 10f44c0a..f89ab01a 100644
--- a/src/mkdwarfs_main.cpp
+++ b/src/mkdwarfs_main.cpp
@@ -868,7 +868,7 @@ int mkdwarfs_main(int argc, sys_char** argv) {
auto pg_mode = DWARFS_NOTHROW(progress_modes.at(progress_mode));
auto log_level = logger::parse_level(log_level_str);
- console_writer lgr(std::cerr, pg_mode, get_term_width(), log_level,
+ console_writer lgr(std::cerr, pg_mode, get_term_width, log_level,
recompress ? console_writer::REWRITE
: console_writer::NORMAL,
log_level >= logger::DEBUG);