1、capicity含义:已排序数据+已缓存但未排序数据
2 函数部分
void push_substring(const string &data, const uint64_t index, const bool eof);
该函数应: 1、将顺序data写入缓冲区
2、将乱序data缓存
3、能够支持接收重复index
4、eof标识流传输结束
最开始使用priority_queue与map存储乱序到达的数据,map中index作为key,data作为value,将index放入queue中。但这样难以对有重复数据的乱序数据进行排序,思考后,决定将value从string变为char。(但是效率很低,个别测试用例时间达到了5~6S)
中途写的时候还忘记思考capicity。这个capicity = 缓存乱序到达的数据量+已排序数据量。
关于Eof:发现了lab0的一个错误
源代码是if(write_==read+1) 导致eof部分一直测试错误
但是改成取余后,会导致超时。所以使用了buffer_size ==0;
#include "stream_reassembler.hh"
#include <iostream>
// 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) : totalsize(0),_output(capacity), _capacity(capacity),_unassembled_bytes(0) ,_writeLen(0),_unassembled_index(),_index_que(),Eof(false),str(){}
//! \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::putin_unassembled(const std::string &data,size_t datalen, const uint64_t index){
if(_output.remaining_capacity()>0&&_unassembled_index.find(index-1)==_unassembled_index.end()) _index_que.push(index);
for(size_t i = 0;i<datalen;i++){
if(_output.buffer_size()+_unassembled_bytes>_capacity) return;
if(_unassembled_index.find(index+i)==_unassembled_index.end()){
_unassembled_index[index+i] = data[i];
_unassembled_bytes++;
}
}
}
void StreamReassembler::write_unassemvled(size_t index){
//有重复数据
while(index<_writeLen){
if(_unassembled_index.find(index)==_unassembled_index.end()) return;
_unassembled_index.erase(index);
index++;
_unassembled_bytes--;
}
str = "";
while (_unassembled_index.find(_writeLen)!=_unassembled_index.end()){
if(_writeLen-index+1>_output.remaining_capacity()){
_index_que.push(_writeLen);
break;
}
str+=_unassembled_index[_writeLen];
_unassembled_index.erase(_writeLen);
_writeLen++;
_unassembled_bytes--;
}
_output.write(str);
}
void StreamReassembler:: push_substring(const std::string &data, const uint64_t index, const bool eof) {
size_t dataLen = data.size();
if(eof==true){
totalsize = index+dataLen;
Eof = true;
}
if(index>_writeLen){
putin_unassembled(data,dataLen,index);
return;
}
else if(index==_writeLen){
size_t buff_size = _output.buffer_size();
_output.write(data);
_writeLen+=_output.buffer_size()-buff_size;
}
else{
size_t repeat_size = _writeLen-index;
if(repeat_size>=dataLen) return;
size_t buff_size = _output.buffer_size();
_output.write(data.substr(repeat_size,dataLen-repeat_size));
_writeLen+=_output.buffer_size()-buff_size;
}
if(_unassembled_bytes!=0){
while (!_index_que.empty()&&_output.remaining_capacity()>0){
size_t top = _index_que.top();
if(top>_writeLen) return;
write_unassemvled(top);
_index_que.pop();
}
}
if(Eof&&totalsize==_writeLen) _output.end_input();
}
size_t StreamReassembler::unassembled_bytes() const {
return _unassembled_bytes;
}
bool StreamReassembler::empty() const {
if(_output.buffer_empty()) return true;
return false;
}
#ifndef SPONGE_LIBSPONGE_STREAM_REASSEMBLER_HH
#define SPONGE_LIBSPONGE_STREAM_REASSEMBLER_HH
#include "byte_stream.hh"
#include <cstdint>
#include <string>
#include <map>
#include <queue>
//! \brief A class that assembles a series of excerpts from a byte stream (possibly out of order,
//! possibly overlapping) into an in-order byte stream.
class StreamReassembler {
private:
// Your code here -- add private members as necessary.
size_t totalsize;
ByteStream _output; //!< The reassembled in-order byte stream
size_t _capacity; //!< The maximum number of bytes
size_t _unassembled_bytes;
size_t _writeLen;
std::map<uint64_t,char> _unassembled_index;
std::priority_queue<size_t,std::vector<size_t>,std::greater<size_t>> _index_que;
bool Eof;
void putin_unassembled(const std::string &data,size_t dadalen, const uint64_t index);
void write_unassemvled(size_t index);
std::string str;
public:
//! \brief Construct a `StreamReassembler` that will store up to `capacity` bytes.
//! \note This capacity limits both the bytes that have been reassembled,
//! and those that have not yet been reassembled.
StreamReassembler(const size_t capacity);
//! \brief Receive a substring and write any newly contiguous bytes into the stream.
//!
//! The StreamReassembler will stay within the memory limits of the `capacity`.
//! Bytes that would exceed the capacity are silently discarded.
//!
//! \param data the substring
//! \param index indicates the index (place in sequence) of the first byte in `data`
//! \param eof the last byte of `data` will be the last byte in the entire stream
void push_substring(const std::string &data, const uint64_t index, const bool eof);
//! \name Access the reassembled byte stream
//!@{
const ByteStream &stream_out() const { return _output; }
ByteStream &stream_out() { return _output; }
//!@}
//! The number of bytes in the substrings stored but not yet reassembled
//!
//! \note If the byte at a particular index has been pushed more than once, it
//! should only be counted once for the purpose of this function.
size_t unassembled_bytes() const;
//! \brief Is the internal state empty (other than the output stream)?
//! \returns `true` if no substrings are waiting to be assembled
bool empty() const;
};
#endif // SPONGE_LIBSPONGE_STREAM_REASSEMBLER_HH