Correctly print final progress when ProgressBar is destructed

Fixes issue #46
This commit is contained in:
Daniel Wolf 2019-01-02 14:29:19 +01:00
parent 11a29ddef6
commit d0c9a294e9
2 changed files with 34 additions and 19 deletions

View File

@ -8,9 +8,21 @@
using std::string; using std::string;
ProgressBar::ProgressBar(std::ostream& stream) : double sanitizeProgress(double progress) {
// Make sure value is in [0..1] range
return std::isnan(progress)
? 0.0
: boost::algorithm::clamp(progress, 0.0, 1.0);
}
ProgressBar::ProgressBar(double progress) :
ProgressBar(std::cerr, progress)
{}
ProgressBar::ProgressBar(std::ostream& stream, double progress) :
stream(stream) stream(stream)
{ {
currentProgress = sanitizeProgress(progress);
updateLoopFuture = std::async(std::launch::async, &ProgressBar::updateLoop, this); updateLoopFuture = std::async(std::launch::async, &ProgressBar::updateLoop, this);
} }
@ -20,37 +32,38 @@ ProgressBar::~ProgressBar() {
} }
void ProgressBar::reportProgress(double value) { void ProgressBar::reportProgress(double value) {
// Make sure value is in [0..1] range currentProgress = sanitizeProgress(value);
value = boost::algorithm::clamp(value, 0.0, 1.0);
if (std::isnan(value)) {
value = 0.0;
}
currentProgress = value;
} }
void ProgressBar::updateLoop() { void ProgressBar::updateLoop() {
const int blockCount = 20;
const std::chrono::milliseconds animationInterval(1000 / 8); const std::chrono::milliseconds animationInterval(1000 / 8);
const string animation = "|/-\\";
while (!done) { while (!done) {
int progressBlockCount = static_cast<int>(currentProgress * blockCount); update();
int percent = static_cast<int>(currentProgress * 100);
string text = fmt::format("[{0}{1}] {2:3}% {3}",
string(progressBlockCount, '#'), string(blockCount - progressBlockCount, '-'),
percent,
animation[animationIndex++ % animation.size()]);
updateText(text);
std::this_thread::sleep_for(animationInterval); std::this_thread::sleep_for(animationInterval);
} }
if (clearOnDestruction) { if (clearOnDestruction) {
updateText(""); updateText("");
} else {
update();
} }
} }
void ProgressBar::update() {
const int blockCount = 20;
const string animation = "|/-\\";
int progressBlockCount = static_cast<int>(currentProgress * blockCount);
const double epsilon = 0.0001;
int percent = static_cast<int>(currentProgress * 100 + epsilon);
string text = fmt::format("[{0}{1}] {2:3}% {3}",
string(progressBlockCount, '#'), string(blockCount - progressBlockCount, '-'),
percent,
animation[animationIndex++ % animation.size()]);
updateText(text);
}
void ProgressBar::updateText(const string& text) { void ProgressBar::updateText(const string& text) {
// Get length of common portion // Get length of common portion
int commonPrefixLength = 0; int commonPrefixLength = 0;

View File

@ -7,7 +7,8 @@
class ProgressBar : public ProgressSink { class ProgressBar : public ProgressSink {
public: public:
ProgressBar(std::ostream& stream = std::cerr); explicit ProgressBar(double progress = 0.0);
ProgressBar(std::ostream& stream, double progress = 0.0);
~ProgressBar(); ~ProgressBar();
void reportProgress(double value) override; void reportProgress(double value) override;
@ -21,6 +22,7 @@ public:
private: private:
void updateLoop(); void updateLoop();
void update();
void updateText(const std::string& text); void updateText(const std::string& text);
std::future<void> updateLoopFuture; std::future<void> updateLoopFuture;