-
-
Save icylord/aab0ca99404163989cb0ac3007bd6b20 to your computer and use it in GitHub Desktop.
liblzma: compress (g)string into (g)string
This file contains hidden or 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 <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