varint.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #pragma once
  2. #include <nall/primitives.hpp>
  3. #include <nall/serializer.hpp>
  4. #include <nall/stdint.hpp>
  5. namespace nall {
  6. struct varint {
  7. virtual auto read() -> uint8_t = 0;
  8. virtual auto write(uint8_t) -> void = 0;
  9. auto readvu() -> uintmax {
  10. uintmax data = 0, shift = 1;
  11. while(true) {
  12. uint8_t x = read();
  13. data += (x & 0x7f) * shift;
  14. if(x & 0x80) break;
  15. shift <<= 7;
  16. data += shift;
  17. }
  18. return data;
  19. }
  20. auto readvs() -> intmax {
  21. uintmax data = readvu();
  22. bool negate = data & 1;
  23. data >>= 1;
  24. if(negate) data = ~data;
  25. return data;
  26. }
  27. auto writevu(uintmax data) -> void {
  28. while(true) {
  29. uint8_t x = data & 0x7f;
  30. data >>= 7;
  31. if(data == 0) return write(0x80 | x);
  32. write(x);
  33. data--;
  34. }
  35. }
  36. auto writevs(intmax data) -> void {
  37. bool negate = data < 0;
  38. if(negate) data = ~data;
  39. data = (data << 1) | negate;
  40. writevu(data);
  41. }
  42. };
  43. struct VariadicNatural {
  44. VariadicNatural() : mask(~0ull) { assign(0); }
  45. template<typename T> VariadicNatural(const T& value) : mask(~0ull) { assign(value); }
  46. operator uint64_t() const { return data; }
  47. template<typename T> auto& operator=(const T& value) { return assign(value); }
  48. auto operator++(int) { auto value = data; assign(data + 1); return value; }
  49. auto operator--(int) { auto value = data; assign(data - 1); return value; }
  50. auto& operator++() { return assign(data + 1); }
  51. auto& operator--() { return assign(data - 1); }
  52. auto& operator &=(const uint64_t value) { return assign(data & value); }
  53. auto& operator |=(const uint64_t value) { return assign(data | value); }
  54. auto& operator ^=(const uint64_t value) { return assign(data ^ value); }
  55. auto& operator<<=(const uint64_t value) { return assign(data << value); }
  56. auto& operator>>=(const uint64_t value) { return assign(data >> value); }
  57. auto& operator +=(const uint64_t value) { return assign(data + value); }
  58. auto& operator -=(const uint64_t value) { return assign(data - value); }
  59. auto& operator *=(const uint64_t value) { return assign(data * value); }
  60. auto& operator /=(const uint64_t value) { return assign(data / value); }
  61. auto& operator %=(const uint64_t value) { return assign(data % value); }
  62. auto resize(uint bits) {
  63. assert(bits <= 64);
  64. mask = ~0ull >> (64 - bits);
  65. data &= mask;
  66. }
  67. auto serialize(serializer& s) {
  68. s(data);
  69. s(mask);
  70. }
  71. struct Reference {
  72. Reference(VariadicNatural& self, uint lo, uint hi) : self(self), Lo(lo), Hi(hi) {}
  73. operator uint64_t() const {
  74. const uint64_t RangeBits = Hi - Lo + 1;
  75. const uint64_t RangeMask = (((1ull << RangeBits) - 1) << Lo) & self.mask;
  76. return (self & RangeMask) >> Lo;
  77. }
  78. auto& operator=(const uint64_t value) {
  79. const uint64_t RangeBits = Hi - Lo + 1;
  80. const uint64_t RangeMask = (((1ull << RangeBits) - 1) << Lo) & self.mask;
  81. self.data = (self.data & ~RangeMask) | ((value << Lo) & RangeMask);
  82. return *this;
  83. }
  84. private:
  85. VariadicNatural& self;
  86. const uint Lo;
  87. const uint Hi;
  88. };
  89. auto bits(uint lo, uint hi) -> Reference { return {*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
  90. auto bit(uint index) -> Reference { return {*this, index, index}; }
  91. auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
  92. private:
  93. auto assign(uint64_t value) -> VariadicNatural& {
  94. data = value & mask;
  95. return *this;
  96. }
  97. uint64_t data;
  98. uint64_t mask;
  99. };
  100. }