llvm-mos-sdk
varint.h
Go to the documentation of this file.
1 #ifndef _VARINT_H_
2 #define _VARINT_H_
3 
4 #include <new>
5 #include <type_traits>
6 
7 namespace __impl {
8 
9 // An unsigned variable-length integer. Must be implemented by a specific
10 // instantiation of BigInt.
11 class VarInt {
12  char size_;
13 
14 public:
15  static VarInt &make(void *space, char size);
16 
17  VarInt() = delete;
18  VarInt(const VarInt &other) = delete;
19 
20  template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
21  VarInt &operator=(T other) {
22  *reinterpret_cast<T *>(bytes()) = other;
23  return *this;
24  }
25 
26  VarInt &operator=(const VarInt &other);
27 
28  char *bytes() { return &size_ + 1; };
29  const char *bytes() const { return &size_ + 1; };
30 
31  char size() const { return size_; }
32 
33  template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
34  operator T() const {
35  return *reinterpret_cast<const T *>(bytes());
36  }
37 
38  bool operator==(const VarInt &other) const;
39  bool operator!=(const VarInt &other) const;
40 
41  bool operator<(const VarInt &other) const;
42  bool operator<=(const VarInt &other) const;
43  bool operator>(const VarInt &other) const;
44  bool operator>=(const VarInt &other) const;
45 
46  bool high_bit() const;
47 
48  bool negative() const;
49 
50  // True if larger than the largest signed value.
51  bool too_positive() const;
52 
53  // True if larger than the absolute value of the smallest signed value.
54  bool too_negative() const;
55 
56  VarInt &operator+=(const VarInt &other);
57  bool add_overflow(const VarInt &other);
58 
59  template <typename T> VarInt &operator+=(T other);
60  template <typename T> VarInt &operator*=(T other);
61 
62  template <typename T> bool add_overflow(T other);
63  template <typename T> bool mul_overflow(T other);
64  bool shl_overflow();
65 
66  void negate();
67  void shl();
68 
69  void zero();
70  void positive_limit();
71  void negative_limit();
72  void unsigned_limit();
73 
74  void dump() const;
75 
76 protected:
77  VarInt(char size) : size_(size) {}
78 };
79 
80 // A variable-sized integer with compile-time constant size. Provides a way to
81 // instantiate a VarInt; otherwise has no specific functionality, in order to
82 // avoid monomorphization of sizes.
83 template <char Size> class BigInt : public VarInt {
84  char bytes[Size];
85 
86 public:
87  BigInt() : VarInt(Size) {}
88 
89  template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
90  BigInt &operator=(T other) {
91  static_assert(sizeof(T) == Size, "incorrect size");
92  return static_cast<BigInt &>(VarInt::operator=(other));
93  }
94 
95  template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
96  BigInt(T other) : VarInt(Size) {
97  static_assert(sizeof(T) == Size, "incorrect size");
98  *this = other;
99  }
100 };
101 
102 template <typename T> VarInt &VarInt::operator+=(T other) {
103  add_overflow(other);
104  return *this;
105 }
106 
107 template <typename T> VarInt &VarInt::operator*=(T other) {
108  mul_overflow(other);
109  return *this;
110 }
111 
112 template <typename T> bool VarInt::add_overflow(T other) {
113  unsigned char carry = 0;
114  char i;
115  const auto *r_bytes = reinterpret_cast<const char *>(&other);
116  for (i = 0; i < sizeof(T); ++i)
117  bytes()[i] = __builtin_addcb(bytes()[0], r_bytes[i], carry, &carry);
118  for (; i < size_; ++i)
119  bytes()[i] = __builtin_addcb(bytes()[i], 0, carry, &carry);
120  return carry;
121 }
122 
123 template <typename T> bool VarInt::mul_overflow(T other) {
124  char space[sizeof(VarInt) + size_]; // VLA
125  auto &p = *new (space) VarInt(size_);
126  p.zero();
127  bool overflow = false;
128  while (true) {
129  if (other & 1) {
130  --other;
131  overflow |= p.add_overflow(*this);
132  }
133  if (!other)
134  break;
135  other >>= 1;
136  overflow |= shl_overflow();
137  }
138  *this = p;
139  return overflow;
140 }
141 
142 } // namespace __impl
143 
144 #endif // not _VARINT_H_
type_traits
new
size
unsigned size
Definition: neslib.h:185