rippled
base_uint.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 // Copyright (c) 2009-2010 Satoshi Nakamoto
21 // Copyright (c) 2011 The Bitcoin developers
22 // Distributed under the MIT/X11 software license, see the accompanying
23 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
24 
25 #ifndef RIPPLE_BASICS_BASE_UINT_H_INCLUDED
26 #define RIPPLE_BASICS_BASE_UINT_H_INCLUDED
27 
28 #include <ripple/basics/Expected.h>
29 #include <ripple/basics/Slice.h>
30 #include <ripple/basics/contract.h>
31 #include <ripple/basics/hardened_hash.h>
32 #include <ripple/basics/strHex.h>
33 #include <ripple/beast/utility/Zero.h>
34 #include <boost/endian/conversion.hpp>
35 #include <boost/functional/hash.hpp>
36 #include <array>
37 #include <cstring>
38 #include <functional>
39 #include <type_traits>
40 
41 namespace ripple {
42 
43 namespace detail {
44 
45 template <class Container, class = std::void_t<>>
47 {
48 };
49 
50 template <class Container>
52  Container,
53  std::void_t<
54  decltype(std::declval<Container const>().size()),
55  decltype(std::declval<Container const>().data()),
56  typename Container::value_type>> : std::true_type
57 {
58 };
59 
60 template <>
62 {
63 };
64 
65 } // namespace detail
66 
80 template <std::size_t Bits, class Tag = void>
81 class base_uint
82 {
83  static_assert(
84  (Bits % 32) == 0,
85  "The length of a base_uint in bits must be a multiple of 32.");
86 
87  static_assert(
88  Bits >= 64,
89  "The length of a base_uint in bits must be at least 64.");
90 
91  static constexpr std::size_t WIDTH = Bits / 32;
92 
93  // This is really big-endian in byte order.
94  // We sometimes use std::uint32_t for speed.
95 
97 
98 public:
99  //--------------------------------------------------------------------------
100  //
101  // STL Container Interface
102  //
103 
104  static std::size_t constexpr bytes = Bits / 8;
105  static_assert(sizeof(data_) == bytes, "");
106 
109  using value_type = unsigned char;
110  using pointer = value_type*;
112  using const_pointer = value_type const*;
113  using const_reference = value_type const&;
114  using iterator = pointer;
118  using tag_type = Tag;
119 
120  pointer
122  {
123  return reinterpret_cast<pointer>(data_.data());
124  }
126  data() const
127  {
128  return reinterpret_cast<const_pointer>(data_.data());
129  }
130 
131  iterator
133  {
134  return data();
135  }
136  iterator
137  end()
138  {
139  return data() + bytes;
140  }
142  begin() const
143  {
144  return data();
145  }
147  end() const
148  {
149  return data() + bytes;
150  }
152  cbegin() const
153  {
154  return data();
155  }
157  cend() const
158  {
159  return data() + bytes;
160  }
161 
167 
168  //--------------------------------------------------------------------------
169 
170 private:
177  // NIKB TODO Remove the need for this constructor.
178  struct VoidHelper
179  {
180  explicit VoidHelper() = default;
181  };
182 
183  explicit base_uint(void const* data, VoidHelper)
184  {
185  memcpy(data_.data(), data, bytes);
186  }
187 
188  // Helper function to initialize a base_uint from a std::string_view.
189  enum class ParseResult {
190  okay,
191  badLength,
192  badChar,
193  };
194 
195  constexpr Expected<decltype(data_), ParseResult>
197  {
198  // Local lambda that converts a single hex char to four bits and
199  // ORs those bits into a uint32_t.
200  auto hexCharToUInt = [](char c,
201  std::uint32_t shift,
202  std::uint32_t& accum) -> ParseResult {
203  std::uint32_t nibble = 0xFFu;
204  if (c < '0' || c > 'f')
205  return ParseResult::badChar;
206 
207  if (c >= 'a')
208  nibble = static_cast<std::uint32_t>(c - 'a' + 0xA);
209  else if (c >= 'A')
210  nibble = static_cast<std::uint32_t>(c - 'A' + 0xA);
211  else if (c <= '9')
212  nibble = static_cast<std::uint32_t>(c - '0');
213 
214  if (nibble > 0xFu)
215  return ParseResult::badChar;
216 
217  accum |= (nibble << shift);
218 
219  return ParseResult::okay;
220  };
221 
222  decltype(data_) ret{};
223 
224  if (sv == "0")
225  {
226  return ret;
227  }
228 
229  if (sv.size() != size() * 2)
231 
232  std::size_t i = 0u;
233  auto in = sv.begin();
234  while (in != sv.end())
235  {
236  std::uint32_t accum = {};
237  for (std::uint32_t shift : {4u, 0u, 12u, 8u, 20u, 16u, 28u, 24u})
238  {
239  if (auto const result = hexCharToUInt(*in++, shift, accum);
240  result != ParseResult::okay)
241  return Unexpected(result);
242  }
243  ret[i++] = accum;
244  }
245  return ret;
246  }
247 
248  constexpr decltype(data_)
249  parseFromStringViewThrows(std::string_view sv) noexcept(false)
250  {
251  auto const result = parseFromStringView(sv);
252  if (!result)
253  {
254  if (result.error() == ParseResult::badLength)
255  Throw<std::invalid_argument>("invalid length for hex string");
256 
257  Throw<std::range_error>("invalid hex character");
258  }
259  return *result;
260  }
261 
262 public:
263  constexpr base_uint() : data_{}
264  {
265  }
266 
267  constexpr base_uint(beast::Zero) : data_{}
268  {
269  }
270 
272  {
273  *this = b;
274  }
275 
276  // This constructor is intended to be used at compile time since it might
277  // throw at runtime. Consider declaring this constructor consteval once
278  // we get to C++23.
279  explicit constexpr base_uint(std::string_view sv) noexcept(false)
281  {
282  }
283 
284  template <
285  class Container,
286  class = std::enable_if_t<
289  explicit base_uint(Container const& c)
290  {
291  assert(c.size() * sizeof(typename Container::value_type) == size());
292  std::memcpy(data_.data(), c.data(), size());
293  }
294 
295  template <class Container>
299  base_uint&>
300  operator=(Container const& c)
301  {
302  assert(c.size() * sizeof(typename Container::value_type) == size());
303  std::memcpy(data_.data(), c.data(), size());
304  return *this;
305  }
306 
307  /* Construct from a raw pointer.
308  The buffer pointed to by `data` must be at least Bits/8 bytes.
309  */
310  static base_uint
311  fromVoid(void const* data)
312  {
313  return base_uint(data, VoidHelper());
314  }
315 
316  template <class T>
318  fromVoidChecked(T const& from)
319  {
320  if (from.size() != size())
321  return {};
322  return fromVoid(from.data());
323  }
324 
325  constexpr int
326  signum() const
327  {
328  for (int i = 0; i < WIDTH; i++)
329  if (data_[i] != 0)
330  return 1;
331 
332  return 0;
333  }
334 
335  bool
336  operator!() const
337  {
338  return *this == beast::zero;
339  }
340 
341  constexpr base_uint
342  operator~() const
343  {
344  base_uint ret;
345 
346  for (int i = 0; i < WIDTH; i++)
347  ret.data_[i] = ~data_[i];
348 
349  return ret;
350  }
351 
352  base_uint&
354  {
355  *this = beast::zero;
356  union
357  {
358  unsigned u[2];
359  std::uint64_t ul;
360  };
361  // Put in least significant bits.
362  ul = boost::endian::native_to_big(uHost);
363  data_[WIDTH - 2] = u[0];
364  data_[WIDTH - 1] = u[1];
365  return *this;
366  }
367 
368  base_uint&
370  {
371  for (int i = 0; i < WIDTH; i++)
372  data_[i] ^= b.data_[i];
373 
374  return *this;
375  }
376 
377  base_uint&
379  {
380  for (int i = 0; i < WIDTH; i++)
381  data_[i] &= b.data_[i];
382 
383  return *this;
384  }
385 
386  base_uint&
388  {
389  for (int i = 0; i < WIDTH; i++)
390  data_[i] |= b.data_[i];
391 
392  return *this;
393  }
394 
395  base_uint&
397  {
398  // prefix operator
399  for (int i = WIDTH - 1; i >= 0; --i)
400  {
401  data_[i] = boost::endian::native_to_big(
402  boost::endian::big_to_native(data_[i]) + 1);
403  if (data_[i] != 0)
404  break;
405  }
406 
407  return *this;
408  }
409 
410  const base_uint
412  {
413  // postfix operator
414  const base_uint ret = *this;
415  ++(*this);
416 
417  return ret;
418  }
419 
420  base_uint&
422  {
423  for (int i = WIDTH - 1; i >= 0; --i)
424  {
425  auto prev = data_[i];
426  data_[i] = boost::endian::native_to_big(
427  boost::endian::big_to_native(data_[i]) - 1);
428 
429  if (prev != 0)
430  break;
431  }
432 
433  return *this;
434  }
435 
436  const base_uint
438  {
439  // postfix operator
440  const base_uint ret = *this;
441  --(*this);
442 
443  return ret;
444  }
445 
446  base_uint
447  next() const
448  {
449  auto ret = *this;
450  return ++ret;
451  }
452 
453  base_uint
454  prev() const
455  {
456  auto ret = *this;
457  return --ret;
458  }
459 
460  base_uint&
462  {
463  std::uint64_t carry = 0;
464 
465  for (int i = WIDTH; i--;)
466  {
467  std::uint64_t n = carry + boost::endian::big_to_native(data_[i]) +
468  boost::endian::big_to_native(b.data_[i]);
469 
470  data_[i] =
471  boost::endian::native_to_big(static_cast<std::uint32_t>(n));
472  carry = n >> 32;
473  }
474 
475  return *this;
476  }
477 
478  template <class Hasher>
479  friend void
480  hash_append(Hasher& h, base_uint const& a) noexcept
481  {
482  // Do not allow any endian transformations on this memory
483  h(a.data_.data(), sizeof(a.data_));
484  }
485 
494  [[nodiscard]] constexpr bool
496  {
497  auto const result = parseFromStringView(sv);
498  if (!result)
499  return false;
500 
501  data_ = *result;
502  return true;
503  }
504 
505  [[nodiscard]] constexpr bool
506  parseHex(const char* str)
507  {
508  return parseHex(std::string_view{str});
509  }
510 
511  [[nodiscard]] bool
512  parseHex(std::string const& str)
513  {
514  return parseHex(std::string_view{str});
515  }
516 
517  constexpr static std::size_t
519  {
520  return bytes;
521  }
522 
524  {
525  data_.fill(0);
526  return *this;
527  }
528 
529  // Deprecated.
530  bool
531  isZero() const
532  {
533  return *this == beast::zero;
534  }
535  bool
536  isNonZero() const
537  {
538  return *this != beast::zero;
539  }
540  void
542  {
543  *this = beast::zero;
544  }
545 };
546 
550 
551 template <std::size_t Bits, class Tag>
552 inline int
554 {
555  auto ret = std::mismatch(a.cbegin(), a.cend(), b.cbegin());
556 
557  if (ret.first == a.cend())
558  return 0;
559 
560  // a > b
561  if (*ret.first > *ret.second)
562  return 1;
563 
564  // a < b
565  return -1;
566 }
567 
568 template <std::size_t Bits, class Tag>
569 inline bool
571 {
572  return compare(a, b) < 0;
573 }
574 
575 template <std::size_t Bits, class Tag>
576 inline bool
578 {
579  return compare(a, b) <= 0;
580 }
581 
582 template <std::size_t Bits, class Tag>
583 inline bool
585 {
586  return compare(a, b) > 0;
587 }
588 
589 template <std::size_t Bits, class Tag>
590 inline bool
592 {
593  return compare(a, b) >= 0;
594 }
595 
596 template <std::size_t Bits, class Tag>
597 inline bool
599 {
600  return compare(a, b) == 0;
601 }
602 
603 template <std::size_t Bits, class Tag>
604 inline bool
606 {
607  return compare(a, b) != 0;
608 }
609 
610 //------------------------------------------------------------------------------
611 template <std::size_t Bits, class Tag>
612 inline bool
614 {
615  return a == base_uint<Bits, Tag>(b);
616 }
617 
618 template <std::size_t Bits, class Tag>
619 inline bool
621 {
622  return !(a == b);
623 }
624 
625 //------------------------------------------------------------------------------
626 template <std::size_t Bits, class Tag>
627 inline const base_uint<Bits, Tag>
629 {
630  return base_uint<Bits, Tag>(a) ^= b;
631 }
632 
633 template <std::size_t Bits, class Tag>
634 inline const base_uint<Bits, Tag>
636 {
637  return base_uint<Bits, Tag>(a) &= b;
638 }
639 
640 template <std::size_t Bits, class Tag>
641 inline const base_uint<Bits, Tag>
643 {
644  return base_uint<Bits, Tag>(a) |= b;
645 }
646 
647 template <std::size_t Bits, class Tag>
648 inline const base_uint<Bits, Tag>
650 {
651  return base_uint<Bits, Tag>(a) += b;
652 }
653 
654 //------------------------------------------------------------------------------
655 template <std::size_t Bits, class Tag>
656 inline std::string
658 {
659  return strHex(a.cbegin(), a.cend());
660 }
661 
662 template <std::size_t Bits, class Tag>
663 inline std::ostream&
665 {
666  return out << to_string(u);
667 }
668 
669 #ifndef __INTELLISENSE__
670 static_assert(sizeof(uint128) == 128 / 8, "There should be no padding bytes");
671 static_assert(sizeof(uint160) == 160 / 8, "There should be no padding bytes");
672 static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes");
673 #endif
674 
675 } // namespace ripple
676 
677 namespace beast {
678 
679 template <std::size_t Bits, class Tag>
680 struct is_uniquely_represented<ripple::base_uint<Bits, Tag>>
681  : public std::true_type
682 {
683  explicit is_uniquely_represented() = default;
684 };
685 
686 } // namespace beast
687 
688 #endif
ripple::operator>
bool operator>(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:584
ripple::base_uint< 256 >::iterator
pointer iterator
Definition: base_uint.h:114
std::false_type
ripple::base_uint::operator--
base_uint & operator--()
Definition: base_uint.h:421
ripple::operator|
const base_uint< Bits, Tag > operator|(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:642
ripple::Dir::const_iterator
Definition: Directory.h:49
ripple::base_uint::operator--
const base_uint operator--(int)
Definition: base_uint.h:437
std::string
STL class.
ripple::base_uint::hash_append
friend void hash_append(Hasher &h, base_uint const &a) noexcept
Definition: base_uint.h:480
ripple::uint160
base_uint< 160 > uint160
Definition: base_uint.h:548
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:536
cstring
ripple::base_uint::ParseResult::badLength
@ badLength
ripple::base_uint< 256 >::value_type
unsigned char value_type
Definition: base_uint.h:109
std::string_view
STL class.
ripple::base_uint::VoidHelper
Construct from a raw pointer.
Definition: base_uint.h:178
functional
ripple::base_uint::ParseResult::badChar
@ badChar
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
ripple::operator>=
bool operator>=(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:591
ripple::base_uint::base_uint
base_uint(Container const &c)
Definition: base_uint.h:289
ripple::base_uint::end
iterator end()
Definition: base_uint.h:137
ripple::base_uint::data
const_pointer data() const
Definition: base_uint.h:126
ripple::Unexpected
Unexpected(E(&)[N]) -> Unexpected< E const * >
ripple::base_uint::operator=
std::enable_if_t< detail::is_contiguous_container< Container >::value &&std::is_trivially_copyable< typename Container::value_type >::value, base_uint & > operator=(Container const &c)
Definition: base_uint.h:300
ripple::QualityDirection::in
@ in
ripple::base_uint::cbegin
const_iterator cbegin() const
Definition: base_uint.h:152
ripple::base_uint< 256 >::pointer
value_type * pointer
Definition: base_uint.h:110
ripple::base_uint::WIDTH
static constexpr std::size_t WIDTH
Definition: base_uint.h:91
ripple::base_uint::next
base_uint next() const
Definition: base_uint.h:447
ripple::base_uint< 256 >::ParseResult
ParseResult
Definition: base_uint.h:189
ripple::base_uint::fromVoidChecked
static std::optional< base_uint > fromVoidChecked(T const &from)
Definition: base_uint.h:318
ripple::operator<<
std::ostream & operator<<(std::ostream &os, TOffer< TIn, TOut > const &offer)
Definition: Offer.h:242
ripple::base_uint::data
pointer data()
Definition: base_uint.h:121
ripple::operator==
bool operator==(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:161
std::array::fill
T fill(T... args)
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:518
ripple::base_uint< 256 >::const_iterator
const_pointer const_iterator
Definition: base_uint.h:115
ripple::base_uint::parseFromStringView
constexpr Expected< decltype(data_), ParseResult > parseFromStringView(std::string_view sv) noexcept
Definition: base_uint.h:196
ripple::base_uint::operator~
constexpr base_uint operator~() const
Definition: base_uint.h:342
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:549
beast::is_uniquely_represented
Definition: hash_append.h:95
ripple::base_uint::parseHex
bool parseHex(std::string const &str)
Definition: base_uint.h:512
beast::is_uniquely_represented::is_uniquely_represented
is_uniquely_represented()=default
std::mismatch
T mismatch(T... args)
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:81
ripple::base_uint< 256 >::const_reference
value_type const & const_reference
Definition: base_uint.h:113
ripple::operator<=
bool operator<=(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:577
ripple::base_uint::operator|=
base_uint & operator|=(const base_uint &b)
Definition: base_uint.h:387
ripple::base_uint::VoidHelper::VoidHelper
VoidHelper()=default
ripple::QualityDirection::out
@ out
ripple::Expected
Definition: Expected.h:132
ripple::operator+
const base_uint< Bits, Tag > operator+(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:649
ripple::base_uint::bytes
static constexpr std::size_t bytes
Definition: base_uint.h:104
ripple::base_uint::data_
std::array< std::uint32_t, WIDTH > data_
Definition: base_uint.h:96
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:531
std::is_trivially_copyable
std::enable_if_t
ripple::operator<
bool operator<(CanonicalTXSet::Key const &lhs, CanonicalTXSet::Key const &rhs)
Definition: CanonicalTXSet.cpp:25
std::ostream
STL class.
ripple::compare
int compare(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:553
ripple::base_uint::operator&=
base_uint & operator&=(const base_uint &b)
Definition: base_uint.h:378
ripple::base_uint::begin
const_iterator begin() const
Definition: base_uint.h:142
ripple::operator!=
bool operator!=(Manifest const &lhs, Manifest const &rhs)
Definition: Manifest.h:171
array
beast::Zero
Zero allows classes to offer efficient comparisons to zero.
Definition: Zero.h:42
ripple::hardened_hash
Seed functor once per construction.
Definition: hardened_hash.h:96
std::uint32_t
ripple::base_uint::signum
constexpr int signum() const
Definition: base_uint.h:326
ripple::base_uint::base_uint
constexpr base_uint(beast::Zero)
Definition: base_uint.h:267
ripple::operator^
const base_uint< Bits, Tag > operator^(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:628
ripple::uint128
base_uint< 128 > uint128
Definition: base_uint.h:547
ripple::operator&
const base_uint< Bits, Tag > operator&(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:635
ripple::base_uint< 256 >::tag_type
void tag_type
Definition: base_uint.h:118
ripple::base_uint::ParseResult::okay
@ okay
ripple::base_uint::operator++
base_uint & operator++()
Definition: base_uint.h:396
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::detail::is_contiguous_container
Definition: base_uint.h:46
ripple::base_uint::parseHex
constexpr bool parseHex(const char *str)
Definition: base_uint.h:506
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:132
ripple::base_uint::base_uint
base_uint(void const *data, VoidHelper)
Definition: base_uint.h:183
ripple::base_uint::parseFromStringViewThrows
constexpr decltype(data_) parseFromStringViewThrows(std::string_view sv) noexcept(false)
Definition: base_uint.h:249
ripple::base_uint::operator=
base_uint< Bits, Tag > & operator=(beast::Zero)
Definition: base_uint.h:523
ripple::base_uint::zero
void zero()
Definition: base_uint.h:541
ripple::base_uint::base_uint
base_uint(std::uint64_t b)
Definition: base_uint.h:271
std
STL namespace.
ripple::base_uint::fromVoid
static base_uint fromVoid(void const *data)
Definition: base_uint.h:311
ripple::base_uint::end
const_iterator end() const
Definition: base_uint.h:147
std::ptrdiff_t
std::optional
std::size_t
ripple::base_uint::operator^=
base_uint & operator^=(const base_uint &b)
Definition: base_uint.h:369
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
std::memcpy
T memcpy(T... args)
ripple::base_uint::operator++
const base_uint operator++(int)
Definition: base_uint.h:411
ripple::base_uint::cend
const_iterator cend() const
Definition: base_uint.h:157
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
std::reverse_iterator
ripple::base_uint::operator=
base_uint & operator=(std::uint64_t uHost)
Definition: base_uint.h:353
ripple::base_uint::operator+=
base_uint & operator+=(const base_uint &b)
Definition: base_uint.h:461
ripple::base_uint::prev
base_uint prev() const
Definition: base_uint.h:454
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:495
ripple::base_uint::operator!
bool operator!() const
Definition: base_uint.h:336
ripple::base_uint< 256 >::const_pointer
value_type const * const_pointer
Definition: base_uint.h:112
ripple::base_uint< 256 >::reference
value_type & reference
Definition: base_uint.h:111
ripple::base_uint::base_uint
constexpr base_uint()
Definition: base_uint.h:263
std::array::data
T data(T... args)
type_traits
ripple::base_uint::base_uint
constexpr base_uint(std::string_view sv) noexcept(false)
Definition: base_uint.h:279
beast
Definition: base_uint.h:677