github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/byte.cpp (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  #include "common/byte.h"
    21  #include "common/base58.h"
    22  #include "common/base64.h"
    23  #include <iomanip>
    24  #include <sstream>
    25  
    26  namespace neb {
    27  
    28  namespace internal {
    29  std::string convert_byte_to_hex(const byte_t *buf, size_t len) {
    30    if (!buf)
    31      return "";
    32    std::stringstream s;
    33    for (size_t i = 0; i < len; i++) {
    34      s << std::hex << std::setw(2) << std::setfill('0')
    35        << static_cast<int>(buf[i]);
    36    }
    37    return s.str();
    38  }
    39  
    40  std::string convert_byte_to_base58(const byte_t *buf, size_t len) {
    41    return ::neb::encode_base58(buf, buf + len);
    42  }
    43  
    44  std::string convert_byte_to_base64(const byte_t *buf, size_t len) {
    45    return ::neb::encode_base64(buf, buf + len);
    46  }
    47  
    48  bool convert_hex_to_bytes(const std::string &s, byte_t *buf, size_t &len) {
    49    auto char2int = [](char input) {
    50      if (input >= '0' && input <= '9')
    51        return input - '0';
    52      if (input >= 'A' && input <= 'F')
    53        return input - 'A' + 10;
    54      if (input >= 'a' && input <= 'f')
    55        return input - 'a' + 10;
    56      throw std::invalid_argument("Invalid input string");
    57    };
    58  
    59    try {
    60      size_t i = 0;
    61      while (i * 2 < s.size() && i * 2 + 1 < s.size()) {
    62        if (buf) {
    63          buf[i] = (char2int(s[i * 2]) << 4) + char2int(s[i * 2 + 1]);
    64        }
    65        i++;
    66      }
    67      len = i;
    68    } catch (std::exception &e) {
    69      return false;
    70    }
    71    return true;
    72  }
    73  
    74  template <typename CHAR>
    75  void convert_string_to_byte(const CHAR *s, byte_t *buf, size_t size) {
    76    if (buf) {
    77      memcpy(buf, s, size);
    78    }
    79  }
    80  
    81  bool convert_base58_to_bytes(const std::string &s, byte_t *buf, size_t &len) {
    82    std::vector<unsigned char> ret;
    83    bool rv = ::neb::decode_base58(s, ret);
    84    if (rv) {
    85      len = ret.size();
    86      convert_string_to_byte(&ret[0], buf, len);
    87    }
    88  
    89    return rv;
    90  }
    91  
    92  bool convert_base64_to_bytes(const std::string &s, byte_t *buf, size_t &len){
    93    std::string output_string;
    94    bool rv = ::neb::decode_base64(s, output_string);
    95  
    96    if (rv) {
    97      len = output_string.size();
    98      if (nullptr != buf) {
    99        convert_string_to_byte(output_string.c_str(), buf, len);
   100      }
   101    } else {
   102      throw std::invalid_argument("Invalid decode_base64.");
   103    }
   104  
   105    return rv;
   106  }
   107  }
   108  bytes::bytes() : m_value(nullptr), m_size(0) {}
   109  
   110  bytes::bytes(size_t len)
   111      : m_value(std::unique_ptr<byte_t[]>(new byte_t[len])), m_size(len) {}
   112  
   113  bytes::bytes(const bytes &v) : bytes(v.size()) {
   114    memcpy(m_value.get(), v.m_value.get(), v.size());
   115    m_size = v.size();
   116  }
   117  
   118  bytes::bytes(bytes &&v) : m_value(std::move(v.m_value)), m_size(v.size()) {}
   119  
   120  bytes::bytes(std::initializer_list<byte_t> l) {
   121    if (l.size() > 0) {
   122      m_value = std::unique_ptr<byte_t[]>(new byte_t[l.size()]);
   123      std::copy(l.begin(), l.end(), m_value.get());
   124    }
   125    m_size = l.size();
   126  }
   127  bytes::bytes(const byte_t *buf, size_t buf_len) {
   128    m_size = buf_len;
   129    if (buf_len > 0) {
   130      m_value = std::unique_ptr<byte_t[]>(new byte_t[buf_len]);
   131      memcpy(m_value.get(), buf, buf_len);
   132    }
   133  }
   134  bytes &bytes::operator=(const bytes &v) {
   135    if (&v == this)
   136      return *this;
   137    if (v.value()) {
   138      m_value = std::unique_ptr<byte_t[]>(new byte_t[v.size()]);
   139      memcpy(m_value.get(), v.m_value.get(), v.size());
   140    }
   141    m_size = v.size();
   142    return *this;
   143  }
   144  
   145  bytes &bytes::operator=(bytes &&v) {
   146    m_value = std::move(v.m_value);
   147    m_size = v.m_size;
   148    return *this;
   149  }
   150  
   151  bool bytes::operator==(const bytes &v) const {
   152    if (v.size() != size())
   153      return false;
   154    return memcmp(v.value(), value(), size()) == 0;
   155  }
   156  bool bytes::operator!=(const bytes &v) const { return !operator==(v); }
   157  
   158  bool bytes::operator<(const bytes &v) const {
   159    return std::to_string(*this) < std::to_string(v);
   160  }
   161  
   162  byte_t bytes::operator[](size_t index) const { return m_value.get()[index]; }
   163  byte_t &bytes::operator[](size_t index) { return m_value.get()[index]; }
   164  
   165  std::string bytes::to_base58() const {
   166    return internal::convert_byte_to_base58(value(), size());
   167  }
   168  
   169  std::string bytes::to_base64() const {
   170    return internal::convert_byte_to_base64(value(), size());
   171  }
   172  
   173  std::string bytes::to_hex() const {
   174    return internal::convert_byte_to_hex(value(), size());
   175  }
   176  
   177  bytes bytes::from_base58(const std::string &t) {
   178    size_t len = 0;
   179    bool succ = internal::convert_base58_to_bytes(t, nullptr, len);
   180    if (!succ)
   181      throw std::invalid_argument("invalid base58 string for from_base58");
   182    bytes ret(len);
   183    internal::convert_base58_to_bytes(t, ret.value(), len);
   184    return ret;
   185  }
   186  
   187  bytes bytes::from_base64(const std::string &t) {
   188    size_t len = 0;
   189    bool succeed = internal::convert_base64_to_bytes(t, nullptr, len);
   190    if (!succeed) {
   191      throw std::invalid_argument("invalid base64 string for from_base64");
   192    }
   193  
   194    bytes ret(len);
   195    internal::convert_base64_to_bytes(t, ret.value(), len);
   196  
   197    return ret;
   198  }
   199  
   200  bytes bytes::from_hex(const std::string &t) {
   201    size_t len = 0;
   202    bool succ = internal::convert_hex_to_bytes(t, nullptr, len);
   203    if (!succ) {
   204      throw std::invalid_argument("invalid hex string for from_hex");
   205    }
   206  
   207    bytes ret(len);
   208    bool succ_ret = internal::convert_hex_to_bytes(t, ret.value(), len);
   209    if (!succ_ret) {
   210      throw std::invalid_argument("invalid hex string for from_hex");
   211    }
   212  
   213    return ret;
   214  }
   215  
   216  bytes &bytes::append_bytes(const byte_t *buf, size_t buf_len) {
   217    if (buf_len <= 0) {
   218      return *this;
   219    }
   220  
   221    auto new_value = std::unique_ptr<byte_t[]>(new byte_t[m_size + buf_len]);
   222    memcpy(new_value.get(), m_value.get(), m_size);
   223    memcpy(new_value.get() + m_size, buf, buf_len);
   224  
   225    m_value = std::move(new_value);
   226    m_size += buf_len;
   227    return *this;
   228  }
   229  bytes &bytes::append_bytes(const bytes &v) {
   230    return append_bytes(v.value(), v.size());
   231  }
   232  } // namespace neb