/* Copyright (C) Teemu Suutari */ #include #include #include #include "onekpaq_common.h" #include "BlockCodec.hpp" #include "StreamCodec.hpp" #include "AsmDecode.hpp" // references used to implement this: // http://en.wikipedia.org/wiki/PAQ // http://en.wikipedia.org/wiki/Context_mixing // http://code4k.blogspot.com/2010/12/crinkler-secrets-4k-intro-executable.html // clean implementation. no foreign code used. // compared against paq8i and paq8l. #define VERIFY_STREAM 1 // sans error handling std::vector readFile(const std::string &fileName) { std::vector ret; std::ifstream file(fileName.c_str(),std::ios::in|std::ios::binary|std::ios::ate); if (file.is_open()) { size_t fileLength=size_t(file.tellg()); file.seekg(0,std::ios::beg); ret.resize(fileLength); file.read(reinterpret_cast(ret.data()),fileLength); file.close(); } return ret; } // ditto void writeFile(const std::string &fileName,const std::vector &src) { std::ofstream file(fileName.c_str(),std::ios::out|std::ios::binary|std::ios::trunc); if (file.is_open()) { file.write(reinterpret_cast(src.data()),src.size()); file.close(); } } int main(int argc,char **argv) { if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { fprintf(stderr, "Usage: %s \n" "\n" "\tmode: possible options:\n" "\t\t1: single block (small decoder)\n" "\t\t2: multi-block (small decoder)\n" "\t\t3: single block (fast decoder)\n" "\t\t4: multi-block (fast decoder)\n" "\tcomplexity: ranges from 1 (low) to 3 (high). 'high' compresses smaller\n" "\t but takes a longer time to compress and decompress\n" , argv[0]); return 0; } /*#ifdef __x86_64__ INFO("oneKpaq v" ONEKPAQ_VERSION " 64-bit"); #else INFO("oneKpaq v" ONEKPAQ_VERSION " 32-bit"); #endif*/ //if (std::string(argv[0]).find("onekpaq_encode")!=std::string::npos) { //if (argc<5) ABORT("usage: onekpaq_encode mode complexity block1 block2 ... blockn output.onekpaq"); StreamCodec::EncodeMode mode=StreamCodec::EncodeMode(atoi(argv[1])); StreamCodec::EncoderComplexity complexity=StreamCodec::EncoderComplexity(atoi(argv[2])); std::vector> blocks(argc-4); for (uint i=0;i src; for (auto &it:blocks) src.insert(src.end(),it.begin(),it.end()); ASSERT(src.size()==verify.size(),"size mismatch"); for (uint i=0;i combine=src1; combine.insert(combine.end(),src2.begin(),src2.end()); for (int i=0;i<4;i++) combine.push_back(0); fprintf(stdout/* not stderr */, "P offset=%zu shift=%u\n", src1.size(), s.GetShift()); writeFile(std::string(argv[argc-1]),combine/*stream*/); /*} else if (std::string(argv[0]).find("onekpaq_decode")!=std::string::npos) { if (argc!=3) ABORT("usage: onekpaq_decode input.onekpaq output"); struct stat st; //ASSERT(::stat(argv[2],&st)==-1,"Destination file exists"); auto src=readFile(std::string(argv[1])); StreamCodec s2; s2.LoadStream(src); auto dest=s2.Decode(); #ifndef __x86_64__ // now same thing with asm-decoder INFO("mode=%u", s2.getMode()); auto asmVerify=AsmDecode(s2.GetAsmDest1(),s2.GetAsmDest2(),s2.getMode(),s2.GetShift()); // asm decoder does not know anything about size, we can only verify contents for (uint i=0;i