Created
June 23, 2017 03:37
-
-
Save redboltz/1934952be51e73d558fe8cd7e861d4da to your computer and use it in GitHub Desktop.
Decompressing chunked data using boost asio and boost iostreams.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sstream> | |
#include <string> | |
#include <iostream> | |
#include <iomanip> | |
#include <algorithm> | |
#include <boost/iostreams/filtering_stream.hpp> | |
#include <boost/iostreams/filtering_streambuf.hpp> | |
#include <boost/iostreams/copy.hpp> | |
#include <boost/iostreams/filter/zlib.hpp> | |
#include <boost/asio.hpp> | |
void hexdump(std::string const& buf) { | |
for (std::string::const_iterator it = buf.begin(), end = buf.end(); | |
it != end; | |
++it) { | |
std::cout | |
<< std::setw(2) | |
<< std::hex | |
<< std::setfill('0') | |
<< (static_cast<int>(*it) & 0xff) | |
<< ' '; | |
} | |
std::cout << std::dec << std::endl; | |
} | |
std::string prepare_compressed_data(std::string const& str) { | |
std::stringstream sender; | |
boost::iostreams::filtering_streambuf<boost::iostreams::input> out; | |
out.push(boost::iostreams::zlib_compressor()); | |
out.push(sender); | |
sender << str; | |
std::stringstream compressed; | |
boost::iostreams::copy(out, compressed); | |
return compressed.str(); | |
} | |
int main() { | |
auto str = prepare_compressed_data("Hello world"); | |
std::cout << "compressed data: "; | |
hexdump(str); | |
// Test settings | |
#if 0 | |
// send all at conce | |
std::size_t const send_size = str.size(); | |
#else | |
// send 5 byte chunks | |
std::size_t const send_size = 5; | |
#endif | |
std::size_t const buf_size = 256; | |
// Prepare decompressing istream | |
boost::asio::streambuf sbuf; | |
boost::iostreams::filtering_istream is; | |
is.push(boost::iostreams::zlib_decompressor()); | |
is.push(sbuf); | |
// Network (asio socket send-receive) emulation | |
auto str_it = str.begin(); | |
auto rest = str.size(); | |
while (rest != 0) { | |
auto copy_size = std::min(rest, send_size); | |
// Emulate receive | |
// In actual code, it is `socket.read_some(mbuf)` | |
// and its return value is `copy_size`. | |
auto mbuf = sbuf.prepare(copy_size); | |
char* p = boost::asio::buffer_cast<char*>(mbuf); | |
std::copy(str_it, str_it + copy_size, p); | |
sbuf.commit(copy_size); | |
hexdump(std::string(boost::asio::buffer_cast<char const*>(sbuf.data()), sbuf.size())); | |
std::cout << "sbuf.size():" << sbuf.size() << std::endl; | |
{ // decompress | |
std::cout << "<<< try decompress >>>" << std::endl; | |
while (is) { | |
std::cout << " `is` has some data." << std::endl; | |
char buf[buf_size + 1] = { '\0' }; | |
is.read(buf, buf_size); | |
std::size_t read_size = is.gcount(); | |
std::cout << " read_size:" << read_size << std::endl; | |
std::cout << " decompressed data: " << buf << std::endl; | |
// It seems that is.read() consumed 5 bytes data in underlying sbuf | |
// even if is.gcount() returned 0. | |
} | |
std::cout << "<<< decompress loop out >>>" << std::endl; | |
} | |
rest -= copy_size; | |
str_it += copy_size; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment