Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <climits>
- #include <cmath>
- #include <cstdlib>
- #include <ctime>
- #include <iostream>
- #include "wallet.h"
- using std::move;
- using std::string;
- constexpr bool debug = false;
- constexpr UInt64 maxCoins = 21'000'000;
- constexpr UInt64 valueOfB = 100'000'000;
- constexpr UInt64 maxValue = maxCoins * valueOfB;
- UInt64 Wallet::totalUnits = 0;
- // constructors
- Wallet::Wallet() {
- if (debug)
- std::cerr << "default constructor\n";
- units = 0;
- update();
- };
- Wallet::Wallet (int n) {
- if (debug)
- std::cerr << "constructor called for int: " << n << '\n';
- units = 0;
- addUnits(valueOfB * checkSign(n));
- update();
- }
- Wallet::Wallet(const char *str) {
- checkNull(str);
- UInt64 valueRead = parse(str);
- printf("value %llu\n", valueRead);
- checkFormat(valueRead);
- units = 0;
- addUnits(valueRead);
- update();
- }
- Wallet::Wallet(const string &str) : Wallet(str.c_str()) {}
- Wallet::Wallet(Wallet &&w2) noexcept {
- if (debug)
- std::cerr << "move constructor 1\n";
- units = w2.units;
- op = move(w2.op);
- w2.units = 0;
- update();
- }
- Wallet::Wallet(Wallet &&w1, Wallet &&w2) noexcept {
- if (debug)
- std::cerr << "move constructor 2\n";
- units = w1.units + w2.units;
- takeHistories(std::ref(w1), std::ref(w2));
- w1 = Wallet();
- w2 = Wallet();
- update();
- }
- //destructor
- Wallet::~Wallet() noexcept {
- totalUnits -= units;
- }
- // getters
- UInt64 Wallet::getUnits() const { return units; }
- size_t Wallet::opSize() const { return op.size(); }
- const Operation & Wallet::operator[](size_t index) const { return op[index]; }
- // member functions
- Wallet Wallet::fromBinary(const char *str) {
- checkNull(str);
- string s(str);
- std::reverse(s.begin(), s.end());
- return Wallet(std::stoi(str, nullptr, 2));
- }
- std::ostream & operator<<(std::ostream &os, const Wallet &w) {
- os << w.units / valueOfB << ',' << w.units % valueOfB;
- return os;
- }
- Wallet operator*(int n, Wallet &&w) {
- Wallet ans;
- UInt64 toAdd = w.units;
- UInt64 mult = Wallet::checkSign(n);
- Wallet::checkTotal(toAdd, mult);
- ans.addUnits(toAdd * mult);
- ans.update();
- return ans;
- }
- Wallet operator*(int n, Wallet &w) { return n * move(w); }
- Wallet operator*(Wallet &w, int n) { return n * w; }
- Wallet operator*(Wallet &&w, int n) { return n * w; }
- Wallet operator+(Wallet &&w1, Wallet &&w2) {
- UInt64 a = w1.units, b = w2.units;
- Wallet ans;
- w1.units = w2.units = 0;
- ans.units = a + b;
- ans.update();
- return ans;
- }
- Wallet operator+(Wallet &&w1, Wallet &w2) {
- UInt64 a = w1.units, b = w2.units;
- Wallet ans;
- w1.units = w2.units = 0;
- w2.update();
- ans.units = a + b;
- ans.update();
- return ans;
- }
- Wallet operator-(Wallet &&w1, Wallet &&w2) {
- Wallet ans;
- UInt64 a = w1.units, b = w2.units;
- w1.remUnits(a);
- ans.addUnits(a);
- ans.remUnits(b);
- w2.addUnits(b);
- ans.update();
- w2.update();
- return ans;
- }
- Wallet operator-(Wallet &&w1, Wallet &w2) {
- Wallet ans;
- UInt64 a = w1.units, b = w2.units;
- w1.remUnits(a);
- ans.addUnits(a);
- ans.remUnits(b);
- w2.addUnits(b);
- ans.update();
- w2.update();
- return ans;
- }
- Wallet & Wallet::operator=(Wallet &&w) noexcept {
- if (debug)
- std::cerr << "operator= called\n";
- if (this == &w) return *this;
- std::swap(w.units, units);
- op = move(w.op);
- return *this;
- }
- Wallet & Wallet::operator+=(Wallet &w) {
- units += w.units;
- w.reset();
- update();
- return *this;
- }
- Wallet & Wallet::operator+=(Wallet &&w) {
- units += w.units;
- w.reset();
- update();
- return *this;
- }
- Wallet & Wallet::operator-=(Wallet &w) {
- checkAffordability(units, w.units);
- units -= w.units;
- w.units *= 2;
- w.update();
- update();
- return *this;
- }
- Wallet & Wallet::operator-=(Wallet &&w) {
- checkAffordability(units, w.units);
- units -= w.units;
- w.units *= 2;
- w.update();
- update();
- return *this;
- }
- Wallet & Wallet::operator*=(int n) {
- UInt64 multiplier = checkSign(n);
- checkTotal(multiplier - 1, units);
- totalUnits += units * (multiplier-1);
- units *= multiplier;
- update();
- return *this;
- }
- bool Wallet::operator !=(const Wallet &w) const {
- return *this < w || w < *this;
- }
- bool Wallet::operator<(const Wallet &w) const { return units < w.units; }
- bool Wallet::operator<=(const Wallet &w) const { return !(w < *this); }
- bool Wallet::operator==(const Wallet &w) const {
- return !(*this < w || w < *this);
- }
- bool Wallet::operator>(const Wallet &w) const { return w < *this; }
- bool Wallet::operator>=(const Wallet &w) const { return !(*this < w); }
- bool operator!=(int x, const Wallet &w) { return w != x; }
- bool operator<(int x, const Wallet &w) { return w > x; }
- bool operator<=(int x, const Wallet &w) { return w >= x; }
- bool operator==(int x, const Wallet &w) { return w == x; }
- bool operator>(int x, const Wallet &w) { return w < x; }
- bool operator>=(int x, const Wallet &w) { return w <= x; }
- // private functions
- bool Wallet::isComma(char c) {
- return c == ',' || c == '.';
- }
- UInt64 Wallet::parse(const char *str) {
- while (*str && isspace(*str)) ++str;
- char *s1;
- UInt64 fraction, floor;
- floor = checkSign(std::strtol(str, &s1, 10));
- // reads until the comma
- if (!isComma(*s1)) {
- checkFormat(floor);
- return floor*valueOfB;
- }
- ++s1;
- fraction = readAfterComma(s1);
- checkFormat(fraction);
- return floor * valueOfB + fraction;
- }
- UInt64 Wallet::readAfterComma(const char *str) noexcept {
- int fracExp = valueOfB / 10;
- UInt64 ans = 0;
- for (; *str && !isspace(*str); fracExp /= 10, ++str) {
- if (!isdigit(*str) || !fracExp) return ULLONG_MAX;
- ans += fracExp * (*str - '0');
- }
- for (; *str; ++str) if (!isspace(*str)) return ULLONG_MAX;
- return ans;
- }
- void Wallet::checkAffordability(UInt64 subtrahend, UInt64 minuend) {
- if (minuend > subtrahend)
- throw WalletException(WalletException::affordMsg);
- }
- void Wallet::checkFormat(UInt64 x) {
- if (x == ULLONG_MAX)
- throw WalletException(WalletException::formatMsg);
- }
- void Wallet::checkNull(const char *x) {
- if (!x) throw WalletException(WalletException::nullPtMsg);
- }
- UInt64 Wallet::checkSign(long x) {
- if (x < 0) throw WalletException(WalletException::negValMsg);
- return UInt64(x);
- }
- void Wallet::checkTotal(UInt64 x, UInt64 y) {
- bool b = false;
- if (x - 1 && y - 1) b = log2(x) + log2(y) > log2(maxValue - totalUnits);
- if (b || x * y > maxValue - totalUnits)
- throw WalletException(WalletException::coinLmMsg);
- }
- void Wallet::addUnits(UInt64 x) {
- checkTotal(x, 1);
- units += x;
- totalUnits += x;
- }
- void Wallet::reset() {
- units = 0;
- update();
- }
- void Wallet::remUnits(UInt64 x) {
- checkAffordability(units, x);
- units -= x;
- totalUnits -= x;
- }
- void Wallet::takeHistories(Wallet &w1, Wallet &w2) {
- size_t n1 = w1.opSize(), n2 = w2.opSize();
- // guards for the merge
- w1.update();
- w2.update();
- op.reserve(n1 + n2);
- for (size_t i = 0, j = 0; i + j < n1 + n2;) {
- if (w1.op[i] < w1.op[j]) {
- op.push_back(w1.op[i]);
- ++i;
- } else {
- op.push_back(w2.op[j]);
- ++j;
- }
- }
- }
- void Wallet::update() {
- op.push_back(Operation(units));
- }
- const Wallet& Empty() {
- static const Wallet empty = Wallet();
- return empty;
- }
- Operation::Operation(UInt64 units) {
- time(&date);
- this->units = units;
- }
- UInt64 Operation::getUnits() const { return units; }
- std::ostream & operator<<(std::ostream &os, const Operation &o) {
- using std::to_string;
- tm *ltm = localtime(&o.date);
- os << "Wallet balance is " << o.units / valueOfB << ',' << o.units % valueOfB;
- os << " B after operation made at day ";
- os << to_string(ltm->tm_year + 1900) + "-";
- os << to_string(ltm->tm_mon + 1) + "-" + to_string(ltm->tm_mday);
- return os;
- }
- // all comparison operators refer to operator<
- bool Operation::operator!=(const Operation &o) const {
- return o < *this || *this < o;
- }
- bool Operation::operator<(const Operation &o) const { return date < o.date; }
- bool Operation::operator<=(const Operation &o) const { return !(o < *this); }
- bool Operation::operator>(const Operation &o) const { return o < *this; }
- bool Operation::operator>=(const Operation &o) const { return !(o < *this); }
- bool Operation::operator==(const Operation &o) const {
- return !(*this < o || o < *this);
- }
- const char * WalletException::affordMsg = "insufficient funds";
- const char * WalletException::coinLmMsg = "coin count exceeds limit";
- const char * WalletException::formatMsg = "incorrect number format";
- const char * WalletException::negValMsg = "unexpected negative argument";
- const char * WalletException::nullPtMsg = "unexpected null pointer";
- const char* WalletException::what() const noexcept { return msg.c_str(); }
- WalletException::WalletException(
- const string &message
- ) noexcept : msg(message) {}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement