#pragma once #include #include #include #include class ByteBufferReader { public: ByteBufferReader( const uint8_t *data, size_t size ) : buffer( data ), bufferSize( size ), offset( 0 ) { } explicit ByteBufferReader( const std::vector &vec ) : ByteBufferReader( vec.data(), vec.size() ) { } template T read() { if( offset + sizeof( T ) > bufferSize ) throw std::out_of_range( "BufferReader: read out of bounds" ); T value; std::memcpy( &value, buffer + offset, sizeof( T ) ); offset += sizeof( T ); return value; } void readBytes( void *dest, size_t size ) { if( offset + size > bufferSize ) throw std::out_of_range( "BufferReader: readBytes out of bounds" ); std::memcpy( dest, buffer + offset, size ); offset += size; } std::string readString( size_t length ) { if( offset + length > bufferSize ) throw std::out_of_range( "BufferReader: readString out of bounds" ); std::string str( reinterpret_cast< const char * >( buffer + offset ), length ); offset += length; return str; } template std::array readArray() { std::array arr; for( size_t i = 0; i < N; ++i ) arr[ i ] = read(); return arr; } void skip( size_t count ) { if( offset + count > bufferSize ) throw std::out_of_range( "BufferReader: skip out of bounds" ); offset += count; } template T peek() const { if( offset + sizeof( T ) > bufferSize ) throw std::out_of_range( "BufferReader: peek out of bounds" ); T value; std::memcpy( &value, buffer + offset, sizeof( T ) ); return value; } bool eof() const { return offset >= bufferSize; } size_t tell() const { return offset; } size_t remaining() const { return bufferSize - offset; } private: const uint8_t *buffer; size_t bufferSize; size_t offset; };