Advertisement
Guest User

Untitled

a guest
Dec 16th, 2018
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.57 KB | None | 0 0
  1. #include <climits>
  2. #include <cmath>
  3. #include <cstdlib>
  4. #include <ctime>
  5. #include <iostream>
  6. #include "wallet.h"
  7.  
  8. using std::move;
  9. using std::string;
  10.  
  11. constexpr bool debug = false;
  12. constexpr UInt64 maxCoins = 21'000'000;
  13. constexpr UInt64 valueOfB = 100'000'000;
  14. constexpr UInt64 maxValue = maxCoins * valueOfB;
  15.  
  16. UInt64 Wallet::totalUnits = 0;
  17. // constructors
  18. Wallet::Wallet() {
  19. if (debug)
  20. std::cerr << "default constructor\n";
  21. units = 0;
  22. update();
  23. };
  24. Wallet::Wallet (int n) {
  25. if (debug)
  26. std::cerr << "constructor called for int: " << n << '\n';
  27. units = 0;
  28. addUnits(valueOfB * checkSign(n));
  29. update();
  30. }
  31. Wallet::Wallet(const char *str) {
  32. checkNull(str);
  33. UInt64 valueRead = parse(str);
  34. printf("value %llu\n", valueRead);
  35. checkFormat(valueRead);
  36. units = 0;
  37. addUnits(valueRead);
  38. update();
  39. }
  40. Wallet::Wallet(const string &str) : Wallet(str.c_str()) {}
  41. Wallet::Wallet(Wallet &&w2) noexcept {
  42. if (debug)
  43. std::cerr << "move constructor 1\n";
  44. units = w2.units;
  45. op = move(w2.op);
  46. w2.units = 0;
  47. update();
  48. }
  49. Wallet::Wallet(Wallet &&w1, Wallet &&w2) noexcept {
  50. if (debug)
  51. std::cerr << "move constructor 2\n";
  52. units = w1.units + w2.units;
  53. takeHistories(std::ref(w1), std::ref(w2));
  54. w1 = Wallet();
  55. w2 = Wallet();
  56. update();
  57. }
  58.  
  59. //destructor
  60. Wallet::~Wallet() noexcept {
  61. totalUnits -= units;
  62. }
  63.  
  64. // getters
  65. UInt64 Wallet::getUnits() const { return units; }
  66. size_t Wallet::opSize() const { return op.size(); }
  67. const Operation & Wallet::operator[](size_t index) const { return op[index]; }
  68.  
  69. // member functions
  70. Wallet Wallet::fromBinary(const char *str) {
  71. checkNull(str);
  72. string s(str);
  73. std::reverse(s.begin(), s.end());
  74. return Wallet(std::stoi(str, nullptr, 2));
  75. }
  76.  
  77. std::ostream & operator<<(std::ostream &os, const Wallet &w) {
  78. os << w.units / valueOfB << ',' << w.units % valueOfB;
  79. return os;
  80. }
  81.  
  82. Wallet operator*(int n, Wallet &&w) {
  83. Wallet ans;
  84. UInt64 toAdd = w.units;
  85. UInt64 mult = Wallet::checkSign(n);
  86. Wallet::checkTotal(toAdd, mult);
  87. ans.addUnits(toAdd * mult);
  88. ans.update();
  89. return ans;
  90. }
  91. Wallet operator*(int n, Wallet &w) { return n * move(w); }
  92. Wallet operator*(Wallet &w, int n) { return n * w; }
  93. Wallet operator*(Wallet &&w, int n) { return n * w; }
  94.  
  95. Wallet operator+(Wallet &&w1, Wallet &&w2) {
  96. UInt64 a = w1.units, b = w2.units;
  97. Wallet ans;
  98. w1.units = w2.units = 0;
  99. ans.units = a + b;
  100. ans.update();
  101. return ans;
  102. }
  103. Wallet operator+(Wallet &&w1, Wallet &w2) {
  104. UInt64 a = w1.units, b = w2.units;
  105. Wallet ans;
  106. w1.units = w2.units = 0;
  107. w2.update();
  108. ans.units = a + b;
  109. ans.update();
  110. return ans;
  111. }
  112. Wallet operator-(Wallet &&w1, Wallet &&w2) {
  113. Wallet ans;
  114. UInt64 a = w1.units, b = w2.units;
  115.  
  116. w1.remUnits(a);
  117. ans.addUnits(a);
  118. ans.remUnits(b);
  119. w2.addUnits(b);
  120. ans.update();
  121. w2.update();
  122. return ans;
  123. }
  124. Wallet operator-(Wallet &&w1, Wallet &w2) {
  125. Wallet ans;
  126. UInt64 a = w1.units, b = w2.units;
  127.  
  128. w1.remUnits(a);
  129. ans.addUnits(a);
  130. ans.remUnits(b);
  131. w2.addUnits(b);
  132. ans.update();
  133. w2.update();
  134. return ans;
  135. }
  136.  
  137. Wallet & Wallet::operator=(Wallet &&w) noexcept {
  138. if (debug)
  139. std::cerr << "operator= called\n";
  140. if (this == &w) return *this;
  141. std::swap(w.units, units);
  142. op = move(w.op);
  143. return *this;
  144. }
  145. Wallet & Wallet::operator+=(Wallet &w) {
  146. units += w.units;
  147. w.reset();
  148. update();
  149. return *this;
  150. }
  151. Wallet & Wallet::operator+=(Wallet &&w) {
  152. units += w.units;
  153. w.reset();
  154. update();
  155. return *this;
  156. }
  157. Wallet & Wallet::operator-=(Wallet &w) {
  158. checkAffordability(units, w.units);
  159. units -= w.units;
  160. w.units *= 2;
  161. w.update();
  162. update();
  163. return *this;
  164. }
  165. Wallet & Wallet::operator-=(Wallet &&w) {
  166. checkAffordability(units, w.units);
  167. units -= w.units;
  168. w.units *= 2;
  169. w.update();
  170. update();
  171. return *this;
  172.  
  173. }
  174. Wallet & Wallet::operator*=(int n) {
  175. UInt64 multiplier = checkSign(n);
  176. checkTotal(multiplier - 1, units);
  177. totalUnits += units * (multiplier-1);
  178. units *= multiplier;
  179. update();
  180. return *this;
  181. }
  182. bool Wallet::operator !=(const Wallet &w) const {
  183. return *this < w || w < *this;
  184. }
  185. bool Wallet::operator<(const Wallet &w) const { return units < w.units; }
  186. bool Wallet::operator<=(const Wallet &w) const { return !(w < *this); }
  187. bool Wallet::operator==(const Wallet &w) const {
  188. return !(*this < w || w < *this);
  189. }
  190. bool Wallet::operator>(const Wallet &w) const { return w < *this; }
  191. bool Wallet::operator>=(const Wallet &w) const { return !(*this < w); }
  192.  
  193. bool operator!=(int x, const Wallet &w) { return w != x; }
  194. bool operator<(int x, const Wallet &w) { return w > x; }
  195. bool operator<=(int x, const Wallet &w) { return w >= x; }
  196. bool operator==(int x, const Wallet &w) { return w == x; }
  197. bool operator>(int x, const Wallet &w) { return w < x; }
  198. bool operator>=(int x, const Wallet &w) { return w <= x; }
  199.  
  200. // private functions
  201. bool Wallet::isComma(char c) {
  202. return c == ',' || c == '.';
  203. }
  204.  
  205. UInt64 Wallet::parse(const char *str) {
  206. while (*str && isspace(*str)) ++str;
  207. char *s1;
  208. UInt64 fraction, floor;
  209. floor = checkSign(std::strtol(str, &s1, 10));
  210. // reads until the comma
  211. if (!isComma(*s1)) {
  212. checkFormat(floor);
  213. return floor*valueOfB;
  214. }
  215. ++s1;
  216. fraction = readAfterComma(s1);
  217. checkFormat(fraction);
  218. return floor * valueOfB + fraction;
  219. }
  220.  
  221. UInt64 Wallet::readAfterComma(const char *str) noexcept {
  222. int fracExp = valueOfB / 10;
  223. UInt64 ans = 0;
  224. for (; *str && !isspace(*str); fracExp /= 10, ++str) {
  225. if (!isdigit(*str) || !fracExp) return ULLONG_MAX;
  226. ans += fracExp * (*str - '0');
  227. }
  228. for (; *str; ++str) if (!isspace(*str)) return ULLONG_MAX;
  229. return ans;
  230. }
  231.  
  232. void Wallet::checkAffordability(UInt64 subtrahend, UInt64 minuend) {
  233. if (minuend > subtrahend)
  234. throw WalletException(WalletException::affordMsg);
  235. }
  236.  
  237. void Wallet::checkFormat(UInt64 x) {
  238. if (x == ULLONG_MAX)
  239. throw WalletException(WalletException::formatMsg);
  240. }
  241.  
  242. void Wallet::checkNull(const char *x) {
  243. if (!x) throw WalletException(WalletException::nullPtMsg);
  244. }
  245.  
  246. UInt64 Wallet::checkSign(long x) {
  247. if (x < 0) throw WalletException(WalletException::negValMsg);
  248. return UInt64(x);
  249. }
  250.  
  251. void Wallet::checkTotal(UInt64 x, UInt64 y) {
  252. bool b = false;
  253. if (x - 1 && y - 1) b = log2(x) + log2(y) > log2(maxValue - totalUnits);
  254. if (b || x * y > maxValue - totalUnits)
  255. throw WalletException(WalletException::coinLmMsg);
  256. }
  257.  
  258. void Wallet::addUnits(UInt64 x) {
  259. checkTotal(x, 1);
  260. units += x;
  261. totalUnits += x;
  262. }
  263.  
  264. void Wallet::reset() {
  265. units = 0;
  266. update();
  267. }
  268.  
  269. void Wallet::remUnits(UInt64 x) {
  270. checkAffordability(units, x);
  271. units -= x;
  272. totalUnits -= x;
  273. }
  274.  
  275. void Wallet::takeHistories(Wallet &w1, Wallet &w2) {
  276. size_t n1 = w1.opSize(), n2 = w2.opSize();
  277. // guards for the merge
  278. w1.update();
  279. w2.update();
  280. op.reserve(n1 + n2);
  281. for (size_t i = 0, j = 0; i + j < n1 + n2;) {
  282. if (w1.op[i] < w1.op[j]) {
  283. op.push_back(w1.op[i]);
  284. ++i;
  285. } else {
  286. op.push_back(w2.op[j]);
  287. ++j;
  288. }
  289. }
  290. }
  291.  
  292. void Wallet::update() {
  293. op.push_back(Operation(units));
  294. }
  295.  
  296. const Wallet& Empty() {
  297. static const Wallet empty = Wallet();
  298. return empty;
  299. }
  300.  
  301. Operation::Operation(UInt64 units) {
  302. time(&date);
  303. this->units = units;
  304. }
  305.  
  306. UInt64 Operation::getUnits() const { return units; }
  307.  
  308. std::ostream & operator<<(std::ostream &os, const Operation &o) {
  309. using std::to_string;
  310.  
  311. tm *ltm = localtime(&o.date);
  312. os << "Wallet balance is " << o.units / valueOfB << ',' << o.units % valueOfB;
  313. os << " B after operation made at day ";
  314. os << to_string(ltm->tm_year + 1900) + "-";
  315. os << to_string(ltm->tm_mon + 1) + "-" + to_string(ltm->tm_mday);
  316. return os;
  317. }
  318.  
  319. // all comparison operators refer to operator<
  320. bool Operation::operator!=(const Operation &o) const {
  321. return o < *this || *this < o;
  322. }
  323. bool Operation::operator<(const Operation &o) const { return date < o.date; }
  324. bool Operation::operator<=(const Operation &o) const { return !(o < *this); }
  325. bool Operation::operator>(const Operation &o) const { return o < *this; }
  326. bool Operation::operator>=(const Operation &o) const { return !(o < *this); }
  327. bool Operation::operator==(const Operation &o) const {
  328. return !(*this < o || o < *this);
  329. }
  330.  
  331. const char * WalletException::affordMsg = "insufficient funds";
  332. const char * WalletException::coinLmMsg = "coin count exceeds limit";
  333. const char * WalletException::formatMsg = "incorrect number format";
  334. const char * WalletException::negValMsg = "unexpected negative argument";
  335. const char * WalletException::nullPtMsg = "unexpected null pointer";
  336.  
  337. const char* WalletException::what() const noexcept { return msg.c_str(); }
  338.  
  339. WalletException::WalletException(
  340. const string &message
  341. ) noexcept : msg(message) {}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement