YPC  0.2.0
bytes.h
Go to the documentation of this file.
1 
8 #pragma once
9 #include "ypc/common/byte/base58.h"
10 #include "ypc/common/byte/base64.h"
11 #include "ypc/common/byte/bytes_common.h"
12 #include <cstdint>
13 #include <cstring>
14 #include <memory>
15 #include <string>
16 
17 namespace ypc {
18 namespace utc {
19 namespace internal {
20 template <typename ByteType> class bytes_base {
21 public:
22  using byte_t = ByteType;
23 
24  static_assert(sizeof(ByteType) == 1,
25  "cannot use ByteType that with larger size than 1");
26 
27  bytes_base() : m_value(nullptr), m_size(0) {}
28  explicit bytes_base(size_t len)
29  : m_value(std::unique_ptr<byte_t[]>(new byte_t[len])), m_size(len) {}
30 
31  bytes_base(const bytes_base<ByteType> &v) : bytes_base(v.size()) {
32  memcpy(m_value.get(), v.m_value.get(), v.size());
33  m_size = v.size();
34  }
35  bytes_base<ByteType> &operator=(const bytes_base<ByteType> &v) {
36  if (this == &v) {
37  return *this;
38  }
39  if (v.m_value.size() == 0) {
40  return *this;
41  }
42 
43  if (m_size < v.size() || m_size > 2 * v.size()) {
44  m_value.reset(new byte_t[v.size()]);
45  }
46  memcpy(m_value.get(), v.m_value.get(), v.size());
47  m_size = v.size();
48  return *this;
49  }
51  if (this == &v) {
52  return *this;
53  }
54  m_value = std::move(v.m_value);
55  m_size = v.size();
56  return *this;
57  }
58 
60  : m_value(std::move(v.m_value)), m_size(v.size()) {}
61 
62  bytes_base(std::initializer_list<byte_t> l) {
63  if (l.size() > 0) {
64  m_value = std::unique_ptr<byte_t[]>(new byte_t[l.size()]);
65  std::copy(l.begin(), l.end(), m_value.get());
66  }
67  m_size = l.size();
68  }
69  template <typename T> bytes_base(const T *v, size_t len) {
70  static_assert(sizeof(T) == 1, "invalid pointer type");
71  m_size = len;
72  if (len > 0) {
73  m_value = std::unique_ptr<byte_t[]>(new byte_t[len]);
74  memcpy(m_value.get(), v, len);
75  }
76  }
77  virtual ~bytes_base() = default;
78 
79  const byte_t &operator[](size_t index) const { return m_value.get()[index]; }
80  byte_t &operator[](size_t index) { return m_value.get()[index]; }
81 
82  inline size_t size() const { return m_size; }
83  inline const byte_t *data() const {
84  if (nullptr != m_value) {
85  return m_value.get();
86  }
87  return nullptr;
88  }
89  inline byte_t *data() {
90  if (nullptr != m_value) {
91  return m_value.get();
92  }
93  return nullptr;
94  }
95 
96  inline bool empty() const { return m_size == 0; }
97 
98  bool operator<(const bytes_base<ByteType> &v) const {
99  if (v.m_size == m_size) {
100  if (memcmp(m_value.get(), v.m_value.get(), m_size) == 0) {
101  return false;
102  }
103  }
104 
105  for (size_t i = 0; i < m_size && i < v.m_size; i++) {
106  if (m_value[i] > v.m_value[i]) {
107  return false;
108  }
109  }
110  if (v.m_size < m_size) {
111  return false;
112  }
113  return true;
114  }
115 
116  bool operator>(const bytes_base<ByteType> &v) const {
117  if (v.m_size == m_size) {
118  if (memcmp(m_value.get(), v.m_value.get(), m_size) == 0) {
119  return false;
120  }
121  }
122 
123  for (size_t i = 0; i < m_size && i < v.m_size; i++) {
124  if (m_value[i] < v.m_value[i]) {
125  return false;
126  }
127  }
128  if (v.m_size > m_size) {
129  return false;
130  }
131  return true;
132  }
133 
134 protected:
135  std::unique_ptr<byte_t[]> m_value;
136  size_t m_size;
137 }; // end class bytes_base
138 
139 } // namespace internal
140 
141 
142 template <typename ByteType, byte_encode Format = byte_encode::raw_bytes>
143 class bytes : public internal::bytes_base<ByteType> {
144 public:
145  using byte_t = ByteType;
146  const static byte_encode format = Format;
151 
153  explicit bytes(size_t len) : internal::bytes_base<ByteType>(len) {}
156  bytes(std::initializer_list<ByteType> l)
158  template <typename T>
159  bytes(const T *v, size_t len) : internal::bytes_base<ByteType>(v, len) {}
160 
161  explicit bytes(const char *str)
162  : internal::bytes_base<ByteType>(str, strlen(str)) {}
163  explicit bytes(const std::string &str)
164  : internal::bytes_base<ByteType>(str.data(), str.size()){};
165  virtual ~bytes() = default;
166 
167  template <typename BytesType>
168  auto as() const -> typename std::enable_if<
169  std::is_same<typename BytesType::byte_t, ByteType>::value &&
170  (BytesType::format == byte_encode::base58_bytes &&
171  Format == byte_encode::raw_bytes),
172  BytesType>::type {
173  std::string s = encode_base58(
174  (const unsigned char *)internal::bytes_base<ByteType>::data(),
175  (const unsigned char *)internal::bytes_base<ByteType>::data() +
177  bytes<ByteType, byte_encode::base58_bytes> ret(s.data(), s.size());
178  return ret;
179  }
180  template <typename BytesType>
181  auto as() const -> typename std::enable_if<
182  std::is_same<typename BytesType::byte_t, ByteType>::value &&
183  (BytesType::format == byte_encode::hex_bytes &&
184  Format == byte_encode::raw_bytes),
185  BytesType>::type {
188  internal::convert_bytes_to_hex(internal::bytes_base<ByteType>::data(),
190  ret.data(), ret.size());
191  return ret;
192  }
193 
194  template <typename BytesType>
195  auto as() const -> typename std::enable_if<
196  std::is_same<typename BytesType::byte_t, ByteType>::value &&
197  (BytesType::format == byte_encode::base64_bytes &&
198  Format == byte_encode::raw_bytes),
199  BytesType>::type {
200  std::string s = base64_encode(
201  (unsigned char const *)internal::bytes_base<ByteType>::data(),
203  bytes<ByteType, byte_encode::base64_bytes> ret(s.data(), s.size());
204  return ret;
205  }
206 
207  template <typename BytesType>
208  auto as() const -> typename std::enable_if<
209  std::is_same<typename BytesType::byte_t, ByteType>::value &&
210  (BytesType::format == byte_encode::raw_bytes &&
211  Format == byte_encode::hex_bytes),
212  BytesType>::type {
215  auto v = internal::convert_hex_to_bytes(
217  internal::bytes_base<ByteType>::size(), ret.data(), ret.size());
218  if (!v) {
219  throw std::invalid_argument("invalid hex string");
220  }
221  return ret;
222  }
223 
224  template <typename BytesType>
225  auto as() const -> typename std::enable_if<
226  std::is_same<typename BytesType::byte_t, ByteType>::value &&
227  (BytesType::format == byte_encode::raw_bytes &&
228  Format == byte_encode::base58_bytes),
229  BytesType>::type {
230  std::vector<unsigned char> v;
231  auto r = decode_base58(
232  std::string((const char *)internal::bytes_base<ByteType>::data(),
234  v);
235  if (!r) {
236  throw std::invalid_argument("Invalid base58 string");
237  }
238  return bytes<ByteType, byte_encode::raw_bytes>(v.data(), v.size());
239  }
240 
241  template <typename BytesType>
242  auto as() const -> typename std::enable_if<
243  std::is_same<typename BytesType::byte_t, ByteType>::value &&
244  (BytesType::format == byte_encode::raw_bytes &&
245  Format == byte_encode::base64_bytes),
246  BytesType>::type {
247  std::string s = base64_decode(
248  std::string((const char *)internal::bytes_base<ByteType>::data(),
250  return bytes<ByteType, byte_encode::raw_bytes>(s.data(), s.size());
251  }
252 
253  bytes<ByteType, Format> &operator=(const bytes<ByteType, Format> &v) {
254  if (&v == this) {
255  return *this;
256  }
257  if (v.data()) {
259  std::unique_ptr<ByteType[]>(new ByteType[v.size()]);
260  memcpy(internal::bytes_base<ByteType>::m_value.get(), v.m_value.get(),
261  v.size());
262  }
264  return *this;
265  }
267  internal::bytes_base<ByteType>::m_value = std::move(v.m_value);
269  return *this;
270  }
271 
272  bool operator==(const bytes<ByteType, Format> &v) const {
273  if (v.size() != internal::bytes_base<ByteType>::size()) {
274  return false;
275  }
276  return memcmp(v.data(), internal::bytes_base<ByteType>::data(),
278  }
279 
280  bool operator!=(const bytes<ByteType, Format> &v) const {
281  return !operator==(v);
282  }
283 
284  bytes<ByteType, Format> operator+(const bytes<ByteType, Format> &v) const {
286  v.size());
288  memcpy(ret.data(), internal::bytes_base<ByteType>::data(),
290  }
291  if (v.size() != 0) {
292  memcpy(ret.data() + internal::bytes_base<ByteType>::size(), v.data(),
293  v.size());
294  }
295  return ret;
296  }
297 
298  bytes<ByteType, Format> operator+(const char *s) const {
299  if (s == nullptr) {
300  return *this;
301  }
302 
304  strlen(s));
306  memcpy(ret.data(), internal::bytes_base<ByteType>::data(),
308  }
309  memcpy(ret.data() + internal::bytes_base<ByteType>::size(), s, strlen(s));
310  return ret;
311  }
312 
313  bytes<ByteType, Format> operator+(const std::string &s) const {
314  if (s.empty()) {
315  return *this;
316  }
318  s.size());
320  memcpy(ret.data(), internal::bytes_base<ByteType>::data(),
322  }
323  memcpy(ret.data() + internal::bytes_base<ByteType>::size(), s.data(),
324  s.size());
325  return ret;
326  }
327  template <typename T> bytes<ByteType, Format> &operator+=(const T &t) {
328  *this = *this + t;
329  return *this;
330  }
331 };
332 
333 
334 } // namespace utc
335 } // namespace ypc
ypc::utc::internal::bytes_base
Definition: bytes.h:20
ypc::utc::bytes
Definition: bytes.h:143