Skip to content

Instantly share code, notes, and snippets.

@ymmt2005
Created April 11, 2012 06:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ymmt2005/2357455 to your computer and use it in GitHub Desktop.
Save ymmt2005/2357455 to your computer and use it in GitHub Desktop.
xz block encode/decode
#include "util.hpp"
#include <Poco/File.h>
#include <lzma.h>
#include <vector>
#include <iostream>
#include <cstddef>
#include <cstring>
#include <cstdlib>
const uint32_t COMPRESSION_LEVEL = 6;
const lzma_check INTEGRITY_CHECK = LZMA_CHECK_CRC64;
const lzma_match_finder FINDER = LZMA_MF_HC4;
const std::size_t BUFSIZ = 2 * 1024 * 1024;
void usage() {
std::cerr << "Usage: test_lzma INFILE" << std::endl;
}
int main(int argc, char** argv) {
if( argc == 1 ) {
usage();
return 1;
}
lzma_options_lzma options;
lzma_lzma_preset(&options, COMPRESSION_LEVEL);
options.mf = FINDER;
std::size_t ENCODED_BUFSIZ = lzma_block_buffer_bound(BUFSIZ);
std::cerr << "max encoded size=" << ENCODED_BUFSIZ << std::endl;
std::vector<uint8_t> buf(BUFSIZ);
uint8_t* const pBuf = &(buf[0]);
std::vector<uint8_t> ebuf(ENCODED_BUFSIZ);
uint8_t* const pEbuf = &(ebuf[0]);
cybozu::file f(Poco::Path(argv[1]), O_RDONLY);
#if 0
lzma_filter filters[LZMA_FILTERS_MAX + 1];
filters[0].id = LZMA_FILTER_LZMA2;
filters[0].options = &options;
filters[1].id = LZMA_VLI_UNKNOWN;
filters[1].options = 0;
uint64_t memory_usage = lzma_raw_encoder_memusage(filters);
if( memory_usage == UINT64_MAX ) {
std::cerr << "failed to check memory usage of encoder." << std::endl;
return 1;
}
std::cerr << "encoder mem usage=" << memory_usage << std::endl;
lzma_block block_header;
std::memset(&block_header, 0, sizeof(block_header));
block_header.version = 0;
block_header.check = INTEGRITY_CHECK;
block_header.filters = filters;
f.read(pBuf, BUFSIZ);
std::size_t out_pos = 0;
if( lzma_block_buffer_encode(&block_header, NULL, pBuf, BUFSIZ,
pEbuf, &out_pos, ENCODED_BUFSIZ) != LZMA_OK ) {
std::cerr << "failed to encode." << std::endl;
return 1;
}
std::cerr << "encoded size=" << out_pos << std::endl;
cybozu::writeall(1, pEbuf, out_pos);
#else
std::size_t len = (std::size_t)Poco::File(argv[1]).getSize();
f.read(pEbuf, len);
lzma_filter filters[LZMA_FILTERS_MAX + 1];
for( int i = 0; i < (LZMA_FILTERS_MAX+1); ++i ) {
filters[i].id = LZMA_VLI_UNKNOWN;
filters[i].options = 0;
}
lzma_block block_header;
std::memset(&block_header, 0, sizeof(block_header));
block_header.version = 0;
block_header.filters = filters;
block_header.header_size = lzma_block_header_size_decode(pEbuf[0]);
std::size_t in_pos = (std::size_t)block_header.header_size;
std::cerr << "block header size=" << in_pos << std::endl;
if( lzma_block_header_decode(&block_header, NULL, pEbuf) != LZMA_OK ) {
std::cerr << "failed to decode header." << std::endl;
return 1;
}
uint64_t memory_usage = lzma_raw_decoder_memusage(filters);
if( memory_usage == UINT64_MAX ) {
std::cerr << "failed to check memory usage of decoder." << std::endl;
return 1;
}
std::cerr << "decoder mem usage=" << memory_usage << std::endl;
std::size_t out_pos = 0;
if( lzma_block_buffer_decode(&block_header, NULL, pEbuf, &in_pos, len,
pBuf, &out_pos, BUFSIZ) != LZMA_OK ) {
std::cerr << "failed to decode." << std::endl;
return 1;
}
std::cerr << "decoded size=" << out_pos << std::endl;
for( int i = 0; i < (LZMA_FILTERS_MAX + 1); ++i ) {
if( filters[i].id == LZMA_VLI_UNKNOWN ) break;
std::free( filters[i].options );
filters[i].options = 0;
}
cybozu::writeall(1, pBuf, out_pos);
#endif
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment