├── .github ├── example-custom.gif └── example-simple.gif ├── .gitignore ├── LICENSE ├── README.md ├── include └── progressbar.hpp └── test └── test.cc /.github/example-custom.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gipert/progressbar/a67ccda1712d572e24cdfd02938e6a782e779787/.github/example-custom.gif -------------------------------------------------------------------------------- /.github/example-simple.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gipert/progressbar/a67ccda1712d572e24cdfd02938e6a782e779787/.github/example-simple.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | test/test 2 | .DS_Store 3 | .*.swp 4 | .*.swo 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Luigi Pertoldi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # progressbar 2 | 3 | A very simple, header-only, fully customizable, progress bar (with percentage) 4 | for c++ loops. 5 | 6 | Very simple to set up: 7 | ```cpp 8 | #include "progressbar.hpp" 9 | 10 | int main() { 11 | progressbar bar(100); 12 | for (int i = 0; i < 100; ++i) { 13 | bar.update(); 14 | // ... the program 15 | } 16 | return 0; 17 | } 18 | ``` 19 | ![animated gif](.github/example-simple.gif) 20 | 21 | Allows customization: 22 | ```cpp 23 | #include "progressbar.hpp" 24 | 25 | int main() { 26 | progressbar bar(100); 27 | bar.set_todo_char(" "); 28 | bar.set_done_char("█"); 29 | bar.set_opening_bracket_char("{"); 30 | bar.set_closing_bracket_char("}"); 31 | for (int i = 0; i < 100; ++i) { 32 | bar.update(); 33 | // ... the program 34 | } 35 | return 0; 36 | } 37 | ``` 38 | ![animated gif](.github/example-custom.gif) 39 | 40 | ## Notes 41 | 42 | To use the bar in parallelized loops call `progressbar::update` in a critical 43 | section. With [OpenMP](http://www.openmp.org) this can be achieved with the 44 | following structure: 45 | ```cpp 46 | #pragma omp parallel for 47 | for ( ... ) { 48 | #pragma omp critical 49 | bar.update(); 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /include/progressbar.hpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2019 Luigi Pertoldi 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to 7 | // deal in the Software without restriction, including without limitation the 8 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | // sell copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | // IN THE SOFTWARE. 22 | // 23 | // ============================================================================ 24 | // ___ ___ ___ __ ___ ____ __ __ ___ __ ___ 25 | // | |_) | |_) / / \ / /`_ | |_) | |_ ( (` ( (` | |_) / /\ | |_) 26 | // |_| |_| \ \_\_/ \_\_/ |_| \ |_|__ _)_) _)_) |_|_) /_/--\ |_| \_ 27 | // 28 | // Very simple progress bar for c++ loops with internal running variable 29 | // 30 | // Author: Luigi Pertoldi 31 | // Created: 3 dic 2016 32 | // 33 | // Notes: The bar must be used when there's no other possible source of output 34 | // inside the for loop 35 | // 36 | 37 | #ifndef __PROGRESSBAR_HPP 38 | #define __PROGRESSBAR_HPP 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | class progressbar { 46 | 47 | public: 48 | // default destructor 49 | ~progressbar() = default; 50 | 51 | // delete everything else 52 | progressbar (progressbar const&) = delete; 53 | progressbar& operator=(progressbar const&) = delete; 54 | progressbar (progressbar&&) = delete; 55 | progressbar& operator=(progressbar&&) = delete; 56 | 57 | // default constructor, must call set_niter later 58 | inline progressbar(); 59 | inline progressbar(int n, bool showbar=true, std::ostream& out=std::cerr); 60 | 61 | // reset bar to use it again 62 | inline void reset(); 63 | // set number of loop iterations 64 | inline void set_niter(int iter); 65 | // chose your style 66 | inline void set_done_char(const std::string& sym) {done_char = sym;} 67 | inline void set_todo_char(const std::string& sym) {todo_char = sym;} 68 | inline void set_opening_bracket_char(const std::string& sym) {opening_bracket_char = sym;} 69 | inline void set_closing_bracket_char(const std::string& sym) {closing_bracket_char = sym;} 70 | // to show only the percentage 71 | inline void show_bar(bool flag = true) {do_show_bar = flag;} 72 | // set the output stream 73 | inline void set_output_stream(const std::ostream& stream) {output.rdbuf(stream.rdbuf());} 74 | // main function 75 | inline void update(); 76 | 77 | private: 78 | int progress; 79 | int n_cycles; 80 | int last_perc; 81 | bool do_show_bar; 82 | bool update_is_called; 83 | 84 | std::string done_char; 85 | std::string todo_char; 86 | std::string opening_bracket_char; 87 | std::string closing_bracket_char; 88 | 89 | std::ostream& output; 90 | }; 91 | 92 | inline progressbar::progressbar() : 93 | progress(0), 94 | n_cycles(0), 95 | last_perc(0), 96 | do_show_bar(true), 97 | update_is_called(false), 98 | done_char("#"), 99 | todo_char(" "), 100 | opening_bracket_char("["), 101 | closing_bracket_char("]"), 102 | output(std::cerr) {} 103 | 104 | inline progressbar::progressbar(int n, bool showbar, std::ostream& out) : 105 | progress(0), 106 | n_cycles(n), 107 | last_perc(0), 108 | do_show_bar(showbar), 109 | update_is_called(false), 110 | done_char("#"), 111 | todo_char(" "), 112 | opening_bracket_char("["), 113 | closing_bracket_char("]"), 114 | output(out) {} 115 | 116 | inline void progressbar::reset() { 117 | progress = 0, 118 | update_is_called = false; 119 | last_perc = 0; 120 | return; 121 | } 122 | 123 | inline void progressbar::set_niter(int niter) { 124 | if (niter <= 0) throw std::invalid_argument( 125 | "progressbar::set_niter: number of iterations null or negative"); 126 | n_cycles = niter; 127 | return; 128 | } 129 | 130 | inline void progressbar::update() { 131 | 132 | if (n_cycles == 0) throw std::runtime_error( 133 | "progressbar::update: number of cycles not set"); 134 | 135 | if (!update_is_called) { 136 | if (do_show_bar == true) { 137 | output << opening_bracket_char; 138 | for (int _ = 0; _ < 50; _++) output << todo_char; 139 | output << closing_bracket_char << " 0%"; 140 | } 141 | else output << "0%"; 142 | } 143 | update_is_called = true; 144 | 145 | int perc = 0; 146 | 147 | // compute percentage, if did not change, do nothing and return 148 | perc = progress*100./(n_cycles-1); 149 | if (perc < last_perc) return; 150 | 151 | // update percentage each unit 152 | if (perc == last_perc + 1) { 153 | // erase the correct number of characters 154 | if (perc <= 10) output << "\b\b" << perc << '%'; 155 | else if (perc > 10 and perc < 100) output << "\b\b\b" << perc << '%'; 156 | else if (perc == 100) output << "\b\b\b" << perc << '%'; 157 | } 158 | if (do_show_bar == true) { 159 | // update bar every ten units 160 | if (perc % 2 == 0) { 161 | // erase closing bracket 162 | output << std::string(closing_bracket_char.size(), '\b'); 163 | // erase trailing percentage characters 164 | if (perc < 10) output << "\b\b\b"; 165 | else if (perc >= 10 && perc < 100) output << "\b\b\b\b"; 166 | else if (perc == 100) output << "\b\b\b\b\b"; 167 | 168 | // erase 'todo_char' 169 | for (int j = 0; j < 50-(perc-1)/2; ++j) { 170 | output << std::string(todo_char.size(), '\b'); 171 | } 172 | 173 | // add one additional 'done_char' 174 | if (perc == 0) output << todo_char; 175 | else output << done_char; 176 | 177 | // refill with 'todo_char' 178 | for (int j = 0; j < 50-(perc-1)/2-1; ++j) output << todo_char; 179 | 180 | // readd trailing percentage characters 181 | output << closing_bracket_char << ' ' << perc << '%'; 182 | } 183 | } 184 | last_perc = perc; 185 | ++progress; 186 | output << std::flush; 187 | 188 | return; 189 | } 190 | 191 | #endif 192 | -------------------------------------------------------------------------------- /test/test.cc: -------------------------------------------------------------------------------- 1 | /* test program for the progressbar class 2 | * 3 | * Author: Luigi Pertoldi 4 | * Created: 9 dic 2016 5 | * 6 | * Compile: c++ -I. -o test test.cc 7 | * Usage: ./test 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "progressbar.hpp" 16 | 17 | int main() { 18 | 19 | int N = 10000; 20 | 21 | progressbar bar(N); 22 | 23 | for ( int i = 0; i < N; i++ ) { 24 | 25 | bar.update(); 26 | 27 | // the program... 28 | std::this_thread::sleep_for( std::chrono::microseconds(300) ); 29 | } 30 | 31 | std::cerr << std::endl; 32 | 33 | N = 5000; 34 | bar.set_niter(N); 35 | bar.reset(); 36 | bar.set_todo_char(" "); 37 | bar.set_done_char("█"); 38 | bar.set_opening_bracket_char("{"); 39 | bar.set_closing_bracket_char("}"); 40 | for ( int i = 0; i < N; i++ ) { 41 | 42 | bar.update(); 43 | 44 | // the program... 45 | std::this_thread::sleep_for( std::chrono::microseconds(300) ); 46 | } 47 | 48 | std::cerr << std::endl; 49 | bar.reset(); 50 | bar.show_bar(false); 51 | for ( int i = 0; i < N; i++ ) { 52 | 53 | bar.update(); 54 | 55 | // the program... 56 | std::this_thread::sleep_for( std::chrono::microseconds(300) ); 57 | } 58 | std::cerr << std::endl; 59 | 60 | bar.reset(); 61 | bar.show_bar(true); 62 | bar.set_output_stream(std::cout); 63 | for ( int i = 0; i < N; i++ ) { 64 | 65 | bar.update(); 66 | 67 | // the program... 68 | std::this_thread::sleep_for( std::chrono::microseconds(300) ); 69 | } 70 | 71 | 72 | return 0; 73 | } 74 | --------------------------------------------------------------------------------