#include <iostream>
#include "Clock.h"
extern void appl(IClock&);
int main()
{
std::cout.setf(std::ios::boolalpha);
Clock c{"myclock"};
appl(c);
}
#include <iostream>
#define SHOW(...)\
(void)(std::cout << __FILE__ << ':' << __LINE__ << '\t'\
<< #__VA_ARGS__ << " --> " << (__VA_ARGS__)\
<< std::endl)
#include "IClock.h"
void appl(IClock& c) {
SHOW(c);
c.TickUp(); SHOW(c);
c.TickUp(); SHOW(c);
c.TickUp(); SHOW(c);
c.Set(0, 0, 0, 58); SHOW(c);
c.TickUp(); SHOW(c);
c.TickUp(); SHOW(c);
c.TickUp(); SHOW(c);
c.Set(2, 0, 59, 58); SHOW(c);
c.TickUp(); SHOW(c);
c.TickUp(); SHOW(c);
c.TickUp(60); SHOW(c);
c.TickUp(600); SHOW(c);
}
#ifndef ICLOCK_H
#define ICLOCK_H
#include <iosfwd>
class IClock {
public:
virtual ~IClock() =default;
virtual void Set(unsigned, unsigned, unsigned, unsigned) =0;
virtual void TickUp(int = 1) =0;
virtual void TickDown(int = 1) =0;
virtual void Print(std::ostream&) const =0;
};
inline
std::ostream& operator<<(std::ostream& lhs, const IClock& rhs) {
rhs.Print(lhs);
return lhs;
}
#endif
#ifndef CLOCK_H
#define CLOCK_H
#include <cstring>
#include <iosfwd>
#include "IClock.h"
#include "UpDownCounter.h"
class Clock : public IClock {
const char* name_;
UpDownCounter days_;
UpDownCounter hours_;
UpDownCounter minutes_;
UpDownCounter seconds_;
public:
Clock(const char* name,
UpDownCounter::value_type days = 0,
UpDownCounter::value_type hours = 0,
UpDownCounter::value_type minutes = 0,
UpDownCounter::value_type seconds = 0)
: name_{std::strcpy(new char[std::strlen(name)+1], name)}
, days_{days}
, hours_{hours, 24, &days_}
, minutes_{minutes, 60, &hours_}
, seconds_{seconds, 60, &minutes_}
{}
~Clock() { delete[] name_; }
Clock(const Clock&) =delete; // copy c'tor
Clock& operator=(const Clock&) =delete; // copy assignment
Clock(Clock&&) =delete; // move c'tor
Clock& operator=(Clock&&) =delete; // move assignment
virtual void Set(unsigned days, unsigned hours, unsigned minutes, unsigned seconds) override {
if (days >= 0) days_.SetValue(days);
if (seconds >= 0) seconds_.SetValue(seconds);
if (minutes >= 0) minutes_.SetValue(minutes);
if (seconds >= 0) seconds_.SetValue(seconds);
}
virtual void TickUp(int n) override { while (n-- > 0) seconds_.UpCount(); }
virtual void TickDown(int n) override { while (n-- > 0) seconds_.DownCount(); }
virtual void Print(std::ostream&) const override;
};
#endif
#include "Clock.h"
#include <iostream>
#include <iomanip>
void Clock::Print(std::ostream& s) const {
std::ostream os{s.rdbuf()};
os.fill('0');
os << name_ << '='
<< std::setw(2) << hours_.GetValue() << ':'
<< std::setw(2) << minutes_.GetValue() << ':'
<< std::setw(2) << seconds_.GetValue();
}
#ifndef UP_DOWN_COUNTER_H
#define UP_DOWN_COUNTER_H
#include <cstdint>
#include <type_traits>
class UpDownCounter {
public:
using value_type = std::uint_fast8_t;
static_assert(std::is_integral<value_type>::value
&& std::is_unsigned<value_type>::value,
"designed to work with unsigned integral types only");
private:
value_type value_{};
const value_type max_value_{};
UpDownCounter *next_counter_{};
public:
UpDownCounter() =default;
UpDownCounter(const UpDownCounter&) =delete;
UpDownCounter(UpDownCounter&&) =delete;
UpDownCounter& operator=(const UpDownCounter&) =delete;
UpDownCounter& operator=(UpDownCounter&&) =delete;
UpDownCounter(value_type value, value_type max_value, UpDownCounter* next_counter)
: value_{value}
, max_value_{max_value}
, next_counter_{next_counter}
{}
UpDownCounter(value_type max_value, UpDownCounter* next_counter)
: UpDownCounter(0, max_value, next_counter)
{}
UpDownCounter(value_type max_value)
: UpDownCounter(0, max_value, nullptr)
{}
UpDownCounter(UpDownCounter* next_counter_)
: UpDownCounter(0, 0, nullptr)
{}
void SetValue(value_type value) { value_ = value; }
int GetValue() const { return value_; }
int GetLimit() const { return max_value_; }
void UpCount();
void DownCount();
};
#endif
#include "UpDownCounter.h"
void UpDownCounter::UpCount() {
if (++value_ == max_value_) {
value_ = 0;
if (next_counter_) {
next_counter_->UpCount();
}
}
}
void UpDownCounter::DownCount() {
if (value_ == 0) {
value_ = max_value_;
next_counter_->DownCount();
}
--value_;
}