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);