classStreamReassembler { private: // Your code here -- add private members as necessary. size_t unass_base; //!< The index of the first unassembled byte size_t unass_size; //!< The number of bytes in the substrings stored but not yet reassembled bool _eof; //!< The last byte has arrived std::deque<char> buffer; //!< The unassembled strings std::deque<bool> bitmap; //!< buffer bitmap
ByteStream _output; //!< The reassembled in-order byte stream size_t _capacity; //!< The maximum number of bytes
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(constsize_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 voidpush_substring(const std::string &data, constuint64_t index, constbool eof);
//! 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_tunassembled_bytes()const;
//! \brief Is the internal state empty (other than the output stream)? //! \returns `true` if no substrings are waiting to be assembled boolempty()const;
//! The acknowledge index of the stream, i.e., the index of the next interested substring size_tack_index()const; };
//! \details This functions calls just after pushing a substring into the //! _output stream. It aims to check if there exists any contiguous substrings //! recorded earlier can be push into the stream. voidStreamReassembler::check_contiguous(){ string tmp = ""; // 检查是否有未拼接到 ByteStream 的连续片段 while(bitmap.front()) { tmp += buffer.front(); buffer.pop_front(); bitmap.pop_front(); buffer.push_back('\0'); bitmap.push_back(false); } if(tmp.length() > 0) { _output.write(tmp); unass_base += tmp.length(); unass_size -= tmp.length(); } }
//! \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. voidStreamReassembler::push_substring(const string &data, constsize_t index, constbool eof){ if(eof) { _eof = true; } size_t len = data.length(); if(len == 0 && _eof && unass_size == 0) { _output.end_input(); return; } // invalid index 无法容纳 if(index >= unass_base + _capacity) { return; } if(index >= unass_base) { // 非连续片段先行抵达 int offset = index - unass_base; // 判断是否可容纳 size_t space_to_accept = min(len, _capacity - _output.buffer_size() - offset); if(space_to_accept < len) { _eof = false; } for(size_t i = 0; i < space_to_accept; i++) { if(bitmap[i + offset]) { // 已有重复片段 continue; } buffer[i + offset] = data[i]; bitmap[i + offset] = true; unass_size++; } } elseif (index + len > unass_base) { // 部分重合 int offset = unass_base - index; size_t space_to_accept = min(len - offset, _capacity - _output.buffer_size()); if(space_to_accept < len - offset) { _eof = false; } for(size_t i = 0; i < space_to_accept; i++) { if(bitmap[i]) { // 已有重复片段 continue; } buffer[i] = data[i + offset]; bitmap[i] = true; unass_size++; } } check_contiguous(); if(_eof && unass_size == 0) { _output.end_input(); } }