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