Added ArchiveReader plug-in based on File_Extractor

CQTexperiment
Chris Moeller 2013-10-04 08:13:30 -07:00
parent 7c5eaed629
commit 1be4894b25
155 changed files with 29074 additions and 0 deletions

View File

@ -0,0 +1,870 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
8359000417FEF40E0060F3ED /* 7z.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF7417FEF40E0060F3ED /* 7z.h */; };
8359000517FEF40E0060F3ED /* 7zAlloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF7517FEF40E0060F3ED /* 7zAlloc.c */; };
8359000617FEF40E0060F3ED /* 7zAlloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF7617FEF40E0060F3ED /* 7zAlloc.h */; };
8359000717FEF40E0060F3ED /* 7zBuf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF7717FEF40E0060F3ED /* 7zBuf.c */; };
8359000817FEF40E0060F3ED /* 7zBuf.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF7817FEF40E0060F3ED /* 7zBuf.h */; };
8359000917FEF40E0060F3ED /* 7zBuf2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF7917FEF40E0060F3ED /* 7zBuf2.c */; };
8359000A17FEF40E0060F3ED /* 7zC.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8359FF7A17FEF40E0060F3ED /* 7zC.txt */; };
8359000B17FEF40E0060F3ED /* 7zCrc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF7B17FEF40E0060F3ED /* 7zCrc.c */; };
8359000C17FEF40E0060F3ED /* 7zCrc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF7C17FEF40E0060F3ED /* 7zCrc.h */; };
8359000D17FEF40E0060F3ED /* 7zCrcOpt.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF7D17FEF40E0060F3ED /* 7zCrcOpt.c */; };
8359000E17FEF40E0060F3ED /* 7zDec.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF7E17FEF40E0060F3ED /* 7zDec.c */; };
8359001017FEF40E0060F3ED /* 7zDecode.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF8017FEF40E0060F3ED /* 7zDecode.h */; };
8359001217FEF40E0060F3ED /* 7zExtract.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF8217FEF40E0060F3ED /* 7zExtract.h */; };
8359001417FEF40E0060F3ED /* 7zFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF8417FEF40E0060F3ED /* 7zFile.h */; };
8359001617FEF40E0060F3ED /* 7zHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF8617FEF40E0060F3ED /* 7zHeader.h */; };
8359001717FEF40E0060F3ED /* 7zIn.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF8717FEF40E0060F3ED /* 7zIn.c */; };
8359001817FEF40E0060F3ED /* 7zIn.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF8817FEF40E0060F3ED /* 7zIn.h */; };
8359001A17FEF40E0060F3ED /* 7zItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF8A17FEF40E0060F3ED /* 7zItem.h */; };
8359001C17FEF40E0060F3ED /* 7zTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF8C17FEF40E0060F3ED /* 7zTypes.h */; };
8359001D17FEF40E0060F3ED /* 7zVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF8D17FEF40E0060F3ED /* 7zVersion.h */; };
8359001E17FEF40E0060F3ED /* Alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF8E17FEF40E0060F3ED /* Alloc.c */; };
8359001F17FEF40E0060F3ED /* Alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF8F17FEF40E0060F3ED /* Alloc.h */; };
8359002017FEF40E0060F3ED /* Bcj2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF9017FEF40E0060F3ED /* Bcj2.c */; };
8359002117FEF40E0060F3ED /* Bcj2.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF9117FEF40E0060F3ED /* Bcj2.h */; };
8359002217FEF40E0060F3ED /* Bra.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF9217FEF40E0060F3ED /* Bra.c */; };
8359002317FEF40E0060F3ED /* Bra.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF9317FEF40E0060F3ED /* Bra.h */; };
8359002417FEF40E0060F3ED /* Bra86.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF9417FEF40E0060F3ED /* Bra86.c */; };
8359002517FEF40E0060F3ED /* BraIA64.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF9517FEF40E0060F3ED /* BraIA64.c */; };
8359002617FEF40E0060F3ED /* changes.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8359FF9617FEF40E0060F3ED /* changes.txt */; };
8359002717FEF40E0060F3ED /* CpuArch.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF9717FEF40E0060F3ED /* CpuArch.c */; };
8359002817FEF40E0060F3ED /* CpuArch.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF9817FEF40E0060F3ED /* CpuArch.h */; };
8359002917FEF40E0060F3ED /* Delta.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF9917FEF40E0060F3ED /* Delta.c */; };
8359002A17FEF40E0060F3ED /* Delta.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF9A17FEF40E0060F3ED /* Delta.h */; };
8359002B17FEF40E0060F3ED /* LzFind.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF9B17FEF40E0060F3ED /* LzFind.c */; };
8359002C17FEF40E0060F3ED /* LzFind.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF9C17FEF40E0060F3ED /* LzFind.h */; };
8359002D17FEF40E0060F3ED /* LzFindMt.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FF9D17FEF40E0060F3ED /* LzFindMt.c */; };
8359002E17FEF40E0060F3ED /* LzFindMt.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF9E17FEF40E0060F3ED /* LzFindMt.h */; };
8359002F17FEF40E0060F3ED /* LzHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FF9F17FEF40E0060F3ED /* LzHash.h */; };
8359003017FEF40E0060F3ED /* lzma.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8359FFA017FEF40E0060F3ED /* lzma.txt */; };
8359003117FEF40E0060F3ED /* Lzma2Dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFA117FEF40E0060F3ED /* Lzma2Dec.c */; };
8359003217FEF40E0060F3ED /* Lzma2Dec.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFA217FEF40E0060F3ED /* Lzma2Dec.h */; };
8359003317FEF40E0060F3ED /* Lzma2Enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFA317FEF40E0060F3ED /* Lzma2Enc.c */; };
8359003417FEF40E0060F3ED /* Lzma2Enc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFA417FEF40E0060F3ED /* Lzma2Enc.h */; };
8359003517FEF40E0060F3ED /* Lzma86.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFA517FEF40E0060F3ED /* Lzma86.h */; };
8359003617FEF40E0060F3ED /* Lzma86Dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFA617FEF40E0060F3ED /* Lzma86Dec.c */; };
8359003717FEF40E0060F3ED /* Lzma86Enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFA717FEF40E0060F3ED /* Lzma86Enc.c */; };
8359003817FEF40E0060F3ED /* LzmaDec.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFA817FEF40E0060F3ED /* LzmaDec.c */; };
8359003917FEF40E0060F3ED /* LzmaDec.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFA917FEF40E0060F3ED /* LzmaDec.h */; };
8359003A17FEF40E0060F3ED /* LzmaEnc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFAA17FEF40E0060F3ED /* LzmaEnc.c */; };
8359003B17FEF40E0060F3ED /* LzmaEnc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFAB17FEF40E0060F3ED /* LzmaEnc.h */; };
8359003C17FEF40E0060F3ED /* LzmaLib.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFAC17FEF40E0060F3ED /* LzmaLib.c */; };
8359003D17FEF40E0060F3ED /* LzmaLib.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFAD17FEF40E0060F3ED /* LzmaLib.h */; };
8359003E17FEF40E0060F3ED /* LzmaTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFAE17FEF40E0060F3ED /* LzmaTypes.h */; };
8359003F17FEF40E0060F3ED /* MtCoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFAF17FEF40E0060F3ED /* MtCoder.c */; };
8359004017FEF40E0060F3ED /* MtCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFB017FEF40E0060F3ED /* MtCoder.h */; };
8359004117FEF40E0060F3ED /* Threads.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFB217FEF40E0060F3ED /* Threads.c */; };
8359004217FEF40E0060F3ED /* Threads.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFB317FEF40E0060F3ED /* Threads.h */; };
8359004317FEF40E0060F3ED /* Ppmd.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFB417FEF40E0060F3ED /* Ppmd.h */; };
8359004417FEF40E0060F3ED /* Ppmd7.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFB517FEF40E0060F3ED /* Ppmd7.c */; };
8359004517FEF40E0060F3ED /* Ppmd7.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFB617FEF40E0060F3ED /* Ppmd7.h */; };
8359004617FEF40E0060F3ED /* Ppmd7Dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFB717FEF40E0060F3ED /* Ppmd7Dec.c */; };
8359004717FEF40E0060F3ED /* Ppmd7Enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFB817FEF40E0060F3ED /* Ppmd7Enc.c */; };
8359004817FEF40E0060F3ED /* readme.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8359FFB917FEF40E0060F3ED /* readme.txt */; };
8359004917FEF40E0060F3ED /* RotateDefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFBA17FEF40E0060F3ED /* RotateDefs.h */; };
8359004A17FEF40E0060F3ED /* Threads.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFBB17FEF40E0060F3ED /* Threads.h */; };
8359004B17FEF40E0060F3ED /* Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFBC17FEF40E0060F3ED /* Types.h */; };
8359004E17FEF40E0060F3ED /* Binary_Extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFC117FEF40E0060F3ED /* Binary_Extractor.cpp */; };
8359004F17FEF40E0060F3ED /* Binary_Extractor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFC217FEF40E0060F3ED /* Binary_Extractor.h */; };
8359005017FEF40E0060F3ED /* blargg_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFC317FEF40E0060F3ED /* blargg_common.cpp */; };
8359005117FEF40E0060F3ED /* blargg_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFC417FEF40E0060F3ED /* blargg_common.h */; };
8359005217FEF40E0060F3ED /* blargg_config.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFC517FEF40E0060F3ED /* blargg_config.h */; };
8359005317FEF40E0060F3ED /* blargg_endian.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFC617FEF40E0060F3ED /* blargg_endian.h */; };
8359005417FEF40E0060F3ED /* blargg_errors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFC717FEF40E0060F3ED /* blargg_errors.cpp */; };
8359005517FEF40E0060F3ED /* blargg_errors.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFC817FEF40E0060F3ED /* blargg_errors.h */; };
8359005617FEF40E0060F3ED /* blargg_source.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFC917FEF40E0060F3ED /* blargg_source.h */; };
8359005717FEF40E0060F3ED /* Data_Reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFCA17FEF40E0060F3ED /* Data_Reader.cpp */; };
8359005817FEF40E0060F3ED /* Data_Reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFCB17FEF40E0060F3ED /* Data_Reader.h */; };
8359005917FEF40E0060F3ED /* fex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFCC17FEF40E0060F3ED /* fex.cpp */; };
8359005A17FEF40E0060F3ED /* fex.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFCD17FEF40E0060F3ED /* fex.h */; settings = {ATTRIBUTES = (Public, ); }; };
8359005B17FEF40E0060F3ED /* File_Extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFCE17FEF40E0060F3ED /* File_Extractor.cpp */; };
8359005C17FEF40E0060F3ED /* File_Extractor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFCF17FEF40E0060F3ED /* File_Extractor.h */; };
8359005D17FEF40E0060F3ED /* Gzip_Extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFD017FEF40E0060F3ED /* Gzip_Extractor.cpp */; };
8359005E17FEF40E0060F3ED /* Gzip_Extractor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFD117FEF40E0060F3ED /* Gzip_Extractor.h */; };
8359005F17FEF40E0060F3ED /* Gzip_Reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFD217FEF40E0060F3ED /* Gzip_Reader.cpp */; };
8359006017FEF40E0060F3ED /* Gzip_Reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFD317FEF40E0060F3ED /* Gzip_Reader.h */; };
8359006117FEF40E0060F3ED /* Rar_Extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFD417FEF40E0060F3ED /* Rar_Extractor.cpp */; };
8359006217FEF40E0060F3ED /* Rar_Extractor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFD517FEF40E0060F3ED /* Rar_Extractor.h */; };
8359006317FEF40E0060F3ED /* Zip7_Extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFD617FEF40E0060F3ED /* Zip7_Extractor.cpp */; };
8359006417FEF40E0060F3ED /* Zip7_Extractor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFD717FEF40E0060F3ED /* Zip7_Extractor.h */; };
8359006517FEF40E0060F3ED /* Zip_Extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFD817FEF40E0060F3ED /* Zip_Extractor.cpp */; };
8359006617FEF40E0060F3ED /* Zip_Extractor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFD917FEF40E0060F3ED /* Zip_Extractor.h */; };
8359006717FEF40E0060F3ED /* Zlib_Inflater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFDA17FEF40E0060F3ED /* Zlib_Inflater.cpp */; };
8359006817FEF40E0060F3ED /* Zlib_Inflater.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFDB17FEF40E0060F3ED /* Zlib_Inflater.h */; };
8359006917FEF40E0060F3ED /* archive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFDD17FEF40E0060F3ED /* archive.cpp */; };
8359006A17FEF40E0060F3ED /* archive.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFDE17FEF40E0060F3ED /* archive.hpp */; };
8359006B17FEF40E0060F3ED /* arcread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFDF17FEF40E0060F3ED /* arcread.cpp */; };
8359006C17FEF40E0060F3ED /* array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFE017FEF40E0060F3ED /* array.hpp */; };
8359006D17FEF40E0060F3ED /* changes.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8359FFE117FEF40E0060F3ED /* changes.txt */; };
8359006E17FEF40E0060F3ED /* coder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFE217FEF40E0060F3ED /* coder.cpp */; };
8359006F17FEF40E0060F3ED /* coder.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFE317FEF40E0060F3ED /* coder.hpp */; };
8359007017FEF40E0060F3ED /* compress.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFE417FEF40E0060F3ED /* compress.hpp */; };
8359007117FEF40E0060F3ED /* crc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFE517FEF40E0060F3ED /* crc.cpp */; };
8359007217FEF40E0060F3ED /* encname.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFE617FEF40E0060F3ED /* encname.cpp */; };
8359007317FEF40E0060F3ED /* encname.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFE717FEF40E0060F3ED /* encname.hpp */; };
8359007417FEF40E0060F3ED /* extract.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFE817FEF40E0060F3ED /* extract.cpp */; };
8359007517FEF40E0060F3ED /* getbits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFE917FEF40E0060F3ED /* getbits.cpp */; };
8359007617FEF40E0060F3ED /* getbits.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFEA17FEF40E0060F3ED /* getbits.hpp */; };
8359007717FEF40E0060F3ED /* headers.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFEB17FEF40E0060F3ED /* headers.hpp */; };
8359007817FEF40E0060F3ED /* license.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8359FFEC17FEF40E0060F3ED /* license.txt */; };
8359007917FEF40E0060F3ED /* model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFED17FEF40E0060F3ED /* model.cpp */; };
8359007A17FEF40E0060F3ED /* model.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFEE17FEF40E0060F3ED /* model.hpp */; };
8359007B17FEF40E0060F3ED /* rar.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFEF17FEF40E0060F3ED /* rar.hpp */; };
8359007C17FEF40E0060F3ED /* rarvm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF017FEF40E0060F3ED /* rarvm.cpp */; };
8359007D17FEF40E0060F3ED /* rarvm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFF117FEF40E0060F3ED /* rarvm.hpp */; };
8359007E17FEF40E0060F3ED /* rarvmtbl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF217FEF40E0060F3ED /* rarvmtbl.cpp */; };
8359007F17FEF40E0060F3ED /* rawread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF317FEF40E0060F3ED /* rawread.cpp */; };
8359008017FEF40E0060F3ED /* rawread.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFF417FEF40E0060F3ED /* rawread.hpp */; };
8359008117FEF40E0060F3ED /* readme.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8359FFF517FEF40E0060F3ED /* readme.txt */; };
8359008217FEF40E0060F3ED /* suballoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF617FEF40E0060F3ED /* suballoc.cpp */; };
8359008317FEF40E0060F3ED /* suballoc.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFF717FEF40E0060F3ED /* suballoc.hpp */; };
8359008417FEF40E0060F3ED /* technote.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8359FFF817FEF40E0060F3ED /* technote.txt */; };
8359008517FEF40E0060F3ED /* unicode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFF917FEF40E0060F3ED /* unicode.cpp */; };
8359008617FEF40E0060F3ED /* unicode.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFFA17FEF40E0060F3ED /* unicode.hpp */; };
8359008717FEF40E0060F3ED /* unpack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFFB17FEF40E0060F3ED /* unpack.cpp */; };
8359008817FEF40E0060F3ED /* unpack.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8359FFFC17FEF40E0060F3ED /* unpack.hpp */; };
8359008917FEF40E0060F3ED /* unpack15.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFFD17FEF40E0060F3ED /* unpack15.cpp */; };
8359008A17FEF40E0060F3ED /* unpack20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFFE17FEF40E0060F3ED /* unpack20.cpp */; };
8359008B17FEF40E0060F3ED /* unrar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359FFFF17FEF40E0060F3ED /* unrar.cpp */; };
8359008C17FEF40E0060F3ED /* unrar.h in Headers */ = {isa = PBXBuildFile; fileRef = 8359000017FEF40E0060F3ED /* unrar.h */; };
8359008D17FEF40E0060F3ED /* unrar_misc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359000117FEF40E0060F3ED /* unrar_misc.cpp */; };
8359008E17FEF40E0060F3ED /* unrar_open.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8359000217FEF40E0060F3ED /* unrar_open.cpp */; };
8359008F17FEF40E0060F3ED /* whatsnew.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8359000317FEF40E0060F3ED /* whatsnew.txt */; };
8359009117FEF5830060F3ED /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 8359009017FEF5830060F3ED /* libz.dylib */; };
8359009F17FF073E0060F3ED /* 7zStream.c in Sources */ = {isa = PBXBuildFile; fileRef = 8359009E17FF073E0060F3ED /* 7zStream.c */; };
8359FF4A17FEF39F0060F3ED /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8359FF4817FEF39F0060F3ED /* InfoPlist.strings */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
8359000017FEF40E0060F3ED /* unrar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unrar.h; sourceTree = "<group>"; };
8359000117FEF40E0060F3ED /* unrar_misc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unrar_misc.cpp; sourceTree = "<group>"; };
8359000217FEF40E0060F3ED /* unrar_open.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unrar_open.cpp; sourceTree = "<group>"; };
8359000317FEF40E0060F3ED /* whatsnew.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = whatsnew.txt; sourceTree = "<group>"; };
8359009017FEF5830060F3ED /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
8359009E17FF073E0060F3ED /* 7zStream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 7zStream.c; sourceTree = "<group>"; };
8359FF3C17FEF39F0060F3ED /* File_Extractor.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = File_Extractor.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8359FF4717FEF39F0060F3ED /* File_Extractor-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "File_Extractor-Info.plist"; sourceTree = "<group>"; };
8359FF4917FEF39F0060F3ED /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
8359FF7417FEF40E0060F3ED /* 7z.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7z.h; sourceTree = "<group>"; };
8359FF7517FEF40E0060F3ED /* 7zAlloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 7zAlloc.c; sourceTree = "<group>"; };
8359FF7617FEF40E0060F3ED /* 7zAlloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zAlloc.h; sourceTree = "<group>"; };
8359FF7717FEF40E0060F3ED /* 7zBuf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 7zBuf.c; sourceTree = "<group>"; };
8359FF7817FEF40E0060F3ED /* 7zBuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zBuf.h; sourceTree = "<group>"; };
8359FF7917FEF40E0060F3ED /* 7zBuf2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 7zBuf2.c; sourceTree = "<group>"; };
8359FF7A17FEF40E0060F3ED /* 7zC.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 7zC.txt; sourceTree = "<group>"; };
8359FF7B17FEF40E0060F3ED /* 7zCrc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 7zCrc.c; sourceTree = "<group>"; };
8359FF7C17FEF40E0060F3ED /* 7zCrc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zCrc.h; sourceTree = "<group>"; };
8359FF7D17FEF40E0060F3ED /* 7zCrcOpt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 7zCrcOpt.c; sourceTree = "<group>"; };
8359FF7E17FEF40E0060F3ED /* 7zDec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 7zDec.c; sourceTree = "<group>"; };
8359FF8017FEF40E0060F3ED /* 7zDecode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zDecode.h; sourceTree = "<group>"; };
8359FF8217FEF40E0060F3ED /* 7zExtract.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zExtract.h; sourceTree = "<group>"; };
8359FF8417FEF40E0060F3ED /* 7zFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zFile.h; sourceTree = "<group>"; };
8359FF8617FEF40E0060F3ED /* 7zHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zHeader.h; sourceTree = "<group>"; };
8359FF8717FEF40E0060F3ED /* 7zIn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 7zIn.c; sourceTree = "<group>"; };
8359FF8817FEF40E0060F3ED /* 7zIn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zIn.h; sourceTree = "<group>"; };
8359FF8A17FEF40E0060F3ED /* 7zItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zItem.h; sourceTree = "<group>"; };
8359FF8C17FEF40E0060F3ED /* 7zTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zTypes.h; sourceTree = "<group>"; };
8359FF8D17FEF40E0060F3ED /* 7zVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 7zVersion.h; sourceTree = "<group>"; };
8359FF8E17FEF40E0060F3ED /* Alloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Alloc.c; sourceTree = "<group>"; };
8359FF8F17FEF40E0060F3ED /* Alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Alloc.h; sourceTree = "<group>"; };
8359FF9017FEF40E0060F3ED /* Bcj2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Bcj2.c; sourceTree = "<group>"; };
8359FF9117FEF40E0060F3ED /* Bcj2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bcj2.h; sourceTree = "<group>"; };
8359FF9217FEF40E0060F3ED /* Bra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Bra.c; sourceTree = "<group>"; };
8359FF9317FEF40E0060F3ED /* Bra.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bra.h; sourceTree = "<group>"; };
8359FF9417FEF40E0060F3ED /* Bra86.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Bra86.c; sourceTree = "<group>"; };
8359FF9517FEF40E0060F3ED /* BraIA64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BraIA64.c; sourceTree = "<group>"; };
8359FF9617FEF40E0060F3ED /* changes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = changes.txt; sourceTree = "<group>"; };
8359FF9717FEF40E0060F3ED /* CpuArch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CpuArch.c; sourceTree = "<group>"; };
8359FF9817FEF40E0060F3ED /* CpuArch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CpuArch.h; sourceTree = "<group>"; };
8359FF9917FEF40E0060F3ED /* Delta.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Delta.c; sourceTree = "<group>"; };
8359FF9A17FEF40E0060F3ED /* Delta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Delta.h; sourceTree = "<group>"; };
8359FF9B17FEF40E0060F3ED /* LzFind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LzFind.c; sourceTree = "<group>"; };
8359FF9C17FEF40E0060F3ED /* LzFind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LzFind.h; sourceTree = "<group>"; };
8359FF9D17FEF40E0060F3ED /* LzFindMt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LzFindMt.c; sourceTree = "<group>"; };
8359FF9E17FEF40E0060F3ED /* LzFindMt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LzFindMt.h; sourceTree = "<group>"; };
8359FF9F17FEF40E0060F3ED /* LzHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LzHash.h; sourceTree = "<group>"; };
8359FFA017FEF40E0060F3ED /* lzma.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lzma.txt; sourceTree = "<group>"; };
8359FFA117FEF40E0060F3ED /* Lzma2Dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Lzma2Dec.c; sourceTree = "<group>"; };
8359FFA217FEF40E0060F3ED /* Lzma2Dec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lzma2Dec.h; sourceTree = "<group>"; };
8359FFA317FEF40E0060F3ED /* Lzma2Enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Lzma2Enc.c; sourceTree = "<group>"; };
8359FFA417FEF40E0060F3ED /* Lzma2Enc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lzma2Enc.h; sourceTree = "<group>"; };
8359FFA517FEF40E0060F3ED /* Lzma86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lzma86.h; sourceTree = "<group>"; };
8359FFA617FEF40E0060F3ED /* Lzma86Dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Lzma86Dec.c; sourceTree = "<group>"; };
8359FFA717FEF40E0060F3ED /* Lzma86Enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Lzma86Enc.c; sourceTree = "<group>"; };
8359FFA817FEF40E0060F3ED /* LzmaDec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LzmaDec.c; sourceTree = "<group>"; };
8359FFA917FEF40E0060F3ED /* LzmaDec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LzmaDec.h; sourceTree = "<group>"; };
8359FFAA17FEF40E0060F3ED /* LzmaEnc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LzmaEnc.c; sourceTree = "<group>"; };
8359FFAB17FEF40E0060F3ED /* LzmaEnc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LzmaEnc.h; sourceTree = "<group>"; };
8359FFAC17FEF40E0060F3ED /* LzmaLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = LzmaLib.c; sourceTree = "<group>"; };
8359FFAD17FEF40E0060F3ED /* LzmaLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LzmaLib.h; sourceTree = "<group>"; };
8359FFAE17FEF40E0060F3ED /* LzmaTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LzmaTypes.h; sourceTree = "<group>"; };
8359FFAF17FEF40E0060F3ED /* MtCoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = MtCoder.c; sourceTree = "<group>"; };
8359FFB017FEF40E0060F3ED /* MtCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MtCoder.h; sourceTree = "<group>"; };
8359FFB217FEF40E0060F3ED /* Threads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Threads.c; sourceTree = "<group>"; };
8359FFB317FEF40E0060F3ED /* Threads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Threads.h; sourceTree = "<group>"; };
8359FFB417FEF40E0060F3ED /* Ppmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Ppmd.h; sourceTree = "<group>"; };
8359FFB517FEF40E0060F3ED /* Ppmd7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Ppmd7.c; sourceTree = "<group>"; };
8359FFB617FEF40E0060F3ED /* Ppmd7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Ppmd7.h; sourceTree = "<group>"; };
8359FFB717FEF40E0060F3ED /* Ppmd7Dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Ppmd7Dec.c; sourceTree = "<group>"; };
8359FFB817FEF40E0060F3ED /* Ppmd7Enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Ppmd7Enc.c; sourceTree = "<group>"; };
8359FFB917FEF40E0060F3ED /* readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.txt; sourceTree = "<group>"; };
8359FFBA17FEF40E0060F3ED /* RotateDefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RotateDefs.h; sourceTree = "<group>"; };
8359FFBB17FEF40E0060F3ED /* Threads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Threads.h; sourceTree = "<group>"; };
8359FFBC17FEF40E0060F3ED /* Types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = "<group>"; };
8359FFC117FEF40E0060F3ED /* Binary_Extractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Binary_Extractor.cpp; sourceTree = "<group>"; };
8359FFC217FEF40E0060F3ED /* Binary_Extractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Binary_Extractor.h; sourceTree = "<group>"; };
8359FFC317FEF40E0060F3ED /* blargg_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blargg_common.cpp; sourceTree = "<group>"; };
8359FFC417FEF40E0060F3ED /* blargg_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blargg_common.h; sourceTree = "<group>"; };
8359FFC517FEF40E0060F3ED /* blargg_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blargg_config.h; sourceTree = "<group>"; };
8359FFC617FEF40E0060F3ED /* blargg_endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blargg_endian.h; sourceTree = "<group>"; };
8359FFC717FEF40E0060F3ED /* blargg_errors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blargg_errors.cpp; sourceTree = "<group>"; };
8359FFC817FEF40E0060F3ED /* blargg_errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blargg_errors.h; sourceTree = "<group>"; };
8359FFC917FEF40E0060F3ED /* blargg_source.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blargg_source.h; sourceTree = "<group>"; };
8359FFCA17FEF40E0060F3ED /* Data_Reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Data_Reader.cpp; sourceTree = "<group>"; };
8359FFCB17FEF40E0060F3ED /* Data_Reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Data_Reader.h; sourceTree = "<group>"; };
8359FFCC17FEF40E0060F3ED /* fex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fex.cpp; sourceTree = "<group>"; };
8359FFCD17FEF40E0060F3ED /* fex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fex.h; sourceTree = "<group>"; };
8359FFCE17FEF40E0060F3ED /* File_Extractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File_Extractor.cpp; sourceTree = "<group>"; };
8359FFCF17FEF40E0060F3ED /* File_Extractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = File_Extractor.h; sourceTree = "<group>"; };
8359FFD017FEF40E0060F3ED /* Gzip_Extractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Gzip_Extractor.cpp; sourceTree = "<group>"; };
8359FFD117FEF40E0060F3ED /* Gzip_Extractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Gzip_Extractor.h; sourceTree = "<group>"; };
8359FFD217FEF40E0060F3ED /* Gzip_Reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Gzip_Reader.cpp; sourceTree = "<group>"; };
8359FFD317FEF40E0060F3ED /* Gzip_Reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Gzip_Reader.h; sourceTree = "<group>"; };
8359FFD417FEF40E0060F3ED /* Rar_Extractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Rar_Extractor.cpp; sourceTree = "<group>"; };
8359FFD517FEF40E0060F3ED /* Rar_Extractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Rar_Extractor.h; sourceTree = "<group>"; };
8359FFD617FEF40E0060F3ED /* Zip7_Extractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Zip7_Extractor.cpp; sourceTree = "<group>"; };
8359FFD717FEF40E0060F3ED /* Zip7_Extractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Zip7_Extractor.h; sourceTree = "<group>"; };
8359FFD817FEF40E0060F3ED /* Zip_Extractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Zip_Extractor.cpp; sourceTree = "<group>"; };
8359FFD917FEF40E0060F3ED /* Zip_Extractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Zip_Extractor.h; sourceTree = "<group>"; };
8359FFDA17FEF40E0060F3ED /* Zlib_Inflater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Zlib_Inflater.cpp; sourceTree = "<group>"; };
8359FFDB17FEF40E0060F3ED /* Zlib_Inflater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Zlib_Inflater.h; sourceTree = "<group>"; };
8359FFDD17FEF40E0060F3ED /* archive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = archive.cpp; sourceTree = "<group>"; };
8359FFDE17FEF40E0060F3ED /* archive.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = archive.hpp; sourceTree = "<group>"; };
8359FFDF17FEF40E0060F3ED /* arcread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = arcread.cpp; sourceTree = "<group>"; };
8359FFE017FEF40E0060F3ED /* array.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = array.hpp; sourceTree = "<group>"; };
8359FFE117FEF40E0060F3ED /* changes.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = changes.txt; sourceTree = "<group>"; };
8359FFE217FEF40E0060F3ED /* coder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coder.cpp; sourceTree = "<group>"; };
8359FFE317FEF40E0060F3ED /* coder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = coder.hpp; sourceTree = "<group>"; };
8359FFE417FEF40E0060F3ED /* compress.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = compress.hpp; sourceTree = "<group>"; };
8359FFE517FEF40E0060F3ED /* crc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = crc.cpp; sourceTree = "<group>"; };
8359FFE617FEF40E0060F3ED /* encname.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = encname.cpp; sourceTree = "<group>"; };
8359FFE717FEF40E0060F3ED /* encname.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = encname.hpp; sourceTree = "<group>"; };
8359FFE817FEF40E0060F3ED /* extract.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = extract.cpp; sourceTree = "<group>"; };
8359FFE917FEF40E0060F3ED /* getbits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = getbits.cpp; sourceTree = "<group>"; };
8359FFEA17FEF40E0060F3ED /* getbits.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = getbits.hpp; sourceTree = "<group>"; };
8359FFEB17FEF40E0060F3ED /* headers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = headers.hpp; sourceTree = "<group>"; };
8359FFEC17FEF40E0060F3ED /* license.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = license.txt; sourceTree = "<group>"; };
8359FFED17FEF40E0060F3ED /* model.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = model.cpp; sourceTree = "<group>"; };
8359FFEE17FEF40E0060F3ED /* model.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = model.hpp; sourceTree = "<group>"; };
8359FFEF17FEF40E0060F3ED /* rar.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rar.hpp; sourceTree = "<group>"; };
8359FFF017FEF40E0060F3ED /* rarvm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rarvm.cpp; sourceTree = "<group>"; };
8359FFF117FEF40E0060F3ED /* rarvm.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rarvm.hpp; sourceTree = "<group>"; };
8359FFF217FEF40E0060F3ED /* rarvmtbl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rarvmtbl.cpp; sourceTree = "<group>"; };
8359FFF317FEF40E0060F3ED /* rawread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rawread.cpp; sourceTree = "<group>"; };
8359FFF417FEF40E0060F3ED /* rawread.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rawread.hpp; sourceTree = "<group>"; };
8359FFF517FEF40E0060F3ED /* readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.txt; sourceTree = "<group>"; };
8359FFF617FEF40E0060F3ED /* suballoc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = suballoc.cpp; sourceTree = "<group>"; };
8359FFF717FEF40E0060F3ED /* suballoc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = suballoc.hpp; sourceTree = "<group>"; };
8359FFF817FEF40E0060F3ED /* technote.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = technote.txt; sourceTree = "<group>"; };
8359FFF917FEF40E0060F3ED /* unicode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unicode.cpp; sourceTree = "<group>"; };
8359FFFA17FEF40E0060F3ED /* unicode.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = unicode.hpp; sourceTree = "<group>"; };
8359FFFB17FEF40E0060F3ED /* unpack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unpack.cpp; sourceTree = "<group>"; };
8359FFFC17FEF40E0060F3ED /* unpack.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = unpack.hpp; sourceTree = "<group>"; };
8359FFFD17FEF40E0060F3ED /* unpack15.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unpack15.cpp; sourceTree = "<group>"; };
8359FFFE17FEF40E0060F3ED /* unpack20.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unpack20.cpp; sourceTree = "<group>"; };
8359FFFF17FEF40E0060F3ED /* unrar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unrar.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8359FF3817FEF39F0060F3ED /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8359009117FEF5830060F3ED /* libz.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
8359FF3217FEF39F0060F3ED = {
isa = PBXGroup;
children = (
8359FF4517FEF39F0060F3ED /* File_Extractor */,
8359FF3E17FEF39F0060F3ED /* Frameworks */,
8359FF3D17FEF39F0060F3ED /* Products */,
);
sourceTree = "<group>";
};
8359FF3D17FEF39F0060F3ED /* Products */ = {
isa = PBXGroup;
children = (
8359FF3C17FEF39F0060F3ED /* File_Extractor.framework */,
);
name = Products;
sourceTree = "<group>";
};
8359FF3E17FEF39F0060F3ED /* Frameworks */ = {
isa = PBXGroup;
children = (
8359009017FEF5830060F3ED /* libz.dylib */,
8359FF4117FEF39F0060F3ED /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "<group>";
};
8359FF4117FEF39F0060F3ED /* Other Frameworks */ = {
isa = PBXGroup;
children = (
);
name = "Other Frameworks";
sourceTree = "<group>";
};
8359FF4517FEF39F0060F3ED /* File_Extractor */ = {
isa = PBXGroup;
children = (
8359FF7317FEF40E0060F3ED /* 7z_C */,
8359FFC017FEF40E0060F3ED /* fex */,
8359FFDC17FEF40E0060F3ED /* unrar */,
8359FF4617FEF39F0060F3ED /* Supporting Files */,
);
path = File_Extractor;
sourceTree = "<group>";
};
8359FF4617FEF39F0060F3ED /* Supporting Files */ = {
isa = PBXGroup;
children = (
8359FF4717FEF39F0060F3ED /* File_Extractor-Info.plist */,
8359FF4817FEF39F0060F3ED /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
8359FF7317FEF40E0060F3ED /* 7z_C */ = {
isa = PBXGroup;
children = (
8359009E17FF073E0060F3ED /* 7zStream.c */,
8359FF7417FEF40E0060F3ED /* 7z.h */,
8359FF7517FEF40E0060F3ED /* 7zAlloc.c */,
8359FF7617FEF40E0060F3ED /* 7zAlloc.h */,
8359FF7717FEF40E0060F3ED /* 7zBuf.c */,
8359FF7817FEF40E0060F3ED /* 7zBuf.h */,
8359FF7917FEF40E0060F3ED /* 7zBuf2.c */,
8359FF7A17FEF40E0060F3ED /* 7zC.txt */,
8359FF7B17FEF40E0060F3ED /* 7zCrc.c */,
8359FF7C17FEF40E0060F3ED /* 7zCrc.h */,
8359FF7D17FEF40E0060F3ED /* 7zCrcOpt.c */,
8359FF7E17FEF40E0060F3ED /* 7zDec.c */,
8359FF8017FEF40E0060F3ED /* 7zDecode.h */,
8359FF8217FEF40E0060F3ED /* 7zExtract.h */,
8359FF8417FEF40E0060F3ED /* 7zFile.h */,
8359FF8617FEF40E0060F3ED /* 7zHeader.h */,
8359FF8717FEF40E0060F3ED /* 7zIn.c */,
8359FF8817FEF40E0060F3ED /* 7zIn.h */,
8359FF8A17FEF40E0060F3ED /* 7zItem.h */,
8359FF8C17FEF40E0060F3ED /* 7zTypes.h */,
8359FF8D17FEF40E0060F3ED /* 7zVersion.h */,
8359FF8E17FEF40E0060F3ED /* Alloc.c */,
8359FF8F17FEF40E0060F3ED /* Alloc.h */,
8359FF9017FEF40E0060F3ED /* Bcj2.c */,
8359FF9117FEF40E0060F3ED /* Bcj2.h */,
8359FF9217FEF40E0060F3ED /* Bra.c */,
8359FF9317FEF40E0060F3ED /* Bra.h */,
8359FF9417FEF40E0060F3ED /* Bra86.c */,
8359FF9517FEF40E0060F3ED /* BraIA64.c */,
8359FF9617FEF40E0060F3ED /* changes.txt */,
8359FF9717FEF40E0060F3ED /* CpuArch.c */,
8359FF9817FEF40E0060F3ED /* CpuArch.h */,
8359FF9917FEF40E0060F3ED /* Delta.c */,
8359FF9A17FEF40E0060F3ED /* Delta.h */,
8359FF9B17FEF40E0060F3ED /* LzFind.c */,
8359FF9C17FEF40E0060F3ED /* LzFind.h */,
8359FF9D17FEF40E0060F3ED /* LzFindMt.c */,
8359FF9E17FEF40E0060F3ED /* LzFindMt.h */,
8359FF9F17FEF40E0060F3ED /* LzHash.h */,
8359FFA017FEF40E0060F3ED /* lzma.txt */,
8359FFA117FEF40E0060F3ED /* Lzma2Dec.c */,
8359FFA217FEF40E0060F3ED /* Lzma2Dec.h */,
8359FFA317FEF40E0060F3ED /* Lzma2Enc.c */,
8359FFA417FEF40E0060F3ED /* Lzma2Enc.h */,
8359FFA517FEF40E0060F3ED /* Lzma86.h */,
8359FFA617FEF40E0060F3ED /* Lzma86Dec.c */,
8359FFA717FEF40E0060F3ED /* Lzma86Enc.c */,
8359FFA817FEF40E0060F3ED /* LzmaDec.c */,
8359FFA917FEF40E0060F3ED /* LzmaDec.h */,
8359FFAA17FEF40E0060F3ED /* LzmaEnc.c */,
8359FFAB17FEF40E0060F3ED /* LzmaEnc.h */,
8359FFAC17FEF40E0060F3ED /* LzmaLib.c */,
8359FFAD17FEF40E0060F3ED /* LzmaLib.h */,
8359FFAE17FEF40E0060F3ED /* LzmaTypes.h */,
8359FFAF17FEF40E0060F3ED /* MtCoder.c */,
8359FFB017FEF40E0060F3ED /* MtCoder.h */,
8359FFB117FEF40E0060F3ED /* posix */,
8359FFB417FEF40E0060F3ED /* Ppmd.h */,
8359FFB517FEF40E0060F3ED /* Ppmd7.c */,
8359FFB617FEF40E0060F3ED /* Ppmd7.h */,
8359FFB717FEF40E0060F3ED /* Ppmd7Dec.c */,
8359FFB817FEF40E0060F3ED /* Ppmd7Enc.c */,
8359FFB917FEF40E0060F3ED /* readme.txt */,
8359FFBA17FEF40E0060F3ED /* RotateDefs.h */,
8359FFBB17FEF40E0060F3ED /* Threads.h */,
8359FFBC17FEF40E0060F3ED /* Types.h */,
);
path = 7z_C;
sourceTree = "<group>";
};
8359FFB117FEF40E0060F3ED /* posix */ = {
isa = PBXGroup;
children = (
8359FFB217FEF40E0060F3ED /* Threads.c */,
8359FFB317FEF40E0060F3ED /* Threads.h */,
);
path = posix;
sourceTree = "<group>";
};
8359FFC017FEF40E0060F3ED /* fex */ = {
isa = PBXGroup;
children = (
8359FFC117FEF40E0060F3ED /* Binary_Extractor.cpp */,
8359FFC217FEF40E0060F3ED /* Binary_Extractor.h */,
8359FFC317FEF40E0060F3ED /* blargg_common.cpp */,
8359FFC417FEF40E0060F3ED /* blargg_common.h */,
8359FFC517FEF40E0060F3ED /* blargg_config.h */,
8359FFC617FEF40E0060F3ED /* blargg_endian.h */,
8359FFC717FEF40E0060F3ED /* blargg_errors.cpp */,
8359FFC817FEF40E0060F3ED /* blargg_errors.h */,
8359FFC917FEF40E0060F3ED /* blargg_source.h */,
8359FFCA17FEF40E0060F3ED /* Data_Reader.cpp */,
8359FFCB17FEF40E0060F3ED /* Data_Reader.h */,
8359FFCC17FEF40E0060F3ED /* fex.cpp */,
8359FFCD17FEF40E0060F3ED /* fex.h */,
8359FFCE17FEF40E0060F3ED /* File_Extractor.cpp */,
8359FFCF17FEF40E0060F3ED /* File_Extractor.h */,
8359FFD017FEF40E0060F3ED /* Gzip_Extractor.cpp */,
8359FFD117FEF40E0060F3ED /* Gzip_Extractor.h */,
8359FFD217FEF40E0060F3ED /* Gzip_Reader.cpp */,
8359FFD317FEF40E0060F3ED /* Gzip_Reader.h */,
8359FFD417FEF40E0060F3ED /* Rar_Extractor.cpp */,
8359FFD517FEF40E0060F3ED /* Rar_Extractor.h */,
8359FFD617FEF40E0060F3ED /* Zip7_Extractor.cpp */,
8359FFD717FEF40E0060F3ED /* Zip7_Extractor.h */,
8359FFD817FEF40E0060F3ED /* Zip_Extractor.cpp */,
8359FFD917FEF40E0060F3ED /* Zip_Extractor.h */,
8359FFDA17FEF40E0060F3ED /* Zlib_Inflater.cpp */,
8359FFDB17FEF40E0060F3ED /* Zlib_Inflater.h */,
);
path = fex;
sourceTree = "<group>";
};
8359FFDC17FEF40E0060F3ED /* unrar */ = {
isa = PBXGroup;
children = (
8359FFDD17FEF40E0060F3ED /* archive.cpp */,
8359FFDE17FEF40E0060F3ED /* archive.hpp */,
8359FFDF17FEF40E0060F3ED /* arcread.cpp */,
8359FFE017FEF40E0060F3ED /* array.hpp */,
8359FFE117FEF40E0060F3ED /* changes.txt */,
8359FFE217FEF40E0060F3ED /* coder.cpp */,
8359FFE317FEF40E0060F3ED /* coder.hpp */,
8359FFE417FEF40E0060F3ED /* compress.hpp */,
8359FFE517FEF40E0060F3ED /* crc.cpp */,
8359FFE617FEF40E0060F3ED /* encname.cpp */,
8359FFE717FEF40E0060F3ED /* encname.hpp */,
8359FFE817FEF40E0060F3ED /* extract.cpp */,
8359FFE917FEF40E0060F3ED /* getbits.cpp */,
8359FFEA17FEF40E0060F3ED /* getbits.hpp */,
8359FFEB17FEF40E0060F3ED /* headers.hpp */,
8359FFEC17FEF40E0060F3ED /* license.txt */,
8359FFED17FEF40E0060F3ED /* model.cpp */,
8359FFEE17FEF40E0060F3ED /* model.hpp */,
8359FFEF17FEF40E0060F3ED /* rar.hpp */,
8359FFF017FEF40E0060F3ED /* rarvm.cpp */,
8359FFF117FEF40E0060F3ED /* rarvm.hpp */,
8359FFF217FEF40E0060F3ED /* rarvmtbl.cpp */,
8359FFF317FEF40E0060F3ED /* rawread.cpp */,
8359FFF417FEF40E0060F3ED /* rawread.hpp */,
8359FFF517FEF40E0060F3ED /* readme.txt */,
8359FFF617FEF40E0060F3ED /* suballoc.cpp */,
8359FFF717FEF40E0060F3ED /* suballoc.hpp */,
8359FFF817FEF40E0060F3ED /* technote.txt */,
8359FFF917FEF40E0060F3ED /* unicode.cpp */,
8359FFFA17FEF40E0060F3ED /* unicode.hpp */,
8359FFFB17FEF40E0060F3ED /* unpack.cpp */,
8359FFFC17FEF40E0060F3ED /* unpack.hpp */,
8359FFFD17FEF40E0060F3ED /* unpack15.cpp */,
8359FFFE17FEF40E0060F3ED /* unpack20.cpp */,
8359FFFF17FEF40E0060F3ED /* unrar.cpp */,
8359000017FEF40E0060F3ED /* unrar.h */,
8359000117FEF40E0060F3ED /* unrar_misc.cpp */,
8359000217FEF40E0060F3ED /* unrar_open.cpp */,
8359000317FEF40E0060F3ED /* whatsnew.txt */,
);
path = unrar;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
8359FF3917FEF39F0060F3ED /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
8359005A17FEF40E0060F3ED /* fex.h in Headers */,
8359005517FEF40E0060F3ED /* blargg_errors.h in Headers */,
8359003417FEF40E0060F3ED /* Lzma2Enc.h in Headers */,
8359008817FEF40E0060F3ED /* unpack.hpp in Headers */,
8359001817FEF40E0060F3ED /* 7zIn.h in Headers */,
8359003D17FEF40E0060F3ED /* LzmaLib.h in Headers */,
8359001417FEF40E0060F3ED /* 7zFile.h in Headers */,
8359000817FEF40E0060F3ED /* 7zBuf.h in Headers */,
8359006217FEF40E0060F3ED /* Rar_Extractor.h in Headers */,
8359002A17FEF40E0060F3ED /* Delta.h in Headers */,
8359006A17FEF40E0060F3ED /* archive.hpp in Headers */,
8359008C17FEF40E0060F3ED /* unrar.h in Headers */,
8359002E17FEF40E0060F3ED /* LzFindMt.h in Headers */,
8359001F17FEF40E0060F3ED /* Alloc.h in Headers */,
8359003517FEF40E0060F3ED /* Lzma86.h in Headers */,
8359002C17FEF40E0060F3ED /* LzFind.h in Headers */,
8359001617FEF40E0060F3ED /* 7zHeader.h in Headers */,
8359005617FEF40E0060F3ED /* blargg_source.h in Headers */,
8359005C17FEF40E0060F3ED /* File_Extractor.h in Headers */,
8359003217FEF40E0060F3ED /* Lzma2Dec.h in Headers */,
8359002F17FEF40E0060F3ED /* LzHash.h in Headers */,
8359002817FEF40E0060F3ED /* CpuArch.h in Headers */,
8359002117FEF40E0060F3ED /* Bcj2.h in Headers */,
8359005E17FEF40E0060F3ED /* Gzip_Extractor.h in Headers */,
8359004317FEF40E0060F3ED /* Ppmd.h in Headers */,
8359003B17FEF40E0060F3ED /* LzmaEnc.h in Headers */,
8359006617FEF40E0060F3ED /* Zip_Extractor.h in Headers */,
8359002317FEF40E0060F3ED /* Bra.h in Headers */,
8359006817FEF40E0060F3ED /* Zlib_Inflater.h in Headers */,
8359006C17FEF40E0060F3ED /* array.hpp in Headers */,
8359007617FEF40E0060F3ED /* getbits.hpp in Headers */,
8359001A17FEF40E0060F3ED /* 7zItem.h in Headers */,
8359007B17FEF40E0060F3ED /* rar.hpp in Headers */,
8359004917FEF40E0060F3ED /* RotateDefs.h in Headers */,
8359000417FEF40E0060F3ED /* 7z.h in Headers */,
8359004A17FEF40E0060F3ED /* Threads.h in Headers */,
8359006417FEF40E0060F3ED /* Zip7_Extractor.h in Headers */,
8359004517FEF40E0060F3ED /* Ppmd7.h in Headers */,
8359000C17FEF40E0060F3ED /* 7zCrc.h in Headers */,
8359004B17FEF40E0060F3ED /* Types.h in Headers */,
8359004217FEF40E0060F3ED /* Threads.h in Headers */,
8359001217FEF40E0060F3ED /* 7zExtract.h in Headers */,
8359001D17FEF40E0060F3ED /* 7zVersion.h in Headers */,
8359000617FEF40E0060F3ED /* 7zAlloc.h in Headers */,
8359007A17FEF40E0060F3ED /* model.hpp in Headers */,
8359008017FEF40E0060F3ED /* rawread.hpp in Headers */,
8359008317FEF40E0060F3ED /* suballoc.hpp in Headers */,
8359005817FEF40E0060F3ED /* Data_Reader.h in Headers */,
8359007D17FEF40E0060F3ED /* rarvm.hpp in Headers */,
8359005217FEF40E0060F3ED /* blargg_config.h in Headers */,
8359006017FEF40E0060F3ED /* Gzip_Reader.h in Headers */,
8359007017FEF40E0060F3ED /* compress.hpp in Headers */,
8359003E17FEF40E0060F3ED /* LzmaTypes.h in Headers */,
8359005317FEF40E0060F3ED /* blargg_endian.h in Headers */,
8359008617FEF40E0060F3ED /* unicode.hpp in Headers */,
8359006F17FEF40E0060F3ED /* coder.hpp in Headers */,
8359007317FEF40E0060F3ED /* encname.hpp in Headers */,
8359001C17FEF40E0060F3ED /* 7zTypes.h in Headers */,
8359004F17FEF40E0060F3ED /* Binary_Extractor.h in Headers */,
8359004017FEF40E0060F3ED /* MtCoder.h in Headers */,
8359005117FEF40E0060F3ED /* blargg_common.h in Headers */,
8359001017FEF40E0060F3ED /* 7zDecode.h in Headers */,
8359003917FEF40E0060F3ED /* LzmaDec.h in Headers */,
8359007717FEF40E0060F3ED /* headers.hpp in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
8359FF3B17FEF39F0060F3ED /* File_Extractor */ = {
isa = PBXNativeTarget;
buildConfigurationList = 8359FF6417FEF39F0060F3ED /* Build configuration list for PBXNativeTarget "File_Extractor" */;
buildPhases = (
8359FF3717FEF39F0060F3ED /* Sources */,
8359FF3817FEF39F0060F3ED /* Frameworks */,
8359FF3917FEF39F0060F3ED /* Headers */,
8359FF3A17FEF39F0060F3ED /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = File_Extractor;
productName = File_Extractor;
productReference = 8359FF3C17FEF39F0060F3ED /* File_Extractor.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
8359FF3317FEF39F0060F3ED /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = "Christopher Snowhill";
};
buildConfigurationList = 8359FF3617FEF39F0060F3ED /* Build configuration list for PBXProject "File_Extractor" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 8359FF3217FEF39F0060F3ED;
productRefGroup = 8359FF3D17FEF39F0060F3ED /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
8359FF3B17FEF39F0060F3ED /* File_Extractor */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
8359FF3A17FEF39F0060F3ED /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8359006D17FEF40E0060F3ED /* changes.txt in Resources */,
8359004817FEF40E0060F3ED /* readme.txt in Resources */,
8359002617FEF40E0060F3ED /* changes.txt in Resources */,
8359007817FEF40E0060F3ED /* license.txt in Resources */,
8359FF4A17FEF39F0060F3ED /* InfoPlist.strings in Resources */,
8359008417FEF40E0060F3ED /* technote.txt in Resources */,
8359003017FEF40E0060F3ED /* lzma.txt in Resources */,
8359008F17FEF40E0060F3ED /* whatsnew.txt in Resources */,
8359008117FEF40E0060F3ED /* readme.txt in Resources */,
8359000A17FEF40E0060F3ED /* 7zC.txt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
8359FF3717FEF39F0060F3ED /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8359004417FEF40E0060F3ED /* Ppmd7.c in Sources */,
8359002017FEF40E0060F3ED /* Bcj2.c in Sources */,
8359006B17FEF40E0060F3ED /* arcread.cpp in Sources */,
8359002B17FEF40E0060F3ED /* LzFind.c in Sources */,
8359005417FEF40E0060F3ED /* blargg_errors.cpp in Sources */,
8359006E17FEF40E0060F3ED /* coder.cpp in Sources */,
8359003817FEF40E0060F3ED /* LzmaDec.c in Sources */,
8359005717FEF40E0060F3ED /* Data_Reader.cpp in Sources */,
8359005D17FEF40E0060F3ED /* Gzip_Extractor.cpp in Sources */,
8359001717FEF40E0060F3ED /* 7zIn.c in Sources */,
8359005B17FEF40E0060F3ED /* File_Extractor.cpp in Sources */,
8359003A17FEF40E0060F3ED /* LzmaEnc.c in Sources */,
8359001E17FEF40E0060F3ED /* Alloc.c in Sources */,
8359008D17FEF40E0060F3ED /* unrar_misc.cpp in Sources */,
8359007917FEF40E0060F3ED /* model.cpp in Sources */,
8359007117FEF40E0060F3ED /* crc.cpp in Sources */,
8359003717FEF40E0060F3ED /* Lzma86Enc.c in Sources */,
8359006917FEF40E0060F3ED /* archive.cpp in Sources */,
8359008517FEF40E0060F3ED /* unicode.cpp in Sources */,
8359004617FEF40E0060F3ED /* Ppmd7Dec.c in Sources */,
8359007F17FEF40E0060F3ED /* rawread.cpp in Sources */,
8359000717FEF40E0060F3ED /* 7zBuf.c in Sources */,
8359002917FEF40E0060F3ED /* Delta.c in Sources */,
8359005017FEF40E0060F3ED /* blargg_common.cpp in Sources */,
8359005F17FEF40E0060F3ED /* Gzip_Reader.cpp in Sources */,
8359002D17FEF40E0060F3ED /* LzFindMt.c in Sources */,
8359000B17FEF40E0060F3ED /* 7zCrc.c in Sources */,
8359008917FEF40E0060F3ED /* unpack15.cpp in Sources */,
8359009F17FF073E0060F3ED /* 7zStream.c in Sources */,
8359000917FEF40E0060F3ED /* 7zBuf2.c in Sources */,
8359002517FEF40E0060F3ED /* BraIA64.c in Sources */,
8359007E17FEF40E0060F3ED /* rarvmtbl.cpp in Sources */,
8359000E17FEF40E0060F3ED /* 7zDec.c in Sources */,
8359008B17FEF40E0060F3ED /* unrar.cpp in Sources */,
8359002417FEF40E0060F3ED /* Bra86.c in Sources */,
8359006317FEF40E0060F3ED /* Zip7_Extractor.cpp in Sources */,
8359006117FEF40E0060F3ED /* Rar_Extractor.cpp in Sources */,
8359003F17FEF40E0060F3ED /* MtCoder.c in Sources */,
8359003317FEF40E0060F3ED /* Lzma2Enc.c in Sources */,
8359008217FEF40E0060F3ED /* suballoc.cpp in Sources */,
8359003617FEF40E0060F3ED /* Lzma86Dec.c in Sources */,
8359008E17FEF40E0060F3ED /* unrar_open.cpp in Sources */,
8359002217FEF40E0060F3ED /* Bra.c in Sources */,
8359000517FEF40E0060F3ED /* 7zAlloc.c in Sources */,
8359007517FEF40E0060F3ED /* getbits.cpp in Sources */,
8359007C17FEF40E0060F3ED /* rarvm.cpp in Sources */,
8359000D17FEF40E0060F3ED /* 7zCrcOpt.c in Sources */,
8359006717FEF40E0060F3ED /* Zlib_Inflater.cpp in Sources */,
8359003117FEF40E0060F3ED /* Lzma2Dec.c in Sources */,
8359007217FEF40E0060F3ED /* encname.cpp in Sources */,
8359004117FEF40E0060F3ED /* Threads.c in Sources */,
8359008717FEF40E0060F3ED /* unpack.cpp in Sources */,
8359003C17FEF40E0060F3ED /* LzmaLib.c in Sources */,
8359005917FEF40E0060F3ED /* fex.cpp in Sources */,
8359004717FEF40E0060F3ED /* Ppmd7Enc.c in Sources */,
8359008A17FEF40E0060F3ED /* unpack20.cpp in Sources */,
8359004E17FEF40E0060F3ED /* Binary_Extractor.cpp in Sources */,
8359007417FEF40E0060F3ED /* extract.cpp in Sources */,
8359006517FEF40E0060F3ED /* Zip_Extractor.cpp in Sources */,
8359002717FEF40E0060F3ED /* CpuArch.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
8359FF4817FEF39F0060F3ED /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
8359FF4917FEF39F0060F3ED /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
8359FF6217FEF39F0060F3ED /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
8359FF6317FEF39F0060F3ED /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
SDKROOT = macosx;
};
name = Release;
};
8359FF6517FEF39F0060F3ED /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LIBRARY = "libstdc++";
COMBINE_HIDPI_IMAGES = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_VERSION = A;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
File_Extractor,
);
INFOPLIST_FILE = "File_Extractor/File_Extractor-Info.plist";
INSTALL_PATH = "@loader_path/../Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = framework;
};
name = Debug;
};
8359FF6617FEF39F0060F3ED /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LIBRARY = "libstdc++";
COMBINE_HIDPI_IMAGES = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
FRAMEWORK_VERSION = A;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
File_Extractor,
);
INFOPLIST_FILE = "File_Extractor/File_Extractor-Info.plist";
INSTALL_PATH = "@loader_path/../Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = framework;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
8359FF3617FEF39F0060F3ED /* Build configuration list for PBXProject "File_Extractor" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8359FF6217FEF39F0060F3ED /* Debug */,
8359FF6317FEF39F0060F3ED /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
8359FF6417FEF39F0060F3ED /* Build configuration list for PBXNativeTarget "File_Extractor" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8359FF6517FEF39F0060F3ED /* Debug */,
8359FF6617FEF39F0060F3ED /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = 8359FF3317FEF39F0060F3ED /* Project object */;
}

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0500"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8359FF3B17FEF39F0060F3ED"
BuildableName = "File_Extractor.framework"
BlueprintName = "File_Extractor"
ReferencedContainer = "container:File_Extractor.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8359FF5217FEF39F0060F3ED"
BuildableName = "File_ExtractorTests.xctest"
BlueprintName = "File_ExtractorTests"
ReferencedContainer = "container:File_Extractor.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>File_Extractor.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>40</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>8359FF3B17FEF39F0060F3ED</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>8359FF5217FEF39F0060F3ED</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,203 @@
/* 7z.h -- 7z interface
2010-03-11 : Igor Pavlov : Public domain */
#ifndef __7Z_H
#define __7Z_H
#include "7zBuf.h"
EXTERN_C_BEGIN
#define k7zStartHeaderSize 0x20
#define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0
enum EIdEnum
{
k7zIdEnd,
k7zIdHeader,
k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo,
k7zIdFilesInfo,
k7zIdPackInfo,
k7zIdUnpackInfo,
k7zIdSubStreamsInfo,
k7zIdSize,
k7zIdCRC,
k7zIdFolder,
k7zIdCodersUnpackSize,
k7zIdNumUnpackStream,
k7zIdEmptyStream,
k7zIdEmptyFile,
k7zIdAnti,
k7zIdName,
k7zIdCTime,
k7zIdATime,
k7zIdMTime,
k7zIdWinAttributes,
k7zIdComment,
k7zIdEncodedHeader,
k7zIdStartPos,
k7zIdDummy
};
typedef struct
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
UInt64 MethodID;
CBuf Props;
} CSzCoderInfo;
void SzCoderInfo_Init(CSzCoderInfo *p);
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
typedef struct
{
UInt32 InIndex;
UInt32 OutIndex;
} CSzBindPair;
typedef struct
{
CSzCoderInfo *Coders;
CSzBindPair *BindPairs;
UInt32 *PackStreams;
UInt64 *UnpackSizes;
UInt32 NumCoders;
UInt32 NumBindPairs;
UInt32 NumPackStreams;
int UnpackCRCDefined;
UInt32 UnpackCRC;
UInt32 NumUnpackStreams;
} CSzFolder;
void SzFolder_Init(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
typedef struct
{
UInt32 Low;
UInt32 High;
} CNtfsFileTime;
typedef struct
{
CNtfsFileTime MTime;
UInt64 Size;
UInt32 Crc;
UInt32 Attrib;
Byte HasStream;
Byte IsDir;
Byte IsAnti;
Byte CrcDefined;
Byte MTimeDefined;
Byte AttribDefined;
} CSzFileItem;
void SzFile_Init(CSzFileItem *p);
typedef struct
{
UInt64 *PackSizes;
Byte *PackCRCsDefined;
UInt32 *PackCRCs;
CSzFolder *Folders;
CSzFileItem *Files;
UInt32 NumPackStreams;
UInt32 NumFolders;
UInt32 NumFiles;
} CSzAr;
void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
/*
SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
typedef struct
{
CSzAr db;
UInt64 startPosAfterHeader;
UInt64 dataPos;
UInt32 *FolderStartPackStreamIndex;
UInt64 *PackStreamStartPositions;
UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap;
size_t *FileNameOffsets; /* in 2-byte steps */
CBuf FileNames; /* UTF-16-LE */
} CSzArEx;
void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
/*
if dest == NULL, the return value specifies the required size of the buffer,
in 16-bit characters, including the null-terminating character.
if dest != NULL, the return value specifies the number of 16-bit characters that
are written to the dest, including the null-terminating character. */
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
SRes SzArEx_Extract(
const CSzArEx *db,
ILookInStream *inStream,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
/*
SzArEx_Open Errors:
SZ_ERROR_NO_ARCHIVE
SZ_ERROR_ARCHIVE
SZ_ERROR_UNSUPPORTED
SZ_ERROR_MEM
SZ_ERROR_CRC
SZ_ERROR_INPUT_EOF
SZ_ERROR_FAIL
*/
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
EXTERN_C_END
#endif

View File

@ -0,0 +1,76 @@
/* 7zAlloc.c -- Allocation functions
2010-10-29 : Igor Pavlov : Public domain */
#include "7zAlloc.h"
/* #define _SZ_ALLOC_DEBUG */
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
#ifdef _SZ_ALLOC_DEBUG
#ifdef _WIN32
#include <windows.h>
#endif
#include <stdio.h>
int g_allocCount = 0;
int g_allocCountTemp = 0;
#endif
void *SzAlloc(void *p, size_t size)
{
p = p;
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
g_allocCount++;
#endif
return malloc(size);
}
void SzFree(void *p, void *address)
{
p = p;
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
{
g_allocCount--;
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
}
#endif
free(address);
}
void *SzAllocTemp(void *p, size_t size)
{
p = p;
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
g_allocCountTemp++;
#ifdef _WIN32
return HeapAlloc(GetProcessHeap(), 0, size);
#endif
#endif
return malloc(size);
}
void SzFreeTemp(void *p, void *address)
{
p = p;
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
{
g_allocCountTemp--;
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
}
#ifdef _WIN32
HeapFree(GetProcessHeap(), 0, address);
return;
#endif
#endif
free(address);
}

View File

@ -0,0 +1,15 @@
/* 7zAlloc.h -- Allocation functions
2010-10-29 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H
#include <stdlib.h>
void *SzAlloc(void *p, size_t size);
void SzFree(void *p, void *address);
void *SzAllocTemp(void *p, size_t size);
void SzFreeTemp(void *p, void *address);
#endif

View File

@ -0,0 +1,36 @@
/* 7zBuf.c -- Byte Buffer
2008-03-28
Igor Pavlov
Public domain */
#include "7zBuf.h"
void Buf_Init(CBuf *p)
{
p->data = 0;
p->size = 0;
}
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
{
p->size = 0;
if (size == 0)
{
p->data = 0;
return 1;
}
p->data = (Byte *)alloc->Alloc(alloc, size);
if (p->data != 0)
{
p->size = size;
return 1;
}
return 0;
}
void Buf_Free(CBuf *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->data);
p->data = 0;
p->size = 0;
}

View File

@ -0,0 +1,39 @@
/* 7zBuf.h -- Byte Buffer
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __7Z_BUF_H
#define __7Z_BUF_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
Byte *data;
size_t size;
} CBuf;
void Buf_Init(CBuf *p);
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
void Buf_Free(CBuf *p, ISzAlloc *alloc);
typedef struct
{
Byte *data;
size_t size;
size_t pos;
} CDynBuf;
void DynBuf_Construct(CDynBuf *p);
void DynBuf_SeekToBeg(CDynBuf *p);
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,45 @@
/* 7zBuf2.c -- Byte Buffer
2008-10-04 : Igor Pavlov : Public domain */
#include <string.h>
#include "7zBuf.h"
void DynBuf_Construct(CDynBuf *p)
{
p->data = 0;
p->size = 0;
p->pos = 0;
}
void DynBuf_SeekToBeg(CDynBuf *p)
{
p->pos = 0;
}
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)
{
if (size > p->size - p->pos)
{
size_t newSize = p->pos + size;
Byte *data;
newSize += newSize / 4;
data = (Byte *)alloc->Alloc(alloc, newSize);
if (data == 0)
return 0;
p->size = newSize;
memcpy(data, p->data, p->pos);
alloc->Free(alloc, p->data);
p->data = data;
}
memcpy(p->data + p->pos, buf, size);
p->pos += size;
return 1;
}
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->data);
p->data = 0;
p->size = 0;
p->pos = 0;
}

View File

@ -0,0 +1,194 @@
7z ANSI-C Decoder 4.62
----------------------
7z ANSI-C provides 7z/LZMA decoding.
7z ANSI-C version is simplified version ported from C++ code.
LZMA is default and general compression method of 7z format
in 7-Zip compression program (www.7-zip.org). LZMA provides high
compression ratio and very fast decompression.
LICENSE
-------
7z ANSI-C Decoder is part of the LZMA SDK.
LZMA SDK is written and placed in the public domain by Igor Pavlov.
Files
---------------------
7zDecode.* - Low level 7z decoding
7zExtract.* - High level 7z decoding
7zHeader.* - .7z format constants
7zIn.* - .7z archive opening
7zItem.* - .7z structures
7zMain.c - Test application
How To Use
----------
You must download 7-Zip program from www.7-zip.org.
You can create .7z archive with 7z.exe or 7za.exe:
7za.exe a archive.7z *.htm -r -mx -m0fb=255
If you have big number of files in archive, and you need fast extracting,
you can use partly-solid archives:
7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K
In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only
512KB for extracting one file from such archive.
Limitations of current version of 7z ANSI-C Decoder
---------------------------------------------------
- It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive.
- It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters.
- It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.
These limitations will be fixed in future versions.
Using 7z ANSI-C Decoder Test application:
-----------------------------------------
Usage: 7zDec <command> <archive_name>
<Command>:
e: Extract files from archive
l: List contents of archive
t: Test integrity of archive
Example:
7zDec l archive.7z
lists contents of archive.7z
7zDec e archive.7z
extracts files from archive.7z to current folder.
How to use .7z Decoder
----------------------
Memory allocation
~~~~~~~~~~~~~~~~~
7z Decoder uses two memory pools:
1) Temporary pool
2) Main pool
Such scheme can allow you to avoid fragmentation of allocated blocks.
Steps for using 7z decoder
--------------------------
Use code at 7zMain.c as example.
1) Declare variables:
inStream /* implements ILookInStream interface */
CSzArEx db; /* 7z archive database structure */
ISzAlloc allocImp; /* memory functions for main pool */
ISzAlloc allocTempImp; /* memory functions for temporary pool */
2) call CrcGenerateTable(); function to initialize CRC structures.
3) call SzArEx_Init(&db); function to initialize db structures.
4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive
This function opens archive "inStream" and reads headers to "db".
All items in "db" will be allocated with "allocMain" functions.
SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions.
5) List items or Extract items
Listing code:
~~~~~~~~~~~~~
{
UInt32 i;
for (i = 0; i < db.db.NumFiles; i++)
{
CFileItem *f = db.db.Files + i;
printf("%10d %s\n", (int)f->Size, f->Name);
}
}
Extracting code:
~~~~~~~~~~~~~~~~
SZ_RESULT SzAr_Extract(
CArchiveDatabaseEx *db,
ILookInStream *inStream,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
If you need to decompress more than one file, you can send these values from previous call:
blockIndex,
outBuffer,
outBufferSize,
You can consider "outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
After decompressing you must free "outBuffer":
allocImp.Free(outBuffer);
6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db".
Memory requirements for .7z decoding
------------------------------------
Memory usage for Archive opening:
- Temporary pool:
- Memory for uncompressed .7z headers
- some other temporary blocks
- Main pool:
- Memory for database:
Estimated size of one file structures in solid archive:
- Size (4 or 8 Bytes)
- CRC32 (4 bytes)
- LastWriteTime (8 bytes)
- Some file information (4 bytes)
- File Name (variable length) + pointer + allocation structures
Memory usage for archive Decompressing:
- Temporary pool:
- Memory for LZMA decompressing structures
- Main pool:
- Memory for decompressed solid block
- Memory for temprorary buffers, if BCJ2 fileter is used. Usually these
temprorary buffers can be about 15% of solid block size.
7z Decoder doesn't allocate memory for compressed blocks.
Instead of this, you must allocate buffer with desired
size before calling 7z Decoder. Use 7zMain.c as example.
Defines
-------
_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr.
---
http://www.7-zip.org
http://www.7-zip.org/sdk.html
http://www.7-zip.org/support.html

View File

@ -0,0 +1,74 @@
/* 7zCrc.c -- CRC32 calculation
2009-11-23 : Igor Pavlov : Public domain */
#include "7zCrc.h"
#include "CpuArch.h"
#define kCrcPoly 0xEDB88320
#ifdef MY_CPU_LE
#define CRC_NUM_TABLES 8
#else
#define CRC_NUM_TABLES 1
#endif
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
static CRC_FUNC g_CrcUpdate;
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
#if CRC_NUM_TABLES == 1
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
#else
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
{
return g_CrcUpdate(v, data, size, g_CrcTable);
}
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
{
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
}
void MY_FAST_CALL CrcGenerateTable()
{
UInt32 i;
for (i = 0; i < 256; i++)
{
UInt32 r = i;
unsigned j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
g_CrcTable[i] = r;
}
#if CRC_NUM_TABLES == 1
g_CrcUpdate = CrcUpdateT1;
#else
for (; i < 256 * CRC_NUM_TABLES; i++)
{
UInt32 r = g_CrcTable[i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
}
g_CrcUpdate = CrcUpdateT4;
#ifdef MY_CPU_X86_OR_AMD64
if (!CPU_Is_InOrder())
g_CrcUpdate = CrcUpdateT8;
#endif
#endif
}

View File

@ -0,0 +1,25 @@
/* 7zCrc.h -- CRC32 calculation
2009-11-21 : Igor Pavlov : Public domain */
#ifndef __7Z_CRC_H
#define __7Z_CRC_H
#include "Types.h"
EXTERN_C_BEGIN
extern UInt32 g_CrcTable[];
/* Call CrcGenerateTable one time before other CRC functions */
void MY_FAST_CALL CrcGenerateTable(void);
#define CRC_INIT_VAL 0xFFFFFFFF
#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
EXTERN_C_END
#endif

View File

@ -0,0 +1,34 @@
/* 7zCrcOpt.c -- CRC32 calculation : optimized version
2009-11-23 : Igor Pavlov : Public domain */
#include "CpuArch.h"
#ifdef MY_CPU_LE
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
for (; size >= 4; size -= 4, p += 4)
{
v ^= *(const UInt32 *)p;
v =
table[0x300 + (v & 0xFF)] ^
table[0x200 + ((v >> 8) & 0xFF)] ^
table[0x100 + ((v >> 16) & 0xFF)] ^
table[0x000 + ((v >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
return CrcUpdateT4(v, data, size, table);
}
#endif

View File

@ -0,0 +1,470 @@
/* 7zDec.c -- Decoding from 7z folder
2010-11-02 : Igor Pavlov : Public domain */
#include <string.h>
#define _7ZIP_PPMD_SUPPPORT
#include "7z.h"
#include "Bcj2.h"
#include "Bra.h"
#include "CpuArch.h"
#include "LzmaDec.h"
#include "Lzma2Dec.h"
#ifdef _7ZIP_PPMD_SUPPPORT
#include "Ppmd7.h"
#endif
#define k_Copy 0
#define k_LZMA2 0x21
#define k_LZMA 0x30101
#define k_BCJ 0x03030103
#define k_PPC 0x03030205
#define k_ARM 0x03030501
#define k_ARMT 0x03030701
#define k_SPARC 0x03030805
#define k_BCJ2 0x0303011B
#ifdef _7ZIP_PPMD_SUPPPORT
#define k_PPMD 0x30401
typedef struct
{
IByteIn p;
const Byte *cur;
const Byte *end;
const Byte *begin;
UInt64 processed;
Bool extra;
SRes res;
ILookInStream *inStream;
} CByteInToLook;
static Byte ReadByte(void *pp)
{
CByteInToLook *p = (CByteInToLook *)pp;
if (p->cur != p->end)
return *p->cur++;
if (p->res == SZ_OK)
{
size_t size = p->cur - p->begin;
p->processed += size;
p->res = p->inStream->Skip(p->inStream, size);
size = (1 << 25);
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
p->cur = p->begin;
p->end = p->begin + size;
if (size != 0)
return *p->cur++;;
}
p->extra = True;
return 0;
}
static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CPpmd7 ppmd;
CByteInToLook s;
SRes res = SZ_OK;
s.p.Read = ReadByte;
s.inStream = inStream;
s.begin = s.end = s.cur = NULL;
s.extra = False;
s.res = SZ_OK;
s.processed = 0;
if (coder->Props.size != 5)
return SZ_ERROR_UNSUPPORTED;
{
unsigned order = coder->Props.data[0];
UInt32 memSize = GetUi32(coder->Props.data + 1);
if (order < PPMD7_MIN_ORDER ||
order > PPMD7_MAX_ORDER ||
memSize < PPMD7_MIN_MEM_SIZE ||
memSize > PPMD7_MAX_MEM_SIZE)
return SZ_ERROR_UNSUPPORTED;
Ppmd7_Construct(&ppmd);
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
return SZ_ERROR_MEM;
Ppmd7_Init(&ppmd, order);
}
{
CPpmd7z_RangeDec rc;
Ppmd7z_RangeDec_CreateVTable(&rc);
rc.Stream = &s.p;
if (!Ppmd7z_RangeDec_Init(&rc))
res = SZ_ERROR_DATA;
else if (s.extra)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else
{
SizeT i;
for (i = 0; i < outSize; i++)
{
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
if (s.extra || sym < 0)
break;
outBuffer[i] = (Byte)sym;
}
if (i != outSize)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
res = SZ_ERROR_DATA;
}
}
Ppmd7_Free(&ppmd, allocMain);
return res;
}
#endif
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CLzmaDec state;
SRes res = SZ_OK;
LzmaDec_Construct(&state);
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
state.dic = outBuffer;
state.dicBufSize = outSize;
LzmaDec_Init(&state);
for (;;)
{
Byte *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
if (res != SZ_OK)
break;
{
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
ELzmaStatus status;
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed;
inSize -= inProcessed;
if (res != SZ_OK)
break;
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
{
if (state.dicBufSize != outSize || lookahead != 0 ||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK)
break;
}
}
LzmaDec_FreeProbs(&state, allocMain);
return res;
}
static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CLzma2Dec state;
SRes res = SZ_OK;
Lzma2Dec_Construct(&state);
if (coder->Props.size != 1)
return SZ_ERROR_DATA;
RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
state.decoder.dic = outBuffer;
state.decoder.dicBufSize = outSize;
Lzma2Dec_Init(&state);
for (;;)
{
Byte *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
if (res != SZ_OK)
break;
{
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
ELzmaStatus status;
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed;
inSize -= inProcessed;
if (res != SZ_OK)
break;
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
{
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
(status != LZMA_STATUS_FINISHED_WITH_MARK))
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK)
break;
}
}
Lzma2Dec_FreeProbs(&state, allocMain);
return res;
}
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
{
while (inSize > 0)
{
void *inBuf;
size_t curSize = (1 << 18);
if (curSize > inSize)
curSize = (size_t)inSize;
RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
if (curSize == 0)
return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize);
outBuffer += curSize;
inSize -= curSize;
RINOK(inStream->Skip((void *)inStream, curSize));
}
return SZ_OK;
}
static Bool IS_MAIN_METHOD(UInt32 m)
{
switch(m)
{
case k_Copy:
case k_LZMA:
case k_LZMA2:
#ifdef _7ZIP_PPMD_SUPPPORT
case k_PPMD:
#endif
return True;
}
return False;
}
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
{
return
c->NumInStreams == 1 &&
c->NumOutStreams == 1 &&
c->MethodID <= (UInt32)0xFFFFFFFF &&
IS_MAIN_METHOD((UInt32)c->MethodID);
}
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
static SRes CheckSupportedFolder(const CSzFolder *f)
{
if (f->NumCoders < 1 || f->NumCoders > 4)
return SZ_ERROR_UNSUPPORTED;
if (!IS_SUPPORTED_CODER(&f->Coders[0]))
return SZ_ERROR_UNSUPPORTED;
if (f->NumCoders == 1)
{
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
if (f->NumCoders == 2)
{
CSzCoderInfo *c = &f->Coders[1];
if (c->MethodID > (UInt32)0xFFFFFFFF ||
c->NumInStreams != 1 ||
c->NumOutStreams != 1 ||
f->NumPackStreams != 1 ||
f->PackStreams[0] != 0 ||
f->NumBindPairs != 1 ||
f->BindPairs[0].InIndex != 1 ||
f->BindPairs[0].OutIndex != 0)
return SZ_ERROR_UNSUPPORTED;
switch ((UInt32)c->MethodID)
{
case k_BCJ:
case k_ARM:
break;
default:
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK;
}
if (f->NumCoders == 4)
{
if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
!IS_SUPPORTED_CODER(&f->Coders[2]) ||
!IS_BCJ2(&f->Coders[3]))
return SZ_ERROR_UNSUPPORTED;
if (f->NumPackStreams != 4 ||
f->PackStreams[0] != 2 ||
f->PackStreams[1] != 6 ||
f->PackStreams[2] != 1 ||
f->PackStreams[3] != 0 ||
f->NumBindPairs != 3 ||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
return SZ_ERROR_UNSUPPORTED;
}
static UInt64 GetSum(const UInt64 *values, UInt32 index)
{
UInt64 sum = 0;
UInt32 i;
for (i = 0; i < index; i++)
sum += values[i];
return sum;
}
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
Byte *tempBuf[])
{
UInt32 ci;
SizeT tempSizes[3] = { 0, 0, 0};
SizeT tempSize3 = 0;
Byte *tempBuf3 = 0;
RINOK(CheckSupportedFolder(folder));
for (ci = 0; ci < folder->NumCoders; ci++)
{
CSzCoderInfo *coder = &folder->Coders[ci];
if (IS_MAIN_METHOD((UInt32)coder->MethodID))
{
UInt32 si = 0;
UInt64 offset;
UInt64 inSize;
Byte *outBufCur = outBuffer;
SizeT outSizeCur = outSize;
if (folder->NumCoders == 4)
{
UInt32 indices[] = { 3, 2, 0 };
UInt64 unpackSize = folder->UnpackSizes[ci];
si = indices[ci];
if (ci < 2)
{
Byte *temp;
outSizeCur = (SizeT)unpackSize;
if (outSizeCur != unpackSize)
return SZ_ERROR_MEM;
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
if (temp == 0 && outSizeCur != 0)
return SZ_ERROR_MEM;
outBufCur = tempBuf[1 - ci] = temp;
tempSizes[1 - ci] = outSizeCur;
}
else if (ci == 2)
{
if (unpackSize > outSize) /* check it */
return SZ_ERROR_PARAM;
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
tempSize3 = outSizeCur = (SizeT)unpackSize;
}
else
return SZ_ERROR_UNSUPPORTED;
}
offset = GetSum(packSizes, si);
inSize = packSizes[si];
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
if (coder->MethodID == k_Copy)
{
if (inSize != outSizeCur) /* check it */
return SZ_ERROR_DATA;
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
}
else if (coder->MethodID == k_LZMA)
{
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
else if (coder->MethodID == k_LZMA2)
{
RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
else
{
#ifdef _7ZIP_PPMD_SUPPPORT
RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
#else
return SZ_ERROR_UNSUPPORTED;
#endif
}
}
else if (coder->MethodID == k_BCJ2)
{
UInt64 offset = GetSum(packSizes, 1);
UInt64 s3Size = packSizes[1];
SRes res;
if (ci != 3)
return SZ_ERROR_UNSUPPORTED;
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
tempSizes[2] = (SizeT)s3Size;
if (tempSizes[2] != s3Size)
return SZ_ERROR_MEM;
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
if (tempBuf[2] == 0 && tempSizes[2] != 0)
return SZ_ERROR_MEM;
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
RINOK(res)
res = Bcj2_Decode(
tempBuf3, tempSize3,
tempBuf[0], tempSizes[0],
tempBuf[1], tempSizes[1],
tempBuf[2], tempSizes[2],
outBuffer, outSize);
RINOK(res)
}
else
{
if (ci != 1)
return SZ_ERROR_UNSUPPORTED;
switch(coder->MethodID)
{
case k_BCJ:
{
UInt32 state;
x86_Convert_Init(state);
x86_Convert(outBuffer, outSize, 0, &state, 0);
break;
}
CASE_BRA_CONV(ARM)
default:
return SZ_ERROR_UNSUPPORTED;
}
}
}
return SZ_OK;
}
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
{
Byte *tempBuf[3] = { 0, 0, 0};
int i;
SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]);
return res;
}

View File

@ -0,0 +1,257 @@
/* 7zDecode.c -- Decoding from 7z folder
2008-11-23 : Igor Pavlov : Public domain */
#include <string.h>
#include "Bcj2.h"
#include "Bra.h"
#include "LzmaDec.h"
#include "7zDecode.h"
#define k_Copy 0
#define k_LZMA 0x30101
#define k_BCJ 0x03030103
#define k_BCJ2 0x0303011B
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CLzmaDec state;
SRes res = SZ_OK;
LzmaDec_Construct(&state);
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
state.dic = outBuffer;
state.dicBufSize = outSize;
LzmaDec_Init(&state);
for (;;)
{
Byte *inBuf = NULL;
size_t lookahead = (1 << 18);
if (lookahead > inSize)
lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead);
if (res != SZ_OK)
break;
{
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
ELzmaStatus status;
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
lookahead -= inProcessed;
inSize -= inProcessed;
if (res != SZ_OK)
break;
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
{
if (state.dicBufSize != outSize || lookahead != 0 ||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
res = SZ_ERROR_DATA;
break;
}
res = inStream->Skip((void *)inStream, inProcessed);
if (res != SZ_OK)
break;
}
}
LzmaDec_FreeProbs(&state, allocMain);
return res;
}
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
{
while (inSize > 0)
{
void *inBuf;
size_t curSize = (1 << 18);
if (curSize > inSize)
curSize = (size_t)inSize;
RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize));
if (curSize == 0)
return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize);
outBuffer += curSize;
inSize -= curSize;
RINOK(inStream->Skip((void *)inStream, curSize));
}
return SZ_OK;
}
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
static
SRes CheckSupportedFolder(const CSzFolder *f)
{
if (f->NumCoders < 1 || f->NumCoders > 4)
return SZ_ERROR_UNSUPPORTED;
if (IS_UNSUPPORTED_CODER(f->Coders[0]))
return SZ_ERROR_UNSUPPORTED;
if (f->NumCoders == 1)
{
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
if (f->NumCoders == 2)
{
if (IS_NO_BCJ(f->Coders[1]) ||
f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
f->NumBindPairs != 1 ||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
if (f->NumCoders == 4)
{
if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
IS_UNSUPPORTED_CODER(f->Coders[2]) ||
IS_NO_BCJ2(f->Coders[3]))
return SZ_ERROR_UNSUPPORTED;
if (f->NumPackStreams != 4 ||
f->PackStreams[0] != 2 ||
f->PackStreams[1] != 6 ||
f->PackStreams[2] != 1 ||
f->PackStreams[3] != 0 ||
f->NumBindPairs != 3 ||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
return SZ_ERROR_UNSUPPORTED;
return SZ_OK;
}
return SZ_ERROR_UNSUPPORTED;
}
static
UInt64 GetSum(const UInt64 *values, UInt32 index)
{
UInt64 sum = 0;
UInt32 i;
for (i = 0; i < index; i++)
sum += values[i];
return sum;
}
static
SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
Byte *tempBuf[])
{
UInt32 ci;
SizeT tempSizes[3] = { 0, 0, 0};
SizeT tempSize3 = 0;
Byte *tempBuf3 = 0;
RINOK(CheckSupportedFolder(folder));
for (ci = 0; ci < folder->NumCoders; ci++)
{
CSzCoderInfo *coder = &folder->Coders[ci];
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
{
UInt32 si = 0;
UInt64 offset;
UInt64 inSize;
Byte *outBufCur = outBuffer;
SizeT outSizeCur = outSize;
if (folder->NumCoders == 4)
{
UInt32 indices[] = { 3, 2, 0 };
UInt64 unpackSize = folder->UnpackSizes[ci];
si = indices[ci];
if (ci < 2)
{
Byte *temp;
outSizeCur = (SizeT)unpackSize;
if (outSizeCur != unpackSize)
return SZ_ERROR_MEM;
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
if (temp == 0 && outSizeCur != 0)
return SZ_ERROR_MEM;
outBufCur = tempBuf[1 - ci] = temp;
tempSizes[1 - ci] = outSizeCur;
}
else if (ci == 2)
{
if (unpackSize > outSize) /* check it */
return SZ_ERROR_PARAM;
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
tempSize3 = outSizeCur = (SizeT)unpackSize;
}
else
return SZ_ERROR_UNSUPPORTED;
}
offset = GetSum(packSizes, si);
inSize = packSizes[si];
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
if (coder->MethodID == k_Copy)
{
if (inSize != outSizeCur) /* check it */
return SZ_ERROR_DATA;
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
}
else
{
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
}
}
else if (coder->MethodID == k_BCJ)
{
UInt32 state;
if (ci != 1)
return SZ_ERROR_UNSUPPORTED;
x86_Convert_Init(state);
x86_Convert(outBuffer, outSize, 0, &state, 0);
}
else if (coder->MethodID == k_BCJ2)
{
UInt64 offset = GetSum(packSizes, 1);
UInt64 s3Size = packSizes[1];
SRes res;
if (ci != 3)
return SZ_ERROR_UNSUPPORTED;
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
tempSizes[2] = (SizeT)s3Size;
if (tempSizes[2] != s3Size)
return SZ_ERROR_MEM;
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
if (tempBuf[2] == 0 && tempSizes[2] != 0)
return SZ_ERROR_MEM;
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
RINOK(res)
res = Bcj2_Decode(
tempBuf3, tempSize3,
tempBuf[0], tempSizes[0],
tempBuf[1], tempSizes[1],
tempBuf[2], tempSizes[2],
outBuffer, outSize);
RINOK(res)
}
else
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK;
}
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
{
Byte *tempBuf[3] = { 0, 0, 0};
int i;
SRes res = SzDecode2(packSizes, folder, inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]);
return res;
}

View File

@ -0,0 +1,13 @@
/* 7zDecode.h -- Decoding from 7z folder
2008-11-23 : Igor Pavlov : Public domain */
#ifndef __7Z_DECODE_H
#define __7Z_DECODE_H
#include "7zItem.h"
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
#endif

View File

@ -0,0 +1,93 @@
/* 7zExtract.c -- Extracting from 7z archive
2008-11-23 : Igor Pavlov : Public domain */
#include "7zCrc.h"
#include "7zDecode.h"
#include "7zExtract.h"
SRes SzAr_Extract(
const CSzArEx *p,
ILookInStream *inStream,
UInt32 fileIndex,
UInt32 *blockIndex,
Byte **outBuffer,
size_t *outBufferSize,
size_t *offset,
size_t *outSizeProcessed,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
SRes res = SZ_OK;
*offset = 0;
*outSizeProcessed = 0;
if (folderIndex == (UInt32)-1)
{
IAlloc_Free(allocMain, *outBuffer);
*blockIndex = folderIndex;
*outBuffer = 0;
*outBufferSize = 0;
return SZ_OK;
}
if (*outBuffer == 0 || *blockIndex != folderIndex)
{
CSzFolder *folder = p->db.Folders + folderIndex;
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
size_t unpackSize = (size_t)unpackSizeSpec;
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
if (unpackSize != unpackSizeSpec)
return SZ_ERROR_MEM;
*blockIndex = folderIndex;
IAlloc_Free(allocMain, *outBuffer);
*outBuffer = 0;
RINOK(LookInStream_SeekTo(inStream, startOffset));
if (res == SZ_OK)
{
*outBufferSize = unpackSize;
if (unpackSize != 0)
{
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
if (*outBuffer == 0)
res = SZ_ERROR_MEM;
}
if (res == SZ_OK)
{
res = SzDecode(p->db.PackSizes +
p->FolderStartPackStreamIndex[folderIndex], folder,
inStream, startOffset,
*outBuffer, unpackSize, allocTemp);
if (res == SZ_OK)
{
if (folder->UnpackCRCDefined)
{
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
res = SZ_ERROR_CRC;
}
}
}
}
}
if (res == SZ_OK)
{
UInt32 i;
CSzFileItem *fileItem = p->db.Files + fileIndex;
*offset = 0;
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
*offset += (UInt32)p->db.Files[i].Size;
*outSizeProcessed = (size_t)fileItem->Size;
if (*offset + *outSizeProcessed > *outBufferSize)
return SZ_ERROR_FAIL;
{
if (fileItem->FileCRCDefined)
{
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
res = SZ_ERROR_CRC;
}
}
}
return res;
}

View File

@ -0,0 +1,49 @@
/* 7zExtract.h -- Extracting from 7z archive
2008-11-23 : Igor Pavlov : Public domain */
#ifndef __7Z_EXTRACT_H
#define __7Z_EXTRACT_H
#include "7zIn.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
SRes SzAr_Extract(
const CSzArEx *db,
ILookInStream *inStream,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,284 @@
/* 7zFile.c -- File IO
2009-11-24 : Igor Pavlov : Public domain */
#include "7zFile.h"
#ifndef USE_WINDOWS_FILE
#ifndef UNDER_CE
#include <errno.h>
#endif
#else
/*
ReadFile and WriteFile functions in Windows have BUG:
If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
(Insufficient system resources exist to complete the requested service).
Probably in some version of Windows there are problems with other sizes:
for 32 MB (maybe also for 16 MB).
And message can be "Network connection was lost"
*/
#define kChunkSizeMax (1 << 22)
#endif
void File_Construct(CSzFile *p)
{
#ifdef USE_WINDOWS_FILE
p->handle = INVALID_HANDLE_VALUE;
#else
p->file = NULL;
#endif
}
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
static WRes File_Open(CSzFile *p, const char *name, int writeMode)
{
#ifdef USE_WINDOWS_FILE
p->handle = CreateFileA(name,
writeMode ? GENERIC_WRITE : GENERIC_READ,
FILE_SHARE_READ, NULL,
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
#else
p->file = fopen(name, writeMode ? "wb+" : "rb");
return (p->file != 0) ? 0 :
#ifdef UNDER_CE
2; /* ENOENT */
#else
errno;
#endif
#endif
}
WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
#endif
#ifdef USE_WINDOWS_FILE
static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
{
p->handle = CreateFileW(name,
writeMode ? GENERIC_WRITE : GENERIC_READ,
FILE_SHARE_READ, NULL,
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
}
WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
#endif
WRes File_Close(CSzFile *p)
{
#ifdef USE_WINDOWS_FILE
if (p->handle != INVALID_HANDLE_VALUE)
{
if (!CloseHandle(p->handle))
return GetLastError();
p->handle = INVALID_HANDLE_VALUE;
}
#else
if (p->file != NULL)
{
int res = fclose(p->file);
if (res != 0)
return res;
p->file = NULL;
}
#endif
return 0;
}
WRes File_Read(CSzFile *p, void *data, size_t *size)
{
size_t originalSize = *size;
if (originalSize == 0)
return 0;
#ifdef USE_WINDOWS_FILE
*size = 0;
do
{
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
DWORD processed = 0;
BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);
data = (void *)((Byte *)data + processed);
originalSize -= processed;
*size += processed;
if (!res)
return GetLastError();
if (processed == 0)
break;
}
while (originalSize > 0);
return 0;
#else
*size = fread(data, 1, originalSize, p->file);
if (*size == originalSize)
return 0;
return ferror(p->file);
#endif
}
WRes File_Write(CSzFile *p, const void *data, size_t *size)
{
size_t originalSize = *size;
if (originalSize == 0)
return 0;
#ifdef USE_WINDOWS_FILE
*size = 0;
do
{
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
DWORD processed = 0;
BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);
data = (void *)((Byte *)data + processed);
originalSize -= processed;
*size += processed;
if (!res)
return GetLastError();
if (processed == 0)
break;
}
while (originalSize > 0);
return 0;
#else
*size = fwrite(data, 1, originalSize, p->file);
if (*size == originalSize)
return 0;
return ferror(p->file);
#endif
}
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
{
#ifdef USE_WINDOWS_FILE
LARGE_INTEGER value;
DWORD moveMethod;
value.LowPart = (DWORD)*pos;
value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */
switch (origin)
{
case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;
case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;
case SZ_SEEK_END: moveMethod = FILE_END; break;
default: return ERROR_INVALID_PARAMETER;
}
value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);
if (value.LowPart == 0xFFFFFFFF)
{
WRes res = GetLastError();
if (res != NO_ERROR)
return res;
}
*pos = ((Int64)value.HighPart << 32) | value.LowPart;
return 0;
#else
int moveMethod;
int res;
switch (origin)
{
case SZ_SEEK_SET: moveMethod = SEEK_SET; break;
case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;
case SZ_SEEK_END: moveMethod = SEEK_END; break;
default: return 1;
}
res = fseek(p->file, (long)*pos, moveMethod);
*pos = ftell(p->file);
return res;
#endif
}
WRes File_GetLength(CSzFile *p, UInt64 *length)
{
#ifdef USE_WINDOWS_FILE
DWORD sizeHigh;
DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
if (sizeLow == 0xFFFFFFFF)
{
DWORD res = GetLastError();
if (res != NO_ERROR)
return res;
}
*length = (((UInt64)sizeHigh) << 32) + sizeLow;
return 0;
#else
long pos = ftell(p->file);
int res = fseek(p->file, 0, SEEK_END);
*length = ftell(p->file);
fseek(p->file, pos, SEEK_SET);
return res;
#endif
}
/* ---------- FileSeqInStream ---------- */
static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)
{
CFileSeqInStream *p = (CFileSeqInStream *)pp;
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
}
void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
{
p->s.Read = FileSeqInStream_Read;
}
/* ---------- FileInStream ---------- */
static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
{
CFileInStream *p = (CFileInStream *)pp;
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
}
static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
{
CFileInStream *p = (CFileInStream *)pp;
return File_Seek(&p->file, pos, origin);
}
void FileInStream_CreateVTable(CFileInStream *p)
{
p->s.Read = FileInStream_Read;
p->s.Seek = FileInStream_Seek;
}
/* ---------- FileOutStream ---------- */
static size_t FileOutStream_Write(void *pp, const void *data, size_t size)
{
CFileOutStream *p = (CFileOutStream *)pp;
File_Write(&p->file, data, &size);
return size;
}
void FileOutStream_CreateVTable(CFileOutStream *p)
{
p->s.Write = FileOutStream_Write;
}

View File

@ -0,0 +1,83 @@
/* 7zFile.h -- File IO
2009-11-24 : Igor Pavlov : Public domain */
#ifndef __7Z_FILE_H
#define __7Z_FILE_H
#ifdef _WIN32
#define USE_WINDOWS_FILE
#endif
#ifdef USE_WINDOWS_FILE
#include <windows.h>
#else
#include <stdio.h>
#endif
#include "Types.h"
EXTERN_C_BEGIN
/* ---------- File ---------- */
typedef struct
{
#ifdef USE_WINDOWS_FILE
HANDLE handle;
#else
FILE *file;
#endif
} CSzFile;
void File_Construct(CSzFile *p);
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
WRes InFile_Open(CSzFile *p, const char *name);
WRes OutFile_Open(CSzFile *p, const char *name);
#endif
#ifdef USE_WINDOWS_FILE
WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
#endif
WRes File_Close(CSzFile *p);
/* reads max(*size, remain file's size) bytes */
WRes File_Read(CSzFile *p, void *data, size_t *size);
/* writes *size bytes */
WRes File_Write(CSzFile *p, const void *data, size_t *size);
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);
WRes File_GetLength(CSzFile *p, UInt64 *length);
/* ---------- FileInStream ---------- */
typedef struct
{
ISeqInStream s;
CSzFile file;
} CFileSeqInStream;
void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
typedef struct
{
ISeekInStream s;
CSzFile file;
} CFileInStream;
void FileInStream_CreateVTable(CFileInStream *p);
typedef struct
{
ISeqOutStream s;
CSzFile file;
} CFileOutStream;
void FileOutStream_CreateVTable(CFileOutStream *p);
EXTERN_C_END
#endif

View File

@ -0,0 +1,6 @@
/* 7zHeader.c -- 7z Headers
2008-10-04 : Igor Pavlov : Public domain */
#include "7zHeader.h"
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

View File

@ -0,0 +1,57 @@
/* 7zHeader.h -- 7z Headers
2008-10-04 : Igor Pavlov : Public domain */
#ifndef __7Z_HEADER_H
#define __7Z_HEADER_H
#include "Types.h"
#define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0
#define k7zStartHeaderSize 0x20
enum EIdEnum
{
k7zIdEnd,
k7zIdHeader,
k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo,
k7zIdFilesInfo,
k7zIdPackInfo,
k7zIdUnpackInfo,
k7zIdSubStreamsInfo,
k7zIdSize,
k7zIdCRC,
k7zIdFolder,
k7zIdCodersUnpackSize,
k7zIdNumUnpackStream,
k7zIdEmptyStream,
k7zIdEmptyFile,
k7zIdAnti,
k7zIdName,
k7zIdCTime,
k7zIdATime,
k7zIdMTime,
k7zIdWinAttributes,
k7zIdComment,
k7zIdEncodedHeader,
k7zIdStartPos,
k7zIdDummy
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
/* 7zIn.h -- 7z Input functions
2008-11-23 : Igor Pavlov : Public domain */
#ifndef __7Z_IN_H
#define __7Z_IN_H
#include "7zHeader.h"
#include "7zItem.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
CSzAr db;
UInt64 startPosAfterHeader;
UInt64 dataPos;
UInt32 *FolderStartPackStreamIndex;
UInt64 *PackStreamStartPositions;
UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap;
} CSzArEx;
void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
/*
Errors:
SZ_ERROR_NO_ARCHIVE
SZ_ERROR_ARCHIVE
SZ_ERROR_UNSUPPORTED
SZ_ERROR_MEM
SZ_ERROR_CRC
SZ_ERROR_INPUT_EOF
SZ_ERROR_FAIL
*/
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,129 @@
/* 7zItem.c -- 7z Items
2008-10-04 : Igor Pavlov : Public domain */
#include "7zItem.h"
void SzCoderInfo_Init(CSzCoderInfo *p)
{
Buf_Init(&p->Props);
}
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
{
Buf_Free(&p->Props, alloc);
SzCoderInfo_Init(p);
}
void SzFolder_Init(CSzFolder *p)
{
p->Coders = 0;
p->BindPairs = 0;
p->PackStreams = 0;
p->UnpackSizes = 0;
p->NumCoders = 0;
p->NumBindPairs = 0;
p->NumPackStreams = 0;
p->UnpackCRCDefined = 0;
p->UnpackCRC = 0;
p->NumUnpackStreams = 0;
}
static
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Coders)
for (i = 0; i < p->NumCoders; i++)
SzCoderInfo_Free(&p->Coders[i], alloc);
IAlloc_Free(alloc, p->Coders);
IAlloc_Free(alloc, p->BindPairs);
IAlloc_Free(alloc, p->PackStreams);
IAlloc_Free(alloc, p->UnpackSizes);
SzFolder_Init(p);
}
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
{
UInt32 result = 0;
UInt32 i;
for (i = 0; i < p->NumCoders; i++)
result += p->Coders[i].NumOutStreams;
return result;
}
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].InIndex == inStreamIndex)
return i;
return -1;
}
static
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].OutIndex == outStreamIndex)
return i;
return -1;
}
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
{
int i = (int)SzFolder_GetNumOutStreams(p);
if (i == 0)
return 0;
for (i--; i >= 0; i--)
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
return p->UnpackSizes[i];
/* throw 1; */
return 0;
}
void SzFile_Init(CSzFileItem *p)
{
p->HasStream = 1;
p->IsDir = 0;
p->IsAnti = 0;
p->FileCRCDefined = 0;
p->MTimeDefined = 0;
p->Name = 0;
}
static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
{
IAlloc_Free(alloc, p->Name);
SzFile_Init(p);
}
void SzAr_Init(CSzAr *p)
{
p->PackSizes = 0;
p->PackCRCsDefined = 0;
p->PackCRCs = 0;
p->Folders = 0;
p->Files = 0;
p->NumPackStreams = 0;
p->NumFolders = 0;
p->NumFiles = 0;
}
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Folders)
for (i = 0; i < p->NumFolders; i++)
SzFolder_Free(&p->Folders[i], alloc);
if (p->Files)
for (i = 0; i < p->NumFiles; i++)
SzFile_Free(&p->Files[i], alloc);
IAlloc_Free(alloc, p->PackSizes);
IAlloc_Free(alloc, p->PackCRCsDefined);
IAlloc_Free(alloc, p->PackCRCs);
IAlloc_Free(alloc, p->Folders);
IAlloc_Free(alloc, p->Files);
SzAr_Init(p);
}

View File

@ -0,0 +1,83 @@
/* 7zItem.h -- 7z Items
2008-10-04 : Igor Pavlov : Public domain */
#ifndef __7Z_ITEM_H
#define __7Z_ITEM_H
#include "7zBuf.h"
typedef struct
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
UInt64 MethodID;
CBuf Props;
} CSzCoderInfo;
void SzCoderInfo_Init(CSzCoderInfo *p);
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
typedef struct
{
UInt32 InIndex;
UInt32 OutIndex;
} CBindPair;
typedef struct
{
CSzCoderInfo *Coders;
CBindPair *BindPairs;
UInt32 *PackStreams;
UInt64 *UnpackSizes;
UInt32 NumCoders;
UInt32 NumBindPairs;
UInt32 NumPackStreams;
int UnpackCRCDefined;
UInt32 UnpackCRC;
UInt32 NumUnpackStreams;
} CSzFolder;
void SzFolder_Init(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
typedef struct
{
UInt32 Low;
UInt32 High;
} CNtfsFileTime;
typedef struct
{
CNtfsFileTime MTime;
UInt64 Size;
char *Name;
UInt32 FileCRC;
Byte HasStream;
Byte IsDir;
Byte IsAnti;
Byte FileCRCDefined;
Byte MTimeDefined;
} CSzFileItem;
void SzFile_Init(CSzFileItem *p);
typedef struct
{
UInt64 *PackSizes;
Byte *PackCRCsDefined;
UInt32 *PackCRCs;
CSzFolder *Folders;
CSzFileItem *Files;
UInt32 NumPackStreams;
UInt32 NumFolders;
UInt32 NumFiles;
} CSzAr;
void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
#endif

View File

@ -0,0 +1,169 @@
/* 7zStream.c -- 7z Stream functions
2010-03-11 : Igor Pavlov : Public domain */
#include <string.h>
#include "Types.h"
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
{
while (size != 0)
{
size_t processed = size;
RINOK(stream->Read(stream, buf, &processed));
if (processed == 0)
return errorType;
buf = (void *)((Byte *)buf + processed);
size -= processed;
}
return SZ_OK;
}
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
{
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
}
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
{
size_t processed = 1;
RINOK(stream->Read(stream, buf, &processed));
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
}
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
{
Int64 t = offset;
return stream->Seek(stream, &t, SZ_SEEK_SET);
}
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
{
const void *lookBuf;
if (*size == 0)
return SZ_OK;
RINOK(stream->Look(stream, &lookBuf, size));
memcpy(buf, lookBuf, *size);
return stream->Skip(stream, *size);
}
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
{
while (size != 0)
{
size_t processed = size;
RINOK(stream->Read(stream, buf, &processed));
if (processed == 0)
return errorType;
buf = (void *)((Byte *)buf + processed);
size -= processed;
}
return SZ_OK;
}
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
{
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
}
static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
{
SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp;
size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0)
{
p->pos = 0;
size2 = LookToRead_BUF_SIZE;
res = p->realStream->Read(p->realStream, p->buf, &size2);
p->size = size2;
}
if (size2 < *size)
*size = size2;
*buf = p->buf + p->pos;
return res;
}
static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
{
SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp;
size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0)
{
p->pos = 0;
if (*size > LookToRead_BUF_SIZE)
*size = LookToRead_BUF_SIZE;
res = p->realStream->Read(p->realStream, p->buf, size);
size2 = p->size = *size;
}
if (size2 < *size)
*size = size2;
*buf = p->buf + p->pos;
return res;
}
static SRes LookToRead_Skip(void *pp, size_t offset)
{
CLookToRead *p = (CLookToRead *)pp;
p->pos += offset;
return SZ_OK;
}
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
{
CLookToRead *p = (CLookToRead *)pp;
size_t rem = p->size - p->pos;
if (rem == 0)
return p->realStream->Read(p->realStream, buf, size);
if (rem > *size)
rem = *size;
memcpy(buf, p->buf + p->pos, rem);
p->pos += rem;
*size = rem;
return SZ_OK;
}
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
{
CLookToRead *p = (CLookToRead *)pp;
p->pos = p->size = 0;
return p->realStream->Seek(p->realStream, pos, origin);
}
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
{
p->s.Look = lookahead ?
LookToRead_Look_Lookahead :
LookToRead_Look_Exact;
p->s.Skip = LookToRead_Skip;
p->s.Read = LookToRead_Read;
p->s.Seek = LookToRead_Seek;
}
void LookToRead_Init(CLookToRead *p)
{
p->pos = p->size = 0;
}
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
{
CSecToLook *p = (CSecToLook *)pp;
return LookInStream_LookRead(p->realStream, buf, size);
}
void SecToLook_CreateVTable(CSecToLook *p)
{
p->s.Read = SecToLook_Read;
}
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
{
CSecToRead *p = (CSecToRead *)pp;
return p->realStream->Read(p->realStream, buf, size);
}
void SecToRead_CreateVTable(CSecToRead *p)
{
p->s.Read = SecToRead_Read;
}

View File

@ -0,0 +1,68 @@
/* 7zTypes.h */
#ifndef __COMMON_TYPES_H
#define __COMMON_TYPES_H
#define _SZ_ONE_DIRECTORY 1
#include <limits.h>
#if ULONG_MAX > 0xFFFFFFFF
#define _SZ_NO_INT_64
#endif
#ifndef UInt32
#ifdef _LZMA_UINT32_IS_ULONG
#define UInt32 unsigned long
#else
#define UInt32 unsigned int
#endif
#endif
#ifndef Byte
#define Byte unsigned char
#endif
#ifndef UInt16
#define UInt16 unsigned short
#endif
/* #define _SZ_NO_INT_64 */
/* define it your compiler doesn't support long long int */
#ifdef _SZ_NO_INT_64
#define UInt64 unsigned long
#else
#ifdef _MSC_VER
#define UInt64 unsigned __int64
#else
#define UInt64 unsigned long long int
#endif
#endif
/* #define _SZ_FILE_SIZE_64 */
/* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/
#ifndef CFileSize
#ifdef _SZ_FILE_SIZE_64
#define CFileSize UInt64
#else
#define CFileSize UInt32
#endif
#endif
#define SZ_RESULT int
#define SZ_OK (0)
#define SZE_DATA_ERROR (1)
#define SZE_OUTOFMEMORY (2)
#define SZE_CRC_ERROR (3)
#define SZE_NOTIMPL (4)
#define SZE_FAIL (5)
#define SZE_ARCHIVE_ERROR (6)
#define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; }
#endif

View File

@ -0,0 +1,7 @@
#define MY_VER_MAJOR 9
#define MY_VER_MINOR 20
#define MY_VER_BUILD 0
#define MY_VERSION "9.20"
#define MY_DATE "2010-11-18"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

@ -0,0 +1,127 @@
/* Alloc.c -- Memory allocation functions
2008-09-24
Igor Pavlov
Public domain */
#ifdef _WIN32
#include <windows.h>
#endif
#include <stdlib.h>
#include "Alloc.h"
/* #define _SZ_ALLOC_DEBUG */
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
#ifdef _SZ_ALLOC_DEBUG
#include <stdio.h>
int g_allocCount = 0;
int g_allocCountMid = 0;
int g_allocCountBig = 0;
#endif
void *MyAlloc(size_t size)
{
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
{
void *p = malloc(size);
fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p);
return p;
}
#else
return malloc(size);
#endif
}
void MyFree(void *address)
{
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address);
#endif
free(address);
}
#ifdef _WIN32
void *MidAlloc(size_t size)
{
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
#endif
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
}
void MidFree(void *address)
{
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
#endif
if (address == 0)
return;
VirtualFree(address, 0, MEM_RELEASE);
}
#ifndef MEM_LARGE_PAGES
#undef _7ZIP_LARGE_PAGES
#endif
#ifdef _7ZIP_LARGE_PAGES
SIZE_T g_LargePageSize = 0;
typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
#endif
void SetLargePageSize()
{
#ifdef _7ZIP_LARGE_PAGES
SIZE_T size = 0;
GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
if (largePageMinimum == 0)
return;
size = largePageMinimum();
if (size == 0 || (size & (size - 1)) != 0)
return;
g_LargePageSize = size;
#endif
}
void *BigAlloc(size_t size)
{
if (size == 0)
return 0;
#ifdef _SZ_ALLOC_DEBUG
fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);
#endif
#ifdef _7ZIP_LARGE_PAGES
if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
{
void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
if (res != 0)
return res;
}
#endif
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
}
void BigFree(void *address)
{
#ifdef _SZ_ALLOC_DEBUG
if (address != 0)
fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
#endif
if (address == 0)
return;
VirtualFree(address, 0, MEM_RELEASE);
}
#endif

View File

@ -0,0 +1,38 @@
/* Alloc.h -- Memory allocation functions
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __COMMON_ALLOC_H
#define __COMMON_ALLOC_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void *MyAlloc(size_t size);
void MyFree(void *address);
#ifdef _WIN32
void SetLargePageSize();
void *MidAlloc(size_t size);
void MidFree(void *address);
void *BigAlloc(size_t size);
void BigFree(void *address);
#else
#define MidAlloc(size) MyAlloc(size)
#define MidFree(address) MyFree(address)
#define BigAlloc(size) MyAlloc(size)
#define BigFree(address) MyFree(address)
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,132 @@
/* Bcj2.c -- Converter for x86 code (BCJ2)
2008-10-04 : Igor Pavlov : Public domain */
#include "Bcj2.h"
#ifdef _LZMA_PROB32
#define CProb UInt32
#else
#define CProb UInt16
#endif
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define RC_READ_BYTE (*buffer++)
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
int Bcj2_Decode(
const Byte *buf0, SizeT size0,
const Byte *buf1, SizeT size1,
const Byte *buf2, SizeT size2,
const Byte *buf3, SizeT size3,
Byte *outBuf, SizeT outSize)
{
CProb p[256 + 2];
SizeT inPos = 0, outPos = 0;
const Byte *buffer, *bufferLim;
UInt32 range, code;
Byte prevByte = 0;
unsigned int i;
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
p[i] = kBitModelTotal >> 1;
buffer = buf3;
bufferLim = buffer + size3;
RC_INIT2
if (outSize == 0)
return SZ_OK;
for (;;)
{
Byte b;
CProb *prob;
UInt32 bound;
UInt32 ttt;
SizeT limit = size0 - inPos;
if (outSize - outPos < limit)
limit = outSize - outPos;
while (limit != 0)
{
Byte b = buf0[inPos];
outBuf[outPos++] = b;
if (IsJ(prevByte, b))
break;
inPos++;
prevByte = b;
limit--;
}
if (limit == 0 || outPos == outSize)
break;
b = buf0[inPos++];
if (b == 0xE8)
prob = p + prevByte;
else if (b == 0xE9)
prob = p + 256;
else
prob = p + 257;
IF_BIT_0(prob)
{
UPDATE_0(prob)
prevByte = b;
}
else
{
UInt32 dest;
const Byte *v;
UPDATE_1(prob)
if (b == 0xE8)
{
v = buf1;
if (size1 < 4)
return SZ_ERROR_DATA;
buf1 += 4;
size1 -= 4;
}
else
{
v = buf2;
if (size2 < 4)
return SZ_ERROR_DATA;
buf2 += 4;
size2 -= 4;
}
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
outBuf[outPos++] = (Byte)dest;
if (outPos == outSize)
break;
outBuf[outPos++] = (Byte)(dest >> 8);
if (outPos == outSize)
break;
outBuf[outPos++] = (Byte)(dest >> 16);
if (outPos == outSize)
break;
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
}
}
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
}

View File

@ -0,0 +1,38 @@
/* Bcj2.h -- Converter for x86 code (BCJ2)
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __BCJ2_H
#define __BCJ2_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
Conditions:
outSize <= FullOutputSize,
where FullOutputSize is full size of output stream of x86_2 filter.
If buf0 overlaps outBuf, there are two required conditions:
1) (buf0 >= outBuf)
2) (buf0 + size0 >= outBuf + FullOutputSize).
Returns:
SZ_OK
SZ_ERROR_DATA - Data error
*/
int Bcj2_Decode(
const Byte *buf0, SizeT size0,
const Byte *buf1, SizeT size1,
const Byte *buf2, SizeT size2,
const Byte *buf3, SizeT size3,
Byte *outBuf, SizeT outSize);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,133 @@
/* Bra.c -- Converters for RISC code
2010-04-16 : Igor Pavlov : Public domain */
#include "Bra.h"
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 4)
return 0;
size -= 4;
ip += 8;
for (i = 0; i <= size; i += 4)
{
if (data[i + 3] == 0xEB)
{
UInt32 dest;
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);
src <<= 2;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
dest >>= 2;
data[i + 2] = (Byte)(dest >> 16);
data[i + 1] = (Byte)(dest >> 8);
data[i + 0] = (Byte)dest;
}
}
return i;
}
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 4)
return 0;
size -= 4;
ip += 4;
for (i = 0; i <= size; i += 2)
{
if ((data[i + 1] & 0xF8) == 0xF0 &&
(data[i + 3] & 0xF8) == 0xF8)
{
UInt32 dest;
UInt32 src =
(((UInt32)data[i + 1] & 0x7) << 19) |
((UInt32)data[i + 0] << 11) |
(((UInt32)data[i + 3] & 0x7) << 8) |
(data[i + 2]);
src <<= 1;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
dest >>= 1;
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
data[i + 0] = (Byte)(dest >> 11);
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
data[i + 2] = (Byte)dest;
i += 2;
}
}
return i;
}
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 4)
return 0;
size -= 4;
for (i = 0; i <= size; i += 4)
{
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
{
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |
((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3] & (~3));
UInt32 dest;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
data[i + 1] = (Byte)(dest >> 16);
data[i + 2] = (Byte)(dest >> 8);
data[i + 3] &= 0x3;
data[i + 3] |= dest;
}
}
return i;
}
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
UInt32 i;
if (size < 4)
return 0;
size -= 4;
for (i = 0; i <= size; i += 4)
{
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
{
UInt32 src =
((UInt32)data[i + 0] << 24) |
((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3]);
UInt32 dest;
src <<= 2;
if (encoding)
dest = ip + i + src;
else
dest = src - (ip + i);
dest >>= 2;
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
data[i + 0] = (Byte)(dest >> 24);
data[i + 1] = (Byte)(dest >> 16);
data[i + 2] = (Byte)(dest >> 8);
data[i + 3] = (Byte)dest;
}
}
return i;
}

View File

@ -0,0 +1,68 @@
/* Bra.h -- Branch converters for executables
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __BRA_H
#define __BRA_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
These functions convert relative addresses to absolute addresses
in CALL instructions to increase the compression ratio.
In:
data - data buffer
size - size of data
ip - current virtual Instruction Pinter (IP) value
state - state variable for x86 converter
encoding - 0 (for decoding), 1 (for encoding)
Out:
state - state variable for x86 converter
Returns:
The number of processed bytes. If you call these functions with multiple calls,
you must start next call with first byte after block of processed bytes.
Type Endian Alignment LookAhead
x86 little 1 4
ARMT little 2 2
ARM little 4 0
PPC big 4 0
SPARC big 4 0
IA64 little 16 0
size must be >= Alignment + LookAhead, if it's not last block.
If (size < Alignment + LookAhead), converter returns 0.
Example:
UInt32 ip = 0;
for ()
{
; size must be >= Alignment + LookAhead, if it's not last block
SizeT processed = Convert(data, size, ip, 1);
data += processed;
size -= processed;
ip += processed;
}
*/
#define x86_Convert_Init(state) { state = 0; }
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,85 @@
/* Bra86.c -- Converter for x86 code (BCJ)
2008-10-04 : Igor Pavlov : Public domain */
#include "Bra.h"
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
{
SizeT bufferPos = 0, prevPosT;
UInt32 prevMask = *state & 0x7;
if (size < 5)
return 0;
ip += 5;
prevPosT = (SizeT)0 - 1;
for (;;)
{
Byte *p = data + bufferPos;
Byte *limit = data + size - 4;
for (; p < limit; p++)
if ((*p & 0xFE) == 0xE8)
break;
bufferPos = (SizeT)(p - data);
if (p >= limit)
break;
prevPosT = bufferPos - prevPosT;
if (prevPosT > 3)
prevMask = 0;
else
{
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
if (prevMask != 0)
{
Byte b = p[4 - kMaskToBitNumber[prevMask]];
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
{
prevPosT = bufferPos;
prevMask = ((prevMask << 1) & 0x7) | 1;
bufferPos++;
continue;
}
}
}
prevPosT = bufferPos;
if (Test86MSByte(p[4]))
{
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
UInt32 dest;
for (;;)
{
Byte b;
int index;
if (encoding)
dest = (ip + (UInt32)bufferPos) + src;
else
dest = src - (ip + (UInt32)bufferPos);
if (prevMask == 0)
break;
index = kMaskToBitNumber[prevMask] * 8;
b = (Byte)(dest >> (24 - index));
if (!Test86MSByte(b))
break;
src = dest ^ ((1 << (32 - index)) - 1);
}
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
p[3] = (Byte)(dest >> 16);
p[2] = (Byte)(dest >> 8);
p[1] = (Byte)dest;
bufferPos += 5;
}
else
{
prevMask = ((prevMask << 1) & 0x7) | 1;
bufferPos++;
}
}
prevPosT = bufferPos - prevPosT;
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
return bufferPos;
}

View File

@ -0,0 +1,67 @@
/* BraIA64.c -- Converter for IA-64 code
2008-10-04 : Igor Pavlov : Public domain */
#include "Bra.h"
static const Byte kBranchTable[32] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
4, 4, 6, 6, 0, 0, 7, 7,
4, 4, 0, 0, 4, 4, 0, 0
};
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 16)
return 0;
size -= 16;
for (i = 0; i <= size; i += 16)
{
UInt32 instrTemplate = data[i] & 0x1F;
UInt32 mask = kBranchTable[instrTemplate];
UInt32 bitPos = 5;
int slot;
for (slot = 0; slot < 3; slot++, bitPos += 41)
{
UInt32 bytePos, bitRes;
UInt64 instruction, instNorm;
int j;
if (((mask >> slot) & 1) == 0)
continue;
bytePos = (bitPos >> 3);
bitRes = bitPos & 0x7;
instruction = 0;
for (j = 0; j < 6; j++)
instruction += (UInt64)data[i + j + bytePos] << (8 * j);
instNorm = instruction >> bitRes;
if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0)
{
UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
UInt32 dest;
src |= ((UInt32)(instNorm >> 36) & 1) << 20;
src <<= 4;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
dest >>= 4;
instNorm &= ~((UInt64)(0x8FFFFF) << 13);
instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);
instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));
instruction &= (1 << bitRes) - 1;
instruction |= (instNorm << bitRes);
for (j = 0; j < 6; j++)
data[i + j + bytePos] = (Byte)(instruction >> (8 * j));
}
}
}
return i;
}

View File

@ -0,0 +1,168 @@
/* CpuArch.c -- CPU specific code
2010-10-26: Igor Pavlov : Public domain */
#include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
#define USE_ASM
#endif
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
static UInt32 CheckFlag(UInt32 flag)
{
#ifdef _MSC_VER
__asm pushfd;
__asm pop EAX;
__asm mov EDX, EAX;
__asm xor EAX, flag;
__asm push EAX;
__asm popfd;
__asm pushfd;
__asm pop EAX;
__asm xor EAX, EDX;
__asm push EDX;
__asm popfd;
__asm and flag, EAX;
#else
__asm__ __volatile__ (
"pushf\n\t"
"pop %%EAX\n\t"
"movl %%EAX,%%EDX\n\t"
"xorl %0,%%EAX\n\t"
"push %%EAX\n\t"
"popf\n\t"
"pushf\n\t"
"pop %%EAX\n\t"
"xorl %%EDX,%%EAX\n\t"
"push %%EDX\n\t"
"popf\n\t"
"andl %%EAX, %0\n\t":
"=c" (flag) : "c" (flag));
#endif
return flag;
}
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
#else
#define CHECK_CPUID_IS_SUPPORTED
#endif
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
#ifdef USE_ASM
#ifdef _MSC_VER
UInt32 a2, b2, c2, d2;
__asm xor EBX, EBX;
__asm xor ECX, ECX;
__asm xor EDX, EDX;
__asm mov EAX, function;
__asm cpuid;
__asm mov a2, EAX;
__asm mov b2, EBX;
__asm mov c2, ECX;
__asm mov d2, EDX;
*a = a2;
*b = b2;
*c = c2;
*d = d2;
#else
__asm__ __volatile__ (
"cpuid"
: "=a" (*a) ,
"=b" (*b) ,
"=c" (*c) ,
"=d" (*d)
: "0" (function)) ;
#endif
#else
int CPUInfo[4];
__cpuid(CPUInfo, function);
*a = CPUInfo[0];
*b = CPUInfo[1];
*c = CPUInfo[2];
*d = CPUInfo[3];
#endif
}
Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
{
CHECK_CPUID_IS_SUPPORTED
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
return True;
}
static UInt32 kVendors[][3] =
{
{ 0x756E6547, 0x49656E69, 0x6C65746E},
{ 0x68747541, 0x69746E65, 0x444D4163},
{ 0x746E6543, 0x48727561, 0x736C7561}
};
int x86cpuid_GetFirm(const Cx86cpuid *p)
{
unsigned i;
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
{
const UInt32 *v = kVendors[i];
if (v[0] == p->vendor[0] &&
v[1] == p->vendor[1] &&
v[2] == p->vendor[2])
return (int)i;
}
return -1;
}
Bool CPU_Is_InOrder()
{
Cx86cpuid p;
int firm;
UInt32 family, model;
if (!x86cpuid_CheckAndRead(&p))
return True;
family = x86cpuid_GetFamily(&p);
model = x86cpuid_GetModel(&p);
firm = x86cpuid_GetFirm(&p);
switch (firm)
{
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
}
return True;
}
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
static Bool CPU_Sys_Is_SSE_Supported()
{
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (!GetVersionEx(&vi))
return False;
return (vi.dwMajorVersion >= 5);
}
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
#else
#define CHECK_SYS_SSE_SUPPORT
#endif
Bool CPU_Is_Aes_Supported()
{
Cx86cpuid p;
CHECK_SYS_SSE_SUPPORT
if (!x86cpuid_CheckAndRead(&p))
return False;
return (p.c >> 25) & 1;
}
#endif

View File

@ -0,0 +1,155 @@
/* CpuArch.h -- CPU specific code
2010-10-26: Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H
#define __CPU_ARCH_H
#include "Types.h"
EXTERN_C_BEGIN
/*
MY_CPU_LE means that CPU is LITTLE ENDIAN.
If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
*/
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
#define MY_CPU_AMD64
#endif
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
#define MY_CPU_64BIT
#endif
#if defined(_M_IX86) || defined(__i386__)
#define MY_CPU_X86
#endif
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
#define MY_CPU_X86_OR_AMD64
#endif
#if defined(MY_CPU_X86) || defined(_M_ARM)
#define MY_CPU_32BIT
#endif
#if defined(_WIN32) && defined(_M_ARM)
#define MY_CPU_ARM_LE
#endif
#if defined(_WIN32) && defined(_M_IA64)
#define MY_CPU_IA64_LE
#endif
#if defined(MY_CPU_X86_OR_AMD64)
#define MY_CPU_LE_UNALIGN
#endif
#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
#define MY_CPU_LE
#endif
#if defined(__BIG_ENDIAN__)
#define MY_CPU_BE
#endif
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
Stop_Compiling_Bad_Endian
#endif
#ifdef MY_CPU_LE_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(p))
#define GetUi32(p) (*(const UInt32 *)(p))
#define GetUi64(p) (*(const UInt64 *)(p))
#define SetUi16(p, d) *(UInt16 *)(p) = (d);
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
#define SetUi64(p, d) *(UInt64 *)(p) = (d);
#else
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
#define GetUi32(p) ( \
((const Byte *)(p))[0] | \
((UInt32)((const Byte *)(p))[1] << 8) | \
((UInt32)((const Byte *)(p))[2] << 16) | \
((UInt32)((const Byte *)(p))[3] << 24))
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
#define SetUi16(p, d) { UInt32 _x_ = (d); \
((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
#define SetUi32(p, d) { UInt32 _x_ = (d); \
((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
SetUi32(p, (UInt32)_x64_); \
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
#endif
#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
#pragma intrinsic(_byteswap_ulong)
#pragma intrinsic(_byteswap_uint64)
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
#else
#define GetBe32(p) ( \
((UInt32)((const Byte *)(p))[0] << 24) | \
((UInt32)((const Byte *)(p))[1] << 16) | \
((UInt32)((const Byte *)(p))[2] << 8) | \
((const Byte *)(p))[3] )
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
#endif
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
#ifdef MY_CPU_X86_OR_AMD64
typedef struct
{
UInt32 maxFunc;
UInt32 vendor[3];
UInt32 ver;
UInt32 b;
UInt32 c;
UInt32 d;
} Cx86cpuid;
enum
{
CPU_FIRM_INTEL,
CPU_FIRM_AMD,
CPU_FIRM_VIA
};
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
Bool CPU_Is_InOrder();
Bool CPU_Is_Aes_Supported();
#endif
EXTERN_C_END
#endif

View File

@ -0,0 +1,62 @@
/* Delta.c -- Delta converter
2009-05-26 : Igor Pavlov : Public domain */
#include "Delta.h"
void Delta_Init(Byte *state)
{
unsigned i;
for (i = 0; i < DELTA_STATE_SIZE; i++)
state[i] = 0;
}
static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)
{
unsigned i;
for (i = 0; i < size; i++)
dest[i] = src[i];
}
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
{
Byte buf[DELTA_STATE_SIZE];
unsigned j = 0;
MyMemCpy(buf, state, delta);
{
SizeT i;
for (i = 0; i < size;)
{
for (j = 0; j < delta && i < size; i++, j++)
{
Byte b = data[i];
data[i] = (Byte)(b - buf[j]);
buf[j] = b;
}
}
}
if (j == delta)
j = 0;
MyMemCpy(state, buf + j, delta - j);
MyMemCpy(state + delta - j, buf, j);
}
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
{
Byte buf[DELTA_STATE_SIZE];
unsigned j = 0;
MyMemCpy(buf, state, delta);
{
SizeT i;
for (i = 0; i < size;)
{
for (j = 0; j < delta && i < size; i++, j++)
{
buf[j] = data[i] = (Byte)(buf[j] + data[i]);
}
}
}
if (j == delta)
j = 0;
MyMemCpy(state, buf + j, delta - j);
MyMemCpy(state + delta - j, buf, j);
}

View File

@ -0,0 +1,23 @@
/* Delta.h -- Delta converter
2009-04-15 : Igor Pavlov : Public domain */
#ifndef __DELTA_H
#define __DELTA_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DELTA_STATE_SIZE 256
void Delta_Init(Byte *state);
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,761 @@
/* LzFind.c -- Match finder for LZ algorithms
2009-04-22 : Igor Pavlov : Public domain */
#include <string.h>
#include "LzFind.h"
#include "LzHash.h"
#define kEmptyHashValue 0
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
#define kNormalizeMask (~(kNormalizeStepMin - 1))
#define kMaxHistorySize ((UInt32)3 << 30)
#define kStartMaxLen 3
static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
{
if (!p->directInput)
{
alloc->Free(alloc, p->bufferBase);
p->bufferBase = 0;
}
}
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
{
UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
if (p->directInput)
{
p->blockSize = blockSize;
return 1;
}
if (p->bufferBase == 0 || p->blockSize != blockSize)
{
LzInWindow_Free(p, alloc);
p->blockSize = blockSize;
p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
}
return (p->bufferBase != 0);
}
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
{
p->posLimit -= subValue;
p->pos -= subValue;
p->streamPos -= subValue;
}
static void MatchFinder_ReadBlock(CMatchFinder *p)
{
if (p->streamEndWasReached || p->result != SZ_OK)
return;
if (p->directInput)
{
UInt32 curSize = 0xFFFFFFFF - p->streamPos;
if (curSize > p->directInputRem)
curSize = (UInt32)p->directInputRem;
p->directInputRem -= curSize;
p->streamPos += curSize;
if (p->directInputRem == 0)
p->streamEndWasReached = 1;
return;
}
for (;;)
{
Byte *dest = p->buffer + (p->streamPos - p->pos);
size_t size = (p->bufferBase + p->blockSize - dest);
if (size == 0)
return;
p->result = p->stream->Read(p->stream, dest, &size);
if (p->result != SZ_OK)
return;
if (size == 0)
{
p->streamEndWasReached = 1;
return;
}
p->streamPos += (UInt32)size;
if (p->streamPos - p->pos > p->keepSizeAfter)
return;
}
}
void MatchFinder_MoveBlock(CMatchFinder *p)
{
memmove(p->bufferBase,
p->buffer - p->keepSizeBefore,
(size_t)(p->streamPos - p->pos + p->keepSizeBefore));
p->buffer = p->bufferBase + p->keepSizeBefore;
}
int MatchFinder_NeedMove(CMatchFinder *p)
{
if (p->directInput)
return 0;
/* if (p->streamEndWasReached) return 0; */
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
}
void MatchFinder_ReadIfRequired(CMatchFinder *p)
{
if (p->streamEndWasReached)
return;
if (p->keepSizeAfter >= p->streamPos - p->pos)
MatchFinder_ReadBlock(p);
}
static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
{
if (MatchFinder_NeedMove(p))
MatchFinder_MoveBlock(p);
MatchFinder_ReadBlock(p);
}
static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
{
p->cutValue = 32;
p->btMode = 1;
p->numHashBytes = 4;
p->bigHash = 0;
}
#define kCrcPoly 0xEDB88320
void MatchFinder_Construct(CMatchFinder *p)
{
UInt32 i;
p->bufferBase = 0;
p->directInput = 0;
p->hash = 0;
MatchFinder_SetDefaultSettings(p);
for (i = 0; i < 256; i++)
{
UInt32 r = i;
int j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
p->crc[i] = r;
}
}
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->hash);
p->hash = 0;
}
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
{
MatchFinder_FreeThisClassMemory(p, alloc);
LzInWindow_Free(p, alloc);
}
static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
{
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
if (sizeInBytes / sizeof(CLzRef) != num)
return 0;
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
}
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc)
{
UInt32 sizeReserv;
if (historySize > kMaxHistorySize)
{
MatchFinder_Free(p, alloc);
return 0;
}
sizeReserv = historySize >> 1;
if (historySize > ((UInt32)2 << 30))
sizeReserv = historySize >> 2;
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
if (LzInWindow_Create(p, sizeReserv, alloc))
{
UInt32 newCyclicBufferSize = historySize + 1;
UInt32 hs;
p->matchMaxLen = matchMaxLen;
{
p->fixedHashSize = 0;
if (p->numHashBytes == 2)
hs = (1 << 16) - 1;
else
{
hs = historySize - 1;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
hs |= (hs >> 8);
hs >>= 1;
hs |= 0xFFFF; /* don't change it! It's required for Deflate */
if (hs > (1 << 24))
{
if (p->numHashBytes == 3)
hs = (1 << 24) - 1;
else
hs >>= 1;
}
}
p->hashMask = hs;
hs++;
if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
hs += p->fixedHashSize;
}
{
UInt32 prevSize = p->hashSizeSum + p->numSons;
UInt32 newSize;
p->historySize = historySize;
p->hashSizeSum = hs;
p->cyclicBufferSize = newCyclicBufferSize;
p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
newSize = p->hashSizeSum + p->numSons;
if (p->hash != 0 && prevSize == newSize)
return 1;
MatchFinder_FreeThisClassMemory(p, alloc);
p->hash = AllocRefs(newSize, alloc);
if (p->hash != 0)
{
p->son = p->hash + p->hashSizeSum;
return 1;
}
}
}
MatchFinder_Free(p, alloc);
return 0;
}
static void MatchFinder_SetLimits(CMatchFinder *p)
{
UInt32 limit = kMaxValForNormalize - p->pos;
UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
if (limit2 < limit)
limit = limit2;
limit2 = p->streamPos - p->pos;
if (limit2 <= p->keepSizeAfter)
{
if (limit2 > 0)
limit2 = 1;
}
else
limit2 -= p->keepSizeAfter;
if (limit2 < limit)
limit = limit2;
{
UInt32 lenLimit = p->streamPos - p->pos;
if (lenLimit > p->matchMaxLen)
lenLimit = p->matchMaxLen;
p->lenLimit = lenLimit;
}
p->posLimit = p->pos + limit;
}
void MatchFinder_Init(CMatchFinder *p)
{
UInt32 i;
for (i = 0; i < p->hashSizeSum; i++)
p->hash[i] = kEmptyHashValue;
p->cyclicBufferPos = 0;
p->buffer = p->bufferBase;
p->pos = p->streamPos = p->cyclicBufferSize;
p->result = SZ_OK;
p->streamEndWasReached = 0;
MatchFinder_ReadBlock(p);
MatchFinder_SetLimits(p);
}
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
{
return (p->pos - p->historySize - 1) & kNormalizeMask;
}
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
{
UInt32 i;
for (i = 0; i < numItems; i++)
{
UInt32 value = items[i];
if (value <= subValue)
value = kEmptyHashValue;
else
value -= subValue;
items[i] = value;
}
}
static void MatchFinder_Normalize(CMatchFinder *p)
{
UInt32 subValue = MatchFinder_GetSubValue(p);
MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
MatchFinder_ReduceOffsets(p, subValue);
}
static void MatchFinder_CheckLimits(CMatchFinder *p)
{
if (p->pos == kMaxValForNormalize)
MatchFinder_Normalize(p);
if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
MatchFinder_CheckAndMoveAndRead(p);
if (p->cyclicBufferPos == p->cyclicBufferSize)
p->cyclicBufferPos = 0;
MatchFinder_SetLimits(p);
}
static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen)
{
son[_cyclicBufferPos] = curMatch;
for (;;)
{
UInt32 delta = pos - curMatch;
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
return distances;
{
const Byte *pb = cur - delta;
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
{
UInt32 len = 0;
while (++len != lenLimit)
if (pb[len] != cur[len])
break;
if (maxLen < len)
{
*distances++ = maxLen = len;
*distances++ = delta - 1;
if (len == lenLimit)
return distances;
}
}
}
}
}
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen)
{
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
return distances;
}
{
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1);
if (pb[len] == cur[len])
{
if (++len != lenLimit && pb[len] == cur[len])
while (++len != lenLimit)
if (pb[len] != cur[len])
break;
if (maxLen < len)
{
*distances++ = maxLen = len;
*distances++ = delta - 1;
if (len == lenLimit)
{
*ptr1 = pair[0];
*ptr0 = pair[1];
return distances;
}
}
}
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
ptr1 = pair + 1;
curMatch = *ptr1;
len1 = len;
}
else
{
*ptr0 = curMatch;
ptr0 = pair;
curMatch = *ptr0;
len0 = len;
}
}
}
}
static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
{
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
return;
}
{
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1);
if (pb[len] == cur[len])
{
while (++len != lenLimit)
if (pb[len] != cur[len])
break;
{
if (len == lenLimit)
{
*ptr1 = pair[0];
*ptr0 = pair[1];
return;
}
}
}
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
ptr1 = pair + 1;
curMatch = *ptr1;
len1 = len;
}
else
{
*ptr0 = curMatch;
ptr0 = pair;
curMatch = *ptr0;
len0 = len;
}
}
}
}
#define MOVE_POS \
++p->cyclicBufferPos; \
p->buffer++; \
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
#define MOVE_POS_RET MOVE_POS return offset;
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define GET_MATCHES_HEADER2(minLen, ret_op) \
UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
cur = p->buffer;
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
#define GET_MATCHES_FOOTER(offset, maxLen) \
offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
distances + offset, maxLen) - distances); MOVE_POS_RET;
#define SKIP_FOOTER \
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(2)
HASH2_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
offset = 0;
GET_MATCHES_FOOTER(offset, 1)
}
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
offset = 0;
GET_MATCHES_FOOTER(offset, 2)
}
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 hash2Value, delta2, maxLen, offset;
GET_MATCHES_HEADER(3)
HASH3_CALC;
delta2 = p->pos - p->hash[hash2Value];
curMatch = p->hash[kFix3HashSize + hashValue];
p->hash[hash2Value] =
p->hash[kFix3HashSize + hashValue] = p->pos;
maxLen = 2;
offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
{
for (; maxLen != lenLimit; maxLen++)
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[0] = maxLen;
distances[1] = delta2 - 1;
offset = 2;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
GET_MATCHES_FOOTER(offset, maxLen)
}
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
GET_MATCHES_HEADER(4)
HASH4_CALC;
delta2 = p->pos - p->hash[ hash2Value];
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] =
p->hash[kFix3HashSize + hash3Value] =
p->hash[kFix4HashSize + hashValue] = p->pos;
maxLen = 1;
offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
{
distances[0] = maxLen = 2;
distances[1] = delta2 - 1;
offset = 2;
}
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
{
maxLen = 3;
distances[offset + 1] = delta3 - 1;
offset += 2;
delta2 = delta3;
}
if (offset != 0)
{
for (; maxLen != lenLimit; maxLen++)
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[offset - 2] = maxLen;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
if (maxLen < 3)
maxLen = 3;
GET_MATCHES_FOOTER(offset, maxLen)
}
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
GET_MATCHES_HEADER(4)
HASH4_CALC;
delta2 = p->pos - p->hash[ hash2Value];
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] =
p->hash[kFix3HashSize + hash3Value] =
p->hash[kFix4HashSize + hashValue] = p->pos;
maxLen = 1;
offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
{
distances[0] = maxLen = 2;
distances[1] = delta2 - 1;
offset = 2;
}
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
{
maxLen = 3;
distances[offset + 1] = delta3 - 1;
offset += 2;
delta2 = delta3;
}
if (offset != 0)
{
for (; maxLen != lenLimit; maxLen++)
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[offset - 2] = maxLen;
if (maxLen == lenLimit)
{
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS_RET;
}
}
if (maxLen < 3)
maxLen = 3;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances + offset, maxLen) - (distances));
MOVE_POS_RET
}
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances, 2) - (distances));
MOVE_POS_RET
}
static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
SKIP_HEADER(2)
HASH2_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
SKIP_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 hash2Value;
SKIP_HEADER(3)
HASH3_CALC;
curMatch = p->hash[kFix3HashSize + hashValue];
p->hash[hash2Value] =
p->hash[kFix3HashSize + hashValue] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 hash2Value, hash3Value;
SKIP_HEADER(4)
HASH4_CALC;
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] =
p->hash[kFix3HashSize + hash3Value] = p->pos;
p->hash[kFix4HashSize + hashValue] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 hash2Value, hash3Value;
SKIP_HEADER(4)
HASH4_CALC;
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] =
p->hash[kFix3HashSize + hash3Value] =
p->hash[kFix4HashSize + hashValue] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
while (--num != 0);
}
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
SKIP_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
while (--num != 0);
}
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
{
vTable->Init = (Mf_Init_Func)MatchFinder_Init;
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
if (!p->btMode)
{
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
}
else if (p->numHashBytes == 2)
{
vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
}
else if (p->numHashBytes == 3)
{
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
}
else
{
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
}
}

View File

@ -0,0 +1,115 @@
/* LzFind.h -- Match finder for LZ algorithms
2009-04-22 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_H
#define __LZ_FIND_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef UInt32 CLzRef;
typedef struct _CMatchFinder
{
Byte *buffer;
UInt32 pos;
UInt32 posLimit;
UInt32 streamPos;
UInt32 lenLimit;
UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
UInt32 matchMaxLen;
CLzRef *hash;
CLzRef *son;
UInt32 hashMask;
UInt32 cutValue;
Byte *bufferBase;
ISeqInStream *stream;
int streamEndWasReached;
UInt32 blockSize;
UInt32 keepSizeBefore;
UInt32 keepSizeAfter;
UInt32 numHashBytes;
int directInput;
size_t directInputRem;
int btMode;
int bigHash;
UInt32 historySize;
UInt32 fixedHashSize;
UInt32 hashSizeSum;
UInt32 numSons;
SRes result;
UInt32 crc[256];
} CMatchFinder;
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
int MatchFinder_NeedMove(CMatchFinder *p);
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
void MatchFinder_MoveBlock(CMatchFinder *p);
void MatchFinder_ReadIfRequired(CMatchFinder *p);
void MatchFinder_Construct(CMatchFinder *p);
/* Conditions:
historySize <= 3 GB
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
*/
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc);
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *distances, UInt32 maxLen);
/*
Conditions:
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
*/
typedef void (*Mf_Init_Func)(void *object);
typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
typedef void (*Mf_Skip_Func)(void *object, UInt32);
typedef struct _IMatchFinder
{
Mf_Init_Func Init;
Mf_GetIndexByte_Func GetIndexByte;
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
Mf_GetMatches_Func GetMatches;
Mf_Skip_Func Skip;
} IMatchFinder;
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
void MatchFinder_Init(CMatchFinder *p);
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,793 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2009-09-20 : Igor Pavlov : Public domain */
#include "LzHash.h"
#include "LzFindMt.h"
void MtSync_Construct(CMtSync *p)
{
p->wasCreated = False;
p->csWasInitialized = False;
p->csWasEntered = False;
Thread_Construct(&p->thread);
Event_Construct(&p->canStart);
Event_Construct(&p->wasStarted);
Event_Construct(&p->wasStopped);
Semaphore_Construct(&p->freeSemaphore);
Semaphore_Construct(&p->filledSemaphore);
}
void MtSync_GetNextBlock(CMtSync *p)
{
if (p->needStart)
{
p->numProcessedBlocks = 1;
p->needStart = False;
p->stopWriting = False;
p->exit = False;
Event_Reset(&p->wasStarted);
Event_Reset(&p->wasStopped);
Event_Set(&p->canStart);
Event_Wait(&p->wasStarted);
}
else
{
CriticalSection_Leave(&p->cs);
p->csWasEntered = False;
p->numProcessedBlocks++;
Semaphore_Release1(&p->freeSemaphore);
}
Semaphore_Wait(&p->filledSemaphore);
CriticalSection_Enter(&p->cs);
p->csWasEntered = True;
}
/* MtSync_StopWriting must be called if Writing was started */
void MtSync_StopWriting(CMtSync *p)
{
UInt32 myNumBlocks = p->numProcessedBlocks;
if (!Thread_WasCreated(&p->thread) || p->needStart)
return;
p->stopWriting = True;
if (p->csWasEntered)
{
CriticalSection_Leave(&p->cs);
p->csWasEntered = False;
}
Semaphore_Release1(&p->freeSemaphore);
Event_Wait(&p->wasStopped);
while (myNumBlocks++ != p->numProcessedBlocks)
{
Semaphore_Wait(&p->filledSemaphore);
Semaphore_Release1(&p->freeSemaphore);
}
p->needStart = True;
}
void MtSync_Destruct(CMtSync *p)
{
if (Thread_WasCreated(&p->thread))
{
MtSync_StopWriting(p);
p->exit = True;
if (p->needStart)
Event_Set(&p->canStart);
Thread_Wait(&p->thread);
Thread_Close(&p->thread);
}
if (p->csWasInitialized)
{
CriticalSection_Delete(&p->cs);
p->csWasInitialized = False;
}
Event_Close(&p->canStart);
Event_Close(&p->wasStarted);
Event_Close(&p->wasStopped);
Semaphore_Close(&p->freeSemaphore);
Semaphore_Close(&p->filledSemaphore);
p->wasCreated = False;
}
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
{
if (p->wasCreated)
return SZ_OK;
RINOK_THREAD(CriticalSection_Init(&p->cs));
p->csWasInitialized = True;
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart));
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
p->needStart = True;
RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj));
p->wasCreated = True;
return SZ_OK;
}
static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
{
SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
if (res != SZ_OK)
MtSync_Destruct(p);
return res;
}
void MtSync_Init(CMtSync *p) { p->needStart = True; }
#define kMtMaxValForNormalize 0xFFFFFFFF
#define DEF_GetHeads2(name, v, action) \
static void GetHeads ## name(const Byte *p, UInt32 pos, \
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \
{ action; for (; numHeads != 0; numHeads--) { \
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)
DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; )
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
void HashThreadFunc(CMatchFinderMt *mt)
{
CMtSync *p = &mt->hashSync;
for (;;)
{
UInt32 numProcessedBlocks = 0;
Event_Wait(&p->canStart);
Event_Set(&p->wasStarted);
for (;;)
{
if (p->exit)
return;
if (p->stopWriting)
{
p->numProcessedBlocks = numProcessedBlocks;
Event_Set(&p->wasStopped);
break;
}
{
CMatchFinder *mf = mt->MatchFinder;
if (MatchFinder_NeedMove(mf))
{
CriticalSection_Enter(&mt->btSync.cs);
CriticalSection_Enter(&mt->hashSync.cs);
{
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
const Byte *afterPtr;
MatchFinder_MoveBlock(mf);
afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
mt->pointerToCurPos -= beforePtr - afterPtr;
mt->buffer -= beforePtr - afterPtr;
}
CriticalSection_Leave(&mt->btSync.cs);
CriticalSection_Leave(&mt->hashSync.cs);
continue;
}
Semaphore_Wait(&p->freeSemaphore);
MatchFinder_ReadIfRequired(mf);
if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))
{
UInt32 subValue = (mf->pos - mf->historySize - 1);
MatchFinder_ReduceOffsets(mf, subValue);
MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
}
{
UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
UInt32 num = mf->streamPos - mf->pos;
heads[0] = 2;
heads[1] = num;
if (num >= mf->numHashBytes)
{
num = num - mf->numHashBytes + 1;
if (num > kMtHashBlockSize - 2)
num = kMtHashBlockSize - 2;
mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);
heads[0] += num;
}
mf->pos += num;
mf->buffer += num;
}
}
Semaphore_Release1(&p->filledSemaphore);
}
}
}
void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
{
MtSync_GetNextBlock(&p->hashSync);
p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];
p->hashNumAvail = p->hashBuf[p->hashBufPos++];
}
#define kEmptyHashValue 0
/* #define MFMT_GM_INLINE */
#ifdef MFMT_GM_INLINE
#define NO_INLINE MY_FAST_CALL
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
{
do
{
UInt32 *distances = _distances + 1;
UInt32 curMatch = pos - *hash++;
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0;
UInt32 cutValue = _cutValue;
UInt32 maxLen = _maxLen;
for (;;)
{
UInt32 delta = pos - curMatch;
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
break;
}
{
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1);
if (pb[len] == cur[len])
{
if (++len != lenLimit && pb[len] == cur[len])
while (++len != lenLimit)
if (pb[len] != cur[len])
break;
if (maxLen < len)
{
*distances++ = maxLen = len;
*distances++ = delta - 1;
if (len == lenLimit)
{
*ptr1 = pair[0];
*ptr0 = pair[1];
break;
}
}
}
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
ptr1 = pair + 1;
curMatch = *ptr1;
len1 = len;
}
else
{
*ptr0 = curMatch;
ptr0 = pair;
curMatch = *ptr0;
len0 = len;
}
}
}
pos++;
_cyclicBufferPos++;
cur++;
{
UInt32 num = (UInt32)(distances - _distances);
*_distances = num - 1;
_distances += num;
limit -= num;
}
}
while (limit > 0 && --size != 0);
*posRes = pos;
return limit;
}
#endif
void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
{
UInt32 numProcessed = 0;
UInt32 curPos = 2;
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
distances[1] = p->hashNumAvail;
while (curPos < limit)
{
if (p->hashBufPos == p->hashBufPosLimit)
{
MatchFinderMt_GetNextBlock_Hash(p);
distances[1] = numProcessed + p->hashNumAvail;
if (p->hashNumAvail >= p->numHashBytes)
continue;
for (; p->hashNumAvail != 0; p->hashNumAvail--)
distances[curPos++] = 0;
break;
}
{
UInt32 size = p->hashBufPosLimit - p->hashBufPos;
UInt32 lenLimit = p->matchMaxLen;
UInt32 pos = p->pos;
UInt32 cyclicBufferPos = p->cyclicBufferPos;
if (lenLimit >= p->hashNumAvail)
lenLimit = p->hashNumAvail;
{
UInt32 size2 = p->hashNumAvail - lenLimit + 1;
if (size2 < size)
size = size2;
size2 = p->cyclicBufferSize - cyclicBufferPos;
if (size2 < size)
size = size2;
}
#ifndef MFMT_GM_INLINE
while (curPos < limit && size-- != 0)
{
UInt32 *startDistances = distances + curPos;
UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
startDistances + 1, p->numHashBytes - 1) - startDistances);
*startDistances = num - 1;
curPos += num;
cyclicBufferPos++;
pos++;
p->buffer++;
}
#else
{
UInt32 posRes;
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
p->hashBufPos += posRes - pos;
cyclicBufferPos += posRes - pos;
p->buffer += posRes - pos;
pos = posRes;
}
#endif
numProcessed += pos - p->pos;
p->hashNumAvail -= pos - p->pos;
p->pos = pos;
if (cyclicBufferPos == p->cyclicBufferSize)
cyclicBufferPos = 0;
p->cyclicBufferPos = cyclicBufferPos;
}
}
distances[0] = curPos;
}
void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
{
CMtSync *sync = &p->hashSync;
if (!sync->needStart)
{
CriticalSection_Enter(&sync->cs);
sync->csWasEntered = True;
}
BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);
if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
{
UInt32 subValue = p->pos - p->cyclicBufferSize;
MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
p->pos -= subValue;
}
if (!sync->needStart)
{
CriticalSection_Leave(&sync->cs);
sync->csWasEntered = False;
}
}
void BtThreadFunc(CMatchFinderMt *mt)
{
CMtSync *p = &mt->btSync;
for (;;)
{
UInt32 blockIndex = 0;
Event_Wait(&p->canStart);
Event_Set(&p->wasStarted);
for (;;)
{
if (p->exit)
return;
if (p->stopWriting)
{
p->numProcessedBlocks = blockIndex;
MtSync_StopWriting(&mt->hashSync);
Event_Set(&p->wasStopped);
break;
}
Semaphore_Wait(&p->freeSemaphore);
BtFillBlock(mt, blockIndex++);
Semaphore_Release1(&p->filledSemaphore);
}
}
}
void MatchFinderMt_Construct(CMatchFinderMt *p)
{
p->hashBuf = 0;
MtSync_Construct(&p->hashSync);
MtSync_Construct(&p->btSync);
}
void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->hashBuf);
p->hashBuf = 0;
}
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
{
MtSync_Destruct(&p->hashSync);
MtSync_Destruct(&p->btSync);
MatchFinderMt_FreeMem(p, alloc);
}
#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
static unsigned MY_STD_CALL BtThreadFunc2(void *p)
{
Byte allocaDummy[0x180];
int i = 0;
for (i = 0; i < 16; i++)
allocaDummy[i] = (Byte)i;
BtThreadFunc((CMatchFinderMt *)p);
return 0;
}
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
{
CMatchFinder *mf = p->MatchFinder;
p->historySize = historySize;
if (kMtBtBlockSize <= matchMaxLen * 4)
return SZ_ERROR_PARAM;
if (p->hashBuf == 0)
{
p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
if (p->hashBuf == 0)
return SZ_ERROR_MEM;
p->btBuf = p->hashBuf + kHashBufferSize;
}
keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
keepAddBufferAfter += kMtHashBlockSize;
if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
return SZ_ERROR_MEM;
RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
return SZ_OK;
}
/* Call it after ReleaseStream / SetStream */
void MatchFinderMt_Init(CMatchFinderMt *p)
{
CMatchFinder *mf = p->MatchFinder;
p->btBufPos = p->btBufPosLimit = 0;
p->hashBufPos = p->hashBufPosLimit = 0;
MatchFinder_Init(mf);
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
p->btNumAvailBytes = 0;
p->lzPos = p->historySize + 1;
p->hash = mf->hash;
p->fixedHashSize = mf->fixedHashSize;
p->crc = mf->crc;
p->son = mf->son;
p->matchMaxLen = mf->matchMaxLen;
p->numHashBytes = mf->numHashBytes;
p->pos = mf->pos;
p->buffer = mf->buffer;
p->cyclicBufferPos = mf->cyclicBufferPos;
p->cyclicBufferSize = mf->cyclicBufferSize;
p->cutValue = mf->cutValue;
}
/* ReleaseStream is required to finish multithreading */
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
{
MtSync_StopWriting(&p->btSync);
/* p->MatchFinder->ReleaseStream(); */
}
void MatchFinderMt_Normalize(CMatchFinderMt *p)
{
MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
p->lzPos = p->historySize + 1;
}
void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
{
UInt32 blockIndex;
MtSync_GetNextBlock(&p->btSync);
blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);
p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
p->btBufPosLimit += p->btBuf[p->btBufPos++];
p->btNumAvailBytes = p->btBuf[p->btBufPos++];
if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
MatchFinderMt_Normalize(p);
}
const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
{
return p->pointerToCurPos;
}
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
{
GET_NEXT_BLOCK_IF_REQUIRED;
return p->btNumAvailBytes;
}
Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
{
return p->pointerToCurPos[index];
}
UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{
UInt32 hash2Value, curMatch2;
UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos;
MT_HASH2_CALC
curMatch2 = hash[hash2Value];
hash[hash2Value] = lzPos;
if (curMatch2 >= matchMinPos)
if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{
*distances++ = 2;
*distances++ = lzPos - curMatch2 - 1;
}
return distances;
}
UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{
UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos;
MT_HASH3_CALC
curMatch2 = hash[ hash2Value];
curMatch3 = hash[kFix3HashSize + hash3Value];
hash[ hash2Value] =
hash[kFix3HashSize + hash3Value] =
lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{
distances[1] = lzPos - curMatch2 - 1;
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
{
distances[0] = 3;
return distances + 2;
}
distances[0] = 2;
distances += 2;
}
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
{
*distances++ = 3;
*distances++ = lzPos - curMatch3 - 1;
}
return distances;
}
/*
UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
{
UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
UInt32 *hash = p->hash;
const Byte *cur = p->pointerToCurPos;
UInt32 lzPos = p->lzPos;
MT_HASH4_CALC
curMatch2 = hash[ hash2Value];
curMatch3 = hash[kFix3HashSize + hash3Value];
curMatch4 = hash[kFix4HashSize + hash4Value];
hash[ hash2Value] =
hash[kFix3HashSize + hash3Value] =
hash[kFix4HashSize + hash4Value] =
lzPos;
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
{
distances[1] = lzPos - curMatch2 - 1;
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
{
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
return distances + 2;
}
distances[0] = 2;
distances += 2;
}
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
{
distances[1] = lzPos - curMatch3 - 1;
if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
{
distances[0] = 4;
return distances + 2;
}
distances[0] = 3;
distances += 2;
}
if (curMatch4 >= matchMinPos)
if (
cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
)
{
*distances++ = 4;
*distances++ = lzPos - curMatch4 - 1;
}
return distances;
}
*/
#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
{
const UInt32 *btBuf = p->btBuf + p->btBufPos;
UInt32 len = *btBuf++;
p->btBufPos += 1 + len;
p->btNumAvailBytes--;
{
UInt32 i;
for (i = 0; i < len; i += 2)
{
*distances++ = *btBuf++;
*distances++ = *btBuf++;
}
}
INCREASE_LZ_POS
return len;
}
UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
{
const UInt32 *btBuf = p->btBuf + p->btBufPos;
UInt32 len = *btBuf++;
p->btBufPos += 1 + len;
if (len == 0)
{
if (p->btNumAvailBytes-- >= 4)
len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
}
else
{
/* Condition: there are matches in btBuf with length < p->numHashBytes */
UInt32 *distances2;
p->btNumAvailBytes--;
distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
do
{
*distances2++ = *btBuf++;
*distances2++ = *btBuf++;
}
while ((len -= 2) != 0);
len = (UInt32)(distances2 - (distances));
}
INCREASE_LZ_POS
return len;
}
#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED
#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0);
void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
{
SKIP_HEADER2_MT { p->btNumAvailBytes--;
SKIP_FOOTER_MT
}
void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
{
SKIP_HEADER_MT(2)
UInt32 hash2Value;
MT_HASH2_CALC
hash[hash2Value] = p->lzPos;
SKIP_FOOTER_MT
}
void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
{
SKIP_HEADER_MT(3)
UInt32 hash2Value, hash3Value;
MT_HASH3_CALC
hash[kFix3HashSize + hash3Value] =
hash[ hash2Value] =
p->lzPos;
SKIP_FOOTER_MT
}
/*
void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
{
SKIP_HEADER_MT(4)
UInt32 hash2Value, hash3Value, hash4Value;
MT_HASH4_CALC
hash[kFix4HashSize + hash4Value] =
hash[kFix3HashSize + hash3Value] =
hash[ hash2Value] =
p->lzPos;
SKIP_FOOTER_MT
}
*/
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
{
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
switch(p->MatchFinder->numHashBytes)
{
case 2:
p->GetHeadsFunc = GetHeads2;
p->MixMatchesFunc = (Mf_Mix_Matches)0;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
break;
case 3:
p->GetHeadsFunc = GetHeads3;
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;
break;
default:
/* case 4: */
p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
/* p->GetHeadsFunc = GetHeads4; */
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
break;
/*
default:
p->GetHeadsFunc = GetHeads5;
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;
break;
*/
}
}

View File

@ -0,0 +1,105 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_MT_H
#define __LZ_FIND_MT_H
#include "LzFind.h"
#include "Threads.h"
#ifdef __cplusplus
extern "C" {
#endif
#define kMtHashBlockSize (1 << 13)
#define kMtHashNumBlocks (1 << 3)
#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)
#define kMtBtBlockSize (1 << 14)
#define kMtBtNumBlocks (1 << 6)
#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)
typedef struct _CMtSync
{
Bool wasCreated;
Bool needStart;
Bool exit;
Bool stopWriting;
CThread thread;
CAutoResetEvent canStart;
CAutoResetEvent wasStarted;
CAutoResetEvent wasStopped;
CSemaphore freeSemaphore;
CSemaphore filledSemaphore;
Bool csWasInitialized;
Bool csWasEntered;
CCriticalSection cs;
UInt32 numProcessedBlocks;
} CMtSync;
typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
#define kMtCacheLineDummy 128
typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
typedef struct _CMatchFinderMt
{
/* LZ */
const Byte *pointerToCurPos;
UInt32 *btBuf;
UInt32 btBufPos;
UInt32 btBufPosLimit;
UInt32 lzPos;
UInt32 btNumAvailBytes;
UInt32 *hash;
UInt32 fixedHashSize;
UInt32 historySize;
const UInt32 *crc;
Mf_Mix_Matches MixMatchesFunc;
/* LZ + BT */
CMtSync btSync;
Byte btDummy[kMtCacheLineDummy];
/* BT */
UInt32 *hashBuf;
UInt32 hashBufPos;
UInt32 hashBufPosLimit;
UInt32 hashNumAvail;
CLzRef *son;
UInt32 matchMaxLen;
UInt32 numHashBytes;
UInt32 pos;
Byte *buffer;
UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
UInt32 cutValue;
/* BT + Hash */
CMtSync hashSync;
/* Byte hashDummy[kMtCacheLineDummy]; */
/* Hash */
Mf_GetHeads GetHeadsFunc;
CMatchFinder *MatchFinder;
} CMatchFinderMt;
void MatchFinderMt_Construct(CMatchFinderMt *p);
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,54 @@
/* LzHash.h -- HASH functions for LZ algorithms
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZ_HASH_H
#define __LZ_HASH_H
#define kHash2Size (1 << 10)
#define kHash3Size (1 << 16)
#define kHash4Size (1 << 20)
#define kFix3HashSize (kHash2Size)
#define kFix4HashSize (kHash2Size + kHash3Size)
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
#define HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
#define HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
#define HASH5_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
hash4Value &= (kHash4Size - 1); }
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
#define MT_HASH2_CALC \
hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
#define MT_HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
#define MT_HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
#endif

View File

@ -0,0 +1,371 @@
/* Lzma2Dec.c -- LZMA2 Decoder
2009-05-03 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */
#ifdef SHOW_DEBUG_INFO
#include <stdio.h>
#endif
#include <string.h>
#include "Lzma2Dec.h"
/*
00000000 - EOS
00000001 U U - Uncompressed Reset Dic
00000010 U U - Uncompressed No Reset
100uuuuu U U P P - LZMA no reset
101uuuuu U U P P - LZMA reset state
110uuuuu U U P P S - LZMA reset state + new prop
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
u, U - Unpack Size
P - Pack Size
S - Props
*/
#define LZMA2_CONTROL_LZMA (1 << 7)
#define LZMA2_CONTROL_COPY_NO_RESET 2
#define LZMA2_CONTROL_COPY_RESET_DIC 1
#define LZMA2_CONTROL_EOF 0
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
#define LZMA2_LCLP_MAX 4
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
#ifdef SHOW_DEBUG_INFO
#define PRF(x) x
#else
#define PRF(x)
#endif
typedef enum
{
LZMA2_STATE_CONTROL,
LZMA2_STATE_UNPACK0,
LZMA2_STATE_UNPACK1,
LZMA2_STATE_PACK0,
LZMA2_STATE_PACK1,
LZMA2_STATE_PROP,
LZMA2_STATE_DATA,
LZMA2_STATE_DATA_CONT,
LZMA2_STATE_FINISHED,
LZMA2_STATE_ERROR
} ELzma2State;
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
{
UInt32 dicSize;
if (prop > 40)
return SZ_ERROR_UNSUPPORTED;
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
props[0] = (Byte)LZMA2_LCLP_MAX;
props[1] = (Byte)(dicSize);
props[2] = (Byte)(dicSize >> 8);
props[3] = (Byte)(dicSize >> 16);
props[4] = (Byte)(dicSize >> 24);
return SZ_OK;
}
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
{
Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props));
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
}
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
{
Byte props[LZMA_PROPS_SIZE];
RINOK(Lzma2Dec_GetOldProps(prop, props));
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
}
void Lzma2Dec_Init(CLzma2Dec *p)
{
p->state = LZMA2_STATE_CONTROL;
p->needInitDic = True;
p->needInitState = True;
p->needInitProp = True;
LzmaDec_Init(&p->decoder);
}
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
{
switch(p->state)
{
case LZMA2_STATE_CONTROL:
p->control = b;
PRF(printf("\n %4X ", p->decoder.dicPos));
PRF(printf(" %2X", b));
if (p->control == 0)
return LZMA2_STATE_FINISHED;
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if ((p->control & 0x7F) > 2)
return LZMA2_STATE_ERROR;
p->unpackSize = 0;
}
else
p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
return LZMA2_STATE_UNPACK0;
case LZMA2_STATE_UNPACK0:
p->unpackSize |= (UInt32)b << 8;
return LZMA2_STATE_UNPACK1;
case LZMA2_STATE_UNPACK1:
p->unpackSize |= (UInt32)b;
p->unpackSize++;
PRF(printf(" %8d", p->unpackSize));
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
case LZMA2_STATE_PACK0:
p->packSize = (UInt32)b << 8;
return LZMA2_STATE_PACK1;
case LZMA2_STATE_PACK1:
p->packSize |= (UInt32)b;
p->packSize++;
PRF(printf(" %8d", p->packSize));
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
case LZMA2_STATE_PROP:
{
int lc, lp;
if (b >= (9 * 5 * 5))
return LZMA2_STATE_ERROR;
lc = b % 9;
b /= 9;
p->decoder.prop.pb = b / 5;
lp = b % 5;
if (lc + lp > LZMA2_LCLP_MAX)
return LZMA2_STATE_ERROR;
p->decoder.prop.lc = lc;
p->decoder.prop.lp = lp;
p->needInitProp = False;
return LZMA2_STATE_DATA;
}
}
return LZMA2_STATE_ERROR;
}
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
{
memcpy(p->dic + p->dicPos, src, size);
p->dicPos += size;
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
p->checkDicSize = p->prop.dicSize;
p->processedPos += (UInt32)size;
}
static
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
{
p->needFlush = 1;
p->remainLen = 0;
p->tempBufSize = 0;
if (initDic)
{
p->processedPos = 0;
p->checkDicSize = 0;
p->needInitState = 1;
}
if (initState)
p->needInitState = 1;
}
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT inSize = *srcLen;
*srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED;
while (p->state != LZMA2_STATE_FINISHED)
{
SizeT dicPos = p->decoder.dicPos;
if (p->state == LZMA2_STATE_ERROR)
return SZ_ERROR_DATA;
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
{
*status = LZMA_STATUS_NOT_FINISHED;
return SZ_OK;
}
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
{
if (*srcLen == inSize)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
(*srcLen)++;
p->state = Lzma2Dec_UpdateState(p, *src++);
continue;
}
{
SizeT destSizeCur = dicLimit - dicPos;
SizeT srcSizeCur = inSize - *srcLen;
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
if (p->unpackSize <= destSizeCur)
{
destSizeCur = (SizeT)p->unpackSize;
curFinishMode = LZMA_FINISH_END;
}
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
{
if (*srcLen == inSize)
{
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
if (p->state == LZMA2_STATE_DATA)
{
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
if (initDic)
p->needInitProp = p->needInitState = True;
else if (p->needInitDic)
return SZ_ERROR_DATA;
p->needInitDic = False;
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
}
if (srcSizeCur > destSizeCur)
srcSizeCur = destSizeCur;
if (srcSizeCur == 0)
return SZ_ERROR_DATA;
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
src += srcSizeCur;
*srcLen += srcSizeCur;
p->unpackSize -= (UInt32)srcSizeCur;
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
}
else
{
SizeT outSizeProcessed;
SRes res;
if (p->state == LZMA2_STATE_DATA)
{
int mode = LZMA2_GET_LZMA_MODE(p);
Bool initDic = (mode == 3);
Bool initState = (mode > 0);
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
return SZ_ERROR_DATA;
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
p->needInitDic = False;
p->needInitState = False;
p->state = LZMA2_STATE_DATA_CONT;
}
if (srcSizeCur > p->packSize)
srcSizeCur = (SizeT)p->packSize;
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
src += srcSizeCur;
*srcLen += srcSizeCur;
p->packSize -= (UInt32)srcSizeCur;
outSizeProcessed = p->decoder.dicPos - dicPos;
p->unpackSize -= (UInt32)outSizeProcessed;
RINOK(res);
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
return res;
if (srcSizeCur == 0 && outSizeProcessed == 0)
{
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
p->unpackSize != 0 || p->packSize != 0)
return SZ_ERROR_DATA;
p->state = LZMA2_STATE_CONTROL;
}
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
*status = LZMA_STATUS_NOT_FINISHED;
}
}
}
*status = LZMA_STATUS_FINISHED_WITH_MARK;
return SZ_OK;
}
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
SizeT outSize = *destLen, inSize = *srcLen;
*srcLen = *destLen = 0;
for (;;)
{
SizeT srcSizeCur = inSize, outSizeCur, dicPos;
ELzmaFinishMode curFinishMode;
SRes res;
if (p->decoder.dicPos == p->decoder.dicBufSize)
p->decoder.dicPos = 0;
dicPos = p->decoder.dicPos;
if (outSize > p->decoder.dicBufSize - dicPos)
{
outSizeCur = p->decoder.dicBufSize;
curFinishMode = LZMA_FINISH_ANY;
}
else
{
outSizeCur = dicPos + outSize;
curFinishMode = finishMode;
}
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
src += srcSizeCur;
inSize -= srcSizeCur;
*srcLen += srcSizeCur;
outSizeCur = p->decoder.dicPos - dicPos;
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
dest += outSizeCur;
outSize -= outSizeCur;
*destLen += outSizeCur;
if (res != 0)
return res;
if (outSizeCur == 0 || outSize == 0)
return SZ_OK;
}
}
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
{
CLzma2Dec decoder;
SRes res;
SizeT outSize = *destLen, inSize = *srcLen;
Byte props[LZMA_PROPS_SIZE];
Lzma2Dec_Construct(&decoder);
*destLen = *srcLen = 0;
*status = LZMA_STATUS_NOT_SPECIFIED;
decoder.decoder.dic = dest;
decoder.decoder.dicBufSize = outSize;
RINOK(Lzma2Dec_GetOldProps(prop, props));
RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
*srcLen = inSize;
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
*destLen = decoder.decoder.dicPos;
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
res = SZ_ERROR_INPUT_EOF;
LzmaDec_FreeProbs(&decoder.decoder, alloc);
return res;
}

View File

@ -0,0 +1,84 @@
/* Lzma2Dec.h -- LZMA2 Decoder
2009-05-03 : Igor Pavlov : Public domain */
#ifndef __LZMA2_DEC_H
#define __LZMA2_DEC_H
#include "LzmaDec.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ---------- State Interface ---------- */
typedef struct
{
CLzmaDec decoder;
UInt32 packSize;
UInt32 unpackSize;
int state;
Byte control;
Bool needInitDic;
Bool needInitState;
Bool needInitProp;
} CLzma2Dec;
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
void Lzma2Dec_Init(CLzma2Dec *p);
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT
SZ_ERROR_DATA - Data error
*/
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- One Call Interface ---------- */
/*
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - use smallest number of input bytes
LZMA_FINISH_END - read EndOfStream marker after decoding
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,477 @@
/* Lzma2Enc.c -- LZMA2 Encoder
2010-09-24 : Igor Pavlov : Public domain */
/* #include <stdio.h> */
#include <string.h>
/* #define _7ZIP_ST */
#include "Lzma2Enc.h"
#ifndef _7ZIP_ST
#include "MtCoder.h"
#else
#define NUM_MT_CODER_THREADS_MAX 1
#endif
#define LZMA2_CONTROL_LZMA (1 << 7)
#define LZMA2_CONTROL_COPY_NO_RESET 2
#define LZMA2_CONTROL_COPY_RESET_DIC 1
#define LZMA2_CONTROL_EOF 0
#define LZMA2_LCLP_MAX 4
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
#define LZMA2_PACK_SIZE_MAX (1 << 16)
#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX
#define LZMA2_UNPACK_SIZE_MAX (1 << 21)
#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX
#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)
#define PRF(x) /* x */
/* ---------- CLzma2EncInt ---------- */
typedef struct
{
CLzmaEncHandle enc;
UInt64 srcPos;
Byte props;
Bool needInitState;
Bool needInitProp;
} CLzma2EncInt;
static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)
{
Byte propsEncoded[LZMA_PROPS_SIZE];
SizeT propsSize = LZMA_PROPS_SIZE;
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
p->srcPos = 0;
p->props = propsEncoded[0];
p->needInitState = True;
p->needInitProp = True;
return SZ_OK;
}
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
void LzmaEnc_Finish(CLzmaEncHandle pp);
void LzmaEnc_SaveState(CLzmaEncHandle pp);
void LzmaEnc_RestoreState(CLzmaEncHandle pp);
static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
size_t *packSizeRes, ISeqOutStream *outStream)
{
size_t packSizeLimit = *packSizeRes;
size_t packSize = packSizeLimit;
UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
Bool useCopyBlock;
SRes res;
*packSizeRes = 0;
if (packSize < lzHeaderSize)
return SZ_ERROR_OUTPUT_EOF;
packSize -= lzHeaderSize;
LzmaEnc_SaveState(p->enc);
res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,
outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);
PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize));
if (unpackSize == 0)
return res;
if (res == SZ_OK)
useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));
else
{
if (res != SZ_ERROR_OUTPUT_EOF)
return res;
res = SZ_OK;
useCopyBlock = True;
}
if (useCopyBlock)
{
size_t destPos = 0;
PRF(printf("################# COPY "));
while (unpackSize > 0)
{
UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
if (packSizeLimit - destPos < u + 3)
return SZ_ERROR_OUTPUT_EOF;
outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
outBuf[destPos++] = (Byte)((u - 1) >> 8);
outBuf[destPos++] = (Byte)(u - 1);
memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);
unpackSize -= u;
destPos += u;
p->srcPos += u;
if (outStream)
{
*packSizeRes += destPos;
if (outStream->Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE;
destPos = 0;
}
else
*packSizeRes = destPos;
/* needInitState = True; */
}
LzmaEnc_RestoreState(p->enc);
return SZ_OK;
}
{
size_t destPos = 0;
UInt32 u = unpackSize - 1;
UInt32 pm = (UInt32)(packSize - 1);
unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
PRF(printf(" "));
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));
outBuf[destPos++] = (Byte)(u >> 8);
outBuf[destPos++] = (Byte)u;
outBuf[destPos++] = (Byte)(pm >> 8);
outBuf[destPos++] = (Byte)pm;
if (p->needInitProp)
outBuf[destPos++] = p->props;
p->needInitProp = False;
p->needInitState = False;
destPos += packSize;
p->srcPos += unpackSize;
if (outStream)
if (outStream->Write(outStream, outBuf, destPos) != destPos)
return SZ_ERROR_WRITE;
*packSizeRes = destPos;
return SZ_OK;
}
}
/* ---------- Lzma2 Props ---------- */
void Lzma2EncProps_Init(CLzma2EncProps *p)
{
LzmaEncProps_Init(&p->lzmaProps);
p->numTotalThreads = -1;
p->numBlockThreads = -1;
p->blockSize = 0;
}
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
{
int t1, t1n, t2, t3;
{
CLzmaEncProps lzmaProps = p->lzmaProps;
LzmaEncProps_Normalize(&lzmaProps);
t1n = lzmaProps.numThreads;
}
t1 = p->lzmaProps.numThreads;
t2 = p->numBlockThreads;
t3 = p->numTotalThreads;
if (t2 > NUM_MT_CODER_THREADS_MAX)
t2 = NUM_MT_CODER_THREADS_MAX;
if (t3 <= 0)
{
if (t2 <= 0)
t2 = 1;
t3 = t1n * t2;
}
else if (t2 <= 0)
{
t2 = t3 / t1n;
if (t2 == 0)
{
t1 = 1;
t2 = t3;
}
if (t2 > NUM_MT_CODER_THREADS_MAX)
t2 = NUM_MT_CODER_THREADS_MAX;
}
else if (t1 <= 0)
{
t1 = t3 / t2;
if (t1 == 0)
t1 = 1;
}
else
t3 = t1n * t2;
p->lzmaProps.numThreads = t1;
p->numBlockThreads = t2;
p->numTotalThreads = t3;
LzmaEncProps_Normalize(&p->lzmaProps);
if (p->blockSize == 0)
{
UInt32 dictSize = p->lzmaProps.dictSize;
UInt64 blockSize = (UInt64)dictSize << 2;
const UInt32 kMinSize = (UInt32)1 << 20;
const UInt32 kMaxSize = (UInt32)1 << 28;
if (blockSize < kMinSize) blockSize = kMinSize;
if (blockSize > kMaxSize) blockSize = kMaxSize;
if (blockSize < dictSize) blockSize = dictSize;
p->blockSize = (size_t)blockSize;
}
}
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
}
/* ---------- Lzma2 ---------- */
typedef struct
{
Byte propEncoded;
CLzma2EncProps props;
Byte *outBuf;
ISzAlloc *alloc;
ISzAlloc *allocBig;
CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];
#ifndef _7ZIP_ST
CMtCoder mtCoder;
#endif
} CLzma2Enc;
/* ---------- Lzma2EncThread ---------- */
static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
{
UInt64 packTotal = 0;
SRes res = SZ_OK;
if (mainEncoder->outBuf == 0)
{
mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
if (mainEncoder->outBuf == 0)
return SZ_ERROR_MEM;
}
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
mainEncoder->alloc, mainEncoder->allocBig));
for (;;)
{
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);
if (res != SZ_OK)
break;
packTotal += packSize;
res = Progress(progress, p->srcPos, packTotal);
if (res != SZ_OK)
break;
if (packSize == 0)
break;
}
LzmaEnc_Finish(p->enc);
if (res == SZ_OK)
{
Byte b = 0;
if (outStream->Write(outStream, &b, 1) != 1)
return SZ_ERROR_WRITE;
}
return res;
}
#ifndef _7ZIP_ST
typedef struct
{
IMtCoderCallback funcTable;
CLzma2Enc *lzma2Enc;
} CMtCallbackImp;
static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,
const Byte *src, size_t srcSize, int finished)
{
CMtCallbackImp *imp = (CMtCallbackImp *)pp;
CLzma2Enc *mainEncoder = imp->lzma2Enc;
CLzma2EncInt *p = &mainEncoder->coders[index];
SRes res = SZ_OK;
{
size_t destLim = *destSize;
*destSize = 0;
if (srcSize != 0)
{
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,
mainEncoder->alloc, mainEncoder->allocBig));
while (p->srcPos < srcSize)
{
size_t packSize = destLim - *destSize;
res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);
if (res != SZ_OK)
break;
*destSize += packSize;
if (packSize == 0)
{
res = SZ_ERROR_FAIL;
break;
}
if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)
{
res = SZ_ERROR_PROGRESS;
break;
}
}
LzmaEnc_Finish(p->enc);
if (res != SZ_OK)
return res;
}
if (finished)
{
if (*destSize == destLim)
return SZ_ERROR_OUTPUT_EOF;
dest[(*destSize)++] = 0;
}
}
return res;
}
#endif
/* ---------- Lzma2Enc ---------- */
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
{
CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
if (p == 0)
return NULL;
Lzma2EncProps_Init(&p->props);
Lzma2EncProps_Normalize(&p->props);
p->outBuf = 0;
p->alloc = alloc;
p->allocBig = allocBig;
{
unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
p->coders[i].enc = 0;
}
#ifndef _7ZIP_ST
MtCoder_Construct(&p->mtCoder);
#endif
return p;
}
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
{
CLzma2EncInt *t = &p->coders[i];
if (t->enc)
{
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
t->enc = 0;
}
}
#ifndef _7ZIP_ST
MtCoder_Destruct(&p->mtCoder);
#endif
IAlloc_Free(p->alloc, p->outBuf);
IAlloc_Free(p->alloc, pp);
}
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
CLzmaEncProps lzmaProps = props->lzmaProps;
LzmaEncProps_Normalize(&lzmaProps);
if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
return SZ_ERROR_PARAM;
p->props = *props;
Lzma2EncProps_Normalize(&p->props);
return SZ_OK;
}
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
unsigned i;
UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
for (i = 0; i < 40; i++)
if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
break;
return (Byte)i;
}
SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
{
CLzma2Enc *p = (CLzma2Enc *)pp;
int i;
for (i = 0; i < p->props.numBlockThreads; i++)
{
CLzma2EncInt *t = &p->coders[i];
if (t->enc == NULL)
{
t->enc = LzmaEnc_Create(p->alloc);
if (t->enc == NULL)
return SZ_ERROR_MEM;
}
}
#ifndef _7ZIP_ST
if (p->props.numBlockThreads <= 1)
#endif
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
#ifndef _7ZIP_ST
{
CMtCallbackImp mtCallback;
mtCallback.funcTable.Code = MtCallbackImp_Code;
mtCallback.lzma2Enc = p;
p->mtCoder.progress = progress;
p->mtCoder.inStream = inStream;
p->mtCoder.outStream = outStream;
p->mtCoder.alloc = p->alloc;
p->mtCoder.mtCallback = &mtCallback.funcTable;
p->mtCoder.blockSize = p->props.blockSize;
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
p->mtCoder.numThreads = p->props.numBlockThreads;
return MtCoder_Code(&p->mtCoder);
}
#endif
}

View File

@ -0,0 +1,66 @@
/* Lzma2Enc.h -- LZMA2 Encoder
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMA2_ENC_H
#define __LZMA2_ENC_H
#include "LzmaEnc.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
CLzmaEncProps lzmaProps;
size_t blockSize;
int numBlockThreads;
int numTotalThreads;
} CLzma2EncProps;
void Lzma2EncProps_Init(CLzma2EncProps *p);
void Lzma2EncProps_Normalize(CLzma2EncProps *p);
/* ---------- CLzmaEnc2Handle Interface ---------- */
/* Lzma2Enc_* functions can return the following exit codes:
Returns:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - Write callback error
SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
typedef void * CLzma2EncHandle;
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);
void Lzma2Enc_Destroy(CLzma2EncHandle p);
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
SRes Lzma2Enc_Encode(CLzma2EncHandle p,
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
/* ---------- One Call Interface ---------- */
/* Lzma2Encode
Return code:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
/*
SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
*/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,111 @@
/* Lzma86.h -- LZMA + x86 (BCJ) Filter
2009-08-14 : Igor Pavlov : Public domain */
#ifndef __LZMA86_H
#define __LZMA86_H
#include "Types.h"
EXTERN_C_BEGIN
#define LZMA86_SIZE_OFFSET (1 + 5)
#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8)
/*
It's an example for LZMA + x86 Filter use.
You can use .lzma86 extension, if you write that stream to file.
.lzma86 header adds one additional byte to standard .lzma header.
.lzma86 header (14 bytes):
Offset Size Description
0 1 = 0 - no filter, pure LZMA
= 1 - x86 filter + LZMA
1 1 lc, lp and pb in encoded form
2 4 dictSize (little endian)
6 8 uncompressed size (little endian)
Lzma86_Encode
-------------
level - compression level: 0 <= level <= 9, the default value for "level" is 5.
dictSize - The dictionary size in bytes. The maximum value is
128 MB = (1 << 27) bytes for 32-bit version
1 GB = (1 << 30) bytes for 64-bit version
The default value is 16 MB = (1 << 24) bytes, for level = 5.
It's recommended to use the dictionary that is larger than 4 KB and
that can be calculated as (1 << N) or (3 << N) sizes.
For better compression ratio dictSize must be >= inSize.
filterMode:
SZ_FILTER_NO - no Filter
SZ_FILTER_YES - x86 Filter
SZ_FILTER_AUTO - it tries both alternatives to select best.
Encoder will use 2 or 3 passes:
2 passes when FILTER_NO provides better compression.
3 passes when FILTER_YES provides better compression.
Lzma86Encode allocates Data with MyAlloc functions.
RAM Requirements for compressing:
RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize
filterMode FilterBlockSize
SZ_FILTER_NO 0
SZ_FILTER_YES inSize
SZ_FILTER_AUTO inSize
Return code:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
enum ESzFilterMode
{
SZ_FILTER_NO,
SZ_FILTER_YES,
SZ_FILTER_AUTO
};
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode);
/*
Lzma86_GetUnpackSize:
In:
src - input data
srcLen - input data size
Out:
unpackSize - size of uncompressed stream
Return code:
SZ_OK - OK
SZ_ERROR_INPUT_EOF - Error in headers
*/
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize);
/*
Lzma86_Decode:
In:
dest - output data
destLen - output data size
src - input data
srcLen - input data size
Out:
destLen - processed output size
srcLen - processed input size
Return code:
SZ_OK - OK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - unsupported file
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer
*/
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
EXTERN_C_END
#endif

View File

@ -0,0 +1,56 @@
/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder
2009-08-14 : Igor Pavlov : Public domain */
#include "Lzma86.h"
#include "Alloc.h"
#include "Bra.h"
#include "LzmaDec.h"
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize)
{
unsigned i;
if (srcLen < LZMA86_HEADER_SIZE)
return SZ_ERROR_INPUT_EOF;
*unpackSize = 0;
for (i = 0; i < sizeof(UInt64); i++)
*unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i);
return SZ_OK;
}
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)
{
ISzAlloc g_Alloc = { SzAlloc, SzFree };
SRes res;
int useFilter;
SizeT inSizePure;
ELzmaStatus status;
if (*srcLen < LZMA86_HEADER_SIZE)
return SZ_ERROR_INPUT_EOF;
useFilter = src[0];
if (useFilter > 1)
{
*destLen = 0;
return SZ_ERROR_UNSUPPORTED;
}
inSizePure = *srcLen - LZMA86_HEADER_SIZE;
res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure,
src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc);
*srcLen = inSizePure + LZMA86_HEADER_SIZE;
if (res != SZ_OK)
return res;
if (useFilter == 1)
{
UInt32 x86State;
x86_Convert_Init(x86State);
x86_Convert(dest, *destLen, 0, &x86State, 0);
}
return SZ_OK;
}

View File

@ -0,0 +1,108 @@
/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
2009-08-14 : Igor Pavlov : Public domain */
#include <string.h>
#include "Lzma86.h"
#include "Alloc.h"
#include "Bra.h"
#include "LzmaEnc.h"
#define SZE_OUT_OVERFLOW SZE_DATA_ERROR
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
int level, UInt32 dictSize, int filterMode)
{
ISzAlloc g_Alloc = { SzAlloc, SzFree };
size_t outSize2 = *destLen;
Byte *filteredStream;
Bool useFilter;
int mainResult = SZ_ERROR_OUTPUT_EOF;
CLzmaEncProps props;
LzmaEncProps_Init(&props);
props.level = level;
props.dictSize = dictSize;
*destLen = 0;
if (outSize2 < LZMA86_HEADER_SIZE)
return SZ_ERROR_OUTPUT_EOF;
{
int i;
UInt64 t = srcLen;
for (i = 0; i < 8; i++, t >>= 8)
dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;
}
filteredStream = 0;
useFilter = (filterMode != SZ_FILTER_NO);
if (useFilter)
{
if (srcLen != 0)
{
filteredStream = (Byte *)MyAlloc(srcLen);
if (filteredStream == 0)
return SZ_ERROR_MEM;
memcpy(filteredStream, src, srcLen);
}
{
UInt32 x86State;
x86_Convert_Init(x86State);
x86_Convert(filteredStream, srcLen, 0, &x86State, 1);
}
}
{
size_t minSize = 0;
Bool bestIsFiltered = False;
/* passes for SZ_FILTER_AUTO:
0 - BCJ + LZMA
1 - LZMA
2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.
*/
int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
int i;
for (i = 0; i < numPasses; i++)
{
size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
size_t outPropsSize = 5;
SRes curRes;
Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
if (curModeIsFiltered && !bestIsFiltered)
break;
if (useFilter && i == 0)
curModeIsFiltered = True;
curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,
curModeIsFiltered ? filteredStream : src, srcLen,
&props, dest + 1, &outPropsSize, 0,
NULL, &g_Alloc, &g_Alloc);
if (curRes != SZ_ERROR_OUTPUT_EOF)
{
if (curRes != SZ_OK)
{
mainResult = curRes;
break;
}
if (outSizeProcessed <= minSize || mainResult != SZ_OK)
{
minSize = outSizeProcessed;
bestIsFiltered = curModeIsFiltered;
mainResult = SZ_OK;
}
}
}
dest[0] = (bestIsFiltered ? 1 : 0);
*destLen = LZMA86_HEADER_SIZE + minSize;
}
if (useFilter)
MyFree(filteredStream);
return mainResult;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,231 @@
/* LzmaDec.h -- LZMA Decoder
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMA_DEC_H
#define __LZMA_DEC_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* #define _LZMA_PROB32 */
/* _LZMA_PROB32 can increase the speed on some CPUs,
but memory usage for CLzmaDec::probs will be doubled in that case */
#ifdef _LZMA_PROB32
#define CLzmaProb UInt32
#else
#define CLzmaProb UInt16
#endif
/* ---------- LZMA Properties ---------- */
#define LZMA_PROPS_SIZE 5
typedef struct _CLzmaProps
{
unsigned lc, lp, pb;
UInt32 dicSize;
} CLzmaProps;
/* LzmaProps_Decode - decodes properties
Returns:
SZ_OK
SZ_ERROR_UNSUPPORTED - Unsupported properties
*/
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
/* ---------- LZMA Decoder state ---------- */
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
#define LZMA_REQUIRED_INPUT_MAX 20
typedef struct
{
CLzmaProps prop;
CLzmaProb *probs;
Byte *dic;
const Byte *buf;
UInt32 range, code;
SizeT dicPos;
SizeT dicBufSize;
UInt32 processedPos;
UInt32 checkDicSize;
unsigned state;
UInt32 reps[4];
unsigned remainLen;
int needFlush;
int needInitState;
UInt32 numProbs;
unsigned tempBufSize;
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
} CLzmaDec;
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
void LzmaDec_Init(CLzmaDec *p);
/* There are two types of LZMA streams:
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
typedef enum
{
LZMA_FINISH_ANY, /* finish at any point */
LZMA_FINISH_END /* block must be finished at the end */
} ELzmaFinishMode;
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
You must use LZMA_FINISH_END, when you know that current output buffer
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
and output value of destLen will be less than output buffer size limit.
You can check status result also.
You can use multiple checks to test data integrity after full decompression:
1) Check Result and "status" variable.
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
You must use correct finish mode in that case. */
typedef enum
{
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
} ELzmaStatus;
/* ELzmaStatus is used only as output value for function call */
/* ---------- Interfaces ---------- */
/* There are 3 levels of interfaces:
1) Dictionary Interface
2) Buffer Interface
3) One Call Interface
You can select any of these interfaces, but don't mix functions from different
groups for same object. */
/* There are two variants to allocate state for Dictionary Interface:
1) LzmaDec_Allocate / LzmaDec_Free
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
You can use variant 2, if you set dictionary buffer manually.
For Buffer Interface you must always use variant 1.
LzmaDec_Allocate* can return:
SZ_OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
*/
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
/* ---------- Dictionary Interface ---------- */
/* You can use it, if you want to eliminate the overhead for data copying from
dictionary to some other external buffer.
You must work with CLzmaDec variables directly in this interface.
STEPS:
LzmaDec_Constr()
LzmaDec_Allocate()
for (each new stream)
{
LzmaDec_Init()
while (it needs more decompression)
{
LzmaDec_DecodeToDic()
use data from CLzmaDec::dic and update CLzmaDec::dicPos
}
}
LzmaDec_Free()
*/
/* LzmaDec_DecodeToDic
The decoding to internal dictionary buffer (CLzmaDec::dic).
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
finishMode:
It has meaning only if the decoding reaches output limit (dicLimit).
LZMA_FINISH_ANY - Decode just dicLimit bytes.
LZMA_FINISH_END - Stream must be finished after dicLimit.
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
*/
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- Buffer Interface ---------- */
/* It's zlib-like interface.
See LzmaDec_DecodeToDic description for information about STEPS and return results,
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
to work with CLzmaDec variables manually.
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
*/
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- One Call Interface ---------- */
/* LzmaDecode
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
/* LzmaEnc.h -- LZMA Encoder
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMA_ENC_H
#define __LZMA_ENC_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LZMA_PROPS_SIZE 5
typedef struct _CLzmaEncProps
{
int level; /* 0 <= level <= 9 */
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version
default = (1 << 24) */
int lc; /* 0 <= lc <= 8, default = 3 */
int lp; /* 0 <= lp <= 4, default = 0 */
int pb; /* 0 <= pb <= 4, default = 2 */
int algo; /* 0 - fast, 1 - normal, default = 1 */
int fb; /* 5 <= fb <= 273, default = 32 */
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
int numHashBytes; /* 2, 3 or 4, default = 4 */
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
int numThreads; /* 1 or 2, default = 2 */
} CLzmaEncProps;
void LzmaEncProps_Init(CLzmaEncProps *p);
void LzmaEncProps_Normalize(CLzmaEncProps *p);
UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
/* ---------- CLzmaEncHandle Interface ---------- */
/* LzmaEnc_* functions can return the following exit codes:
Returns:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater in props
SZ_ERROR_WRITE - Write callback error.
SZ_ERROR_PROGRESS - some break from progress callback
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
typedef void * CLzmaEncHandle;
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
/* ---------- One Call Interface ---------- */
/* LzmaEncode
Return code:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,46 @@
/* LzmaLib.c -- LZMA library wrapper
2008-08-05
Igor Pavlov
Public domain */
#include "LzmaEnc.h"
#include "LzmaDec.h"
#include "Alloc.h"
#include "LzmaLib.h"
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
unsigned char *outProps, size_t *outPropsSize,
int level, /* 0 <= level <= 9, default = 5 */
unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
int lc, /* 0 <= lc <= 8, default = 3 */
int lp, /* 0 <= lp <= 4, default = 0 */
int pb, /* 0 <= pb <= 4, default = 2 */
int fb, /* 5 <= fb <= 273, default = 32 */
int numThreads /* 1 or 2, default = 2 */
)
{
CLzmaEncProps props;
LzmaEncProps_Init(&props);
props.level = level;
props.dictSize = dictSize;
props.lc = lc;
props.lp = lp;
props.pb = pb;
props.fb = fb;
props.numThreads = numThreads;
return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0,
NULL, &g_Alloc, &g_Alloc);
}
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen,
const unsigned char *props, size_t propsSize)
{
ELzmaStatus status;
return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc);
}

View File

@ -0,0 +1,135 @@
/* LzmaLib.h -- LZMA library interface
2009-04-07 : Igor Pavlov : Public domain */
#ifndef __LZMA_LIB_H
#define __LZMA_LIB_H
#include "Types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MY_STDAPI int MY_STD_CALL
#define LZMA_PROPS_SIZE 5
/*
RAM requirements for LZMA:
for compression: (dictSize * 11.5 + 6 MB) + state_size
for decompression: dictSize + state_size
state_size = (4 + (1.5 << (lc + lp))) KB
by default (lc=3, lp=0), state_size = 16 KB.
LZMA properties (5 bytes) format
Offset Size Description
0 1 lc, lp and pb in encoded form.
1 4 dictSize (little endian).
*/
/*
LzmaCompress
------------
outPropsSize -
In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
LZMA Encoder will use defult values for any parameter, if it is
-1 for any from: level, loc, lp, pb, fb, numThreads
0 for dictSize
level - compression level: 0 <= level <= 9;
level dictSize algo fb
0: 16 KB 0 32
1: 64 KB 0 32
2: 256 KB 0 32
3: 1 MB 0 32
4: 4 MB 0 32
5: 16 MB 1 32
6: 32 MB 1 32
7+: 64 MB 1 64
The default value for "level" is 5.
algo = 0 means fast method
algo = 1 means normal method
dictSize - The dictionary size in bytes. The maximum value is
128 MB = (1 << 27) bytes for 32-bit version
1 GB = (1 << 30) bytes for 64-bit version
The default value is 16 MB = (1 << 24) bytes.
It's recommended to use the dictionary that is larger than 4 KB and
that can be calculated as (1 << N) or (3 << N) sizes.
lc - The number of literal context bits (high bits of previous literal).
It can be in the range from 0 to 8. The default value is 3.
Sometimes lc=4 gives the gain for big files.
lp - The number of literal pos bits (low bits of current position for literals).
It can be in the range from 0 to 4. The default value is 0.
The lp switch is intended for periodical data when the period is equal to 2^lp.
For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's
better to set lc=0, if you change lp switch.
pb - The number of pos bits (low bits of current position).
It can be in the range from 0 to 4. The default value is 2.
The pb switch is intended for periodical data when the period is equal 2^pb.
fb - Word size (the number of fast bytes).
It can be in the range from 5 to 273. The default value is 32.
Usually, a big number gives a little bit better compression ratio and
slower compression process.
numThreads - The number of thereads. 1 or 2. The default value is 2.
Fast mode (algo = 0) can use only 1 thread.
Out:
destLen - processed output size
Returns:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
*/
MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */
int level, /* 0 <= level <= 9, default = 5 */
unsigned dictSize, /* default = (1 << 24) */
int lc, /* 0 <= lc <= 8, default = 3 */
int lp, /* 0 <= lp <= 4, default = 0 */
int pb, /* 0 <= pb <= 4, default = 2 */
int fb, /* 5 <= fb <= 273, default = 32 */
int numThreads /* 1 or 2, default = 2 */
);
/*
LzmaUncompress
--------------
In:
dest - output data
destLen - output data size
src - input data
srcLen - input data size
Out:
destLen - processed output size
srcLen - processed input size
Returns:
SZ_OK - OK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation arror
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src)
*/
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
const unsigned char *props, size_t propsSize);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,42 @@
/*
LzmaTypes.h
Types for LZMA Decoder
This file written and distributed to public domain by Igor Pavlov.
This file is part of LZMA SDK 4.40 (2006-05-01)
*/
#ifndef __LZMATYPES_H
#define __LZMATYPES_H
#define _LZMA_IN_CB 1
#define _LZMA_LOC_OPT 1
#include <limits.h>
#if ULONG_MAX == 0xFFFFFFFF
#define _LZMA_UINT32_IS_ULONG
#endif
#ifndef Byte
typedef unsigned char Byte;
typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG
typedef unsigned long UInt32;
#else
typedef unsigned int UInt32;
#endif
#endif
/* #define _LZMA_SYSTEM_SIZE_T */
/* Use system's size_t. You can use it to enable 64-bit sizes supporting */
#ifdef _LZMA_SYSTEM_SIZE_T
#include <stddef.h>
typedef size_t SizeT;
#else
typedef UInt32 SizeT;
#endif
#endif

View File

@ -0,0 +1,327 @@
/* MtCoder.c -- Multi-thread Coder
2010-09-24 : Igor Pavlov : Public domain */
#include <stdio.h>
#include "MtCoder.h"
void LoopThread_Construct(CLoopThread *p)
{
Thread_Construct(&p->thread);
Event_Construct(&p->startEvent);
Event_Construct(&p->finishedEvent);
}
void LoopThread_Close(CLoopThread *p)
{
Thread_Close(&p->thread);
Event_Close(&p->startEvent);
Event_Close(&p->finishedEvent);
}
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
{
CLoopThread *p = (CLoopThread *)pp;
for (;;)
{
if (Event_Wait(&p->startEvent) != 0)
return SZ_ERROR_THREAD;
if (p->stop)
return 0;
p->res = p->func(p->param);
if (Event_Set(&p->finishedEvent) != 0)
return SZ_ERROR_THREAD;
}
}
WRes LoopThread_Create(CLoopThread *p)
{
p->stop = 0;
RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));
RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));
return Thread_Create(&p->thread, LoopThreadFunc, p);
}
WRes LoopThread_StopAndWait(CLoopThread *p)
{
p->stop = 1;
if (Event_Set(&p->startEvent) != 0)
return SZ_ERROR_THREAD;
return Thread_Wait(&p->thread);
}
WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }
WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
{
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
}
static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
{
unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
p->inSizes[i] = p->outSizes[i] = 0;
p->totalInSize = p->totalOutSize = 0;
p->progress = progress;
p->res = SZ_OK;
}
static void MtProgress_Reinit(CMtProgress *p, unsigned index)
{
p->inSizes[index] = 0;
p->outSizes[index] = 0;
}
#define UPDATE_PROGRESS(size, prev, total) \
if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)
{
SRes res;
CriticalSection_Enter(&p->cs);
UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)
UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)
if (p->res == SZ_OK)
p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);
res = p->res;
CriticalSection_Leave(&p->cs);
return res;
}
static void MtProgress_SetError(CMtProgress *p, SRes res)
{
CriticalSection_Enter(&p->cs);
if (p->res == SZ_OK)
p->res = res;
CriticalSection_Leave(&p->cs);
}
static void MtCoder_SetError(CMtCoder* p, SRes res)
{
CriticalSection_Enter(&p->cs);
if (p->res == SZ_OK)
p->res = res;
CriticalSection_Leave(&p->cs);
}
/* ---------- MtThread ---------- */
void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
{
p->mtCoder = mtCoder;
p->outBuf = 0;
p->inBuf = 0;
Event_Construct(&p->canRead);
Event_Construct(&p->canWrite);
LoopThread_Construct(&p->thread);
}
#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }
static void CMtThread_CloseEvents(CMtThread *p)
{
Event_Close(&p->canRead);
Event_Close(&p->canWrite);
}
static void CMtThread_Destruct(CMtThread *p)
{
CMtThread_CloseEvents(p);
if (Thread_WasCreated(&p->thread.thread))
{
LoopThread_StopAndWait(&p->thread);
LoopThread_Close(&p->thread);
}
if (p->mtCoder->alloc)
IAlloc_Free(p->mtCoder->alloc, p->outBuf);
p->outBuf = 0;
if (p->mtCoder->alloc)
IAlloc_Free(p->mtCoder->alloc, p->inBuf);
p->inBuf = 0;
}
#define MY_BUF_ALLOC(buf, size, newSize) \
if (buf == 0 || size != newSize) \
{ IAlloc_Free(p->mtCoder->alloc, buf); \
size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \
if (buf == 0) return SZ_ERROR_MEM; }
static SRes CMtThread_Prepare(CMtThread *p)
{
MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)
MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)
p->stopReading = False;
p->stopWriting = False;
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));
return SZ_OK;
}
static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
{
size_t size = *processedSize;
*processedSize = 0;
while (size != 0)
{
size_t curSize = size;
SRes res = stream->Read(stream, data, &curSize);
*processedSize += curSize;
data += curSize;
size -= curSize;
RINOK(res);
if (curSize == 0)
return SZ_OK;
}
return SZ_OK;
}
#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads - 1 ? 0 : p->index + 1]
static SRes MtThread_Process(CMtThread *p, Bool *stop)
{
CMtThread *next;
*stop = True;
if (Event_Wait(&p->canRead) != 0)
return SZ_ERROR_THREAD;
next = GET_NEXT_THREAD(p);
if (p->stopReading)
{
next->stopReading = True;
return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;
}
{
size_t size = p->mtCoder->blockSize;
size_t destSize = p->outBufSize;
RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));
next->stopReading = *stop = (size != p->mtCoder->blockSize);
if (Event_Set(&next->canRead) != 0)
return SZ_ERROR_THREAD;
RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,
p->outBuf, &destSize, p->inBuf, size, *stop));
MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);
if (Event_Wait(&p->canWrite) != 0)
return SZ_ERROR_THREAD;
if (p->stopWriting)
return SZ_ERROR_FAIL;
if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)
return SZ_ERROR_WRITE;
return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;
}
}
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
{
CMtThread *p = (CMtThread *)pp;
for (;;)
{
Bool stop;
CMtThread *next = GET_NEXT_THREAD(p);
SRes res = MtThread_Process(p, &stop);
if (res != SZ_OK)
{
MtCoder_SetError(p->mtCoder, res);
MtProgress_SetError(&p->mtCoder->mtProgress, res);
next->stopReading = True;
next->stopWriting = True;
Event_Set(&next->canRead);
Event_Set(&next->canWrite);
return res;
}
if (stop)
return 0;
}
}
void MtCoder_Construct(CMtCoder* p)
{
unsigned i;
p->alloc = 0;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
{
CMtThread *t = &p->threads[i];
t->index = i;
CMtThread_Construct(t, p);
}
CriticalSection_Init(&p->cs);
CriticalSection_Init(&p->mtProgress.cs);
}
void MtCoder_Destruct(CMtCoder* p)
{
unsigned i;
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
CMtThread_Destruct(&p->threads[i]);
CriticalSection_Delete(&p->cs);
CriticalSection_Delete(&p->mtProgress.cs);
}
SRes MtCoder_Code(CMtCoder *p)
{
unsigned i, numThreads = p->numThreads;
SRes res = SZ_OK;
p->res = SZ_OK;
MtProgress_Init(&p->mtProgress, p->progress);
for (i = 0; i < numThreads; i++)
{
RINOK(CMtThread_Prepare(&p->threads[i]));
}
for (i = 0; i < numThreads; i++)
{
CMtThread *t = &p->threads[i];
CLoopThread *lt = &t->thread;
if (!Thread_WasCreated(&lt->thread))
{
lt->func = ThreadFunc;
lt->param = t;
if (LoopThread_Create(lt) != SZ_OK)
{
res = SZ_ERROR_THREAD;
break;
}
}
}
if (res == SZ_OK)
{
unsigned j;
for (i = 0; i < numThreads; i++)
{
CMtThread *t = &p->threads[i];
if (LoopThread_StartSubThread(&t->thread) != SZ_OK)
{
res = SZ_ERROR_THREAD;
p->threads[0].stopReading = True;
break;
}
}
Event_Set(&p->threads[0].canWrite);
Event_Set(&p->threads[0].canRead);
for (j = 0; j < i; j++)
LoopThread_WaitSubThread(&p->threads[j].thread);
}
for (i = 0; i < numThreads; i++)
CMtThread_CloseEvents(&p->threads[i]);
return (res == SZ_OK) ? p->res : res;
}

View File

@ -0,0 +1,98 @@
/* MtCoder.h -- Multi-thread Coder
2009-11-19 : Igor Pavlov : Public domain */
#ifndef __MT_CODER_H
#define __MT_CODER_H
#include "Threads.h"
EXTERN_C_BEGIN
typedef struct
{
CThread thread;
CAutoResetEvent startEvent;
CAutoResetEvent finishedEvent;
int stop;
THREAD_FUNC_TYPE func;
LPVOID param;
THREAD_FUNC_RET_TYPE res;
} CLoopThread;
void LoopThread_Construct(CLoopThread *p);
void LoopThread_Close(CLoopThread *p);
WRes LoopThread_Create(CLoopThread *p);
WRes LoopThread_StopAndWait(CLoopThread *p);
WRes LoopThread_StartSubThread(CLoopThread *p);
WRes LoopThread_WaitSubThread(CLoopThread *p);
#ifndef _7ZIP_ST
#define NUM_MT_CODER_THREADS_MAX 32
#else
#define NUM_MT_CODER_THREADS_MAX 1
#endif
typedef struct
{
UInt64 totalInSize;
UInt64 totalOutSize;
ICompressProgress *progress;
SRes res;
CCriticalSection cs;
UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];
UInt64 outSizes[NUM_MT_CODER_THREADS_MAX];
} CMtProgress;
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);
struct _CMtCoder;
typedef struct
{
struct _CMtCoder *mtCoder;
Byte *outBuf;
size_t outBufSize;
Byte *inBuf;
size_t inBufSize;
unsigned index;
CLoopThread thread;
Bool stopReading;
Bool stopWriting;
CAutoResetEvent canRead;
CAutoResetEvent canWrite;
} CMtThread;
typedef struct
{
SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize,
const Byte *src, size_t srcSize, int finished);
} IMtCoderCallback;
typedef struct _CMtCoder
{
size_t blockSize;
size_t destBlockSize;
unsigned numThreads;
ISeqInStream *inStream;
ISeqOutStream *outStream;
ICompressProgress *progress;
ISzAlloc *alloc;
IMtCoderCallback *mtCallback;
CCriticalSection cs;
SRes res;
CMtProgress mtProgress;
CMtThread threads[NUM_MT_CODER_THREADS_MAX];
} CMtCoder;
void MtCoder_Construct(CMtCoder* p);
void MtCoder_Destruct(CMtCoder* p);
SRes MtCoder_Code(CMtCoder *p);
EXTERN_C_END
#endif

View File

@ -0,0 +1,81 @@
/* Ppmd.h -- PPMD codec common code
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#ifndef __PPMD_H
#define __PPMD_H
#include "Types.h"
#include "CpuArch.h"
EXTERN_C_BEGIN
#ifdef MY_CPU_32BIT
#define PPMD_32BIT
#endif
#define PPMD_INT_BITS 7
#define PPMD_PERIOD_BITS 7
#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
#define PPMD_N1 4
#define PPMD_N2 4
#define PPMD_N3 4
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
/* SEE-contexts for PPM-contexts with masked symbols */
typedef struct
{
UInt16 Summ; /* Freq */
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
Byte Count; /* Count to next change of Shift */
} CPpmd_See;
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
typedef struct
{
Byte Symbol;
Byte Freq;
UInt16 SuccessorLow;
UInt16 SuccessorHigh;
} CPpmd_State;
typedef
#ifdef PPMD_32BIT
CPpmd_State *
#else
UInt32
#endif
CPpmd_State_Ref;
typedef
#ifdef PPMD_32BIT
void *
#else
UInt32
#endif
CPpmd_Void_Ref;
typedef
#ifdef PPMD_32BIT
Byte *
#else
UInt32
#endif
CPpmd_Byte_Ref;
#define PPMD_SetAllBitsIn256Bytes(p) \
{ unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}
EXTERN_C_END
#endif

View File

@ -0,0 +1,708 @@
/* Ppmd7.c -- PPMdH codec
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include <memory.h>
#include "Ppmd7.h"
const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
#define MAX_FREQ 124
#define UNIT_SIZE 12
#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
#define U2I(nu) (p->Units2Indx[(nu) - 1])
#define I2U(indx) (p->Indx2Units[indx])
#ifdef PPMD_32BIT
#define REF(ptr) (ptr)
#else
#define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
#endif
#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
#define STATS(ctx) Ppmd7_GetStats(p, ctx)
#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
#define SUFFIX(ctx) CTX((ctx)->Suffix)
typedef CPpmd7_Context * CTX_PTR;
struct CPpmd7_Node_;
typedef
#ifdef PPMD_32BIT
struct CPpmd7_Node_ *
#else
UInt32
#endif
CPpmd7_Node_Ref;
typedef struct CPpmd7_Node_
{
UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
UInt16 NU;
CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
CPpmd7_Node_Ref Prev;
} CPpmd7_Node;
#ifdef PPMD_32BIT
#define NODE(ptr) (ptr)
#else
#define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
#endif
void Ppmd7_Construct(CPpmd7 *p)
{
unsigned i, k, m;
p->Base = 0;
for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
{
unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
do { p->Units2Indx[k++] = (Byte)i; } while(--step);
p->Indx2Units[i] = (Byte)k;
}
p->NS2BSIndx[0] = (0 << 1);
p->NS2BSIndx[1] = (1 << 1);
memset(p->NS2BSIndx + 2, (2 << 1), 9);
memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
for (i = 0; i < 3; i++)
p->NS2Indx[i] = (Byte)i;
for (m = i, k = 1; i < 256; i++)
{
p->NS2Indx[i] = (Byte)m;
if (--k == 0)
k = (++m) - 2;
}
memset(p->HB2Flag, 0, 0x40);
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
}
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->Base);
p->Size = 0;
p->Base = 0;
}
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
{
if (p->Base == 0 || p->Size != size)
{
Ppmd7_Free(p, alloc);
p->AlignOffset =
#ifdef PPMD_32BIT
(4 - size) & 3;
#else
4 - (size & 3);
#endif
if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
#ifndef PPMD_32BIT
+ UNIT_SIZE
#endif
)) == 0)
return False;
p->Size = size;
}
return True;
}
static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
{
*((CPpmd_Void_Ref *)node) = p->FreeList[indx];
p->FreeList[indx] = REF(node);
}
static void *RemoveNode(CPpmd7 *p, unsigned indx)
{
CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
p->FreeList[indx] = *node;
return node;
}
static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
{
unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
ptr = (Byte *)ptr + U2B(I2U(newIndx));
if (I2U(i = U2I(nu)) != nu)
{
unsigned k = I2U(--i);
InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
}
InsertNode(p, ptr, i);
}
static void GlueFreeBlocks(CPpmd7 *p)
{
#ifdef PPMD_32BIT
CPpmd7_Node headItem;
CPpmd7_Node_Ref head = &headItem;
#else
CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
#endif
CPpmd7_Node_Ref n = head;
unsigned i;
p->GlueCount = 255;
/* create doubly-linked list of free blocks */
for (i = 0; i < PPMD_NUM_INDEXES; i++)
{
UInt16 nu = I2U(i);
CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
p->FreeList[i] = 0;
while (next != 0)
{
CPpmd7_Node *node = NODE(next);
node->Next = n;
n = NODE(n)->Prev = next;
next = *(const CPpmd7_Node_Ref *)node;
node->Stamp = 0;
node->NU = (UInt16)nu;
}
}
NODE(head)->Stamp = 1;
NODE(head)->Next = n;
NODE(n)->Prev = head;
if (p->LoUnit != p->HiUnit)
((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
/* Glue free blocks */
while (n != head)
{
CPpmd7_Node *node = NODE(n);
UInt32 nu = (UInt32)node->NU;
for (;;)
{
CPpmd7_Node *node2 = NODE(n) + nu;
nu += node2->NU;
if (node2->Stamp != 0 || nu >= 0x10000)
break;
NODE(node2->Prev)->Next = node2->Next;
NODE(node2->Next)->Prev = node2->Prev;
node->NU = (UInt16)nu;
}
n = node->Next;
}
/* Fill lists of free blocks */
for (n = NODE(head)->Next; n != head;)
{
CPpmd7_Node *node = NODE(n);
unsigned nu;
CPpmd7_Node_Ref next = node->Next;
for (nu = node->NU; nu > 128; nu -= 128, node += 128)
InsertNode(p, node, PPMD_NUM_INDEXES - 1);
if (I2U(i = U2I(nu)) != nu)
{
unsigned k = I2U(--i);
InsertNode(p, node + k, nu - k - 1);
}
InsertNode(p, node, i);
n = next;
}
}
static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
{
unsigned i;
void *retVal;
if (p->GlueCount == 0)
{
GlueFreeBlocks(p);
if (p->FreeList[indx] != 0)
return RemoveNode(p, indx);
}
i = indx;
do
{
if (++i == PPMD_NUM_INDEXES)
{
UInt32 numBytes = U2B(I2U(indx));
p->GlueCount--;
return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
}
}
while (p->FreeList[i] == 0);
retVal = RemoveNode(p, i);
SplitBlock(p, retVal, i, indx);
return retVal;
}
static void *AllocUnits(CPpmd7 *p, unsigned indx)
{
UInt32 numBytes;
if (p->FreeList[indx] != 0)
return RemoveNode(p, indx);
numBytes = U2B(I2U(indx));
if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
{
void *retVal = p->LoUnit;
p->LoUnit += numBytes;
return retVal;
}
return AllocUnitsRare(p, indx);
}
#define MyMem12Cpy(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
{
unsigned i0 = U2I(oldNU);
unsigned i1 = U2I(newNU);
if (i0 == i1)
return oldPtr;
if (p->FreeList[i1] != 0)
{
void *ptr = RemoveNode(p, i1);
MyMem12Cpy(ptr, oldPtr, newNU);
InsertNode(p, oldPtr, i0);
return ptr;
}
SplitBlock(p, oldPtr, i0, i1);
return oldPtr;
}
#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
{
(p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
}
static void RestartModel(CPpmd7 *p)
{
unsigned i, k, m;
memset(p->FreeList, 0, sizeof(p->FreeList));
p->Text = p->Base + p->AlignOffset;
p->HiUnit = p->Text + p->Size;
p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
p->GlueCount = 0;
p->OrderFall = p->MaxOrder;
p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
p->PrevSuccess = 0;
p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
p->MinContext->Suffix = 0;
p->MinContext->NumStats = 256;
p->MinContext->SummFreq = 256 + 1;
p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
p->LoUnit += U2B(256 / 2);
p->MinContext->Stats = REF(p->FoundState);
for (i = 0; i < 256; i++)
{
CPpmd_State *s = &p->FoundState[i];
s->Symbol = (Byte)i;
s->Freq = 1;
SetSuccessor(s, 0);
}
for (i = 0; i < 128; i++)
for (k = 0; k < 8; k++)
{
UInt16 *dest = p->BinSumm[i] + k;
UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
for (m = 0; m < 64; m += 8)
dest[m] = val;
}
for (i = 0; i < 25; i++)
for (k = 0; k < 16; k++)
{
CPpmd_See *s = &p->See[i][k];
s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
s->Count = 4;
}
}
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
{
p->MaxOrder = maxOrder;
RestartModel(p);
p->DummySee.Shift = PPMD_PERIOD_BITS;
p->DummySee.Summ = 0; /* unused */
p->DummySee.Count = 64; /* unused */
}
static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
{
CPpmd_State upState;
CTX_PTR c = p->MinContext;
CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
CPpmd_State *ps[PPMD7_MAX_ORDER];
unsigned numPs = 0;
if (!skip)
ps[numPs++] = p->FoundState;
while (c->Suffix)
{
CPpmd_Void_Ref successor;
CPpmd_State *s;
c = SUFFIX(c);
if (c->NumStats != 1)
{
for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
}
else
s = ONE_STATE(c);
successor = SUCCESSOR(s);
if (successor != upBranch)
{
c = CTX(successor);
if (numPs == 0)
return c;
break;
}
ps[numPs++] = s;
}
upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
SetSuccessor(&upState, upBranch + 1);
if (c->NumStats == 1)
upState.Freq = ONE_STATE(c)->Freq;
else
{
UInt32 cf, s0;
CPpmd_State *s;
for (s = STATS(c); s->Symbol != upState.Symbol; s++);
cf = s->Freq - 1;
s0 = c->SummFreq - c->NumStats - cf;
upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
}
do
{
/* Create Child */
CTX_PTR c1; /* = AllocContext(p); */
if (p->HiUnit != p->LoUnit)
c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
else if (p->FreeList[0] != 0)
c1 = (CTX_PTR)RemoveNode(p, 0);
else
{
c1 = (CTX_PTR)AllocUnitsRare(p, 0);
if (!c1)
return NULL;
}
c1->NumStats = 1;
*ONE_STATE(c1) = upState;
c1->Suffix = REF(c);
SetSuccessor(ps[--numPs], REF(c1));
c = c1;
}
while (numPs != 0);
return c;
}
static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
{
CPpmd_State tmp = *t1;
*t1 = *t2;
*t2 = tmp;
}
static void UpdateModel(CPpmd7 *p)
{
CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
CTX_PTR c;
unsigned s0, ns;
if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
{
c = SUFFIX(p->MinContext);
if (c->NumStats == 1)
{
CPpmd_State *s = ONE_STATE(c);
if (s->Freq < 32)
s->Freq++;
}
else
{
CPpmd_State *s = STATS(c);
if (s->Symbol != p->FoundState->Symbol)
{
do { s++; } while (s->Symbol != p->FoundState->Symbol);
if (s[0].Freq >= s[-1].Freq)
{
SwapStates(&s[0], &s[-1]);
s--;
}
}
if (s->Freq < MAX_FREQ - 9)
{
s->Freq += 2;
c->SummFreq += 2;
}
}
}
if (p->OrderFall == 0)
{
p->MinContext = p->MaxContext = CreateSuccessors(p, True);
if (p->MinContext == 0)
{
RestartModel(p);
return;
}
SetSuccessor(p->FoundState, REF(p->MinContext));
return;
}
*p->Text++ = p->FoundState->Symbol;
successor = REF(p->Text);
if (p->Text >= p->UnitsStart)
{
RestartModel(p);
return;
}
if (fSuccessor)
{
if (fSuccessor <= successor)
{
CTX_PTR cs = CreateSuccessors(p, False);
if (cs == NULL)
{
RestartModel(p);
return;
}
fSuccessor = REF(cs);
}
if (--p->OrderFall == 0)
{
successor = fSuccessor;
p->Text -= (p->MaxContext != p->MinContext);
}
}
else
{
SetSuccessor(p->FoundState, successor);
fSuccessor = REF(p->MinContext);
}
s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
{
unsigned ns1;
UInt32 cf, sf;
if ((ns1 = c->NumStats) != 1)
{
if ((ns1 & 1) == 0)
{
/* Expand for one UNIT */
unsigned oldNU = ns1 >> 1;
unsigned i = U2I(oldNU);
if (i != U2I(oldNU + 1))
{
void *ptr = AllocUnits(p, i + 1);
void *oldPtr;
if (!ptr)
{
RestartModel(p);
return;
}
oldPtr = STATS(c);
MyMem12Cpy(ptr, oldPtr, oldNU);
InsertNode(p, oldPtr, i);
c->Stats = STATS_REF(ptr);
}
}
c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
}
else
{
CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
if (!s)
{
RestartModel(p);
return;
}
*s = *ONE_STATE(c);
c->Stats = REF(s);
if (s->Freq < MAX_FREQ / 4 - 1)
s->Freq <<= 1;
else
s->Freq = MAX_FREQ - 4;
c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
}
cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
sf = (UInt32)s0 + c->SummFreq;
if (cf < 6 * sf)
{
cf = 1 + (cf > sf) + (cf >= 4 * sf);
c->SummFreq += 3;
}
else
{
cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
c->SummFreq = (UInt16)(c->SummFreq + cf);
}
{
CPpmd_State *s = STATS(c) + ns1;
SetSuccessor(s, successor);
s->Symbol = p->FoundState->Symbol;
s->Freq = (Byte)cf;
c->NumStats = (UInt16)(ns1 + 1);
}
}
p->MaxContext = p->MinContext = CTX(fSuccessor);
}
static void Rescale(CPpmd7 *p)
{
unsigned i, adder, sumFreq, escFreq;
CPpmd_State *stats = STATS(p->MinContext);
CPpmd_State *s = p->FoundState;
{
CPpmd_State tmp = *s;
for (; s != stats; s--)
s[0] = s[-1];
*s = tmp;
}
escFreq = p->MinContext->SummFreq - s->Freq;
s->Freq += 4;
adder = (p->OrderFall != 0);
s->Freq = (Byte)((s->Freq + adder) >> 1);
sumFreq = s->Freq;
i = p->MinContext->NumStats - 1;
do
{
escFreq -= (++s)->Freq;
s->Freq = (Byte)((s->Freq + adder) >> 1);
sumFreq += s->Freq;
if (s[0].Freq > s[-1].Freq)
{
CPpmd_State *s1 = s;
CPpmd_State tmp = *s1;
do
s1[0] = s1[-1];
while (--s1 != stats && tmp.Freq > s1[-1].Freq);
*s1 = tmp;
}
}
while (--i);
if (s->Freq == 0)
{
unsigned numStats = p->MinContext->NumStats;
unsigned n0, n1;
do { i++; } while ((--s)->Freq == 0);
escFreq += i;
p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
if (p->MinContext->NumStats == 1)
{
CPpmd_State tmp = *stats;
do
{
tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
escFreq >>= 1;
}
while (escFreq > 1);
InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
*(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
return;
}
n0 = (numStats + 1) >> 1;
n1 = (p->MinContext->NumStats + 1) >> 1;
if (n0 != n1)
p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
}
p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
p->FoundState = STATS(p->MinContext);
}
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
{
CPpmd_See *see;
unsigned nonMasked = p->MinContext->NumStats - numMasked;
if (p->MinContext->NumStats != 256)
{
see = p->See[p->NS2Indx[nonMasked - 1]] +
(nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
4 * (numMasked > nonMasked) +
p->HiBitsFlag;
{
unsigned r = (see->Summ >> see->Shift);
see->Summ = (UInt16)(see->Summ - r);
*escFreq = r + (r == 0);
}
}
else
{
see = &p->DummySee;
*escFreq = 1;
}
return see;
}
static void NextContext(CPpmd7 *p)
{
CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
if (p->OrderFall == 0 && (Byte *)c > p->Text)
p->MinContext = p->MaxContext = c;
else
UpdateModel(p);
}
void Ppmd7_Update1(CPpmd7 *p)
{
CPpmd_State *s = p->FoundState;
s->Freq += 4;
p->MinContext->SummFreq += 4;
if (s[0].Freq > s[-1].Freq)
{
SwapStates(&s[0], &s[-1]);
p->FoundState = --s;
if (s->Freq > MAX_FREQ)
Rescale(p);
}
NextContext(p);
}
void Ppmd7_Update1_0(CPpmd7 *p)
{
p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
p->RunLength += p->PrevSuccess;
p->MinContext->SummFreq += 4;
if ((p->FoundState->Freq += 4) > MAX_FREQ)
Rescale(p);
NextContext(p);
}
void Ppmd7_UpdateBin(CPpmd7 *p)
{
p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
p->PrevSuccess = 1;
p->RunLength++;
NextContext(p);
}
void Ppmd7_Update2(CPpmd7 *p)
{
p->MinContext->SummFreq += 4;
if ((p->FoundState->Freq += 4) > MAX_FREQ)
Rescale(p);
p->RunLength = p->InitRL;
UpdateModel(p);
}

View File

@ -0,0 +1,140 @@
/* Ppmd7.h -- PPMdH compression codec
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
/* This code supports virtual RangeDecoder and includes the implementation
of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
#ifndef __PPMD7_H
#define __PPMD7_H
#include "Ppmd.h"
EXTERN_C_BEGIN
#define PPMD7_MIN_ORDER 2
#define PPMD7_MAX_ORDER 64
#define PPMD7_MIN_MEM_SIZE (1 << 11)
#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
struct CPpmd7_Context_;
typedef
#ifdef PPMD_32BIT
struct CPpmd7_Context_ *
#else
UInt32
#endif
CPpmd7_Context_Ref;
typedef struct CPpmd7_Context_
{
UInt16 NumStats;
UInt16 SummFreq;
CPpmd_State_Ref Stats;
CPpmd7_Context_Ref Suffix;
} CPpmd7_Context;
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
typedef struct
{
CPpmd7_Context *MinContext, *MaxContext;
CPpmd_State *FoundState;
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
Int32 RunLength, InitRL; /* must be 32-bit at least */
UInt32 Size;
UInt32 GlueCount;
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
UInt32 AlignOffset;
Byte Indx2Units[PPMD_NUM_INDEXES];
Byte Units2Indx[128];
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
CPpmd_See DummySee, See[25][16];
UInt16 BinSumm[128][64];
} CPpmd7;
void Ppmd7_Construct(CPpmd7 *p);
Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc);
void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
/* ---------- Internal Functions ---------- */
extern const Byte PPMD7_kExpEscape[16];
#ifdef PPMD_32BIT
#define Ppmd7_GetPtr(p, ptr) (ptr)
#define Ppmd7_GetContext(p, ptr) (ptr)
#define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
#else
#define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
#define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
#define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
#endif
void Ppmd7_Update1(CPpmd7 *p);
void Ppmd7_Update1_0(CPpmd7 *p);
void Ppmd7_Update2(CPpmd7 *p);
void Ppmd7_UpdateBin(CPpmd7 *p);
#define Ppmd7_GetBinSumm(p) \
&p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
(p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
((p->RunLength >> 26) & 0x20)]
CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
/* ---------- Decode ---------- */
typedef struct
{
UInt32 (*GetThreshold)(void *p, UInt32 total);
void (*Decode)(void *p, UInt32 start, UInt32 size);
UInt32 (*DecodeBit)(void *p, UInt32 size0);
} IPpmd7_RangeDec;
typedef struct
{
IPpmd7_RangeDec p;
UInt32 Range;
UInt32 Code;
IByteIn *Stream;
} CPpmd7z_RangeDec;
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc);
/* ---------- Encode ---------- */
typedef struct
{
UInt64 Low;
UInt32 Range;
Byte Cache;
UInt64 CacheSize;
IByteOut *Stream;
} CPpmd7z_RangeEnc;
void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p);
void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p);
void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
EXTERN_C_END
#endif

View File

@ -0,0 +1,187 @@
/* Ppmd7Dec.c -- PPMdH Decoder
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Ppmd7.h"
#define kTopValue (1 << 24)
Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
{
unsigned i;
p->Code = 0;
p->Range = 0xFFFFFFFF;
if (p->Stream->Read((void *)p->Stream) != 0)
return False;
for (i = 0; i < 4; i++)
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
return (p->Code < 0xFFFFFFFF);
}
static UInt32 Range_GetThreshold(void *pp, UInt32 total)
{
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
return (p->Code) / (p->Range /= total);
}
static void Range_Normalize(CPpmd7z_RangeDec *p)
{
if (p->Range < kTopValue)
{
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
p->Range <<= 8;
if (p->Range < kTopValue)
{
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
p->Range <<= 8;
}
}
}
static void Range_Decode(void *pp, UInt32 start, UInt32 size)
{
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
p->Code -= start * p->Range;
p->Range *= size;
Range_Normalize(p);
}
static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
{
CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
UInt32 newBound = (p->Range >> 14) * size0;
UInt32 symbol;
if (p->Code < newBound)
{
symbol = 0;
p->Range = newBound;
}
else
{
symbol = 1;
p->Code -= newBound;
p->Range -= newBound;
}
Range_Normalize(p);
return symbol;
}
void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
{
p->p.GetThreshold = Range_GetThreshold;
p->p.Decode = Range_Decode;
p->p.DecodeBit = Range_DecodeBit;
}
#define MASK(sym) ((signed char *)charMask)[sym]
int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 1)
{
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
unsigned i;
UInt32 count, hiCnt;
if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
{
Byte symbol;
rc->Decode(rc, 0, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd7_Update1_0(p);
return symbol;
}
p->PrevSuccess = 0;
i = p->MinContext->NumStats - 1;
do
{
if ((hiCnt += (++s)->Freq) > count)
{
Byte symbol;
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
p->FoundState = s;
symbol = s->Symbol;
Ppmd7_Update1(p);
return symbol;
}
}
while (--i);
if (count >= p->MinContext->SummFreq)
return -2;
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
i = p->MinContext->NumStats - 1;
do { MASK((--s)->Symbol) = 0; } while (--i);
}
else
{
UInt16 *prob = Ppmd7_GetBinSumm(p);
if (rc->DecodeBit(rc, *prob) == 0)
{
Byte symbol;
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
Ppmd7_UpdateBin(p);
return symbol;
}
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
p->PrevSuccess = 0;
}
for (;;)
{
CPpmd_State *ps[256], *s;
UInt32 freqSum, count, hiCnt;
CPpmd_See *see;
unsigned i, num, numMasked = p->MinContext->NumStats;
do
{
p->OrderFall++;
if (!p->MinContext->Suffix)
return -1;
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
}
while (p->MinContext->NumStats == numMasked);
hiCnt = 0;
s = Ppmd7_GetStats(p, p->MinContext);
i = 0;
num = p->MinContext->NumStats - numMasked;
do
{
int k = (int)(MASK(s->Symbol));
hiCnt += (s->Freq & k);
ps[i] = s++;
i -= k;
}
while (i != num);
see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
freqSum += hiCnt;
count = rc->GetThreshold(rc, freqSum);
if (count < hiCnt)
{
Byte symbol;
CPpmd_State **pps = ps;
for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
s = *pps;
rc->Decode(rc, hiCnt - s->Freq, s->Freq);
Ppmd_See_Update(see);
p->FoundState = s;
symbol = s->Symbol;
Ppmd7_Update2(p);
return symbol;
}
if (count >= freqSum)
return -2;
rc->Decode(rc, hiCnt, freqSum - hiCnt);
see->Summ = (UInt16)(see->Summ + freqSum);
do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
}
}

View File

@ -0,0 +1,185 @@
/* Ppmd7Enc.c -- PPMdH Encoder
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Ppmd7.h"
#define kTopValue (1 << 24)
void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p)
{
p->Low = 0;
p->Range = 0xFFFFFFFF;
p->Cache = 0;
p->CacheSize = 1;
}
static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
{
if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0)
{
Byte temp = p->Cache;
do
{
p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32)));
temp = 0xFF;
}
while(--p->CacheSize != 0);
p->Cache = (Byte)((UInt32)p->Low >> 24);
}
p->CacheSize++;
p->Low = (UInt32)p->Low << 8;
}
static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
{
p->Low += start * (p->Range /= total);
p->Range *= size;
while (p->Range < kTopValue)
{
p->Range <<= 8;
RangeEnc_ShiftLow(p);
}
}
static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0)
{
p->Range = (p->Range >> 14) * size0;
while (p->Range < kTopValue)
{
p->Range <<= 8;
RangeEnc_ShiftLow(p);
}
}
static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0)
{
UInt32 newBound = (p->Range >> 14) * size0;
p->Low += newBound;
p->Range -= newBound;
while (p->Range < kTopValue)
{
p->Range <<= 8;
RangeEnc_ShiftLow(p);
}
}
void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p)
{
unsigned i;
for (i = 0; i < 5; i++)
RangeEnc_ShiftLow(p);
}
#define MASK(sym) ((signed char *)charMask)[sym]
void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol)
{
size_t charMask[256 / sizeof(size_t)];
if (p->MinContext->NumStats != 1)
{
CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
UInt32 sum;
unsigned i;
if (s->Symbol == symbol)
{
RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq);
p->FoundState = s;
Ppmd7_Update1_0(p);
return;
}
p->PrevSuccess = 0;
sum = s->Freq;
i = p->MinContext->NumStats - 1;
do
{
if ((++s)->Symbol == symbol)
{
RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq);
p->FoundState = s;
Ppmd7_Update1(p);
return;
}
sum += s->Freq;
}
while (--i);
p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
i = p->MinContext->NumStats - 1;
do { MASK((--s)->Symbol) = 0; } while (--i);
RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq);
}
else
{
UInt16 *prob = Ppmd7_GetBinSumm(p);
CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);
if (s->Symbol == symbol)
{
RangeEnc_EncodeBit_0(rc, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
p->FoundState = s;
Ppmd7_UpdateBin(p);
return;
}
else
{
RangeEnc_EncodeBit_1(rc, *prob);
*prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
PPMD_SetAllBitsIn256Bytes(charMask);
MASK(s->Symbol) = 0;
p->PrevSuccess = 0;
}
}
for (;;)
{
UInt32 escFreq;
CPpmd_See *see;
CPpmd_State *s;
UInt32 sum;
unsigned i, numMasked = p->MinContext->NumStats;
do
{
p->OrderFall++;
if (!p->MinContext->Suffix)
return; /* EndMarker (symbol = -1) */
p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
}
while (p->MinContext->NumStats == numMasked);
see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);
s = Ppmd7_GetStats(p, p->MinContext);
sum = 0;
i = p->MinContext->NumStats;
do
{
int cur = s->Symbol;
if (cur == symbol)
{
UInt32 low = sum;
CPpmd_State *s1 = s;
do
{
sum += (s->Freq & (int)(MASK(s->Symbol)));
s++;
}
while (--i);
RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq);
Ppmd_See_Update(see);
p->FoundState = s1;
Ppmd7_Update2(p);
return;
}
sum += (s->Freq & (int)(MASK(cur)));
MASK(cur) = 0;
s++;
}
while (--i);
RangeEnc_Encode(rc, sum, escFreq, sum + escFreq);
see->Summ = (UInt16)(see->Summ + sum + escFreq);
}
}

View File

@ -0,0 +1,20 @@
/* RotateDefs.h -- Rotate functions
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __ROTATE_DEFS_H
#define __ROTATE_DEFS_H
#ifdef _MSC_VER
#include <stdlib.h>
#define rotlFixed(x, n) _rotl((x), (n))
#define rotrFixed(x, n) _rotr((x), (n))
#else
#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
#endif
#endif

View File

@ -0,0 +1,5 @@
#ifdef _WIN32
#include "win32/Threads.h"
#else
#include "posix/Threads.h"
#endif

View File

@ -0,0 +1,264 @@
/* Types.h -- Basic types
2010-10-09 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
#include <stddef.h>
#ifdef _WIN32
#include <windows.h>
#else
typedef unsigned char BOOL;
#define FALSE 0
#define TRUE 1
typedef long LONG;
typedef void *LPVOID;
#endif
#ifndef EXTERN_C_BEGIN
#ifdef __cplusplus
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C_BEGIN
#define EXTERN_C_END
#endif
#endif
EXTERN_C_BEGIN
#define SZ_OK 0
#define SZ_ERROR_DATA 1
#define SZ_ERROR_MEM 2
#define SZ_ERROR_CRC 3
#define SZ_ERROR_UNSUPPORTED 4
#define SZ_ERROR_PARAM 5
#define SZ_ERROR_INPUT_EOF 6
#define SZ_ERROR_OUTPUT_EOF 7
#define SZ_ERROR_READ 8
#define SZ_ERROR_WRITE 9
#define SZ_ERROR_PROGRESS 10
#define SZ_ERROR_FAIL 11
#define SZ_ERROR_THREAD 12
#define SZ_ERROR_ARCHIVE 16
#define SZ_ERROR_NO_ARCHIVE 17
typedef int SRes;
#ifdef _WIN32
typedef DWORD WRes;
#else
typedef int WRes;
#endif
#ifndef RINOK
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
#endif
typedef unsigned char Byte;
typedef short Int16;
typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG
typedef long Int32;
typedef unsigned long UInt32;
#else
typedef int Int32;
typedef unsigned int UInt32;
#endif
#ifdef _SZ_NO_INT_64
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
NOTES: Some code will work incorrectly in that case! */
typedef long Int64;
typedef unsigned long UInt64;
#else
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#define UINT64_CONST(n) n
#else
typedef long long int Int64;
typedef unsigned long long int UInt64;
#define UINT64_CONST(n) n ## ULL
#endif
#endif
#ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT;
#else
typedef size_t SizeT;
#endif
typedef int Bool;
#define True 1
#define False 0
#ifdef _WIN32
#define MY_STD_CALL __stdcall
#else
#define MY_STD_CALL
#endif
#ifdef _MSC_VER
#if _MSC_VER >= 1300
#define MY_NO_INLINE __declspec(noinline)
#else
#define MY_NO_INLINE
#endif
#define MY_CDECL __cdecl
#define MY_FAST_CALL __fastcall
#else
#define MY_CDECL
#define MY_FAST_CALL
#endif
/* The following interfaces use first parameter as pointer to structure */
typedef struct
{
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
} IByteIn;
typedef struct
{
void (*Write)(void *p, Byte b);
} IByteOut;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */
} ISeqInStream;
/* it can return SZ_ERROR_INPUT_EOF */
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
typedef struct
{
size_t (*Write)(void *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes.
(result < size) means error */
} ISeqOutStream;
typedef enum
{
SZ_SEEK_SET = 0,
SZ_SEEK_CUR = 1,
SZ_SEEK_END = 2
} ESzSeek;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ISeekInStream;
typedef struct
{
SRes (*Look)(void *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */
SRes (*Skip)(void *p, size_t offset);
/* offset must be <= output(*size) of Look */
SRes (*Read)(void *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ILookInStream;
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
/* reads via ILookInStream::Read */
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
#define LookToRead_BUF_SIZE (1 << 14)
typedef struct
{
ILookInStream s;
ISeekInStream *realStream;
size_t pos;
size_t size;
Byte buf[LookToRead_BUF_SIZE];
} CLookToRead;
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
void LookToRead_Init(CLookToRead *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p);
typedef struct
{
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */
} ICompressProgress;
typedef struct
{
void *(*Alloc)(void *p, size_t size);
void (*Free)(void *p, void *address); /* address can be 0 */
} ISzAlloc;
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef _WIN32
#define CHAR_PATH_SEPARATOR '\\'
#define WCHAR_PATH_SEPARATOR L'\\'
#define STRING_PATH_SEPARATOR "\\"
#define WSTRING_PATH_SEPARATOR L"\\"
#else
#define CHAR_PATH_SEPARATOR '/'
#define WCHAR_PATH_SEPARATOR L'/'
#define STRING_PATH_SEPARATOR "/"
#define WSTRING_PATH_SEPARATOR L"/"
#endif
EXTERN_C_END
#endif

View File

@ -0,0 +1,18 @@
Changes to 7z_C source
----------------------
I made several minor changes:
* Hard-coded setup to _SZ_ONE_DIRECTORY, _LZMA_IN_CB, _LZMA_LOC_OPT
* Fixed several memory free functions to not access NULL when cleaning
up after a failed allocation.
* Made private functions static.
* Fixed SzArchiveOpen to properly report error when header can't be
read.
* Fixed glaring conflicts between LzmaTypes.h and 7zTypes.h.
--
Shay Green <gblargg@gmail.com>

View File

@ -0,0 +1,594 @@
LZMA SDK 4.65
-------------
LZMA SDK provides the documentation, samples, header files, libraries,
and tools you need to develop applications that use LZMA compression.
LZMA is default and general compression method of 7z format
in 7-Zip compression program (www.7-zip.org). LZMA provides high
compression ratio and very fast decompression.
LZMA is an improved version of famous LZ77 compression algorithm.
It was improved in way of maximum increasing of compression ratio,
keeping high decompression speed and low memory requirements for
decompressing.
LICENSE
-------
LZMA SDK is written and placed in the public domain by Igor Pavlov.
LZMA SDK Contents
-----------------
LZMA SDK includes:
- ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing
- Compiled file->file LZMA compressing/decompressing program for Windows system
UNIX/Linux version
------------------
To compile C++ version of file->file LZMA encoding, go to directory
C++/7zip/Compress/LZMA_Alone
and call make to recompile it:
make -f makefile.gcc clean all
In some UNIX/Linux versions you must compile LZMA with static libraries.
To compile with static libraries, you can use
LIB = -lm -static
Files
---------------------
lzma.txt - LZMA SDK description (this file)
7zFormat.txt - 7z Format description
7zC.txt - 7z ANSI-C Decoder description
methods.txt - Compression method IDs for .7z
lzma.exe - Compiled file->file LZMA encoder/decoder for Windows
history.txt - history of the LZMA SDK
Source code structure
---------------------
C/ - C files
7zCrc*.* - CRC code
Alloc.* - Memory allocation functions
Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
LzFind.* - Match finder for LZ (LZMA) encoders
LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding
LzHash.h - Additional file for LZ match finder
LzmaDec.* - LZMA decoding
LzmaEnc.* - LZMA encoding
LzmaLib.* - LZMA Library for DLL calling
Types.h - Basic types for another .c files
Threads.* - The code for multithreading.
LzmaLib - LZMA Library (.DLL for Windows)
LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder).
Archive - files related to archiving
7z - 7z ANSI-C Decoder
CPP/ -- CPP files
Common - common files for C++ projects
Windows - common files for Windows related code
7zip - files related to 7-Zip Project
Common - common files for 7-Zip
Compress - files related to compression/decompression
Copy - Copy coder
RangeCoder - Range Coder (special code of compression/decompression)
LZMA - LZMA compression/decompression on C++
LZMA_Alone - file->file LZMA compression/decompression
Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
Archive - files related to archiving
Common - common files for archive handling
7z - 7z C++ Encoder/Decoder
Bundles - Modules that are bundles of other modules
Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.
UI - User Interface files
Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll
Common - Common UI files
Console - Code for console archiver
CS/ - C# files
7zip
Common - some common files for 7-Zip
Compress - files related to compression/decompression
LZ - files related to LZ (Lempel-Ziv) compression algorithm
LZMA - LZMA compression/decompression
LzmaAlone - file->file LZMA compression/decompression
RangeCoder - Range Coder (special code of compression/decompression)
Java/ - Java files
SevenZip
Compression - files related to compression/decompression
LZ - files related to LZ (Lempel-Ziv) compression algorithm
LZMA - LZMA compression/decompression
RangeCoder - Range Coder (special code of compression/decompression)
C/C++ source code of LZMA SDK is part of 7-Zip project.
7-Zip source code can be downloaded from 7-Zip's SourceForge page:
http://sourceforge.net/projects/sevenzip/
LZMA features
-------------
- Variable dictionary size (up to 1 GB)
- Estimated compressing speed: about 2 MB/s on 2 GHz CPU
- Estimated decompressing speed:
- 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64
- 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC
- Small memory requirements for decompressing (16 KB + DictionarySize)
- Small code size for decompressing: 5-8 KB
LZMA decoder uses only integer operations and can be
implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).
Some critical operations that affect the speed of LZMA decompression:
1) 32*16 bit integer multiply
2) Misspredicted branches (penalty mostly depends from pipeline length)
3) 32-bit shift and arithmetic operations
The speed of LZMA decompressing mostly depends from CPU speed.
Memory speed has no big meaning. But if your CPU has small data cache,
overall weight of memory speed will slightly increase.
How To Use
----------
Using LZMA encoder/decoder executable
--------------------------------------
Usage: LZMA <e|d> inputFile outputFile [<switches>...]
e: encode file
d: decode file
b: Benchmark. There are two tests: compressing and decompressing
with LZMA method. Benchmark shows rating in MIPS (million
instructions per second). Rating value is calculated from
measured speed and it is normalized with Intel's Core 2 results.
Also Benchmark checks possible hardware errors (RAM
errors in most cases). Benchmark uses these settings:
(-a1, -d21, -fb32, -mfbt4). You can change only -d parameter.
Also you can change the number of iterations. Example for 30 iterations:
LZMA b 30
Default number of iterations is 10.
<Switches>
-a{N}: set compression mode 0 = fast, 1 = normal
default: 1 (normal)
d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB)
The maximum value for dictionary size is 1 GB = 2^30 bytes.
Dictionary size is calculated as DictionarySize = 2^N bytes.
For decompressing file compressed by LZMA method with dictionary
size D = 2^N you need about D bytes of memory (RAM).
-fb{N}: set number of fast bytes - [5, 273], default: 128
Usually big number gives a little bit better compression ratio
and slower compression process.
-lc{N}: set number of literal context bits - [0, 8], default: 3
Sometimes lc=4 gives gain for big files.
-lp{N}: set number of literal pos bits - [0, 4], default: 0
lp switch is intended for periodical data when period is
equal 2^N. For example, for 32-bit (4 bytes)
periodical data you can use lp=2. Often it's better to set lc0,
if you change lp switch.
-pb{N}: set number of pos bits - [0, 4], default: 2
pb switch is intended for periodical data
when period is equal 2^N.
-mf{MF_ID}: set Match Finder. Default: bt4.
Algorithms from hc* group doesn't provide good compression
ratio, but they often works pretty fast in combination with
fast mode (-a0).
Memory requirements depend from dictionary size
(parameter "d" in table below).
MF_ID Memory Description
bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing.
bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing.
bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing.
hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing.
-eos: write End Of Stream marker. By default LZMA doesn't write
eos marker, since LZMA decoder knows uncompressed size
stored in .lzma file header.
-si: Read data from stdin (it will write End Of Stream marker).
-so: Write data to stdout
Examples:
1) LZMA e file.bin file.lzma -d16 -lc0
compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)
and 0 literal context bits. -lc0 allows to reduce memory requirements
for decompression.
2) LZMA e file.bin file.lzma -lc0 -lp2
compresses file.bin to file.lzma with settings suitable
for 32-bit periodical data (for example, ARM or MIPS code).
3) LZMA d file.lzma file.bin
decompresses file.lzma to file.bin.
Compression ratio hints
-----------------------
Recommendations
---------------
To increase the compression ratio for LZMA compressing it's desirable
to have aligned data (if it's possible) and also it's desirable to locate
data in such order, where code is grouped in one place and data is
grouped in other place (it's better than such mixing: code, data, code,
data, ...).
Filters
-------
You can increase the compression ratio for some data types, using
special filters before compressing. For example, it's possible to
increase the compression ratio on 5-10% for code for those CPU ISAs:
x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.
You can find C source code of such filters in C/Bra*.* files
You can check the compression ratio gain of these filters with such
7-Zip commands (example for ARM code):
No filter:
7z a a1.7z a.bin -m0=lzma
With filter for little-endian ARM code:
7z a a2.7z a.bin -m0=arm -m1=lzma
It works in such manner:
Compressing = Filter_encoding + LZMA_encoding
Decompressing = LZMA_decoding + Filter_decoding
Compressing and decompressing speed of such filters is very high,
so it will not increase decompressing time too much.
Moreover, it reduces decompression time for LZMA_decoding,
since compression ratio with filtering is higher.
These filters convert CALL (calling procedure) instructions
from relative offsets to absolute addresses, so such data becomes more
compressible.
For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.
LZMA compressed file format
---------------------------
Offset Size Description
0 1 Special LZMA properties (lc,lp, pb in encoded form)
1 4 Dictionary size (little endian)
5 8 Uncompressed size (little endian). -1 means unknown size
13 Compressed data
ANSI-C LZMA Decoder
~~~~~~~~~~~~~~~~~~~
Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.
If you want to use old interfaces you can download previous version of LZMA SDK
from sourceforge.net site.
To use ANSI-C LZMA Decoder you need the following files:
1) LzmaDec.h + LzmaDec.c + Types.h
LzmaUtil/LzmaUtil.c is example application that uses these files.
Memory requirements for LZMA decoding
-------------------------------------
Stack usage of LZMA decoding function for local variables is not
larger than 200-400 bytes.
LZMA Decoder uses dictionary buffer and internal state structure.
Internal state structure consumes
state_size = (4 + (1.5 << (lc + lp))) KB
by default (lc=3, lp=0), state_size = 16 KB.
How To decompress data
----------------------
LZMA Decoder (ANSI-C version) now supports 2 interfaces:
1) Single-call Decompressing
2) Multi-call State Decompressing (zlib-like interface)
You must use external allocator:
Example:
void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
void SzFree(void *p, void *address) { p = p; free(address); }
ISzAlloc alloc = { SzAlloc, SzFree };
You can use p = p; operator to disable compiler warnings.
Single-call Decompressing
-------------------------
When to use: RAM->RAM decompressing
Compile files: LzmaDec.h + LzmaDec.c + Types.h
Compile defines: no defines
Memory Requirements:
- Input buffer: compressed size
- Output buffer: uncompressed size
- LZMA Internal Structures: state_size (16 KB for default settings)
Interface:
int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc);
In:
dest - output data
destLen - output data size
src - input data
srcLen - input data size
propData - LZMA properties (5 bytes)
propSize - size of propData buffer (5 bytes)
finishMode - It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
You can use LZMA_FINISH_END, when you know that
current output buffer covers last bytes of stream.
alloc - Memory allocator.
Out:
destLen - processed output size
srcLen - processed input size
Output:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
If LZMA decoder sees end_marker before reaching output limit, it returns OK result,
and output value of destLen will be less than output buffer size limit.
You can use multiple checks to test data integrity after full decompression:
1) Check Result and "status" variable.
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
You must use correct finish mode in that case. */
Multi-call State Decompressing (zlib-like interface)
----------------------------------------------------
When to use: file->file decompressing
Compile files: LzmaDec.h + LzmaDec.c + Types.h
Memory Requirements:
- Buffer for input stream: any size (for example, 16 KB)
- Buffer for output stream: any size (for example, 16 KB)
- LZMA Internal Structures: state_size (16 KB for default settings)
- LZMA dictionary (dictionary size is encoded in LZMA properties header)
1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:
unsigned char header[LZMA_PROPS_SIZE + 8];
ReadFile(inFile, header, sizeof(header)
2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties
CLzmaDec state;
LzmaDec_Constr(&state);
res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
if (res != SZ_OK)
return res;
3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop
LzmaDec_Init(&state);
for (;;)
{
...
int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);
...
}
4) Free all allocated structures
LzmaDec_Free(&state, &g_Alloc);
For full code example, look at C/LzmaUtil/LzmaUtil.c code.
How To compress data
--------------------
Compile files: LzmaEnc.h + LzmaEnc.c + Types.h +
LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h
Memory Requirements:
- (dictSize * 11.5 + 6 MB) + state_size
Lzma Encoder can use two memory allocators:
1) alloc - for small arrays.
2) allocBig - for big arrays.
For example, you can use Large RAM Pages (2 MB) in allocBig allocator for
better compression speed. Note that Windows has bad implementation for
Large RAM Pages.
It's OK to use same allocator for alloc and allocBig.
Single-call Compression with callbacks
--------------------------------------
Check C/LzmaUtil/LzmaUtil.c as example,
When to use: file->file decompressing
1) you must implement callback structures for interfaces:
ISeqInStream
ISeqOutStream
ICompressProgress
ISzAlloc
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
CFileSeqInStream inStream;
CFileSeqOutStream outStream;
inStream.funcTable.Read = MyRead;
inStream.file = inFile;
outStream.funcTable.Write = MyWrite;
outStream.file = outFile;
2) Create CLzmaEncHandle object;
CLzmaEncHandle enc;
enc = LzmaEnc_Create(&g_Alloc);
if (enc == 0)
return SZ_ERROR_MEM;
3) initialize CLzmaEncProps properties;
LzmaEncProps_Init(&props);
Then you can change some properties in that structure.
4) Send LZMA properties to LZMA Encoder
res = LzmaEnc_SetProps(enc, &props);
5) Write encoded properties to header
Byte header[LZMA_PROPS_SIZE + 8];
size_t headerSize = LZMA_PROPS_SIZE;
UInt64 fileSize;
int i;
res = LzmaEnc_WriteProperties(enc, header, &headerSize);
fileSize = MyGetFileLength(inFile);
for (i = 0; i < 8; i++)
header[headerSize++] = (Byte)(fileSize >> (8 * i));
MyWriteFileAndCheck(outFile, header, headerSize)
6) Call encoding function:
res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable,
NULL, &g_Alloc, &g_Alloc);
7) Destroy LZMA Encoder Object
LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
If callback function return some error code, LzmaEnc_Encode also returns that code.
Single-call RAM->RAM Compression
--------------------------------
Single-call RAM->RAM Compression is similar to Compression with callbacks,
but you provide pointers to buffers instead of pointers to stream callbacks:
HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
Return code:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
LZMA Defines
------------
_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.
_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for
some structures will be doubled in that case.
_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit.
_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type.
C++ LZMA Encoder/Decoder
~~~~~~~~~~~~~~~~~~~~~~~~
C++ LZMA code use COM-like interfaces. So if you want to use it,
you can study basics of COM/OLE.
C++ LZMA code is just wrapper over ANSI-C code.
C++ Notes
~~~~~~~~~~~~~~~~~~~~~~~~
If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),
you must check that you correctly work with "new" operator.
7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.
So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:
operator new(size_t size)
{
void *p = ::malloc(size);
if (p == 0)
throw CNewException();
return p;
}
If you use MSCV that throws exception for "new" operator, you can compile without
"NewHandler.cpp". So standard exception will be used. Actually some code of
7-Zip catches any exception in internal code and converts it to HRESULT code.
So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.
---
http://www.7-zip.org
http://www.7-zip.org/sdk.html
http://www.7-zip.org/support.html

View File

@ -0,0 +1,92 @@
/* Threads.c -- multithreading library
2012-12-20 : Chris Moeller : Public domain */
#include "Threads.h"
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
{
int ret;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
ret = pthread_create( &p->thread, &attr, func, param );
if ( ret == 0 )
{
p->created = TRUE;
return 0;
}
return -1;
}
WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
{
pthread_mutex_init( &p->mutex, NULL );
pthread_cond_init( &p->cond, NULL );
p->created = TRUE;
p->autoreset = !manualReset;
p->triggered = !!signaled;
return 0;
}
WRes Event_Wait(CEvent *p)
{
pthread_mutex_lock(&p->mutex);
while (!p->triggered)
pthread_cond_wait(&p->cond, &p->mutex);
if ( p->autoreset )
p->triggered = FALSE;
pthread_mutex_unlock(&p->mutex);
return 0;
}
WRes Event_Set(CEvent *p)
{
pthread_mutex_lock(&p->mutex);
p->triggered = TRUE;
pthread_cond_signal(&p->cond);
pthread_mutex_unlock(&p->mutex);
return 0;
}
WRes Event_Reset(CEvent *p)
{
pthread_mutex_lock(&p->mutex);
p->triggered = FALSE;
pthread_mutex_unlock(&p->mutex);
return 0;
}
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
{
sem_init( &p->sem, 0, initCount );
p->maxCount = maxCount;
return 0;
}
static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
{
if (previousCount)
{
int sval = 0;
sem_getvalue( &p->sem, &sval );
*previousCount = sval;
}
while (releaseCount--)
sem_post( &p->sem );
return 0;
}
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
{ return Semaphore_Release(p, (LONG)num, NULL); }
WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
WRes CriticalSection_Init(CCriticalSection *p)
{
pthread_mutex_init( p, NULL );
return 0;
}

View File

@ -0,0 +1,80 @@
/* Threads.h -- multithreading library
2009-03-27 : Igor Pavlov : Public domain */
#ifndef __7Z_THREADS_H
#define __7Z_THREADS_H
#include "../Types.h"
#include <pthread.h>
#include <semaphore.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
pthread_t thread;
BOOL created;
}
CThread;
#define Thread_Construct(p) { (p)->created = FALSE; }
#define Thread_WasCreated(p) ((p)->created)
#define Thread_Close(p) { pthread_join((p)->thread, NULL); (p)->created = FALSE; }
#define Thread_Wait(p) pthread_join((p)->thread, NULL);
typedef void *THREAD_FUNC_RET_TYPE;
#define THREAD_FUNC_CALL_TYPE
#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
typedef struct
{
pthread_mutex_t mutex;
pthread_cond_t cond;
BOOL created;
BOOL autoreset;
BOOL triggered;
} CEvent;
typedef CEvent CAutoResetEvent;
typedef CEvent CManualResetEvent;
#define Event_Construct(p) { (p)->created = FALSE; }
#define Event_IsCreated(p) ((p)->created)
#define Event_Close(p) { (p)->created = FALSE; }
WRes Event_Wait(CEvent *p);
WRes Event_Set(CEvent *p);
WRes Event_Reset(CEvent *p);
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
typedef struct
{
sem_t sem;
UInt32 maxCount;
}
CSemaphore;
#define Semaphore_Construct(p)
#define Semaphore_Close(p)
#define Semaphore_Wait(p) { sem_wait(&((p)->sem)); }
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
WRes Semaphore_Release1(CSemaphore *p);
typedef pthread_mutex_t CCriticalSection;
WRes CriticalSection_Init(CCriticalSection *p);
#define CriticalSection_Delete(p)
#define CriticalSection_Enter(p) pthread_mutex_lock(p)
#define CriticalSection_Leave(p) pthread_mutex_unlock(p)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,19 @@
Modified LZMA 4.65
------------------
This is just the ANSI C 7-zip extraction code from the LZMA 4.65 source
code release, with unnecessary files removed. I've made minor changes to
allow the code to compile with almost all warnings enabled in GCC.
* Made relevant functions extern "C" so that they can be called from
C++.
* Put all files in same directory and removed "../../" from #includes.
* Made private (unprototyped) functions static.
* #if'd out code that is never called.
* Removed a couple of Windows references.
--
Shay Green <gblargg@gmail.com>

View File

@ -0,0 +1,84 @@
/* Threads.c -- multithreading library
2009-09-20 : Igor Pavlov : Public domain */
#ifndef _WIN32_WCE
#include <process.h>
#endif
#include "Threads.h"
static WRes GetError()
{
DWORD res = GetLastError();
return (res) ? (WRes)(res) : 1;
}
WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
WRes HandlePtr_Close(HANDLE *p)
{
if (*p != NULL)
if (!CloseHandle(*p))
return GetError();
*p = NULL;
return 0;
}
WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
{
unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
*p =
#ifdef UNDER_CE
CreateThread(0, 0, func, param, 0, &threadId);
#else
(HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
#endif
/* maybe we must use errno here, but probably GetLastError() is also OK. */
return HandleToWRes(*p);
}
WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
{
*p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
return HandleToWRes(*p);
}
WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }
WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
{
*p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
return HandleToWRes(*p);
}
static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
{ return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
{ return Semaphore_Release(p, (LONG)num, NULL); }
WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
WRes CriticalSection_Init(CCriticalSection *p)
{
/* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
#ifdef _MSC_VER
__try
#endif
{
InitializeCriticalSection(p);
/* InitializeCriticalSectionAndSpinCount(p, 0); */
}
#ifdef _MSC_VER
__except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
#endif
return 0;
}

View File

@ -0,0 +1,59 @@
/* Threads.h -- multithreading library
2009-03-27 : Igor Pavlov : Public domain */
#ifndef __7Z_THREADS_H
#define __7Z_THREADS_H
#include "../Types.h"
#ifdef __cplusplus
extern "C" {
#endif
WRes HandlePtr_Close(HANDLE *h);
WRes Handle_WaitObject(HANDLE h);
typedef HANDLE CThread;
#define Thread_Construct(p) *(p) = NULL
#define Thread_WasCreated(p) (*(p) != NULL)
#define Thread_Close(p) HandlePtr_Close(p)
#define Thread_Wait(p) Handle_WaitObject(*(p))
typedef unsigned THREAD_FUNC_RET_TYPE;
#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
typedef HANDLE CEvent;
typedef CEvent CAutoResetEvent;
typedef CEvent CManualResetEvent;
#define Event_Construct(p) *(p) = NULL
#define Event_IsCreated(p) (*(p) != NULL)
#define Event_Close(p) HandlePtr_Close(p)
#define Event_Wait(p) Handle_WaitObject(*(p))
WRes Event_Set(CEvent *p);
WRes Event_Reset(CEvent *p);
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
typedef HANDLE CSemaphore;
#define Semaphore_Construct(p) (*p) = NULL
#define Semaphore_Close(p) HandlePtr_Close(p)
#define Semaphore_Wait(p) Handle_WaitObject(*(p))
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
WRes Semaphore_Release1(CSemaphore *p);
typedef CRITICAL_SECTION CCriticalSection;
WRes CriticalSection_Init(CCriticalSection *p);
#define CriticalSection_Delete(p) DeleteCriticalSection(p)
#define CriticalSection_Enter(p) EnterCriticalSection(p)
#define CriticalSection_Leave(p) LeaveCriticalSection(p)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>NoWork-Inc.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2013 Christopher Snowhill. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

View File

@ -0,0 +1,77 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Binary_Extractor.h"
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
// TODO: could close file once data has been read into memory
static File_Extractor* new_binary()
{
return BLARGG_NEW Binary_Extractor;
}
fex_type_t_ const fex_bin_type [1] = {{
"",
&new_binary,
"file",
NULL
}};
Binary_Extractor::Binary_Extractor() :
File_Extractor( fex_bin_type )
{ }
Binary_Extractor::~Binary_Extractor()
{
close();
}
blargg_err_t Binary_Extractor::open_path_v()
{
set_name( arc_path() );
return blargg_ok;
}
blargg_err_t Binary_Extractor::open_v()
{
set_name( arc_path() );
set_info( arc().remain(), 0, 0 );
return blargg_ok;
}
void Binary_Extractor::close_v()
{ }
blargg_err_t Binary_Extractor::next_v()
{
return blargg_ok;
}
blargg_err_t Binary_Extractor::rewind_v()
{
return open_path_v();
}
blargg_err_t Binary_Extractor::stat_v()
{
RETURN_ERR( open_arc_file() );
RETURN_ERR( arc().seek( 0 ) );
return open_v();
}
blargg_err_t Binary_Extractor::extract_v( void* p, int n )
{
return arc().read( p, n );
}

View File

@ -0,0 +1,26 @@
// Presents a single file as an "archive" of just that file.
// File_Extractor 1.0.0
#ifndef BINARY_EXTRACTOR_H
#define BINARY_EXTRACTOR_H
#include "File_Extractor.h"
class Binary_Extractor : public File_Extractor {
public:
Binary_Extractor();
virtual ~Binary_Extractor();
protected:
virtual blargg_err_t open_path_v();
virtual blargg_err_t open_v();
virtual void close_v();
virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v();
virtual blargg_err_t stat_v();
virtual blargg_err_t extract_v( void*, int );
};
#endif

View File

@ -0,0 +1,764 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Data_Reader.h"
#include "blargg_endian.h"
#include <stdio.h>
#include <errno.h>
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
// Data_Reader
blargg_err_t Data_Reader::read( void* p, int n )
{
assert( n >= 0 );
if ( n < 0 )
return blargg_err_caller;
if ( n <= 0 )
return blargg_ok;
if ( n > remain() )
return blargg_err_file_eof;
blargg_err_t err = read_v( p, n );
if ( !err )
remain_ -= n;
return err;
}
blargg_err_t Data_Reader::read_avail( void* p, int* n_ )
{
assert( *n_ >= 0 );
int n = min( (BOOST::uint64_t)(*n_), remain() );
*n_ = 0;
if ( n < 0 )
return blargg_err_caller;
if ( n <= 0 )
return blargg_ok;
blargg_err_t err = read_v( p, n );
if ( !err )
{
remain_ -= n;
*n_ = n;
}
return err;
}
blargg_err_t Data_Reader::read_avail( void* p, long* n )
{
int i = STATIC_CAST(int, *n);
blargg_err_t err = read_avail( p, &i );
*n = i;
return err;
}
blargg_err_t Data_Reader::skip_v( int count )
{
char buf [512];
while ( count )
{
int n = min( count, (int) sizeof buf );
count -= n;
RETURN_ERR( read_v( buf, n ) );
}
return blargg_ok;
}
blargg_err_t Data_Reader::skip( int n )
{
assert( n >= 0 );
if ( n < 0 )
return blargg_err_caller;
if ( n <= 0 )
return blargg_ok;
if ( n > remain() )
return blargg_err_file_eof;
blargg_err_t err = skip_v( n );
if ( !err )
remain_ -= n;
return err;
}
// File_Reader
blargg_err_t File_Reader::seek( BOOST::uint64_t n )
{
assert( n >= 0 );
if ( n < 0 )
return blargg_err_caller;
if ( n == tell() )
return blargg_ok;
if ( n > size() )
return blargg_err_file_eof;
blargg_err_t err = seek_v( n );
if ( !err )
set_tell( n );
return err;
}
blargg_err_t File_Reader::skip_v( BOOST::uint64_t n )
{
return seek_v( tell() + n );
}
// Subset_Reader
Subset_Reader::Subset_Reader( Data_Reader* dr, BOOST::uint64_t size ) :
in( dr )
{
set_remain( min( size, dr->remain() ) );
}
blargg_err_t Subset_Reader::read_v( void* p, int s )
{
return in->read( p, s );
}
// Remaining_Reader
Remaining_Reader::Remaining_Reader( void const* h, int size, Data_Reader* r ) :
in( r )
{
header = h;
header_remain = size;
set_remain( size + r->remain() );
}
blargg_err_t Remaining_Reader::read_v( void* out, int count )
{
int first = min( count, header_remain );
if ( first )
{
memcpy( out, header, first );
header = STATIC_CAST(char const*, header) + first;
header_remain -= first;
}
return in->read( STATIC_CAST(char*, out) + first, count - first );
}
// Mem_File_Reader
Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
begin( STATIC_CAST(const char*, p) )
{
set_size( s );
}
blargg_err_t Mem_File_Reader::read_v( void* p, int s )
{
memcpy( p, begin + tell(), s );
return blargg_ok;
}
blargg_err_t Mem_File_Reader::seek_v( int )
{
return blargg_ok;
}
// Callback_Reader
Callback_Reader::Callback_Reader( callback_t c, BOOST::uint64_t s, void* d ) :
callback( c ),
user_data( d )
{
set_remain( s );
}
blargg_err_t Callback_Reader::read_v( void* out, int count )
{
return callback( user_data, out, count );
}
// Callback_File_Reader
Callback_File_Reader::Callback_File_Reader( callback_t c, BOOST::uint64_t s, void* d ) :
callback( c ),
user_data( d )
{
set_size( s );
}
blargg_err_t Callback_File_Reader::read_v( void* out, int count )
{
return callback( user_data, out, count, tell() );
}
blargg_err_t Callback_File_Reader::seek_v( int )
{
return blargg_ok;
}
static const BOOST::uint8_t mask_tab[6]={0x80,0xE0,0xF0,0xF8,0xFC,0xFE};
static const BOOST::uint8_t val_tab[6]={0,0xC0,0xE0,0xF0,0xF8,0xFC};
size_t utf8_char_len_from_header( char p_c )
{
BOOST::uint8_t c = (BOOST::uint8_t)p_c;
size_t cnt = 0;
for(;;)
{
if ( ( p_c & mask_tab[cnt] ) == val_tab[cnt] ) break;
if ( ++cnt >= 6 ) return 0;
}
return cnt + 1;
}
size_t utf8_decode_char( const char *p_utf8, unsigned & wide, size_t mmax )
{
const BOOST::uint8_t * utf8 = ( const BOOST::uint8_t* )p_utf8;
if ( mmax == 0 )
{
wide = 0;
return 0;
}
if ( utf8[0] < 0x80 )
{
wide = utf8[0];
return utf8[0]>0 ? 1 : 0;
}
if ( mmax > 6 ) mmax = 6;
wide = 0;
unsigned res=0;
unsigned n;
unsigned cnt=0;
for(;;)
{
if ( ( *utf8 & mask_tab[cnt] ) == val_tab[cnt] ) break;
if ( ++cnt >= mmax ) return 0;
}
cnt++;
if ( cnt==2 && !( *utf8 & 0x1E ) ) return 0;
if ( cnt == 1 )
res = *utf8;
else
res = ( 0xFF >> ( cnt + 1 ) ) & *utf8;
for ( n = 1; n < cnt; n++ )
{
if ( ( utf8[n] & 0xC0 ) != 0x80 )
return 0;
if ( !res && n == 2 && !( ( utf8[n] & 0x7F ) >> ( 7 - cnt ) ) )
return 0;
res = ( res << 6 ) | ( utf8[n] & 0x3F );
}
wide = res;
return cnt;
}
size_t utf8_encode_char( unsigned wide, char * target )
{
size_t count;
if ( wide < 0x80 )
count = 1;
else if ( wide < 0x800 )
count = 2;
else if ( wide < 0x10000 )
count = 3;
else if ( wide < 0x200000 )
count = 4;
else if ( wide < 0x4000000 )
count = 5;
else if ( wide <= 0x7FFFFFFF )
count = 6;
else
return 0;
if ( target == 0 )
return count;
switch ( count )
{
case 6:
target[5] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x4000000;
case 5:
target[4] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x200000;
case 4:
target[3] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x10000;
case 3:
target[2] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x800;
case 2:
target[1] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0xC0;
case 1:
target[0] = wide;
}
return count;
}
size_t utf16_encode_char( unsigned cur_wchar, blargg_wchar_t * out )
{
if ( cur_wchar < 0x10000 )
{
if ( out ) *out = (blargg_wchar_t) cur_wchar; return 1;
}
else if ( cur_wchar < ( 1 << 20 ) )
{
unsigned c = cur_wchar - 0x10000;
//MSDN:
//The first (high) surrogate is a 16-bit code value in the range U+D800 to U+DBFF. The second (low) surrogate is a 16-bit code value in the range U+DC00 to U+DFFF. Using surrogates, Unicode can support over one million characters. For more details about surrogates, refer to The Unicode Standard, version 2.0.
if ( out )
{
out[0] = ( blargg_wchar_t )( 0xD800 | ( 0x3FF & ( c >> 10 ) ) );
out[1] = ( blargg_wchar_t )( 0xDC00 | ( 0x3FF & c ) ) ;
}
return 2;
}
else
{
if ( out ) *out = '?'; return 1;
}
}
size_t utf16_decode_char( const blargg_wchar_t * p_source, unsigned * p_out, size_t p_source_length )
{
if ( p_source_length == 0 ) return 0;
else if ( p_source_length == 1 )
{
*p_out = p_source[0];
return 1;
}
else
{
size_t retval = 0;
unsigned decoded = p_source[0];
if ( decoded != 0 )
{
retval = 1;
if ( ( decoded & 0xFC00 ) == 0xD800 )
{
unsigned low = p_source[1];
if ( ( low & 0xFC00 ) == 0xDC00 )
{
decoded = 0x10000 + ( ( ( decoded & 0x3FF ) << 10 ) | ( low & 0x3FF ) );
retval = 2;
}
}
}
*p_out = decoded;
return retval;
}
}
// Converts wide-character path to UTF-8. Free result with free(). Only supported on Windows.
char* blargg_to_utf8( const blargg_wchar_t* wpath )
{
if ( wpath == NULL )
return NULL;
size_t needed = 0;
size_t mmax = blargg_wcslen( wpath );
if ( mmax <= 0 )
return NULL;
size_t ptr = 0;
while ( ptr < mmax )
{
unsigned wide = 0;
size_t char_len = utf16_decode_char( wpath + ptr, &wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
needed += utf8_encode_char( wide, 0 );
}
if ( needed <= 0 )
return NULL;
char* path = (char*) calloc( needed + 1, 1 );
if ( path == NULL )
return NULL;
ptr = 0;
size_t actual = 0;
while ( ptr < mmax && actual < needed )
{
unsigned wide = 0;
size_t char_len = utf16_decode_char( wpath + ptr, &wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
actual += utf8_encode_char( wide, path + actual );
}
if ( actual == 0 )
{
free( path );
return NULL;
}
assert( actual == needed );
return path;
}
// Converts UTF-8 path to wide-character. Free result with free() Only supported on Windows.
blargg_wchar_t* blargg_to_wide( const char* path )
{
if ( path == NULL )
return NULL;
size_t mmax = strlen( path );
if ( mmax <= 0 )
return NULL;
size_t needed = 0;
size_t ptr = 0;
while ( ptr < mmax )
{
unsigned wide = 0;
size_t char_len = utf8_decode_char( path + ptr, wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
needed += utf16_encode_char( wide, 0 );
}
if ( needed <= 0 )
return NULL;
blargg_wchar_t* wpath = (blargg_wchar_t*) calloc( needed + 1, sizeof *wpath );
if ( wpath == NULL )
return NULL;
ptr = 0;
size_t actual = 0;
while ( ptr < mmax && actual < needed )
{
unsigned wide = 0;
size_t char_len = utf8_decode_char( path + ptr, wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
actual += utf16_encode_char( wide, wpath + actual );
}
if ( actual == 0 )
{
free( wpath );
return NULL;
}
assert( actual == needed );
return wpath;
}
#ifdef _WIN32
static FILE* blargg_fopen( const char path [], const char mode [] )
{
FILE* file = NULL;
blargg_wchar_t* wmode = NULL;
blargg_wchar_t* wpath = NULL;
wpath = blargg_to_wide( path );
if ( wpath )
{
wmode = blargg_to_wide( mode );
if ( wmode )
file = _wfopen( wpath, wmode );
}
// Save and restore errno in case free() clears it
int saved_errno = errno;
free( wmode );
free( wpath );
errno = saved_errno;
return file;
}
#else
static inline FILE* blargg_fopen( const char path [], const char mode [] )
{
return fopen( path, mode );
}
#endif
// Std_File_Reader
Std_File_Reader::Std_File_Reader()
{
file_ = NULL;
}
Std_File_Reader::~Std_File_Reader()
{
close();
}
static blargg_err_t blargg_fopen( FILE** out, const char path [] )
{
errno = 0;
*out = blargg_fopen( path, "rb" );
if ( !*out )
{
#ifdef ENOENT
if ( errno == ENOENT )
return blargg_err_file_missing;
#endif
#ifdef ENOMEM
if ( errno == ENOMEM )
return blargg_err_memory;
#endif
return blargg_err_file_read;
}
return blargg_ok;
}
static blargg_err_t blargg_fsize( FILE* f, long* out )
{
if ( fseek( f, 0, SEEK_END ) )
return blargg_err_file_io;
*out = ftell( f );
if ( *out < 0 )
return blargg_err_file_io;
if ( fseek( f, 0, SEEK_SET ) )
return blargg_err_file_io;
return blargg_ok;
}
blargg_err_t Std_File_Reader::open( const char path [] )
{
close();
FILE* f;
RETURN_ERR( blargg_fopen( &f, path ) );
long s;
blargg_err_t err = blargg_fsize( f, &s );
if ( err )
{
fclose( f );
return err;
}
file_ = f;
set_size( s );
return blargg_ok;
}
void Std_File_Reader::make_unbuffered()
{
if ( setvbuf( STATIC_CAST(FILE*, file_), NULL, _IONBF, 0 ) )
check( false ); // shouldn't fail, but OK if it does
}
blargg_err_t Std_File_Reader::read_v( void* p, int s )
{
if ( (size_t) s != fread( p, 1, s, STATIC_CAST(FILE*, file_) ) )
{
// Data_Reader's wrapper should prevent EOF
check( !feof( STATIC_CAST(FILE*, file_) ) );
return blargg_err_file_io;
}
return blargg_ok;
}
blargg_err_t Std_File_Reader::seek_v( BOOST::uint64_t n )
{
#ifdef _WIN32
if ( _fseeki64( STATIC_CAST(FILE*, file_), n, SEEK_SET ) )
#else
if ( fseeko( STATIC_CAST(FILE*, file_), n, SEEK_SET ) )
#endif
{
// Data_Reader's wrapper should prevent EOF
check( !feof( STATIC_CAST(FILE*, file_) ) );
return blargg_err_file_io;
}
return blargg_ok;
}
void Std_File_Reader::close()
{
if ( file_ )
{
fclose( STATIC_CAST(FILE*, file_) );
file_ = NULL;
}
}
// Gzip_File_Reader
#ifdef HAVE_ZLIB_H
#include "zlib.h"
static const char* get_gzip_eof( const char path [], long* eof )
{
FILE* file;
RETURN_ERR( blargg_fopen( &file, path ) );
int const h_size = 4;
unsigned char h [h_size];
// read four bytes to ensure that we can seek to -4 later
if ( fread( h, 1, h_size, file ) != (size_t) h_size || h[0] != 0x1F || h[1] != 0x8B )
{
// Not gzipped
if ( ferror( file ) )
return blargg_err_file_io;
if ( fseek( file, 0, SEEK_END ) )
return blargg_err_file_io;
*eof = ftell( file );
if ( *eof < 0 )
return blargg_err_file_io;
}
else
{
// Gzipped; get uncompressed size from end
if ( fseek( file, -h_size, SEEK_END ) )
return blargg_err_file_io;
if ( fread( h, 1, h_size, file ) != (size_t) h_size )
return blargg_err_file_io;
*eof = get_le32( h );
}
if ( fclose( file ) )
check( false );
return blargg_ok;
}
Gzip_File_Reader::Gzip_File_Reader()
{
file_ = NULL;
}
Gzip_File_Reader::~Gzip_File_Reader()
{
close();
}
blargg_err_t Gzip_File_Reader::open( const char path [] )
{
close();
long s;
RETURN_ERR( get_gzip_eof( path, &s ) );
file_ = gzopen( path, "rb" );
if ( !file_ )
return blargg_err_file_read;
set_size( s );
return blargg_ok;
}
static blargg_err_t convert_gz_error( gzFile file )
{
int err;
gzerror( file, &err );
switch ( err )
{
case Z_STREAM_ERROR: break;
case Z_DATA_ERROR: return blargg_err_file_corrupt;
case Z_MEM_ERROR: return blargg_err_memory;
case Z_BUF_ERROR: break;
}
return blargg_err_internal;
}
blargg_err_t Gzip_File_Reader::read_v( void* p, int s )
{
int result = gzread( (gzFile) file_, p, s );
if ( result != s )
{
if ( result < 0 )
return convert_gz_error( (gzFile) file_ );
return blargg_err_file_corrupt;
}
return blargg_ok;
}
blargg_err_t Gzip_File_Reader::seek_v( int n )
{
if ( gzseek( (gzFile) file_, n, SEEK_SET ) < 0 )
return convert_gz_error( (gzFile) file_ );
return blargg_ok;
}
void Gzip_File_Reader::close()
{
if ( file_ )
{
if ( gzclose( (gzFile) file_ ) )
check( false );
file_ = NULL;
}
}
#endif

View File

@ -0,0 +1,274 @@
// Lightweight interface for reading data from byte stream
// File_Extractor 1.0.0
#ifndef DATA_READER_H
#define DATA_READER_H
#include "blargg_common.h"
/* Some functions accept a long instead of int for convenience where caller has
a long due to some other interface, and would otherwise have to get a warning,
or cast it (and verify that it wasn't outside the range of an int).
To really support huge (>2GB) files, long isn't a solution, since there's no
guarantee it's more than 32 bits. We'd need to use long long (if available), or
something compiler-specific, and change all places file sizes or offsets are
used. */
// Supports reading and finding out how many bytes are remaining
class Data_Reader {
public:
// Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more
// tham remain() bytes doesn't result in error, just *n being set to remain().
blargg_err_t read_avail( void* p, int* n );
blargg_err_t read_avail( void* p, long* n );
// Reads exactly n bytes, or returns error if they couldn't ALL be read.
// Reading past end of file results in blargg_err_file_eof.
blargg_err_t read( void* p, int n );
// Number of bytes remaining until end of file
BOOST::uint64_t remain() const { return remain_; }
// Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof.
blargg_err_t skip( int n );
virtual ~Data_Reader() { }
private:
// noncopyable
Data_Reader( const Data_Reader& );
Data_Reader& operator = ( const Data_Reader& );
// Derived interface
protected:
Data_Reader() : remain_( 0 ) { }
// Sets remain
void set_remain( BOOST::uint64_t n ) { assert( n >= 0 ); remain_ = n; }
// Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated
// AFTER this call succeeds, not before. set_remain() should NOT be called from this.
virtual blargg_err_t read_v( void*, int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
// Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data
// and discards it. Value of remain() is updated AFTER this call succeeds, not
// before. set_remain() should NOT be called from this.
virtual blargg_err_t skip_v( int n );
// Implementation
public:
BLARGG_DISABLE_NOTHROW
private:
BOOST::uint64_t remain_;
};
// Supports seeking in addition to Data_Reader operations
class File_Reader : public Data_Reader {
public:
// Size of file
BOOST::uint64_t size() const { return size_; }
// Current position in file
BOOST::uint64_t tell() const { return size_ - remain(); }
// Goes to new position
blargg_err_t seek( BOOST::uint64_t );
// Derived interface
protected:
// Sets size and resets position
void set_size( BOOST::uint64_t n ) { size_ = n; Data_Reader::set_remain( n ); }
void set_size( int n ) { set_size( STATIC_CAST(BOOST::uint64_t, n) ); }
void set_size( long n ) { set_size( STATIC_CAST(BOOST::uint64_t, n) ); }
// Sets reported position
void set_tell( BOOST::uint64_t i ) { assert( 0 <= i && i <= size_ ); Data_Reader::set_remain( size_ - i ); }
// Do same as seek(). Guaranteed that 0 <= n <= size(). Value of tell() is updated
// AFTER this call succeeds, not before. set_* functions should NOT be called from this.
virtual blargg_err_t seek_v( BOOST::uint64_t n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
// Implementation
protected:
File_Reader() : size_( 0 ) { }
virtual blargg_err_t skip_v( BOOST::uint64_t );
private:
BOOST::uint64_t size_;
void set_remain(); // avoid accidental use of set_remain
};
// Reads from file on disk
class Std_File_Reader : public File_Reader {
public:
// Opens file
blargg_err_t open( const char path [] );
// Closes file if one was open
void close();
// Switches to unbuffered mode. Useful if buffering is already being
// done at a higher level.
void make_unbuffered();
// Implementation
public:
Std_File_Reader();
virtual ~Std_File_Reader();
protected:
virtual blargg_err_t read_v( void*, int );
virtual blargg_err_t seek_v( BOOST::uint64_t );
private:
void* file_;
};
// Treats range of memory as a file
class Mem_File_Reader : public File_Reader {
public:
Mem_File_Reader( const void* begin, long size );
// Implementation
protected:
virtual blargg_err_t read_v( void*, int );
virtual blargg_err_t seek_v( int );
private:
const char* const begin;
};
// Allows only count bytes to be read from reader passed
class Subset_Reader : public Data_Reader {
public:
Subset_Reader( Data_Reader*, BOOST::uint64_t count );
// Implementation
protected:
virtual blargg_err_t read_v( void*, int );
private:
Data_Reader* const in;
};
// Joins already-read header and remaining data into original file.
// Meant for cases where you've already read header and don't want
// to seek and re-read data (for efficiency).
class Remaining_Reader : public Data_Reader {
public:
Remaining_Reader( void const* header, int header_size, Data_Reader* );
// Implementation
protected:
virtual blargg_err_t read_v( void*, int );
private:
Data_Reader* const in;
void const* header;
int header_remain;
};
// Invokes callback function to read data
extern "C" { // necessary to be usable from C
typedef const char* (*callback_reader_func_t)(
void* user_data, // Same value passed to constructor
void* out, // Buffer to place data into
int count // Number of bytes to read
);
}
class Callback_Reader : public Data_Reader {
public:
typedef callback_reader_func_t callback_t;
Callback_Reader( callback_t, BOOST::uint64_t size, void* user_data );
// Implementation
protected:
virtual blargg_err_t read_v( void*, int );
private:
callback_t const callback;
void* const user_data;
};
// Invokes callback function to read data
extern "C" { // necessary to be usable from C
typedef const char* (*callback_file_reader_func_t)(
void* user_data, // Same value passed to constructor
void* out, // Buffer to place data into
int count, // Number of bytes to read
BOOST::uint64_t pos // Position in file to read from
);
}
class Callback_File_Reader : public File_Reader {
public:
typedef callback_file_reader_func_t callback_t;
Callback_File_Reader( callback_t, BOOST::uint64_t size, void* user_data );
// Implementation
protected:
virtual blargg_err_t read_v( void*, int );
virtual blargg_err_t seek_v( int );
private:
callback_t const callback;
void* const user_data;
};
#ifdef HAVE_ZLIB_H
// Reads file compressed with gzip (or uncompressed)
class Gzip_File_Reader : public File_Reader {
public:
// Opens possibly gzipped file
blargg_err_t open( const char path [] );
// Closes file if one was open
void close();
// Implementation
public:
Gzip_File_Reader();
~Gzip_File_Reader();
protected:
virtual blargg_err_t read_v( void*, int );
virtual blargg_err_t seek_v( int );
private:
// void* so "zlib.h" doesn't have to be included here
void* file_;
};
#endif
#ifdef _WIN32
typedef wchar_t blargg_wchar_t;
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
typedef uint16_t blargg_wchar_t;
#else
typedef unsigned short blargg_wchar_t;
#endif
char* blargg_to_utf8( const blargg_wchar_t* );
blargg_wchar_t* blargg_to_wide( const char* );
#endif

View File

@ -0,0 +1,341 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "File_Extractor.h"
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
File_Extractor::fex_t( fex_type_t t ) :
type_( t )
{
own_file_ = NULL;
close_();
}
// Open
blargg_err_t File_Extractor::set_path( const char* path )
{
if ( !path )
path = "";
RETURN_ERR( path_.resize( strlen( path ) + 1 ) );
memcpy( path_.begin(), path, path_.size() );
return blargg_ok;
}
blargg_err_t File_Extractor::open( const char path [] )
{
close();
RETURN_ERR( set_path( path ) );
blargg_err_t err = open_path_v();
if ( err )
close();
else
opened_ = true;
return err;
}
blargg_err_t File_Extractor::open_path_v()
{
RETURN_ERR( open_arc_file() );
return open_v();
}
inline
static void make_unbuffered( Std_File_Reader* r )
{
r->make_unbuffered();
}
inline
static void make_unbuffered( void* )
{ }
blargg_err_t File_Extractor::open_arc_file( bool unbuffered )
{
if ( reader_ )
return blargg_ok;
FEX_FILE_READER* in = BLARGG_NEW FEX_FILE_READER;
CHECK_ALLOC( in );
blargg_err_t err = in->open( arc_path() );
if ( err )
{
delete in;
}
else
{
reader_ = in;
own_file();
if ( unbuffered )
make_unbuffered( in );
}
return err;
}
blargg_err_t File_Extractor::open( File_Reader* input, const char* path )
{
close();
RETURN_ERR( set_path( path ) );
RETURN_ERR( input->seek( 0 ) );
reader_ = input;
blargg_err_t err = open_v();
if ( err )
close();
else
opened_ = true;
return err;
}
// Close
void File_Extractor::close()
{
close_v();
close_();
}
void File_Extractor::close_()
{
delete own_file_;
own_file_ = NULL;
tell_ = 0;
reader_ = NULL;
opened_ = false;
path_.clear();
clear_file();
}
File_Extractor::~fex_t()
{
check( !opened() ); // fails if derived destructor didn't call close()
delete own_file_;
}
// Scanning
void File_Extractor::clear_file()
{
name_ = NULL;
wname_ = NULL;
done_ = true;
stat_called = false;
data_ptr_ = NULL;
set_info( 0 );
own_data_.clear();
clear_file_v();
}
void File_Extractor::set_name( const char new_name [], const blargg_wchar_t* new_wname )
{
name_ = new_name;
wname_ = new_wname;
done_ = false;
}
void File_Extractor::set_info( BOOST::uint64_t new_size, unsigned date, unsigned crc )
{
size_ = new_size;
date_ = (date != 0xFFFFFFFF ? date : 0);
crc32_ = crc;
set_remain( new_size );
}
blargg_err_t File_Extractor::next_()
{
tell_++;
clear_file();
blargg_err_t err = next_v();
if ( err )
clear_file();
return err;
}
blargg_err_t File_Extractor::next()
{
assert( !done() );
return next_();
}
blargg_err_t File_Extractor::rewind()
{
assert( opened() );
tell_ = 0;
clear_file();
blargg_err_t err = rewind_v();
if ( err )
clear_file();
return err;
}
blargg_err_t File_Extractor::stat()
{
assert( !done() );
if ( !stat_called )
{
RETURN_ERR( stat_v() );
stat_called = true;
}
return blargg_ok;
}
// Tell/seek
int const pos_offset = 1;
fex_pos_t File_Extractor::tell_arc() const
{
assert( opened() );
fex_pos_t pos = tell_arc_v();
assert( pos >= 0 );
return pos + pos_offset;
}
blargg_err_t File_Extractor::seek_arc( fex_pos_t pos )
{
assert( opened() );
assert( pos != 0 );
clear_file();
blargg_err_t err = seek_arc_v( pos - pos_offset );
if ( err )
clear_file();
return err;
}
fex_pos_t File_Extractor::tell_arc_v() const
{
return tell_;
}
blargg_err_t File_Extractor::seek_arc_v( fex_pos_t pos )
{
// >= because seeking to current file should always reset read pointer etc.
if ( tell_ >= pos )
RETURN_ERR( rewind() );
while ( tell_ < pos )
{
RETURN_ERR( next_() );
if ( done() )
{
assert( false );
return blargg_err_caller;
}
}
assert( tell_ == pos );
return blargg_ok;
}
// Extraction
blargg_err_t File_Extractor::rewind_file()
{
RETURN_ERR( stat() );
if ( tell() > 0 )
{
if ( data_ptr_ )
{
set_remain( size() );
}
else
{
RETURN_ERR( seek_arc( tell_arc() ) );
RETURN_ERR( stat() );
}
}
return blargg_ok;
}
blargg_err_t File_Extractor::data( const void** data_out )
{
assert( !done() );
*data_out = NULL;
if ( !data_ptr_ )
{
BOOST::uint64_t old_tell = tell();
RETURN_ERR( rewind_file() );
void const* ptr;
RETURN_ERR( data_v( &ptr ) );
data_ptr_ = ptr;
// Now that data is in memory, we can seek by simply setting remain
set_remain( size() - old_tell );
}
*data_out = data_ptr_;
return blargg_ok;
}
blargg_err_t File_Extractor::data_v( void const** out )
{
RETURN_ERR( own_data_.resize( size() ) );
*out = own_data_.begin();
blargg_err_t err = extract_v( own_data_.begin(), own_data_.size() );
if ( err )
own_data_.clear();
return err;
}
blargg_err_t File_Extractor::extract_v( void* out, int count )
{
void const* p;
RETURN_ERR( data( &p ) );
memcpy( out, STATIC_CAST(char const*,p) + (size() - remain()), count );
return blargg_ok;
}
blargg_err_t File_Extractor::read_v( void* out, int count )
{
if ( data_ptr_ )
return File_Extractor::extract_v( out, count );
return extract_v( out, count );
}

View File

@ -0,0 +1,191 @@
// Compressed file archive interface
// File_Extractor 1.0.0
#ifndef FILE_EXTRACTOR_H
#define FILE_EXTRACTOR_H
#include "blargg_common.h"
#include "Data_Reader.h"
#include "fex.h"
struct fex_t : private Data_Reader {
public:
virtual ~fex_t();
// Open/close
// Opens archive from custom data source. Keeps pointer until close().
blargg_err_t open( File_Reader* input, const char* path = NULL );
// Takes ownership of File_Reader* passed to open(), so that close()
// will delete it.
void own_file() { own_file_ = reader_; }
// See fex.h
blargg_err_t open( const char path [] );
fex_type_t type() const { return type_; }
void close();
// Scanning
// See fex.h
bool done() const { return done_; }
blargg_err_t next();
blargg_err_t rewind();
fex_pos_t tell_arc() const;
blargg_err_t seek_arc( fex_pos_t );
// Info
// See fex.h
const char* name() const { return name_; }
const blargg_wchar_t* wname() const { return wname_; }
blargg_err_t stat();
BOOST::uint64_t size() const { assert( stat_called ); return size_; }
unsigned int dos_date() const { return date_; }
unsigned int crc32() const { return crc32_; }
// Extraction
// Data_Reader to current file's data, so standard Data_Reader interface can
// be used, rather than having to treat archives specially. stat() must have
// been called.
Data_Reader& reader() { assert( stat_called ); return *this; }
// See fex.h
blargg_err_t data( const void** data_out );
BOOST::uint64_t tell() const { return size_ - remain(); }
// Derived interface
protected:
// Sets type of object
fex_t( fex_type_t );
// Path to archive file, or "" if none supplied
const char* arc_path() const { return path_.begin(); }
// Opens archive file if it's not already. If unbuffered is true, opens file
// without any buffering.
blargg_err_t open_arc_file( bool unbuffered = false );
// Archive file
File_Reader& arc() const { return *reader_; }
// Sets current file name
void set_name( const char name [], const blargg_wchar_t* wname = NULL );
// Sets current file information
void set_info( BOOST::uint64_t size, unsigned date = 0, unsigned crc = 0 );
// User overrides
// Overrides must do indicated task. Non-pure functions have reasonable default
// implementation. Overrides should avoid calling public functions like
// next() and rewind().
// Open archive using file_path(). OK to delay actual file opening until later.
// Default just calls open_arc_file(), then open_v().
virtual blargg_err_t open_path_v();
// Open archive using file() for source data. If unsupported, return error.
virtual blargg_err_t open_v() BLARGG_PURE( ; )
// Go to next file in archive and call set_name() and optionally set_info()
virtual blargg_err_t next_v() BLARGG_PURE( ; )
// Go back to first file in archive
virtual blargg_err_t rewind_v() BLARGG_PURE( ; )
// Close archive. Called even if open_path_v() or open_v() return unsuccessfully.
virtual void close_v() BLARGG_PURE( ; )
// Clear any fields related to current file
virtual void clear_file_v() { }
// Call set_info() if not already called by next_v()
virtual blargg_err_t stat_v() { return blargg_ok; }
// Return value that allows later return to this file. Result must be >= 0.
virtual fex_pos_t tell_arc_v() const;
// Return to previously saved position
virtual blargg_err_t seek_arc_v( fex_pos_t );
// One or both of the following must be overridden
// Provide pointer to data for current file in archive
virtual blargg_err_t data_v( const void** out );
// Extract next n bytes
virtual blargg_err_t extract_v( void* out, int n );
// Implementation
public:
BLARGG_DISABLE_NOTHROW
private:
fex_type_t const type_;
// Archive file
blargg_vector<char> path_;
File_Reader* reader_;
File_Reader* own_file_;
bool opened_;
// Position in archive
fex_pos_t tell_; // only used by default implementation of tell/seek
bool done_;
// Info for current file in archive
const char* name_;
const blargg_wchar_t* wname_;
unsigned date_;
unsigned crc32_;
BOOST::uint64_t size_;
bool stat_called;
// Current file contents
void const* data_ptr_; // NULL if not read into memory
blargg_vector<char> own_data_;
bool opened() const { return opened_; }
void clear_file();
void close_();
blargg_err_t set_path( const char* path );
blargg_err_t rewind_file();
blargg_err_t next_();
// Data_Reader overrides
// TODO: override skip_v?
virtual blargg_err_t read_v( void* out, int n );
};
struct fex_type_t_
{
const char* extension;
File_Extractor* (*new_fex)();
const char* name;
blargg_err_t (*init)(); // Called by fex_init(). Can be NULL.
};
extern const fex_type_t_
fex_7z_type [1],
fex_gz_type [1],
fex_rar_type [1],
fex_zip_type [1],
fex_bin_type [1];
inline blargg_err_t File_Extractor::open_v() { return blargg_ok; }
inline blargg_err_t File_Extractor::next_v() { return blargg_ok; }
inline blargg_err_t File_Extractor::rewind_v() { return blargg_ok; }
inline void File_Extractor::close_v() { }
// Default to Std_File_Reader for archive access
#ifndef FEX_FILE_READER
#define FEX_FILE_READER Std_File_Reader
#elif defined (FEX_FILE_READER_INCLUDE)
#include FEX_FILE_READER_INCLUDE
#endif
#endif

View File

@ -0,0 +1,98 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Gzip_Extractor.h"
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
// TODO: could close file once data has been read into memory
static blargg_err_t init_gzip_file()
{
get_crc_table(); // initialize zlib's CRC-32 tables
return blargg_ok;
}
static File_Extractor* new_gzip()
{
return BLARGG_NEW Gzip_Extractor;
}
fex_type_t_ const fex_gz_type [1] = {{
".gz",
&new_gzip,
"gzipped file",
&init_gzip_file
}};
Gzip_Extractor::Gzip_Extractor() :
File_Extractor( fex_gz_type )
{ }
Gzip_Extractor::~Gzip_Extractor()
{
close();
}
blargg_err_t Gzip_Extractor::open_path_v()
{
// skip opening file
return open_v();
}
blargg_err_t Gzip_Extractor::stat_v()
{
RETURN_ERR( open_arc_file( true ) );
if ( !gr.opened() || gr.tell() != 0 )
RETURN_ERR( gr.open( &arc() ) );
set_info( gr.remain(), 0, gr.crc32() );
return blargg_ok;
}
blargg_err_t Gzip_Extractor::open_v()
{
// Remove .gz suffix
size_t len = strlen( arc_path() );
if ( fex_has_extension( arc_path(), ".gz" ) )
len -= 3;
RETURN_ERR( name.resize( len + 1 ) );
memcpy( name.begin(), arc_path(), name.size() );
name [name.size() - 1] = '\0';
set_name( name.begin() );
return blargg_ok;
}
void Gzip_Extractor::close_v()
{
name.clear();
gr.close();
}
blargg_err_t Gzip_Extractor::next_v()
{
return blargg_ok;
}
blargg_err_t Gzip_Extractor::rewind_v()
{
set_name( name.begin() );
return blargg_ok;
}
blargg_err_t Gzip_Extractor::extract_v( void* p, int n )
{
return gr.read( p, n );
}

View File

@ -0,0 +1,34 @@
// Presents a gzipped file as an "archive" of just that file.
// Also handles non-gzipped files.
// File_Extractor 1.0.0
#ifndef GZIP_EXTRACTOR_H
#define GZIP_EXTRACTOR_H
#include "File_Extractor.h"
#include "Gzip_Reader.h"
class Gzip_Extractor : public File_Extractor {
public:
Gzip_Extractor();
virtual ~Gzip_Extractor();
protected:
virtual blargg_err_t open_path_v();
virtual blargg_err_t open_v();
virtual void close_v();
virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v();
virtual blargg_err_t stat_v();
virtual blargg_err_t extract_v( void*, int );
private:
Gzip_Reader gr;
blargg_vector<char> name;
void set_info_();
};
#endif

View File

@ -0,0 +1,85 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Gzip_Reader.h"
#include "blargg_endian.h"
/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
Gzip_Reader::Gzip_Reader()
{
close();
}
Gzip_Reader::~Gzip_Reader()
{ }
static blargg_err_t gzip_reader_read( void* file, void* out, int* count )
{
return STATIC_CAST(File_Reader*,file)->read_avail( out, count );
}
blargg_err_t Gzip_Reader::calc_size()
{
size_ = in->size();
crc32_ = 0;
if ( inflater.deflated() )
{
byte trailer [8];
int old_pos = in->tell();
RETURN_ERR( in->seek( size_ - sizeof trailer ) );
RETURN_ERR( in->read( trailer, sizeof trailer ) );
RETURN_ERR( in->seek( old_pos ) );
crc32_ = get_le32( trailer + 0 );
unsigned n = get_le32( trailer + 4 );
if ( n > INT_MAX )
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "gzip larger than 2GB" );
size_ = n;
}
return blargg_ok;
}
blargg_err_t Gzip_Reader::open( File_Reader* new_in )
{
close();
in = new_in;
RETURN_ERR( in->seek( 0 ) );
RETURN_ERR( inflater.begin( gzip_reader_read, new_in ) );
RETURN_ERR( inflater.set_mode( inflater.mode_auto ) );
RETURN_ERR( calc_size() );
set_remain( size_ );
return blargg_ok;
}
void Gzip_Reader::close()
{
in = NULL;
inflater.end();
}
blargg_err_t Gzip_Reader::read_v( void* out, int count )
{
assert( in );
int actual = count;
RETURN_ERR( inflater.read( out, &actual ) );
if ( actual != count )
return blargg_err_file_corrupt;
return blargg_ok;
}

View File

@ -0,0 +1,46 @@
// Transparently decompresses gzip files, as well as uncompressed
// File_Extractor 1.0.0
#ifndef GZIP_READER_H
#define GZIP_READER_H
#include "Data_Reader.h"
#include "Zlib_Inflater.h"
class Gzip_Reader : public Data_Reader {
public:
// Keeps pointer to reader until close(). If
blargg_err_t open( File_Reader* );
// True if file is open
bool opened() const { return in != NULL; }
// Frees memory
void close();
// True if file is compressed
bool deflated() const { return inflater.deflated(); }
// CRC-32 of data, of 0 if unavailable
unsigned int crc32() const { return crc32_; }
// Number of bytes read since opening
BOOST::uint64_t tell() const { return size_ - remain(); }
public:
Gzip_Reader();
virtual ~Gzip_Reader();
protected:
virtual blargg_err_t read_v( void*, int );
private:
File_Reader* in;
unsigned crc32_;
int size_;
Zlib_Inflater inflater;
blargg_err_t calc_size();
};
#endif

View File

@ -0,0 +1,197 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "blargg_common.h"
#if FEX_ENABLE_RAR
#include "Rar_Extractor.h"
/* Copyright (C) 2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
static blargg_err_t init_rar()
{
unrar_init();
return blargg_ok;
}
static File_Extractor* new_rar()
{
return BLARGG_NEW Rar_Extractor;
}
fex_type_t_ const fex_rar_type [1] = {{
".rar",
&new_rar,
"RAR archive",
&init_rar
}};
blargg_err_t Rar_Extractor::convert_err( unrar_err_t err )
{
blargg_err_t reader_err = reader.err;
reader.err = blargg_ok;
if ( reader_err )
check( err == unrar_next_err );
switch ( err )
{
case unrar_ok: return blargg_ok;
case unrar_err_memory: return blargg_err_memory;
case unrar_err_open: return blargg_err_file_read;
case unrar_err_not_arc: return blargg_err_file_type;
case unrar_err_corrupt: return blargg_err_file_corrupt;
case unrar_err_io: return blargg_err_file_io;
case unrar_err_arc_eof: return blargg_err_internal;
case unrar_err_encrypted: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR encryption not supported" );
case unrar_err_segmented: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR segmentation not supported" );
case unrar_err_huge: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Huge RAR files not supported" );
case unrar_err_old_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Old RAR compression not supported" );
case unrar_err_new_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR uses unknown newer compression" );
case unrar_next_err: break;
default:
check( false ); // unhandled RAR error
}
if ( reader_err )
return reader_err;
check( false );
return BLARGG_ERR( BLARGG_ERR_INTERNAL, "RAR archive" );
}
static inline unrar_err_t handle_err( Rar_Extractor::read_callback_t* h, blargg_err_t err )
{
if ( !err )
return unrar_ok;
h->err = err;
return unrar_next_err;
}
extern "C"
{
static unrar_err_t my_unrar_read( void* data, void* out, int* count, unrar_pos_t pos )
{
// TODO: 64-bit file support
Rar_Extractor::read_callback_t* h = STATIC_CAST(Rar_Extractor::read_callback_t*,data);
if ( h->pos != pos )
{
blargg_err_t err = h->in->seek( pos );
if ( err )
return handle_err( h, err );
h->pos = pos;
}
blargg_err_t err = h->in->read_avail( out, count );
if ( err )
return handle_err( h, err );
h->pos += *count;
return unrar_ok;
}
}
Rar_Extractor::Rar_Extractor() :
File_Extractor( fex_rar_type )
{
unrar = NULL;
}
Rar_Extractor::~Rar_Extractor()
{
close();
}
blargg_err_t Rar_Extractor::open_v()
{
reader.pos = 0;
reader.in = &arc();
reader.err = blargg_ok;
RETURN_ERR( arc().seek( 0 ) );
RETURN_ERR( convert_err( unrar_open_custom( &unrar, &my_unrar_read, &reader ) ) );
return skip_unextractables();
}
void Rar_Extractor::close_v()
{
unrar_close( unrar );
unrar = NULL;
reader.in = NULL;
}
blargg_err_t Rar_Extractor::skip_unextractables()
{
while ( !unrar_done( unrar ) && unrar_try_extract( unrar ) )
RETURN_ERR( next_raw() );
if ( !unrar_done( unrar ) )
{
unrar_info_t const* info = unrar_info( unrar );
set_name( info->name, (info->name_w && *info->name_w) ? info->name_w : NULL );
set_info( info->size, info->dos_date, (info->is_crc32 ? info->crc : 0) );
}
return blargg_ok;
}
blargg_err_t Rar_Extractor::next_raw()
{
return convert_err( unrar_next( unrar ) );
}
blargg_err_t Rar_Extractor::next_v()
{
RETURN_ERR( next_raw() );
return skip_unextractables();
}
blargg_err_t Rar_Extractor::rewind_v()
{
RETURN_ERR( convert_err( unrar_rewind( unrar ) ) );
return skip_unextractables();
}
fex_pos_t Rar_Extractor::tell_arc_v() const
{
return unrar_tell( unrar );
}
blargg_err_t Rar_Extractor::seek_arc_v( fex_pos_t pos )
{
RETURN_ERR( convert_err( unrar_seek( unrar, pos ) ) );
return skip_unextractables();
}
blargg_err_t Rar_Extractor::data_v( void const** out )
{
return convert_err( unrar_extract_mem( unrar, out ) );
}
blargg_err_t Rar_Extractor::extract_v( void* out, int count )
{
// We can read entire file directly into user buffer
if ( count == size() )
return convert_err( unrar_extract( unrar, out, count ) );
// This will call data_v() and copy from that buffer for us
return File_Extractor::extract_v( out, count );
}
#endif

View File

@ -0,0 +1,43 @@
// RAR archive extractor
// File_Extractor 1.0.0
#ifndef RAR_EXTRACTOR_H
#define RAR_EXTRACTOR_H
#include "File_Extractor.h"
#include "unrar/unrar.h"
class Rar_Extractor : public File_Extractor {
public:
Rar_Extractor();
virtual ~Rar_Extractor();
struct read_callback_t
{
const char* err;
BOOST::uint64_t pos;
File_Reader* in;
};
protected:
virtual blargg_err_t open_v();
virtual void close_v();
virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v();
virtual fex_pos_t tell_arc_v() const;
virtual blargg_err_t seek_arc_v( fex_pos_t );
virtual blargg_err_t data_v( void const** );
virtual blargg_err_t extract_v( void*, int );
private:
unrar_t* unrar;
read_callback_t reader;
blargg_err_t convert_err( unrar_err_t );
blargg_err_t skip_unextractables();
blargg_err_t next_raw();
};
#endif

View File

@ -0,0 +1,290 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Zip7_Extractor.h"
extern "C" {
#include "7z_C/7z.h"
#include "7z_C/7zAlloc.h"
#include "7z_C/7zCrc.h"
}
#include <time.h>
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
static ISzAlloc zip7_alloc = { SzAlloc, SzFree };
static ISzAlloc zip7_alloc_temp = { SzAllocTemp, SzFreeTemp };
struct Zip7_Extractor_Impl :
ISeekInStream
{
CLookToRead look;
CSzArEx db;
// SzExtract state
UInt32 block_index;
Byte* buf;
size_t buf_size;
File_Reader* in;
const char* in_err;
};
extern "C"
{
// 7-zip callbacks pass an ISeekInStream* for data, so we must cast it
// back to ISeekInStream* FIRST, then cast to our Impl structure
static SRes zip7_read_( void* vstream, void* out, size_t* size )
{
assert( out && size );
ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream);
Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream);
long lsize = *size;
blargg_err_t err = impl->in->read_avail( out, &lsize );
if ( err )
{
*size = 0;
impl->in_err = err;
return SZ_ERROR_READ;
}
*size = lsize;
return SZ_OK;
}
static SRes zip7_seek_( void* vstream, Int64* pos, ESzSeek mode )
{
ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream);
Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream);
if ( mode == SZ_SEEK_CUR )
{
assert( *pos == 0 ); // only used to find the archive start position
*pos = impl->in->tell();
return SZ_OK;
}
if ( mode == SZ_SEEK_END )
{
assert( *pos == 0 ); // only used to find file length
*pos = impl->in->size();
return SZ_OK;
}
assert( mode == SZ_SEEK_SET );
blargg_err_t err = impl->in->seek( *pos );
if ( err )
{
// don't set in_err in this case, since it might be benign
if ( err == blargg_err_file_eof )
return SZ_ERROR_INPUT_EOF;
impl->in_err = err;
return SZ_ERROR_READ;
}
return SZ_OK;
}
}
blargg_err_t Zip7_Extractor::zip7_err( int err )
{
// TODO: ignore in_err in some cases? unsure about which error to use
blargg_err_t in_err = impl->in_err;
impl->in_err = NULL;
if ( in_err )
{
check( err != SZ_OK );
return in_err;
}
switch ( err )
{
case SZ_OK: return blargg_ok;
case SZ_ERROR_MEM: return blargg_err_memory;
case SZ_ERROR_READ: return blargg_err_file_io;
case SZ_ERROR_CRC:
case SZ_ERROR_DATA:
case SZ_ERROR_INPUT_EOF:
case SZ_ERROR_ARCHIVE: return blargg_err_file_corrupt;
case SZ_ERROR_UNSUPPORTED: return blargg_err_file_feature;
case SZ_ERROR_NO_ARCHIVE: return blargg_err_file_type;
}
return blargg_err_generic;
}
static blargg_err_t init_7z()
{
static bool inited;
if ( !inited )
{
inited = true;
CrcGenerateTable();
}
return blargg_ok;
}
static File_Extractor* new_7z()
{
return BLARGG_NEW Zip7_Extractor;
}
fex_type_t_ const fex_7z_type [1] = {{
".7z",
&new_7z,
"7-zip archive",
&init_7z
}};
Zip7_Extractor::Zip7_Extractor() :
File_Extractor( fex_7z_type )
{
impl = NULL;
}
Zip7_Extractor::~Zip7_Extractor()
{
close();
}
blargg_err_t Zip7_Extractor::open_v()
{
RETURN_ERR( init_7z() );
if ( !impl )
{
impl = (Zip7_Extractor_Impl*) malloc( sizeof *impl );
CHECK_ALLOC( impl );
}
impl->in = &arc();
impl->block_index = (UInt32) -1;
impl->buf = NULL;
impl->buf_size = 0;
LookToRead_CreateVTable( &impl->look, false );
impl->ISeekInStream::Read = zip7_read_;
impl->ISeekInStream::Seek = zip7_seek_;
impl->look.realStream = impl;
LookToRead_Init( &impl->look );
SzArEx_Init( &impl->db );
impl->in_err = NULL;
RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.s,
&zip7_alloc, &zip7_alloc_temp ) ) );
return seek_arc_v( 0 );
}
void Zip7_Extractor::close_v()
{
if ( impl )
{
if ( impl->in )
{
impl->in = NULL;
SzArEx_Free( &impl->db, &zip7_alloc );
}
IAlloc_Free( &zip7_alloc, impl->buf );
free( impl );
impl = NULL;
}
}
blargg_err_t Zip7_Extractor::next_v()
{
while ( ++index < (int) impl->db.db.NumFiles )
{
CSzFileItem const& item = impl->db.db.Files [index];
if ( !item.IsDir )
{
unsigned long date = 0;
if ( item.MTimeDefined )
{
const UInt64 epoch = ((UInt64)0x019db1de << 32) + 0xd53e8000;
/* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
struct tm tm;
UInt64 time = ((UInt64)item.MTime.High << 32) + item.MTime.Low - epoch;
time /= 1000000;
time_t _time = time;
#ifdef _WIN32
localtime_s( &tm, &_time );
#else
localtime_r( &_time, &tm );
#endif
date = ( tm.tm_sec >> 1 ) & 0x1F |
(( tm.tm_min & 0x3F ) << 5 ) |
(( tm.tm_hour & 0x1F ) << 11 ) |
(( tm.tm_mday & 0x1F ) << 16 ) |
(( ( tm.tm_mon + 1 ) & 0x0F ) << 21 ) |
(( ( tm.tm_year - 80 ) & 0x7F ) << 25 );
}
size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 );
name16.resize( name_length );
SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() );
char * temp = blargg_to_utf8( name16.begin() );
if ( !temp ) temp = "";
size_t utf8_length = strlen( temp );
name8.resize( utf8_length + 1 );
memcpy( name8.begin(), temp, utf8_length + 1 );
free( temp );
set_name( name8.begin(), name16.begin() );
set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) );
break;
}
}
return blargg_ok;
}
blargg_err_t Zip7_Extractor::rewind_v()
{
return seek_arc_v( 0 );
}
fex_pos_t Zip7_Extractor::tell_arc_v() const
{
return index;
}
blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos )
{
assert( 0 <= pos && pos <= (int) impl->db.db.NumFiles );
index = pos - 1;
return next_v();
}
blargg_err_t Zip7_Extractor::data_v( void const** out )
{
impl->in_err = NULL;
size_t offset = 0;
size_t count = 0;
RETURN_ERR( zip7_err( SzArEx_Extract( &impl->db, &impl->look.s, index,
&impl->block_index, &impl->buf, &impl->buf_size,
&offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) );
assert( count == (size_t) size() );
*out = impl->buf + offset;
return blargg_ok;
}

View File

@ -0,0 +1,36 @@
// 7-zip archive extractor
// File_Extractor 1.0.0
#ifndef ZIP7_EXTRACTOR_H
#define ZIP7_EXTRACTOR_H
#include "File_Extractor.h"
struct Zip7_Extractor_Impl;
class Zip7_Extractor : public File_Extractor {
public:
Zip7_Extractor();
virtual ~Zip7_Extractor();
protected:
virtual blargg_err_t open_v();
virtual void close_v();
virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v();
virtual fex_pos_t tell_arc_v() const;
virtual blargg_err_t seek_arc_v( fex_pos_t );
virtual blargg_err_t data_v( void const** out );
private:
Zip7_Extractor_Impl* impl;
int index;
blargg_vector<char> name8;
blargg_vector<blargg_wchar_t> name16;
blargg_err_t zip7_err( int err );
};
#endif

View File

@ -0,0 +1,390 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Zip_Extractor.h"
#include "blargg_endian.h"
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
/* To avoid copying filename string from catalog, I terminate it by modifying
catalog data. This potentially requires moving the first byte of the type
of the next entry elsewhere; I move it to the first byte of made_by. Kind
of hacky, but I'd rather not have to allocate memory for a copy of it. */
#include "blargg_source.h"
/* Reads this much from end of file when first opening. Only this much is
searched for the end catalog entry. If whole catalog is within this data,
nothing more needs to be read on open. */
int const end_read_size = 8 * 1024;
/* Reads are are made using file offset that's a multiple of this,
increasing performance. */
int const disk_block_size = 4 * 1024;
// Read buffer used for extracting file data
int const read_buf_size = 16 * 1024;
struct header_t
{
char type [4];
byte vers [2];
byte flags [2];
byte method [2];
byte date [4];
byte crc [4];
byte raw_size [4];
byte size [4];
byte filename_len [2];
byte extra_len [2];
char filename [2]; // [filename_len]
//char extra [extra_len];
};
int const header_size = 30;
struct entry_t
{
char type [4];
byte made_by [2];
byte vers [2];
byte flags [2];
byte method [2];
byte date [4];
byte crc [4];
byte raw_size [4];
byte size [4];
byte filename_len [2];
byte extra_len [2];
byte comment_len [2];
byte disk [2];
byte int_attrib [2];
byte ext_attrib [4];
byte file_offset [4];
char filename [2]; // [filename_len]
//char extra [extra_len];
//char comment [comment_len];
};
int const entry_size = 46;
struct end_entry_t
{
char type [4];
byte disk [2];
byte first_disk [2];
byte disk_entry_count [2];
byte entry_count [2];
byte dir_size [4];
byte dir_offset [4];
byte comment_len [2];
char comment [2]; // [comment_len]
};
int const end_entry_size = 22;
static blargg_err_t init_zip()
{
get_crc_table(); // initialize zlib's CRC-32 tables
return blargg_ok;
}
static File_Extractor* new_zip()
{
return BLARGG_NEW Zip_Extractor;
}
fex_type_t_ const fex_zip_type [1] = {{
".zip",
&new_zip,
"ZIP archive",
&init_zip
}};
Zip_Extractor::Zip_Extractor() :
File_Extractor( fex_zip_type )
{
Zip_Extractor::clear_file_v();
// If these fail, structures had extra padding inserted by compiler
assert( offsetof (header_t,filename) == header_size );
assert( offsetof (entry_t,filename) == entry_size );
assert( offsetof (end_entry_t,comment) == end_entry_size );
}
Zip_Extractor::~Zip_Extractor()
{
close();
}
blargg_err_t Zip_Extractor::open_path_v()
{
RETURN_ERR( open_arc_file( true ) );
return File_Extractor::open_path_v();
}
inline
void Zip_Extractor::reorder_entry_header( int offset )
{
catalog [offset + 0] = 0;
catalog [offset + 4] = 'P';
}
blargg_err_t Zip_Extractor::open_v()
{
if ( arc().size() < end_entry_size )
return blargg_err_file_type;
// Read final end_read_size bytes of file
BOOST::uint64_t file_pos = max( (BOOST::uint64_t) 0, arc().size() - end_read_size );
file_pos -= file_pos % disk_block_size;
RETURN_ERR( catalog.resize( arc().size() - file_pos ) );
RETURN_ERR( arc().seek( file_pos ) );
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
// Find end-of-catalog entry
BOOST::uint64_t end_pos = catalog.size() - end_entry_size;
while ( end_pos >= 0 && memcmp( &catalog [end_pos], "PK\5\6", 4 ) )
end_pos--;
if ( end_pos < 0 )
return blargg_err_file_type;
end_entry_t const& end_entry = (end_entry_t&) catalog [end_pos];
end_pos += file_pos;
// some idiotic zip compressors add data to end of zip without setting comment len
// check( arc().size() == end_pos + end_entry_size + get_le16( end_entry.comment_len ) );
// Find file offset of beginning of catalog
catalog_begin = get_le32( end_entry.dir_offset );
int catalog_size = end_pos - catalog_begin;
if ( catalog_size < 0 )
return blargg_err_file_corrupt;
catalog_size += end_entry_size;
// See if catalog is entirely contained in bytes already read
BOOST::uint64_t begin_offset = catalog_begin - file_pos;
if ( begin_offset >= 0 )
memmove( catalog.begin(), &catalog [begin_offset], catalog_size );
RETURN_ERR( catalog.resize( catalog_size ) );
if ( begin_offset < 0 )
{
// Catalog begins before bytes read, so it needs to be read
RETURN_ERR( arc().seek( catalog_begin ) );
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
}
// First entry in catalog should be a file or end of archive
if ( memcmp( catalog.begin(), "PK\1\2", 4 ) && memcmp( catalog.begin(), "PK\5\6", 4 ) )
return blargg_err_file_type;
reorder_entry_header( 0 );
return rewind_v();
}
void Zip_Extractor::close_v()
{
catalog.clear();
}
// Scanning
inline
static bool is_normal_file( entry_t const& e, unsigned len )
{
int last_char = (len ? e.filename [len - 1] : '/');
bool is_dir = (last_char == '/' || last_char == '\\');
if ( is_dir && get_le32( e.size ) == 0 )
return false;
check( !is_dir );
// Mac OS X puts meta-information in separate files with normal extensions,
// so they must be filtered out or caller will mistake them for normal files.
if ( e.made_by[1] == 3 )
{
const char* dir = strrchr( e.filename, '/' );
if ( dir )
dir++;
else
dir = e.filename;
if ( *dir == '.' )
return false;
if ( !strcmp( dir, "Icon\x0D" ) )
return false;
}
return true;
}
blargg_err_t Zip_Extractor::update_info( bool advance_first )
{
while ( 1 )
{
entry_t& e = (entry_t&) catalog [catalog_pos];
if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) )
{
check( !memcmp( e.type, "\0K\5\6P", 5 ) );
break;
}
unsigned len = get_le16( e.filename_len );
int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) +
get_le16( e.comment_len );
if ( (unsigned) next_offset > catalog.size() - end_entry_size )
return blargg_err_file_corrupt;
if ( catalog [next_offset] == 'P' )
reorder_entry_header( next_offset );
if ( !advance_first )
{
e.filename [len] = 0; // terminate name
if ( is_normal_file( e, len ) )
{
set_name( e.filename );
set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) );
break;
}
}
catalog_pos = next_offset;
advance_first = false;
}
return blargg_ok;
}
blargg_err_t Zip_Extractor::next_v()
{
return update_info( true );
}
blargg_err_t Zip_Extractor::rewind_v()
{
return seek_arc_v( 0 );
}
fex_pos_t Zip_Extractor::tell_arc_v() const
{
return catalog_pos;
}
blargg_err_t Zip_Extractor::seek_arc_v( fex_pos_t pos )
{
assert( 0 <= pos && (size_t) pos <= catalog.size() - end_entry_size );
catalog_pos = pos;
return update_info( false );
}
// Reading
void Zip_Extractor::clear_file_v()
{
buf.end();
}
blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, int* count )
{
Zip_Extractor& self = *STATIC_CAST(Zip_Extractor*,data);
if ( *count > self.raw_remain )
*count = self.raw_remain;
self.raw_remain -= *count;
return self.arc().read( out, *count );
}
blargg_err_t Zip_Extractor::fill_buf( int offset, int buf_size, int initial_read )
{
raw_remain = arc().size() - offset;
RETURN_ERR( arc().seek( offset ) );
return buf.begin( inflater_read, this, buf_size, initial_read );
}
blargg_err_t Zip_Extractor::first_read( int count )
{
entry_t const& e = (entry_t&) catalog [catalog_pos];
// Determine compression
{
int method = get_le16( e.method );
if ( (method && method != Z_DEFLATED) || get_le16( e.vers ) > 20 )
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "compression method" );
file_deflated = (method != 0);
}
int raw_size = get_le32( e.raw_size );
int file_offset = get_le32( e.file_offset );
int align = file_offset % disk_block_size;
{
// read header
int buf_size = 3 * disk_block_size - 1 + raw_size; // space for all raw data
buf_size -= buf_size % disk_block_size;
int initial_read = buf_size;
if ( !file_deflated || count < size() )
{
buf_size = read_buf_size;
initial_read = disk_block_size * 2;
}
// TODO: avoid re-reading if buffer already has data we want?
RETURN_ERR( fill_buf( file_offset - align, buf_size, initial_read ) );
}
header_t const& h = (header_t&) buf.data() [align];
if ( buf.filled() < align + header_size || memcmp( h.type, "PK\3\4", 4 ) )
return blargg_err_file_corrupt;
// CRCs of header and file data
correct_crc = get_le32( h.crc );
if ( !correct_crc )
correct_crc = get_le32( e.crc );
check( correct_crc == get_le32( e.crc ) ); // catalog CRC should match
crc = ::crc32( 0, NULL, 0 );
// Data offset
int data_offset = file_offset + header_size +
get_le16( h.filename_len ) + get_le16( h.extra_len );
if ( data_offset + raw_size > catalog_begin )
return blargg_err_file_corrupt;
// Refill buffer if there's lots of extra data after header
int buf_offset = data_offset - file_offset + align;
if ( buf_offset > buf.filled() )
{
// TODO: this will almost never occur, making it a good place for bugs
buf_offset = data_offset % disk_block_size;
RETURN_ERR( fill_buf( data_offset - buf_offset, read_buf_size, disk_block_size ) );
}
raw_remain = raw_size - (buf.filled() - buf_offset);
return buf.set_mode( (file_deflated ? buf.mode_raw_deflate : buf.mode_copy), buf_offset );
}
blargg_err_t Zip_Extractor::extract_v( void* out, int count )
{
if ( tell() == 0 )
RETURN_ERR( first_read( count ) );
int actual = count;
RETURN_ERR( buf.read( out, &actual ) );
if ( actual < count )
return blargg_err_file_corrupt;
crc = ::crc32( crc, (byte const*) out, count );
if ( count == reader().remain() && crc != correct_crc )
return blargg_err_file_corrupt;
return blargg_ok;
}

View File

@ -0,0 +1,45 @@
// ZIP archive extractor. Only supports deflation and store (no compression).
// File_Extractor 1.0.0
#ifndef ZIP_EXTRACTOR_H
#define ZIP_EXTRACTOR_H
#include "File_Extractor.h"
#include "Zlib_Inflater.h"
class Zip_Extractor : public File_Extractor {
public:
Zip_Extractor();
virtual ~Zip_Extractor();
protected:
virtual blargg_err_t open_path_v();
virtual blargg_err_t open_v();
virtual void close_v();
virtual void clear_file_v();
virtual blargg_err_t next_v();
virtual blargg_err_t rewind_v();
virtual fex_pos_t tell_arc_v() const;
virtual blargg_err_t seek_arc_v( fex_pos_t );
virtual blargg_err_t extract_v( void*, int );
private:
blargg_vector<char> catalog;
int catalog_begin; // offset of first catalog entry in file (to detect corruption)
int catalog_pos; // position of current entry in catalog
BOOST::uint64_t raw_remain; // bytes remaining to be read from zip file for current file
unsigned crc; // ongoing CRC of extracted bytes
unsigned correct_crc;
bool file_deflated;
Zlib_Inflater buf;
blargg_err_t fill_buf( int offset, int buf_size, int initial_read );
blargg_err_t update_info( bool advance_first );
blargg_err_t first_read( int count );
void reorder_entry_header( int offset );
static blargg_err_t inflater_read( void* data, void* out, int* count );
};
#endif

View File

@ -0,0 +1,257 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "Zlib_Inflater.h"
/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
int const block_size = 4096;
static const char* get_zlib_err( int code )
{
assert( code != Z_OK );
switch ( code )
{
case Z_MEM_ERROR: return blargg_err_memory;
case Z_DATA_ERROR: return blargg_err_file_corrupt;
// TODO: handle more error codes
}
const char* str = zError( code );
if ( !str )
str = BLARGG_ERR( BLARGG_ERR_GENERIC, "problem unzipping data" );
return str;
}
void Zlib_Inflater::end()
{
if ( deflated_ )
{
deflated_ = false;
if ( inflateEnd( &zbuf ) )
check( false );
}
buf.clear();
static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
memcpy( &zbuf, &empty, sizeof zbuf );
}
Zlib_Inflater::Zlib_Inflater()
{
deflated_ = false;
end(); // initialize things
}
Zlib_Inflater::~Zlib_Inflater()
{
end();
}
blargg_err_t Zlib_Inflater::fill_buf( int count )
{
byte* out = buf.end() - count;
RETURN_ERR( callback( user_data, out, &count ) );
zbuf.avail_in = count;
zbuf.next_in = out;
return blargg_ok;
}
blargg_err_t Zlib_Inflater::begin( callback_t new_callback, void* new_user_data,
int new_buf_size, int initial_read )
{
callback = new_callback;
user_data = new_user_data;
end();
// TODO: decide whether using different size on alloc failure is a good idea
//RETURN_ERR( buf.resize( new_buf_size ? new_buf_size : 4 * block_size ) );
if ( new_buf_size && buf.resize( new_buf_size ) )
{
ACK_FAILURE();
new_buf_size = 0;
}
if ( !new_buf_size )
{
RETURN_ERR( buf.resize( 4 * block_size ) );
initial_read = 0;
}
// Fill buffer with some data, less than normal buffer size since caller might
// just be examining beginning of file.
return fill_buf( initial_read ? initial_read : block_size );
}
blargg_err_t Zlib_Inflater::set_mode( mode_t mode, int data_offset )
{
zbuf.next_in += data_offset;
zbuf.avail_in -= data_offset;
if ( mode == mode_auto )
{
// examine buffer for gzip header
mode = mode_copy;
unsigned const min_gzip_size = 2 + 8 + 8;
if ( zbuf.avail_in >= min_gzip_size &&
zbuf.next_in [0] == 0x1F && zbuf.next_in [1] == 0x8B )
mode = mode_ungz;
}
if ( mode != mode_copy )
{
int wb = MAX_WBITS + 16; // have zlib handle gzip header
if ( mode == mode_raw_deflate )
wb = -MAX_WBITS;
int zerr = inflateInit2( &zbuf, wb );
if ( zerr )
{
zbuf.next_in = NULL;
return get_zlib_err( zerr );
}
deflated_ = true;
}
return blargg_ok;
}
/*
// Reads/inflates entire stream. All input must be in buffer, and count must be total
// of all output.
blargg_err_t read_all( void* out, int count );
// zlib automatically applies this optimization (uses inflateFast)
// TODO: remove
blargg_err_t Zlib_Inflater::read_all( void* out, int count )
{
if ( deflated_ )
{
zbuf.next_out = (Bytef*) out;
zbuf.avail_out = count;
int err = inflate( &zbuf, Z_FINISH );
if ( zbuf.avail_out || err != Z_STREAM_END )
return blargg_err_file_corrupt;
}
else
{
if ( zbuf.avail_in < count )
return blargg_err_file_corrupt;
memcpy( out, zbuf.next_in, count );
zbuf.next_in += count;
zbuf.avail_in -= count;
}
return blargg_ok;
}
*/
blargg_err_t Zlib_Inflater::read( void* out, int* count_io )
{
int remain = *count_io;
if ( remain && zbuf.next_in )
{
if ( deflated_ )
{
zbuf.next_out = (Bytef*) out;
zbuf.avail_out = remain;
while ( 1 )
{
uInt old_avail_in = zbuf.avail_in;
int err = inflate( &zbuf, Z_NO_FLUSH );
if ( err == Z_STREAM_END )
{
remain = zbuf.avail_out;
end();
break; // no more data to inflate
}
if ( err && (err != Z_BUF_ERROR || old_avail_in) )
return get_zlib_err( err );
if ( !zbuf.avail_out )
{
remain = 0;
break; // requested number of bytes inflated
}
if ( zbuf.avail_in )
{
// inflate() should never leave input if there's still space for output
check( false );
return blargg_err_file_corrupt;
}
RETURN_ERR( fill_buf( buf.size() ) );
if ( !zbuf.avail_in )
return blargg_err_file_corrupt; // stream didn't end but there's no more data
}
}
else
{
while ( 1 )
{
// copy buffered data
if ( zbuf.avail_in )
{
long count = zbuf.avail_in;
if ( count > remain )
count = remain;
memcpy( out, zbuf.next_in, count );
zbuf.total_out += count;
out = (char*) out + count;
remain -= count;
zbuf.next_in += count;
zbuf.avail_in -= count;
}
if ( !zbuf.avail_in && zbuf.next_in < buf.end() )
{
end();
break;
}
// read large request directly
if ( remain + zbuf.total_out % block_size >= buf.size() )
{
int count = remain;
RETURN_ERR( callback( user_data, out, &count ) );
zbuf.total_out += count;
out = (char*) out + count;
remain -= count;
if ( remain )
{
end();
break;
}
}
if ( !remain )
break;
RETURN_ERR( fill_buf( buf.size() - zbuf.total_out % block_size ) );
}
}
}
*count_io -= remain;
return blargg_ok;
}

View File

@ -0,0 +1,70 @@
// Simplifies use of zlib for inflating data
// File_Extractor 1.0.0
#ifndef ZLIB_INFLATER_H
#define ZLIB_INFLATER_H
#include "blargg_common.h"
#include "Data_Reader.h"
#include <zlib.h>
class Zlib_Inflater {
public:
// Reads at most min(*count,bytes_until_eof()) bytes into *out and set *count
// to that number, or returns error if that many can't be read.
typedef blargg_err_t (*callback_t)( void* user_data, void* out, int* count );
// Begins by setting callback and filling buffer. Default buffer is 16K and
// filled to 4K, or specify buf_size and initial_read for custom buffer size
// and how much to read initially.
blargg_err_t begin( callback_t, void* user_data,
int buf_size = 0, int initial_read = 0 );
// Data read into buffer by begin()
const unsigned char* data() const { return zbuf.next_in; }
int filled() const { return zbuf.avail_in; }
// Begins inflation using specified mode. Using mode_auto selects between
// mode_copy and mode_ungz by examining first two bytes of buffer. Use
// buf_offset to specify where data begins in buffer, in case there is
// header data that should be skipped.
enum mode_t { mode_copy, mode_ungz, mode_raw_deflate, mode_auto };
blargg_err_t set_mode( mode_t, int buf_offset = 0 );
// True if set_mode() has been called with mode_ungz or mode_raw_deflate
bool deflated() const { return deflated_; }
// Reads/inflates at most *count_io bytes into *out and sets *count_io to actual
// number of bytes read (less than requested if end of data was reached).
// Buffers source data internally, even in copy mode, so input file can be
// unbuffered without sacrificing performance.
blargg_err_t read( void* out, int* count_io );
// Total number of bytes read since begin()
int tell() const { return zbuf.total_out; }
// Ends inflation and frees memory
void end();
private:
// noncopyable
Zlib_Inflater( const Zlib_Inflater& );
Zlib_Inflater& operator = ( const Zlib_Inflater& );
// Implementation
public:
Zlib_Inflater();
~Zlib_Inflater();
private:
z_stream_s zbuf;
blargg_vector<unsigned char> buf;
bool deflated_;
callback_t callback;
void* user_data;
blargg_err_t fill_buf( int count );
};
#endif

View File

@ -0,0 +1,51 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include "blargg_common.h"
/* Copyright (C) 2008-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
void blargg_vector_::init()
{
begin_ = NULL;
size_ = 0;
}
void blargg_vector_::clear()
{
void* p = begin_;
begin_ = NULL;
size_ = 0;
free( p );
}
blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size )
{
if ( n != size_ )
{
if ( n == 0 )
{
// Simpler to handle explicitly. Realloc will handle a size of 0,
// but then we have to avoid raising an error for a NULL return.
clear();
}
else
{
void* p = realloc( begin_, n * elem_size );
CHECK_ALLOC( p );
begin_ = p;
size_ = n;
}
}
return blargg_ok;
}

View File

@ -0,0 +1,217 @@
// Sets up common environment for Shay Green's libraries.
// To change configuration options, modify blargg_config.h, not this file.
// File_Extractor 1.0.0
#ifndef BLARGG_COMMON_H
#define BLARGG_COMMON_H
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <limits.h>
typedef const char* blargg_err_t; // 0 on success, otherwise error string
#ifdef _WIN32
typedef wchar_t blargg_wchar_t;
#else
typedef uint16_t blargg_wchar_t;
#endif
inline size_t blargg_wcslen( const blargg_wchar_t* str )
{
size_t length = 0;
while ( *str++ ) length++;
return length;
}
// Success; no error
blargg_err_t const blargg_ok = 0;
// BLARGG_RESTRICT: equivalent to C99's restrict, where supported
#if __GNUC__ >= 3 || _MSC_VER >= 1100
#define BLARGG_RESTRICT __restrict
#else
#define BLARGG_RESTRICT
#endif
#if __cplusplus >= 199711
#define BLARGG_MUTABLE mutable
#else
#define BLARGG_MUTABLE
#endif
/* BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant).
I don't just use 'abcd' because that's implementation-dependent. */
#define BLARGG_4CHAR( a, b, c, d ) \
((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF))
/* BLARGG_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
Can be used at file, function, or class scope. */
#ifdef _MSC_VER
// MSVC6 (_MSC_VER < 1300) __LINE__ fails when /Zl is specified
#define BLARGG_STATIC_ASSERT( expr ) \
void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
#else
// Others fail when declaring same function multiple times in class,
// so differentiate them by line
#define BLARGG_STATIC_ASSERT( expr ) \
void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
#endif
/* Pure virtual functions cause a vtable entry to a "called pure virtual"
error handler, requiring linkage to the C++ runtime library. This macro is
used in place of the "= 0", and simply expands to its argument. During
development, it expands to "= 0", allowing detection of missing overrides. */
#define BLARGG_PURE( def ) def
/* My code depends on ASCII anywhere a character or string constant is
compared with data read from a file, and anywhere file data is read and
treated as a string. */
#if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61
#error "ASCII character set required"
#endif
/* My code depends on int being at least 32 bits. Almost everything these days
uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints
to test with. The issue can't be gotten around by using a suitable blargg_int
everywhere either, because int is often converted to implicitly when doing
arithmetic on smaller types. */
#if UINT_MAX < 0xFFFFFFFF
#error "int must be at least 32 bits"
#endif
// In case compiler doesn't support these properly. Used rarely.
#define STATIC_CAST(T,expr) static_cast<T> (expr)
#define CONST_CAST( T,expr) const_cast<T> (expr)
// User configuration can override the above macros if necessary
#include "blargg_config.h"
/* BLARGG_DEPRECATED [_TEXT] for any declarations/text to be removed in a
future version. In GCC, we can let the compiler warn. In other compilers,
we strip it out unless BLARGG_LEGACY is true. */
#if BLARGG_LEGACY
// Allow old client code to work without warnings
#define BLARGG_DEPRECATED_TEXT( text ) text
#define BLARGG_DEPRECATED( text ) text
#elif __GNUC__ >= 4
// In GCC, we can mark declarations and let the compiler warn
#define BLARGG_DEPRECATED_TEXT( text ) text
#define BLARGG_DEPRECATED( text ) __attribute__ ((deprecated)) text
#else
// By default, deprecated items are removed, to avoid use in new code
#define BLARGG_DEPRECATED_TEXT( text )
#define BLARGG_DEPRECATED( text )
#endif
/* BOOST::int8_t, BOOST::int32_t, etc.
I used BOOST since I originally was going to allow use of the boost library
for prividing the definitions. If I'm defining them, they must be scoped or
else they could conflict with the standard ones at global scope. Even if
HAVE_STDINT_H isn't defined, I can't assume the typedefs won't exist at
global scope already. */
#if defined (HAVE_STDINT_H) || \
UCHAR_MAX != 0xFF || USHRT_MAX != 0xFFFF || UINT_MAX != 0xFFFFFFFF
#include <stdint.h>
#define BOOST
#else
struct BOOST
{
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
};
#endif
/* My code is not written with exceptions in mind, so either uses new (nothrow)
OR overrides operator new in my classes. The former is best since clients
creating objects will get standard exceptions on failure, but that causes it
to require the standard C++ library. So, when the client is using the C
interface, I override operator new to use malloc. */
// BLARGG_DISABLE_NOTHROW is put inside classes
#ifndef BLARGG_DISABLE_NOTHROW
// throw spec mandatory in ISO C++ if NULL can be returned
#if __cplusplus >= 199711 || __GNUC__ >= 3 || _MSC_VER >= 1300
#define BLARGG_THROWS_NOTHING throw ()
#else
#define BLARGG_THROWS_NOTHING
#endif
#define BLARGG_DISABLE_NOTHROW \
void* operator new ( size_t s ) BLARGG_THROWS_NOTHING { return malloc( s ); }\
void operator delete( void* p ) BLARGG_THROWS_NOTHING { free( p ); }
#define BLARGG_NEW new
#else
// BLARGG_NEW is used in place of new in library code
#include <new>
#define BLARGG_NEW new (std::nothrow)
#endif
class blargg_vector_ {
protected:
void* begin_;
size_t size_;
void init();
blargg_err_t resize_( size_t n, size_t elem_size );
public:
size_t size() const { return size_; }
void clear();
};
// Very lightweight vector for POD types (no constructor/destructor)
template<class T>
class blargg_vector : public blargg_vector_ {
union T_must_be_pod { T t; }; // fails if T is not POD
public:
blargg_vector() { init(); }
~blargg_vector() { clear(); }
blargg_err_t resize( size_t n ) { return resize_( n, sizeof (T) ); }
T* begin() { return static_cast<T*> (begin_); }
const T* begin() const { return static_cast<T*> (begin_); }
T* end() { return static_cast<T*> (begin_) + size_; }
const T* end() const { return static_cast<T*> (begin_) + size_; }
T& operator [] ( size_t n )
{
assert( n < size_ );
return static_cast<T*> (begin_) [n];
}
const T& operator [] ( size_t n ) const
{
assert( n < size_ );
return static_cast<T*> (begin_) [n];
}
};
// Callback function with user data.
// blargg_callback<T> set_callback; // for user, this acts like...
// void set_callback( T func, void* user_data = NULL ); // ...this
// To call function, do set_callback.f( .. set_callback.data ... );
template<class T>
struct blargg_callback
{
T f;
void* data;
blargg_callback() { f = NULL; }
void operator () ( T callback, void* user_data = NULL ) { f = callback; data = user_data; }
};
BLARGG_DEPRECATED( typedef signed int blargg_long; )
BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; )
#if BLARGG_LEGACY
#define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT
#endif
#endif

View File

@ -0,0 +1,37 @@
// Library configuration. Modify this file as necessary.
// File_Extractor 1.0.0
#ifndef BLARGG_CONFIG_H
#define BLARGG_CONFIG_H
// Uncomment a #define line below to have effect described.
#define HAVE_ZLIB_H
// Enable RAR archive support. Doing so adds extra licensing restrictions
// to this library (see unrar/readme.txt for more information).
#define FEX_ENABLE_RAR 1
// Accept file paths encoded as UTF-8. Currently only affects Windows,
// as Unix/Linux/Mac OS X already use UTF-8 paths.
#define BLARGG_UTF8_PATHS 1
// Enable support for as building DLL on Windows.
//#define BLARGG_BUILD_DLL 1
// Support only the listed archive types. Remove any you don't need.
/*
#define FEX_TYPE_LIST \
fex_7z_type,\
fex_gz_type,\
fex_rar_type,\
fex_zip_type,
*/
#define HAVE_STDINT_H
// Use standard config.h if present
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More