| 2 | #include <iostream> |
| 3 | |
| 4 | class ProgressDisplay { |
| 5 | public: |
| 6 | explicit ProgressDisplay(unsigned long expected_count_, |
| 7 | std::ostream& os = std::cout, |
| 8 | const std::string& s1 = "\n", //leading strings |
| 9 | const std::string& s2 = "", |
| 10 | const std::string& s3 = "") |
| 11 | // os is hint; implementation may ignore, particularly in embedded systems |
| 12 | : m_os(os), m_s1(s1), m_s2(s2), m_s3(s3) { |
| 13 | restart(expected_count_); |
| 14 | } |
| 15 | |
| 16 | ProgressDisplay(const ProgressDisplay&) = delete; |
| 17 | ProgressDisplay& operator=(const ProgressDisplay&) = delete; |
| 18 | |
| 19 | void restart(unsigned long expected_count_) { |
| 20 | _count = _next_tic_count = _tic = 0; |
| 21 | _expected_count = expected_count_; |
| 22 | |
| 23 | m_os << m_s1 << "0% 10 20 30 40 50 60 70 80 90 100%\n" |
| 24 | << m_s2 << "|----|----|----|----|----|----|----|----|----|----|" |
| 25 | << std::endl // endl implies flush, which ensures display |
| 26 | << m_s3; |
| 27 | if (!_expected_count) _expected_count = 1; // prevent divide by zero |
| 28 | } // restart |
| 29 | |
| 30 | unsigned long operator+=(unsigned long increment) |
| 31 | // Effects: Display appropriate progress tic if needed. |
| 32 | // Postconditions: count()== original count() + increment |
| 33 | // Returns: count(). |
| 34 | { |
| 35 | if ((_count += increment) >= _next_tic_count) { display_tic(); } |
| 36 | return _count; |
| 37 | } |
| 38 | |
| 39 | unsigned long operator++() { return operator+=(1); } |
| 40 | unsigned long count() const { return _count; } |
| 41 | unsigned long expected_count() const { return _expected_count; } |
| 42 | |
| 43 | private: |
| 44 | std::ostream& m_os; // may not be present in all imps |
| 45 | const std::string m_s1; // string is more general, safer than |
| 46 | const std::string m_s2; // const char *, and efficiency or size are |
| 47 | const std::string m_s3; // not issues |
| 48 | |
| 49 | unsigned long _count, _expected_count, _next_tic_count; |
| 50 | unsigned int _tic; |
| 51 | void display_tic() |
| 52 | { |
| 53 | // use of floating point ensures that both large and small counts |
| 54 | // work correctly. static_cast<>() is also used several places |
| 55 | // to suppress spurious compiler warnings. |
| 56 | unsigned int tics_needed = static_cast<unsigned int>((static_cast<double>(_count) |
| 57 | / static_cast<double>(_expected_count)) * 50.0); |
| 58 | do { m_os << '*' << std::flush; } while (++_tic < tics_needed); |
| 59 | _next_tic_count = |
| 60 | static_cast<unsigned long>((_tic / 50.0) * static_cast<double>(_expected_count)); |
| 61 | if (_count == _expected_count) { |
nothing calls this directly
no outgoing calls
no test coverage detected