159 lines · 5.1 KB · C
RawDownload
//// Dis VM// File: buffered_reader.h// Author: arr// #ifndef _DISVM_SRC_INCLUDE_BUFFERED_READER_H_#define _DISVM_SRC_INCLUDE_BUFFERED_READER_H_ #include <cstdint>#include <cassert>#include <vector>#include <sstream>#include <tuple>#include <iosfwd> namespace disvm{    namespace util    {        class buffered_reader_t        {        public:            buffered_reader_t(std::istream &stream)                : _buffer(64 * 1024) // 64k is an optimization for the Windows filesystem manager                , _current_index{ 0 }                , _current_size{ 0 }                , _stream{ stream }            {                assert(!stream.fail());            }             buffered_reader_t(const buffered_reader_t&) = delete;            buffered_reader_t& operator=(const buffered_reader_t&) = delete;             // Get the next 'n' number of bytes.            // Returns the number of bytes retrieved.            uint32_t get_next_bytes(uint32_t bytes_requested, uint8_t *buffer)            {                if (bytes_requested == 0)                    return 0;                 assert(buffer != nullptr);                 auto bytes_requested_acc = uint32_t{ 0 };                 for (;;)                {                    const auto amount_in_buffer = check_buffer_content();                    if (amount_in_buffer == 0)                        return 0;                     // Buffer contains requested amount                    if (bytes_requested <= amount_in_buffer)                    {                        std::memcpy(buffer, (_buffer.data() + _current_index), bytes_requested);                        _current_index += bytes_requested;                        bytes_requested_acc += bytes_requested;                        return bytes_requested_acc;                    }                    else                    {                        // Buffer does not contain all the data requested                        std::memcpy(buffer, (_buffer.data() + _current_index), amount_in_buffer);                        _current_index += amount_in_buffer;                         // Subtract the bytes consumed                        bytes_requested -= amount_in_buffer;                         bytes_requested_acc += amount_in_buffer;                        buffer += amount_in_buffer;                    }                }            }             // Read from the stream as a string until the supplied delimiter is encountered.            std::string get_as_string_until(const char delim)            {                std::stringstream ss;                auto amount_in_buffer = check_buffer_content();                while (amount_in_buffer != 0)                {                    while (_current_index < _current_size)                    {                        auto c = _buffer[_current_index++];                        if (c == delim)                            return ss.str();                         ss << c;                    }                     amount_in_buffer = check_buffer_content();                }                 return{};            }             // Read from the stream until the supplied value is encountered.            bool get_bytes_until(const uint8_t delim, std::vector<uint8_t> &byte_buffer)            {                auto amount_in_buffer = check_buffer_content();                while (amount_in_buffer != 0)                {                    while(_current_index < _current_size)                    {                        auto b = _buffer[_current_index++];                        if (b == delim)                            return true;                         byte_buffer.push_back(b);                    }                     amount_in_buffer = check_buffer_content();                }                 return false;            }             // Get the next byte in the buffer.            // Returns success and the byte.            std::tuple<bool, uint8_t> get_next_byte()            {                const auto amount_in_buffer = check_buffer_content();                if (amount_in_buffer == 0)                    return std::make_tuple(false, 0);                 return std::make_tuple(true, _buffer[_current_index++]);            }         private:            std::size_t check_buffer_content()            {                if (_current_size <= _current_index)                {                    _current_index = 0;                    _current_size = 0;                     if (_stream.fail())                        return 0;                     _stream.read(_buffer.data(), _buffer.size());                     // If the stream has failed, set the current size, otherwise the buffer size                    _current_size = _stream.fail() ? static_cast<std::size_t>(_stream.gcount()) : _buffer.size();                }                 return _current_size - _current_index;            }         private:            std::istream &_stream;            std::size_t _current_index;            std::size_t _current_size;            std::vector<char> _buffer;        };    }} #endif // _DISVM_SRC_INCLUDE_BUFFERED_READER_H_