0

If I have:

char buffer[16];

How can I convert its raw bytes into a:

boost::multiprecision::uint128_t ?

I tried doing a standard C-style cast:

uint128_t myInt = *(uint128_t*)buffer;

though it doesn't seem to work properly. Also tried using a dynamic_cast

I found this page: https://www.boost.org/doc/libs/1_56_0/libs/multiprecision/doc/html/boost_multiprecision/tut/conversions.html

on how to do conversations, but it doesn't seem to cover this type of thing. Any ideas?

EDIT: One of the comments suggested using memcpy (if it was like GCC's 128 bit uint) to copy the bytes into the uint128_t. That doesn't seem to work properly if done in the way I would expect: memcpy() try Am I missing something?

csm10495
  • 569
  • 6
  • 12

3 Answers3

2

I found a way to do this that works based off of the dynamic nature of the uint128_t type. It seems to not use all 16 bytes for the numeric value at all times. It only uses them if it thinks they are needed (which is why a primitive memcpy() doesn't work).

So the trick is to force it think all 16 bytes are needed, then memcpy() the data in. We can do that by setting an initial value of -1 (or all Fs):

boost::multiprecision::uint128_t getUintFromBuffer(const std::vector<unsigned char> &buf)
{
    boost::multiprecision::uint128_t retU = -1;
    memset(&retU, 0, 16);
    memcpy(&retU, buf.data(), std::min(buf.size(), (size_t)16));
    return retU;
}

int main()
{
    std::vector<unsigned char> buf;
    buf.resize(16);
    buf[0] = 0xaa;
    buf[15] = 0xff;

    std::cout << std::hex << getUintFromBuffer(buf) << std::endl;

    return EXIT_SUCCESS;
}

Running this example prints: FF0000000000000000000000000000AA

And that is what I was looking for :)

csm10495
  • 569
  • 6
  • 12
0

I'd suggest that may be this is what you're looking for:

#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
#include <iomanip>
#include <vector>
#include <iterator>

int main()
{
   using boost::multiprecision::cpp_int;
   // Create a cpp_int with just a couple of bits set:
   cpp_int i;
   bit_set(i, 5000); // set the 5000'th bit
   bit_set(i, 200);
   bit_set(i, 50);
   // export into 8-bit unsigned values, most significant bit first:
   std::vector<unsigned char> v;
   export_bits(i, std::back_inserter(v), 8);
   // import back again, and check for equality:
   cpp_int j;
   import_bits(j, v.begin(), v.end());
   assert(i == j);
}
evilrix
  • 152
  • 1
  • 3
0

I found that just using boost::multiprecision::import_bits works.

template <unsigned Bits, boost::multiprecision::cpp_integer_type SignType,
          boost::multiprecision::cpp_int_check_type Checked>
boost::multiprecision::number<
    boost::multiprecision::cpp_int_backend<Bits, Bits, SignType, Checked, void>>
rawToBoost(const void *V) {
  using namespace boost::multiprecision;

#if BOOST_ENDIAN_BIG_BYTE
  static const auto msv_first = true;
#else
  static const auto msv_first = false;
#endif

  number<cpp_int_backend<Bits, Bits, SignType, Checked, void>> ret;
  auto VPtr = reinterpret_cast<const unsigned char *>(V);
  import_bits(ret, VPtr, VPtr + (Bits / 8), 0, msv_first);
  return ret;
}

boost::multiprecision::int128_t rawToBoost_int128(const void *V) {
  using namespace boost::multiprecision;
  return rawToBoost<128, signed_magnitude, unchecked>(V);
}

boost::multiprecision::int128_t rawToBoost_int128_safe(const void *V) {
  using namespace boost::multiprecision;
  return rawToBoost<128, signed_magnitude, checked>(V);
}

boost::multiprecision::uint128_t rawToBoost_uint128(const void *V) {
  using namespace boost::multiprecision;
  return rawToBoost<128, unsigned_magnitude, unchecked>(V);
}

boost::multiprecision::uint128_t rawToBoost_uint128_safe(const void *V) {
  using namespace boost::multiprecision;
  return rawToBoost<128, unsigned_magnitude, checked>(V);
}

This is the same link that OP referred to (but a different boost version). https://www.boost.org/doc/libs/1_62_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/cpp_int.html

Vaivaswatha N
  • 153
  • 1
  • 7