Last active
January 17, 2018 20:08
-
-
Save kevinkreiser/00bc8aa0502e600f1dd2a3274f183a25 to your computer and use it in GitHub Desktop.
lz4 Compress Test Utility
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 <vector> | |
#include <string> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <cstdint> | |
#include <fstream> | |
#include <lz4.h> | |
#include <lz4hc.h> | |
#include <lz4frame.h> | |
long file_size(const std::string& file_name) { | |
//TODO: detect gzip and actually validate the uncompressed size? | |
struct stat s; | |
int rc = stat(file_name.c_str(), &s); | |
return rc == 0 ? s.st_size : -1; | |
} | |
std::vector<char> read_file(const std::string& file_name, long size) { | |
int fd = open(file_name.c_str(), O_RDONLY); | |
if(fd == -1) | |
throw std::runtime_error("Could not open: " + file_name); | |
posix_fadvise(fd, 0, 0, 1); // FDADVICE_SEQUENTIAL | |
std::vector<char> in(size); | |
if(read(fd, in.data(), size) != size) | |
throw std::runtime_error("Could not open: " + file_name); | |
close(fd); | |
return in; | |
} | |
void write_file(const std::string& file_name, const std::vector<char>& out) { | |
std::ofstream file(file_name, std::ios::binary | std::ios::trunc); | |
file.write(out.data(), out.size()); | |
} | |
enum class algorithm_t { DEFAULT, HIGH, FRAME }; | |
std::vector<char> lzip(const std::string& file_name, int compression_level, algorithm_t algorithm) { | |
auto in_size = file_size(file_name); | |
auto in = read_file(file_name, in_size); | |
LZ4F_preferences_t frame_prefs{LZ4F_frameInfo_t{}, compression_level}; | |
//prepair for destination in memory | |
size_t max_compressed_size = algorithm == algorithm_t::FRAME ? | |
LZ4F_compressFrameBound(in_size, &frame_prefs) : LZ4_compressBound(in_size); | |
std::vector<char> out(max_compressed_size); | |
//compress it in memory | |
int compressed_size = 0; | |
switch(algorithm) { | |
case algorithm_t::DEFAULT: | |
compressed_size = LZ4_compress_fast(in.data(), out.data(), in_size, max_compressed_size, compression_level); | |
break; | |
case algorithm_t::HIGH: | |
compressed_size = LZ4_compress_HC(in.data(), out.data(), in_size, max_compressed_size, compression_level); | |
break; | |
case algorithm_t::FRAME: | |
compressed_size = LZ4F_compressFrame(out.data(), max_compressed_size, in.data(), in_size, &frame_prefs); | |
break; | |
default: | |
throw std::runtime_error("Wrong compression type"); | |
} | |
if(compressed_size <= 0) | |
throw std::runtime_error("Compression failed: " + std::to_string(compressed_size)); | |
out.resize(compressed_size); | |
return out; | |
} | |
std::vector<char> lunzip(const std::string& file_name, size_t out_size, algorithm_t algorithm) { | |
size_t in_size = file_size(file_name); | |
auto in = read_file(file_name, in_size); | |
auto* in_ptr = in.data(); | |
auto* in_end = in.data() + in_size; | |
LZ4F_decompressionContext_t context = nullptr; | |
LZ4F_frameInfo_t info; | |
int hint = -1; | |
auto decompressed_size = 0; | |
std::vector<char> out(0); | |
switch(algorithm) { | |
case algorithm_t::DEFAULT: | |
case algorithm_t::HIGH: | |
out.resize(out_size); | |
decompressed_size = LZ4_decompress_fast(in.data(), out.data(), out_size); | |
break; | |
case algorithm_t::FRAME: | |
hint = LZ4F_createDecompressionContext(&context, LZ4F_VERSION); | |
if(LZ4F_isError(hint)) | |
throw std::runtime_error("Decompression initialization failed " + std::string(LZ4F_getErrorName(hint))); | |
/* | |
out_size = LZ4F_getFrameInfo(context, &info, in_ptr, &in_size); | |
if(LZ4F_isError(hint)) | |
throw std::runtime_error("Decompression header parsing failed " + std::string(LZ4F_getErrorName(hint))); | |
in_ptr += in_size; | |
in_size = in_end - in_ptr; | |
*/ | |
//cant get the info to tell us how much to reserve in total so we'll just have it known for now.. | |
out.resize(out_size); | |
//decompress | |
do { | |
hint = LZ4F_decompress(context, out.data(), &out_size, in_ptr, &in_size, nullptr); | |
if(LZ4F_isError(hint)) | |
throw std::runtime_error("Decompression of frame failed " + std::string(LZ4F_getErrorName(hint))); | |
in_ptr += in_size; | |
in_size = in_end - in_ptr; | |
} while(hint && in_size); | |
LZ4F_freeDecompressionContext(context); | |
break; | |
default: | |
throw std::runtime_error("Wrong decompression algorithm"); | |
} | |
if(decompressed_size < 0) | |
throw std::runtime_error("Deompression failed: " + std::to_string(decompressed_size)); | |
return out; | |
} | |
int main(int argc, char** argv){ | |
for(int i = 1; i < argc; ++i) { | |
//auto raw = read_file(argv[i], file_size(argv[1])); | |
auto raw = lunzip(argv[i], 3601*3601*2, algorithm_t::FRAME); | |
//auto raw = lzip(argv[i], 4, algorithm_t::FRAME); | |
write_file(std::string(argv[i]) + ".lz4.raw", raw); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment