11 #include <hilti/rt/extension-points.h> 12 #include <hilti/rt/result.h> 13 #include <hilti/rt/safe-int.h> 14 #include <hilti/rt/types/bytes.h> 15 #include <hilti/rt/unpack.h> 16 #include <hilti/rt/util.h> 20 namespace detail::adl {
21 inline std::string
to_string(hilti::rt::integer::safe<uint64_t> x, adl::tag ) {
22 return fmt(
"%" PRIu64, *x.Ptr());
25 inline std::string
to_string(hilti::rt::integer::safe<int64_t> x, adl::tag ) {
26 return fmt(
"%" PRId64, *x.Ptr());
29 inline std::string
to_string(hilti::rt::integer::safe<uint32_t> x, adl::tag ) {
30 return fmt(
"%" PRIu32, *x.Ptr());
33 inline std::string
to_string(hilti::rt::integer::safe<int32_t> x, adl::tag ) {
34 return fmt(
"%" PRId32, *x.Ptr());
37 inline std::string
to_string(hilti::rt::integer::safe<uint16_t> x, adl::tag ) {
38 return fmt(
"%" PRIu16, *x.Ptr());
41 inline std::string
to_string(hilti::rt::integer::safe<int16_t> x, adl::tag ) {
42 return fmt(
"%" PRId16, *x.Ptr());
45 inline std::string
to_string(hilti::rt::integer::safe<uint8_t> x, adl::tag ) {
46 return fmt(
"%" PRIu8, *x.Ptr());
49 inline std::string
to_string(hilti::rt::integer::safe<int8_t> x, adl::tag ) {
50 return fmt(
"%" PRId8, *x.Ptr());
53 inline std::string
to_string(hilti::rt::integer::safe<char> x, adl::tag ) {
return fmt(
"%" PRId8, *x.Ptr()); }
55 inline std::string
to_string(uint64_t x, adl::tag ) {
return fmt(
"%" PRIu64, x); }
57 inline std::string
to_string(int64_t x, adl::tag ) {
return fmt(
"%" PRId64, x); }
59 inline std::string
to_string(uint32_t x, adl::tag ) {
return fmt(
"%" PRIu32, x); }
61 inline std::string
to_string(int32_t x, adl::tag ) {
return fmt(
"%" PRId32, x); }
63 inline std::string
to_string(uint16_t x, adl::tag ) {
return fmt(
"%" PRIu16, x); }
65 inline std::string
to_string(int16_t x, adl::tag ) {
return fmt(
"%" PRId16, x); }
67 inline std::string
to_string(uint8_t x, adl::tag ) {
return fmt(
"%" PRIu8, x); }
69 inline std::string
to_string(int8_t x, adl::tag ) {
return fmt(
"%" PRId8, x); }
76 template<
typename T,
typename D>
77 inline Result<std::tuple<integer::safe<T>, D>> unpack(D b,
const uint8_t* dst, std::initializer_list<int> bytes) {
79 for (
auto i : bytes ) {
81 x |= (
static_cast<T
>(dst[i]));
84 return std::make_tuple(
static_cast<integer::safe<T>
>(x), std::move(b));
89 template<
typename T,
typename D>
90 inline Result<std::tuple<integer::safe<T>, D>> unpack(D b,
ByteOrder fmt) {
91 if ( fmt == ByteOrder::Host )
94 if ( b.size() <
static_cast<int64_t
>(
sizeof(T)) )
95 return result::Error(
"insufficient data to unpack integer");
97 uint8_t raw[
sizeof(T)];
102 case ByteOrder::Network:
103 if constexpr ( std::is_same<T, uint8_t>::value )
104 return std::make_tuple(
static_cast<integer::safe<uint8_t>
>(raw[0]), std::move(b));
106 if constexpr ( std::is_same<T, int8_t>::value ) {
107 auto x =
static_cast<int8_t
>(raw[0]);
108 return std::make_tuple(
static_cast<integer::safe<int8_t>
>(x), std::move(b));
111 if constexpr ( std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value )
112 return detail::unpack<T>(std::move(b), raw, {0, 1});
114 if constexpr ( std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value )
115 return detail::unpack<T>(std::move(b), raw, {0, 1, 2, 3});
117 if constexpr ( std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value )
118 return detail::unpack<T>(std::move(b), raw, {0, 1, 2, 3, 4, 5, 6, 7});
122 case ByteOrder::Little:
123 if constexpr ( std::is_same<T, uint8_t>::value )
124 return std::make_tuple(
static_cast<integer::safe<uint8_t>
>(raw[0]), std::move(b));
126 if constexpr ( std::is_same<T, int8_t>::value ) {
127 auto x =
static_cast<int8_t
>(raw[0]);
128 return std::make_tuple(
static_cast<integer::safe<int8_t>
>(x), std::move(b));
131 if constexpr ( std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value )
132 return detail::unpack<T>(std::move(b), raw, {1, 0});
134 if constexpr ( std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value )
135 return detail::unpack<T>(std::move(b), raw, {3, 2, 1, 0});
137 if constexpr ( std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value )
138 return detail::unpack<T>(std::move(b), raw, {7, 6, 5, 4, 3, 2, 1, 0});
142 case ByteOrder::Host:
146 case ByteOrder::Undef:
return result::Error(
"undefined byte order");
157 extern uint64_t hton64(uint64_t v);
164 extern uint32_t hton32(uint32_t v);
171 extern uint16_t hton16(uint16_t v);
178 extern uint64_t ntoh64(uint64_t v);
185 extern uint32_t ntoh32(uint32_t v);
192 extern uint16_t ntoh16(uint16_t v);
199 extern uint16_t flip16(uint16_t v);
206 extern uint32_t flip32(uint32_t v);
213 extern uint64_t flip64(uint64_t v);
222 inline int64_t flip(int64_t v, uint64_t n) {
225 auto i =
static_cast<uint64_t
>(v);
226 i = flip64(i) >> (64 - n * 8);
227 return static_cast<int64_t
>(i);
237 inline uint64_t flip(uint64_t v, uint64_t n) {
240 return (flip64(v) >> (64 - n * 8));
244 enum class BitOrder { LSB0, MSB0, Undef };
247 template<
typename UINT>
248 inline hilti::rt::integer::safe<UINT> bits(hilti::rt::integer::safe<UINT> v, uint64_t lower, uint64_t upper,
250 constexpr
auto width = std::numeric_limits<UINT>::digits;
253 throw InvalidArgument(
"lower limit needs to be less or equal the upper limit");
255 if ( upper >= width )
256 throw InvalidArgument(
"upper limit needs to be less or equal the input width");
259 case BitOrder::LSB0:
break;
262 lower = (width - lower - 1);
263 upper = (width - upper - 1);
264 std::swap(lower, upper);
267 case BitOrder::Undef:
throw RuntimeError(
"undefined bit order");
270 assert(lower <= upper);
271 const auto range = upper - lower + 1;
276 if (
range == width )
279 const auto mask = ((uint64_t(1) <<
range) - uint64_t(1U)) << lower;
280 return (v & mask) >> lower;
285 namespace detail::adl {
286 std::string
to_string(
const integer::BitOrder& x, tag );
ByteOrder
Definition: util.h:503
std::string to_string(T &&x)
Definition: extension-points.h:26
auto range(const T &t)
Definition: iterator.h:37
void cannot_be_reached() __attribute__((noreturn))
Definition: util.cc:52
ByteOrder systemByteOrder()
Definition: util.cc:392
void abort_with_backtrace() __attribute__((noreturn))
Definition: util.cc:44
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13