CS144Lab/libsponge/stream_reassembler.cc
2023-02-16 05:08:25 +00:00

64 lines
2.4 KiB
C++

#include "stream_reassembler.hh"
#include <algorithm>
// 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 <typename... Targs>
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); }