github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/byte.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/common.h"
    23  #include <boost/endian/conversion.hpp>
    24  #include <utility>
    25  
    26  namespace neb {
    27  
    28  namespace internal {
    29  std::string convert_byte_to_hex(const byte_t *buf, size_t len);
    30  std::string convert_byte_to_base58(const byte_t *buf, size_t len);
    31  std::string convert_byte_to_base64(const byte_t *buf, size_t len);
    32  
    33  bool convert_hex_to_bytes(const std::string &s, byte_t *buf, size_t &len);
    34  bool convert_base58_to_bytes(const std::string &s, byte_t *buf, size_t &len);
    35  bool convert_base64_to_bytes(const std::string &s, byte_t *buf, size_t &len);
    36  
    37  template <typename T, std::size_t N, std::size_t... Ns>
    38  std::array<T, N> make_array_impl(std::initializer_list<T> t,
    39                                   std::index_sequence<Ns...>) {
    40    return std::array<T, N>{*(t.begin() + Ns)...};
    41  }
    42  
    43  template <typename T, std::size_t N>
    44  std::array<T, N> make_array(std::initializer_list<T> t) {
    45    if (N < t.size())
    46      throw std::out_of_range("make_array out of range");
    47    return make_array_impl<T, N>(t, std::make_index_sequence<N>());
    48  };
    49  } // end namespace internal
    50  
    51  template <size_t ByteLength = 32> class fix_bytes {
    52  public:
    53    fix_bytes() : m_value{0} {};
    54    fix_bytes(std::initializer_list<byte_t> l)
    55        : m_value(internal::make_array<byte_t, ByteLength>(l)) {}
    56    fix_bytes(const fix_bytes<ByteLength> &v) : m_value(v.m_value) {}
    57    fix_bytes(fix_bytes &&v) : m_value(std::move(v.m_value)) {}
    58    fix_bytes(const byte_t *buf, size_t buf_len) {
    59      if (buf_len >= ByteLength) {
    60        memcpy(m_value.data(), buf, ByteLength);
    61      } else {
    62        LOG(ERROR) << "buf len is: " << buf_len << ", less than " << ByteLength;
    63      }
    64    }
    65  
    66    fix_bytes<ByteLength> &operator=(const fix_bytes<ByteLength> &v) {
    67      if (&v == this)
    68        return *this;
    69      m_value = v.m_value;
    70      return *this;
    71    }
    72  
    73    fix_bytes<ByteLength> &operator=(fix_bytes<ByteLength> &&v) {
    74      m_value = std::move(v.m_value);
    75      return *this;
    76    }
    77  
    78    bool operator==(const fix_bytes<ByteLength> &v) const {
    79      return m_value == v.m_value;
    80    }
    81  
    82    bool operator!=(const fix_bytes<ByteLength> &v) const {
    83      return m_value != v.m_value;
    84    }
    85    bool operator<(const fix_bytes<ByteLength> &v) const {
    86      return memcmp(m_value, v.m_value, ByteLength) < 0;
    87    }
    88    byte_t operator[](size_t index) const { return m_value[index]; }
    89    byte_t &operator[](size_t index) { return m_value[index]; }
    90  
    91    std::string to_base58() const {
    92      return internal::convert_byte_to_base58(value(), size());
    93    }
    94  
    95    std::string to_base64() const {
    96      return internal::convert_byte_to_base64(value(), size());
    97    }
    98  
    99    std::string to_hex() const {
   100      return internal::convert_byte_to_hex(value(), size());
   101    }
   102  
   103    inline size_t size() const { return ByteLength; }
   104  
   105    inline const byte_t *value() const { return m_value.data(); }
   106  
   107    inline byte_t *value() { return m_value.data(); }
   108  
   109    static fix_bytes<ByteLength> from_base58(const std::string &t) {
   110      fix_bytes<ByteLength> ret;
   111      size_t s = ret.size();
   112      bool succ = internal::convert_base58_to_bytes(t, ret.value(), s);
   113      if (!succ)
   114        throw std::invalid_argument("invalid base58 string for from_base58");
   115      return ret;
   116    }
   117  
   118    static fix_bytes<ByteLength> from_base64(const std::string &t) {
   119      fix_bytes<ByteLength> ret;
   120      size_t s = ret.size();
   121      bool succ = internal::convert_base64_to_bytes(t, ret.value(), s);
   122      if (!succ)
   123        throw std::invalid_argument("invalid base64 string for from_base64");
   124      return ret;
   125    }
   126  
   127    static fix_bytes<ByteLength> from_hex(const std::string &t) {
   128      fix_bytes<ByteLength> ret;
   129      size_t s = ret.size();
   130      bool succ = internal::convert_hex_to_bytes(t, ret.value(), s);
   131      if (!succ)
   132        throw std::invalid_argument("invalid hex string for from_hex");
   133      return ret;
   134    }
   135  
   136    bool empty() const { return m_value.empty(); }
   137  
   138  protected:
   139    std::array<byte_t, ByteLength> m_value;
   140  }; // end class fix_bytes
   141  
   142  template <typename T> struct is_fix_bytes { const static bool value = false; };
   143  template <size_t N> struct is_fix_bytes<fix_bytes<N>> {
   144    const static bool value = true;
   145  };
   146  
   147  class bytes {
   148  public:
   149    bytes();
   150    bytes(size_t len);
   151  
   152    bytes(const bytes &v);
   153    bytes(bytes &&v);
   154    bytes(std::initializer_list<byte_t> l);
   155    bytes(const byte_t *v, size_t len);
   156  
   157    bytes &operator=(const bytes &v);
   158    bytes &operator=(bytes &&v);
   159  
   160    bool operator==(const bytes &v) const;
   161    bool operator!=(const bytes &v) const;
   162    bool operator<(const bytes &v) const;
   163  
   164    byte_t operator[](size_t index) const;
   165    byte_t &operator[](size_t index);
   166  
   167    std::string to_base58() const;
   168    std::string to_base64() const;
   169    std::string to_hex() const;
   170  
   171    static bytes from_base58(const std::string &t);
   172    static bytes from_base64(const std::string &t);
   173    static bytes from_hex(const std::string &t);
   174  
   175    inline size_t size() const { return m_size; }
   176    inline const byte_t *value() const {
   177      if(nullptr != m_value){
   178        return m_value.get();
   179      }else{
   180        return nullptr;
   181      }
   182    }
   183    inline byte_t *value() {
   184      if(nullptr != m_value){
   185        return m_value.get();
   186      }else{
   187        return nullptr;
   188      }
   189    }
   190  
   191    inline bool empty() const { return m_size == 0; }
   192  
   193    bytes &append_bytes(const byte_t *buf, size_t buf_len);
   194    bytes &append_bytes(const bytes &v);
   195  
   196  private:
   197    std::unique_ptr<byte_t[]> m_value;
   198    size_t m_size;
   199  }; // end class bytes
   200  
   201  inline bytes string_to_byte(const std::string &str) {
   202    return bytes((const byte_t *)(str.c_str()), str.size());
   203  }
   204  
   205  inline std::string byte_to_string(const bytes &b) {
   206    return std::string((const char*)b.value(), b.size());
   207  }
   208  
   209  template <typename T>
   210  auto byte_to_number(byte_t *bytes, size_t len) ->
   211      typename std::enable_if<std::is_arithmetic<T>::value, T>::type {
   212    if (len < sizeof(T))
   213      return T();
   214  
   215    T *val = (T *)bytes;
   216    T ret = boost::endian::big_to_native(*val);
   217    return ret;
   218  }
   219  
   220  template <typename T>
   221  auto number_to_byte(T val, byte_t *bytes, size_t len) ->
   222      typename std::enable_if<std::is_arithmetic<T>::value, void>::type {
   223    if (len < sizeof(T))
   224      return;
   225  
   226    T v = boost::endian::native_to_big(val);
   227    T *p = (T *)bytes;
   228    *p = v;
   229    return;
   230  }
   231  
   232  template <typename T, typename BytesType>
   233  auto byte_to_number(const BytesType &v) ->
   234      typename std::enable_if<std::is_arithmetic<T>::value, T>::type {
   235    if (v.size() < sizeof(T))
   236      return T();
   237  
   238    T *val = (T *)v.value();
   239    T ret = boost::endian::big_to_native(*val);
   240    return ret;
   241  }
   242  
   243  template <typename BytesType, typename T>
   244  auto number_to_byte(T val) ->
   245      typename std::enable_if<std::is_arithmetic<T>::value &&
   246                                  std::is_same<BytesType, bytes>::value,
   247                              BytesType>::type {
   248    T v = boost::endian::native_to_big(val);
   249    BytesType b((byte_t *)&v, sizeof(v));
   250    return b;
   251  }
   252  
   253  template <typename BytesType, typename T>
   254  auto number_to_byte(T val) ->
   255      typename std::enable_if<std::is_arithmetic<T>::value &&
   256                                  is_fix_bytes<BytesType>::value,
   257                              BytesType>::type {
   258    T v = boost::endian::native_to_big(val);
   259    BytesType b;
   260    T *rval = (T *)b.value();
   261    *rval = v;
   262    return b;
   263  }
   264  template <typename FixBytesType> FixBytesType to_fix_bytes(const bytes &val) {
   265    FixBytesType ret;
   266    assert(val.size() == ret.size());
   267    memcpy(ret.value(), val.value(), ret.size());
   268    return ret;
   269  }
   270  
   271  template <typename FixBytesType> bytes from_fix_bytes(const FixBytesType &val) {
   272    return bytes(val.value(), val.size());
   273  }
   274  }
   275  namespace std {
   276  template <> struct hash<::neb::bytes> {
   277    typedef ::neb::bytes argument_type;
   278    typedef std::size_t result_type;
   279    result_type operator()(argument_type const &s) const noexcept {
   280      return std::hash<std::string>{}(byte_to_string(s));
   281    }
   282  };
   283  
   284  template <size_t ByteLength> struct hash<::neb::fix_bytes<ByteLength>> {
   285    typedef ::neb::fix_bytes<ByteLength> argument_type;
   286    typedef std::size_t result_type;
   287    result_type operator()(argument_type const &s) const noexcept {
   288      return std::hash<std::string>{}(byte_to_string(s));
   289    }
   290  };
   291  
   292  inline std::string to_string(const ::neb::bytes &s) {
   293    return byte_to_string(s);
   294  }
   295  } // namespace std