#include "stream_reassembler.hh" #include // Dummy implementation of a stream reassembler. // For Lab 1, please replace with a real implementation that passes the // automated checks run by `make check_lab1`. // You will need to add private members to the class declaration in `stream_reassembler.hh` template void DUMMY_CODE(Targs &&.../* unused */) {} using namespace std; StreamReassembler::StreamReassembler(const size_t capacity) : _output(capacity), _capacity(capacity), _aux_buffer(capacity, '\0'), _aux_buffer_valid(capacity, false) {} // pre-allocate is working //! \details This function accepts a substring (aka a segment) of bytes, //! possibly out-of-order, from the logical stream, and assembles any newly //! contiguous substrings and writes them into the output stream in order. void StreamReassembler::push_substring(const string &data, const size_t index, const bool eof) { auto _unread = _unassem - _output.buffer_size(); _aux_buffer.resize(_capacity - _output.buffer_size(), '\0'); _aux_buffer_valid.resize(_aux_buffer.size(), false); // resize to spare space for incoming bytes if (eof) { _eof = index + data.size(); // record first, in case eof packet arrives ahead of non-eof ones } auto start = std::max(index, _unassem); auto end = std::min(index + data.size(), _unread + _capacity); // it is possible that index < _unassem (overlap with packets that have already been pushed into bytestream) for (auto i = start; i < end; ++i) { _aux_buffer[i - _unassem] = data[i - index]; if (!_aux_buffer_valid[i - _unassem]) { _aux_buffer_valid[i - _unassem] = true; _unassem_count++; // calculate unassembled bytes, this only counts valid bytes } } std::string wr_data; while (!_aux_buffer_valid.empty() && _aux_buffer_valid.front()) { // watch out for fetching front from an empty queue wr_data.push_back(_aux_buffer.front()); _aux_buffer.pop_front(); _aux_buffer_valid.pop_front(); // remember to pop assistent queue ++_unassem; --_unassem_count; } if (wr_data.size()) { _output.write(wr_data); } if (_unassem == _eof) { _output.end_input(); // stream approached to eof } } size_t StreamReassembler::unassembled_bytes() const { return _unassem_count; } bool StreamReassembler::empty() const { return (_unassem_count == 0); }