github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/nebulas_currency.h (about)

     1  // Copyright (C) 2018 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or
     6  // modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or
     9  // (at your option) any later version.
    10  //
    11  // the go-nebulas library is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with the go-nebulas library.  If not, see
    18  // <http://www.gnu.org/licenses/>.
    19  //
    20  
    21  #pragma once
    22  #include "common/byte.h"
    23  #include "common/common.h"
    24  
    25  namespace neb {
    26  
    27  template <int64_t ratio> class nas_currency_t {
    28  public:
    29    typedef boost::multiprecision::int128_t nas_currency_value_t;
    30  
    31    nas_currency_t() : m_value(0) {}
    32    nas_currency_t(const nas_currency_value_t &v) : m_value(v) {}
    33  
    34    template <int64_t r>
    35    nas_currency_t(const nas_currency_t<r> &v) : m_value(v.wei_value()){};
    36  
    37    nas_currency_t(long double v) : m_value(v * ratio) {}
    38  
    39    nas_currency_t(const nas_currency_t<ratio> &v) : m_value(v.m_value) {}
    40  
    41    nas_currency_t<ratio> &operator=(const nas_currency_t<ratio> &v) {
    42      if (&v == this)
    43        return *this;
    44      m_value = v.m_value;
    45      return *this;
    46    }
    47  
    48    nas_currency_t<ratio> &operator++() {
    49      m_value += ratio;
    50      return *this;
    51    }
    52    nas_currency_t<ratio> operator++(int) {
    53      nas_currency_t<ratio> tmp(*this); // copy
    54      operator++();                     // pre-increment
    55      return tmp;                       // return old value
    56    }
    57  
    58    nas_currency_t<ratio> &operator--() {
    59      m_value -= ratio;
    60      return *this;
    61    }
    62    nas_currency_t<ratio> operator--(int) {
    63      nas_currency_t<ratio> tmp(*this); // copy
    64      operator--();                     // pre-increment
    65      return tmp;                       // return old value
    66    }
    67  
    68    template <int64_t r1, int64_t r2>
    69    friend bool operator<(const nas_currency_t<r1> &l,
    70                          const nas_currency_t<r2> &r) {
    71      return l.m_value < r.m_value;
    72    }
    73    template <int64_t r1, int64_t r2>
    74    friend bool operator>(const nas_currency_t<r1> &lhs,
    75                          const nas_currency_t<r2> &rhs) {
    76      return rhs < lhs;
    77    }
    78    template <int64_t r1, int64_t r2>
    79    friend bool operator<=(const nas_currency_t<r1> &lhs,
    80                           const nas_currency_t<r2> &rhs) {
    81      return !(lhs > rhs);
    82    }
    83    template <int64_t r1, int64_t r2>
    84    friend bool operator>=(const nas_currency_t<r1> &lhs,
    85                           const nas_currency_t<r2> &rhs) {
    86      return !(lhs < rhs);
    87    }
    88    template <int64_t r1, int64_t r2>
    89    friend bool operator==(const nas_currency_t<r1> &lhs,
    90                           const nas_currency_t<r2> &rhs) {
    91      return lhs.m_value == rhs.m_value;
    92    }
    93    template <int64_t r1, int64_t r2>
    94    friend bool operator!=(const nas_currency_t<r1> &lhs,
    95                           const nas_currency_t<r2> &rhs) {
    96      return lhs.m_value != rhs.m_value;
    97    }
    98  
    99    template <int64_t r1, int64_t r2>
   100    friend nas_currency_t<r1> operator+(const nas_currency_t<r1> &l,
   101                                        const nas_currency_t<r2> &r) {
   102      nas_currency_t<r1> tmp;
   103      tmp.m_value = l.m_value + r.m_value;
   104      return tmp;
   105    }
   106  
   107    template <int64_t r1, int64_t r2>
   108    friend nas_currency_t<r1> operator-(const nas_currency_t<r1> &l,
   109                                        const nas_currency_t<r2> &r) {
   110      nas_currency_t<r1> tmp;
   111      tmp.m_value = l.m_value + r.m_value;
   112      return tmp;
   113    }
   114  
   115    nas_currency_value_t wei_value() const { return m_value; }
   116  
   117    long double value() const {
   118      return m_value.convert_to<long double>() / ratio;
   119    }
   120  
   121  protected:
   122    nas_currency_value_t m_value;
   123  
   124  }; // end class nas_currency_unit
   125  
   126  typedef nas_currency_t<1000000000000000000> nas;
   127  typedef nas_currency_t<1> wei;
   128  
   129  template <int64_t r1, int64_t r2>
   130  nas_currency_t<r1> nas_cast(const nas_currency_t<r2> &v) {
   131    return nas_currency_t<r1>(v);
   132  }
   133  
   134  template <class T> struct is_nas_currency { const static bool value = false; };
   135  template <int64_t r> struct is_nas_currency<nas_currency_t<r>> {
   136    const static bool value = true;
   137  };
   138  
   139  template <class T1, class T2>
   140  auto nas_cast(const T2 &v) -> typename std::enable_if<
   141      is_nas_currency<T1>::value && is_nas_currency<T2>::value, T1>::type {
   142    return T1(v);
   143  }
   144  
   145  typedef fix_bytes<16> nas_storage_t;
   146  
   147  template <typename T> nas_storage_t nas_to_storage(const T &v) {
   148    nas::nas_currency_value_t cv = v.wei_value();
   149  
   150    uint64_t high = static_cast<uint64_t>(cv >> 64);
   151    nas::nas_currency_value_t mask(0xFFFFFFFFFFFFFFFF);
   152    auto lm = cv & mask;
   153    uint64_t low = static_cast<uint64_t>(lm);
   154    nas_storage_t ret;
   155    uint64_t *low_ptr = (uint64_t *)ret.value();
   156    *low_ptr = boost::endian::native_to_big(high);
   157    uint64_t *high_ptr = (uint64_t *)(ret.value() + 8);
   158    *high_ptr = boost::endian::native_to_big(low);
   159  
   160    return ret;
   161  }
   162  
   163  template <typename T> T storage_to_nas(const nas_storage_t &v) {
   164    uint64_t low;
   165    uint64_t high;
   166    low = *(uint64_t *)(v.value());
   167    high = *(uint64_t *)(v.value() + 8);
   168  
   169    low = boost::endian::big_to_native(low);
   170    high = boost::endian::big_to_native(high);
   171    nas::nas_currency_value_t cv(low);
   172    cv = cv << 64;
   173    cv += nas::nas_currency_value_t(high);
   174  
   175    return nas(cv);
   176  }
   177  
   178  inline neb::bytes wei_to_storage(const wei_t &v) {
   179    return from_fix_bytes(nas_to_storage(nas(v)));
   180  }
   181  inline wei_t storage_to_wei(const neb::bytes &v) {
   182    return storage_to_nas<nas>(to_fix_bytes<nas_storage_t>(v)).wei_value();
   183  }
   184  
   185  } // end namespace neb
   186  
   187  neb::nas operator"" _nas(long double x);
   188  neb::nas operator"" _nas(const char *s);
   189  
   190  neb::wei operator"" _wei(long double x);
   191  neb::wei operator"" _wei(const char *s);
   192  
   193  std::ostream &operator<<(std::ostream &os, const neb::nas &obj);
   194  
   195  std::ostream &operator<<(std::ostream &os, const neb::wei &obj);