Skip to content

Instantly share code, notes, and snippets.

@ArtemGr
Last active February 9, 2018 08:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ArtemGr/4095416 to your computer and use it in GitHub Desktop.
Save ArtemGr/4095416 to your computer and use it in GitHub Desktop.
liblzma: compress (g)string into (g)string
#include <lzma.h> // http://tukaani.org/xz/
#include <memory> // unique_ptr
#include <stdexcept> // runtime_error
#include <glim/gstring.hpp> // Here glim::gstring can be replaced with std::string.
using glim::gstring;
static void xzCompress (const gstring& from, gstring& to) {
// See also LZMA example at: http://git.tukaani.org/?p=xz.git;a=blob;f=doc/examples/01_compress_easy.c
lzma_stream strm = LZMA_STREAM_INIT;
std::unique_ptr<lzma_stream, void(*)(lzma_stream*)> freeStream (&strm, lzma_end);
if (lzma_easy_encoder (&strm, 6, LZMA_CHECK_CRC64) != LZMA_OK) throw std::runtime_error ("!lzma_easy_encoder");
strm.next_in = (const uint8_t*) from.data(); strm.avail_in = from.length();
uint8_t outbuf[4096]; strm.next_out = outbuf; strm.avail_out = sizeof (outbuf);
for (;;) {
lzma_ret ret = lzma_code (&strm, LZMA_FINISH);
if (strm.avail_out == 0 || ret == LZMA_STREAM_END) {
size_t write_size = sizeof (outbuf) - strm.avail_out;
to.append ((const char*) outbuf, write_size);
strm.next_out = outbuf; strm.avail_out = sizeof (outbuf);
}
if (ret == LZMA_STREAM_END) break;
if (ret == LZMA_OK) continue;
throw std::runtime_error ("lzma_code == " + std::to_string (ret));
}
}
#include <ext/rope> // cf. http://www.sgi.com/tech/stl/Rope.html
using __gnu_cxx::crope;
// NB: Might prefer deque to crope in the future.
static void xzDecompress (const char* data, int length, crope& to) {
// See also LZMA example at: http://git.tukaani.org/?p=xz.git;a=blob;f=doc/examples/02_decompress.c
lzma_stream strm = LZMA_STREAM_INIT;
strm.next_in = (const uint8_t*) data; strm.avail_in = length;
std::unique_ptr<lzma_stream, void(*)(lzma_stream*)> freeStream (&strm, lzma_end);
lzma_ret rc = lzma_stream_decoder (&strm, 99 * 1024 * 1024, LZMA_CONCATENATED);
if (rc != LZMA_OK) GTHROW ("!lzma_stream_decoder: " + std::to_string (rc));
uint8_t outbuf[4096]; strm.next_out = outbuf; strm.avail_out = sizeof outbuf;
auto&& flush = [&]() {
to.append ((const char*) outbuf, sizeof (outbuf) - strm.avail_out);
strm.next_out = outbuf; strm.avail_out = sizeof outbuf;
};
while (strm.avail_in != 0) {
rc = lzma_code (&strm, LZMA_FINISH);
flush(); if (rc == LZMA_STREAM_END) break;
if (rc != LZMA_OK) GTHROW ("!lzma_code: " + std::to_string (rc));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment