|
1 | 1 | #include "progress_bar.hpp" |
2 | 2 |
|
3 | | -ProgressBar::ProgressBar() {} |
| 3 | +#include <iomanip> |
4 | 4 |
|
5 | | -ProgressBar::ProgressBar(unsigned long n_, const char* description_, std::ostream& out_){ |
6 | | - |
7 | | - n = n_; |
8 | | - frequency_update = n_; |
9 | | - description = description_; |
| 5 | +const size_t kMessageSize = 25; |
| 6 | +const double kTotalPercentage = 100.0; |
| 7 | +const size_t kCharacterWidthPercentage = 4; |
| 8 | + |
| 9 | + |
| 10 | +ProgressBar::ProgressBar(uint64_t total, |
| 11 | + const std::string &description, |
| 12 | + std::ostream &out_) |
| 13 | + : total_(total), description_(description) { |
| 14 | + frequency_update = std::min(static_cast<uint64_t>(1000), total_); |
10 | 15 | out = &out_; |
11 | | - |
12 | | - unit_bar = "="; |
13 | | - unit_space = " "; |
14 | | - desc_width = std::strlen(description); // character width of description field |
| 16 | + *out << "\n"; |
15 | 17 |
|
| 18 | + assert(description_.size() <= kMessageSize); |
| 19 | + description_.resize(kMessageSize, ' '); |
16 | 20 | } |
17 | 21 |
|
18 | | -void ProgressBar::SetFrequencyUpdate(unsigned long frequency_update_){ |
19 | | - |
20 | | - if(frequency_update_ > n){ |
21 | | - frequency_update = n; // prevents crash if freq_updates_ > n_ |
22 | | - } |
23 | | - else{ |
24 | | - frequency_update = frequency_update_; |
25 | | - } |
| 22 | +ProgressBar::~ProgressBar() { |
| 23 | + *out << "\n"; |
26 | 24 | } |
27 | 25 |
|
28 | | -void ProgressBar::SetStyle(const char* unit_bar_, const char* unit_space_){ |
29 | | - |
30 | | - unit_bar = unit_bar_; |
31 | | - unit_space = unit_space_; |
| 26 | +void ProgressBar::SetFrequencyUpdate(uint64_t frequency_update_) { |
| 27 | + if(frequency_update_ > total_){ |
| 28 | + frequency_update = total_; // prevents crash if freq_updates_ > total_ |
| 29 | + } else{ |
| 30 | + frequency_update = frequency_update_; |
| 31 | + } |
32 | 32 | } |
33 | 33 |
|
34 | | -int ProgressBar::GetConsoleWidth(){ |
| 34 | +void ProgressBar::SetStyle(char unit_bar, char unit_space){ |
| 35 | + unit_bar_ = unit_bar; |
| 36 | + unit_space_ = unit_space; |
| 37 | +} |
35 | 38 |
|
| 39 | +int ProgressBar::GetConsoleWidth() { |
36 | 40 | int width; |
37 | 41 |
|
38 | | - #ifdef _WINDOWS |
39 | | - CONSOLE_SCREEN_BUFFER_INFO csbi; |
40 | | - GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); |
41 | | - width = csbi.srWindow.Right - csbi.srWindow.Left; |
42 | | - #else |
43 | | - struct winsize win; |
44 | | - ioctl(0, TIOCGWINSZ, &win); |
| 42 | + #ifdef _WINDOWS |
| 43 | + CONSOLE_SCREEN_BUFFER_INFO csbi; |
| 44 | + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); |
| 45 | + width = csbi.srWindow.Right - csbi.srWindow.Left; |
| 46 | + #else |
| 47 | + struct winsize win; |
| 48 | + ioctl(0, TIOCGWINSZ, &win); |
45 | 49 | width = win.ws_col; |
46 | | - #endif |
| 50 | + #endif |
47 | 51 |
|
48 | 52 | return width; |
49 | 53 | } |
50 | 54 |
|
51 | | -int ProgressBar::GetBarLength(){ |
52 | | - |
53 | | - // get console width and according adjust the length of the progress bar |
54 | | - |
55 | | - int bar_length = static_cast<int>((GetConsoleWidth() - desc_width - CHARACTER_WIDTH_PERCENTAGE) / 2.); |
56 | | - |
57 | | - return bar_length; |
| 55 | +int ProgressBar::GetBarLength() { |
| 56 | + // get console width and according adjust the length of the progress bar |
| 57 | + return (GetConsoleWidth() - description_.size() |
| 58 | + - kCharacterWidthPercentage) / 2.; |
58 | 59 | } |
59 | 60 |
|
60 | | -void ProgressBar::ClearBarField(){ |
61 | | - |
62 | | - for(int i=0;i<GetConsoleWidth();++i){ |
| 61 | +void ProgressBar::ClearBarField() { |
| 62 | + for(int i = 0; i < GetConsoleWidth(); ++i) { |
63 | 63 | *out << " "; |
64 | 64 | } |
65 | 65 | *out << "\r" << std::flush; |
66 | 66 | } |
67 | 67 |
|
68 | | -void ProgressBar::Progressed(unsigned long idx_) |
69 | | -{ |
70 | | - try{ |
71 | | - if(idx_ > n) throw idx_; |
| 68 | +void ProgressBar::Progressed(uint64_t idx_) { |
| 69 | + try { |
| 70 | + if (idx_ > total_) |
| 71 | + throw idx_; |
| 72 | + |
| 73 | + progress_ = idx_; |
72 | 74 |
|
73 | 75 | // determines whether to update the progress bar from frequency_update |
74 | | - if ((idx_ != n) && (idx_ % (n/frequency_update) != 0)) return; |
| 76 | + if ((idx_ != total_) && (idx_ % (total_ / frequency_update) != 0)) |
| 77 | + return; |
75 | 78 |
|
76 | 79 | // calculate the size of the progress bar |
77 | | - int bar_size = GetBarLength(); |
78 | | - |
| 80 | + int bar_size = GetBarLength(); |
| 81 | + |
79 | 82 | // calculate percentage of progress |
80 | | - double progress_percent = idx_* TOTAL_PERCENTAGE/n; |
| 83 | + double progress_percent = idx_* kTotalPercentage / total_; |
81 | 84 |
|
82 | | - // calculate the percentage value of a unit bar |
83 | | - double percent_per_unit_bar = TOTAL_PERCENTAGE/bar_size; |
| 85 | + // calculate the percentage value of a unit bar |
| 86 | + double percent_per_unit_bar = kTotalPercentage / bar_size; |
84 | 87 |
|
85 | 88 | // display progress bar |
86 | | - *out << " " << description << " ["; |
87 | | - |
88 | | - for(int bar_length=0;bar_length<=bar_size-1;++bar_length){ |
89 | | - if(bar_length*percent_per_unit_bar<progress_percent){ |
90 | | - *out << unit_bar; |
91 | | - } |
92 | | - else{ |
93 | | - *out << unit_space; |
94 | | - } |
| 89 | + // *out << " " << (percent_per_unit_bar < 1 |
| 90 | + // ? description |
| 91 | + // : std::string(' ', desc_width)) << " ["; |
| 92 | + *out << " " << description_ << " ["; |
| 93 | + |
| 94 | + for(int bar_length = 0; bar_length <= bar_size - 1; ++bar_length) { |
| 95 | + *out << (bar_length * percent_per_unit_bar < progress_percent |
| 96 | + ? unit_bar_ |
| 97 | + : unit_space_); |
95 | 98 | } |
96 | 99 |
|
97 | | - *out << "]" << std::setw(CHARACTER_WIDTH_PERCENTAGE + 1) << std::setprecision(1) << std::fixed << progress_percent << "%\r" << std::flush; |
98 | | - } |
99 | | - catch(unsigned long e){ |
| 100 | + *out << "]" << std::setw(kCharacterWidthPercentage + 1) |
| 101 | + << std::setprecision(1) |
| 102 | + << std::fixed |
| 103 | + << progress_percent << "%\r" << std::flush; |
| 104 | + } catch (uint64_t e) { |
100 | 105 | ClearBarField(); |
101 | | - std::cerr << "PROGRESS_BAR_EXCEPTION: _idx (" << e << ") went out of bounds, greater than n (" << n << ")." << std::endl << std::flush; |
| 106 | + std::cerr << "PROGRESS_BAR_EXCEPTION: _idx (" |
| 107 | + << e << ") went out of bounds, greater than total_ (" |
| 108 | + << total_ << ")." << std::endl << std::flush; |
102 | 109 | } |
| 110 | +} |
103 | 111 |
|
| 112 | +ProgressBar& ProgressBar::operator++() { |
| 113 | + this->Progressed(progress_ + 1); |
| 114 | + return *this; |
104 | 115 | } |
0 commit comments