Skip to content

Instantly share code, notes, and snippets.

@redboltz
Created June 23, 2017 03:37
Show Gist options
  • Save redboltz/1934952be51e73d558fe8cd7e861d4da to your computer and use it in GitHub Desktop.
Save redboltz/1934952be51e73d558fe8cd7e861d4da to your computer and use it in GitHub Desktop.
Decompressing chunked data using boost asio and boost iostreams.
#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