/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "base/basic_types.h" inline constexpr auto kOneStarInNano = int64(1'000'000'000); class StarsAmount { public: StarsAmount() = default; explicit StarsAmount(int64 whole) : _whole(whole) {} StarsAmount(int64 whole, int64 nano) : _whole(whole), _nano(nano) { normalize(); } [[nodiscard]] int64 whole() const { return _whole; } [[nodiscard]] int64 nano() const { return _nano; } [[nodiscard]] double value() const { return double(_whole) + double(_nano) / kOneStarInNano; } [[nodiscard]] bool empty() const { return !_whole && !_nano; } [[nodiscard]] inline bool operator!() const { return empty(); } [[nodiscard]] inline explicit operator bool() const { return !empty(); } inline StarsAmount &operator+=(StarsAmount other) { _whole += other._whole; _nano += other._nano; normalize(); return *this; } inline StarsAmount &operator-=(StarsAmount other) { _whole -= other._whole; _nano -= other._nano; normalize(); return *this; } inline StarsAmount &operator*=(int64 multiplier) { _whole *= multiplier; _nano *= multiplier; normalize(); return *this; } inline StarsAmount operator-() const { auto result = *this; result *= -1; return result; } friend inline auto operator<=>(StarsAmount, StarsAmount) = default; friend inline bool operator==(StarsAmount, StarsAmount) = default; [[nodiscard]] StarsAmount abs() const { return (_whole < 0) ? StarsAmount(-_whole, -_nano) : *this; } private: int64 _whole = 0; int64 _nano = 0; void normalize() { if (_nano < 0) { const auto shifts = (-_nano + kOneStarInNano - 1) / kOneStarInNano; _nano += shifts * kOneStarInNano; _whole -= shifts; } else if (_nano >= kOneStarInNano) { const auto shifts = _nano / kOneStarInNano; _nano -= shifts * kOneStarInNano; _whole += shifts; } } }; [[nodiscard]] inline StarsAmount operator+(StarsAmount a, StarsAmount b) { return a += b; } [[nodiscard]] inline StarsAmount operator-(StarsAmount a, StarsAmount b) { return a -= b; } [[nodiscard]] inline StarsAmount operator*(StarsAmount a, int64 b) { return a *= b; } [[nodiscard]] inline StarsAmount operator*(int64 a, StarsAmount b) { return b *= a; }