#ifndef BYTE_STREAM_WRAPPER_H #define BYTE_STREAM_WRAPPER_H #include #include #include namespace FLOAT { static const uint32_t positive_infinity = 0x007FFFFE; static const uint32_t negative_infinity = 0x00800002; static const uint32_t NaN = 0x007FFFFF; static const uint32_t NRes = 0x00800000; static const uint32_t FLAOT_reserved_value = 0x00800001; // (2^23 - 3) * 10^127 static const double max = 8.388604999999999e+133; static const double min = -max; static const double mantissa_max = 0x007FFFFD; static const double exponent_max = 127; static const double exponent_min = -128; // 10^-128 static const double epsilon = 1e-128; // 10^upper(23 * log(2) / log(10)) static const double precision = 10000000; } class ByteBufferException : public std::runtime_error { public: explicit ByteBufferException(std::string const &what) : std::runtime_error(what) {} }; class ByteBuffer { public: template explicit ByteBuffer(uint8_t (&bytes)[N]) : zero(bytes), end_(&bytes[N]), cursor(bytes) {} ByteBuffer(uint8_t* bytes, size_t capacity); inline size_t getSize() const { return end_ - zero; } inline size_t getCursor() const { return cursor - zero; } inline size_t getBytesLeft() const { return end_ - cursor; } inline ByteBuffer &setCursor(size_t newCursor) { auto tmp = (uint8_t *) &zero[newCursor]; assertCanAccessIndex(tmp); cursor = tmp; return *this; } inline void skip(size_t length) { cursor += length; } inline const uint8_t *cbegin() const { return zero; } inline const uint8_t *cend() const { return end_; } inline uint8_t *begin() const { return const_cast(zero); } inline uint8_t *end() const { return const_cast(end_); } ByteBuffer &write8(uint8_t value); ByteBuffer &write16le(uint16_t value); ByteBuffer &write32le(uint32_t value); /** * Appends the entire buffer. Make a view if you want to write a part of it. */ ByteBuffer &write(const ByteBuffer &value); ByteBuffer &write(const uint8_t *bytes, size_t len); ByteBuffer &writeFLOAT(double d); /** * Reads a uint8_t from the start of the buffer. */ uint8_t get8(size_t index) const; /** * Reads a uint8_t relative to the pointer. */ uint8_t peek8(size_t relative_index) const; uint8_t read8(); uint16_t read16le(); uint32_t read32le(); /** * IEEE-11073 32-bit FLOAT */ double readFLOAT(); void copy(uint8_t *bytes, size_t length) const; void copy(ByteBuffer& other) const; void reset(); /** * Creates a view from cursor to size. */ ByteBuffer view() const; ByteBuffer view(size_t length) const; ByteBuffer viewAndSkip(size_t length) { auto v = view(length); skip(length); return v; } std::string toString() const; private: void assertCanAccessRelative(size_t diff) const; void assertCanAccessIndex(uint8_t *p) const; const uint8_t *zero; const uint8_t *end_; uint8_t *cursor; }; template class StaticByteBuffer : public ByteBuffer { public: StaticByteBuffer() : ByteBuffer(raw) {} private: uint8_t raw[N] = {}; }; #endif