123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- #pragma once
- #include <nall/primitives.hpp>
- #include <nall/serializer.hpp>
- #include <nall/stdint.hpp>
- namespace nall {
- struct varint {
- virtual auto read() -> uint8_t = 0;
- virtual auto write(uint8_t) -> void = 0;
- auto readvu() -> uintmax {
- uintmax data = 0, shift = 1;
- while(true) {
- uint8_t x = read();
- data += (x & 0x7f) * shift;
- if(x & 0x80) break;
- shift <<= 7;
- data += shift;
- }
- return data;
- }
- auto readvs() -> intmax {
- uintmax data = readvu();
- bool negate = data & 1;
- data >>= 1;
- if(negate) data = ~data;
- return data;
- }
- auto writevu(uintmax data) -> void {
- while(true) {
- uint8_t x = data & 0x7f;
- data >>= 7;
- if(data == 0) return write(0x80 | x);
- write(x);
- data--;
- }
- }
- auto writevs(intmax data) -> void {
- bool negate = data < 0;
- if(negate) data = ~data;
- data = (data << 1) | negate;
- writevu(data);
- }
- };
- struct VariadicNatural {
- VariadicNatural() : mask(~0ull) { assign(0); }
- template<typename T> VariadicNatural(const T& value) : mask(~0ull) { assign(value); }
- operator uint64_t() const { return data; }
- template<typename T> auto& operator=(const T& value) { return assign(value); }
- auto operator++(int) { auto value = data; assign(data + 1); return value; }
- auto operator--(int) { auto value = data; assign(data - 1); return value; }
- auto& operator++() { return assign(data + 1); }
- auto& operator--() { return assign(data - 1); }
- auto& operator &=(const uint64_t value) { return assign(data & value); }
- auto& operator |=(const uint64_t value) { return assign(data | value); }
- auto& operator ^=(const uint64_t value) { return assign(data ^ value); }
- auto& operator<<=(const uint64_t value) { return assign(data << value); }
- auto& operator>>=(const uint64_t value) { return assign(data >> value); }
- auto& operator +=(const uint64_t value) { return assign(data + value); }
- auto& operator -=(const uint64_t value) { return assign(data - value); }
- auto& operator *=(const uint64_t value) { return assign(data * value); }
- auto& operator /=(const uint64_t value) { return assign(data / value); }
- auto& operator %=(const uint64_t value) { return assign(data % value); }
- auto resize(uint bits) {
- assert(bits <= 64);
- mask = ~0ull >> (64 - bits);
- data &= mask;
- }
- auto serialize(serializer& s) {
- s(data);
- s(mask);
- }
- struct Reference {
- Reference(VariadicNatural& self, uint lo, uint hi) : self(self), Lo(lo), Hi(hi) {}
- operator uint64_t() const {
- const uint64_t RangeBits = Hi - Lo + 1;
- const uint64_t RangeMask = (((1ull << RangeBits) - 1) << Lo) & self.mask;
- return (self & RangeMask) >> Lo;
- }
- auto& operator=(const uint64_t value) {
- const uint64_t RangeBits = Hi - Lo + 1;
- const uint64_t RangeMask = (((1ull << RangeBits) - 1) << Lo) & self.mask;
- self.data = (self.data & ~RangeMask) | ((value << Lo) & RangeMask);
- return *this;
- }
- private:
- VariadicNatural& self;
- const uint Lo;
- const uint Hi;
- };
- auto bits(uint lo, uint hi) -> Reference { return {*this, lo < hi ? lo : hi, hi > lo ? hi : lo}; }
- auto bit(uint index) -> Reference { return {*this, index, index}; }
- auto byte(uint index) -> Reference { return {*this, index * 8 + 0, index * 8 + 7}; }
- private:
- auto assign(uint64_t value) -> VariadicNatural& {
- data = value & mask;
- return *this;
- }
- uint64_t data;
- uint64_t mask;
- };
- }
|