r923 - in trunk: . lzma lzma/C lzma/C/Archive lzma/C/Archive/7z lzma/C/Compress lzma/C/Compress/Branch lzma/C/Compress/Huffman lzma/C/Compress/Lz lzma/C/Compress/Lzma lzma/CPP lzma/CPP/7zip lzma/CPP/7zip/Archive lzma/CPP/7zip/Archive/7z lzma/CPP/7zip/Archive/Common lzma/CPP/7zip/Bundles lzma/CPP/7zip/Bundles/Alone7z lzma/CPP/7zip/Bundles/Format7zExtractR lzma/CPP/7zip/Bundles/Format7zR lzma/CPP/7zip/Common lzma/CPP/7zip/Compress lzma/CPP/7zip/Compress/Branch lzma/CPP/7zip/Compress/ByteSwap lzma/CPP/7zip/Compress/Copy lzma/CPP/7zip/Compress/LZ lzma/CPP/7zip/Compress/LZMA lzma/CPP/7zip/Compress/LZMA_Alone lzma/CPP/7zip/Compress/RangeCoder lzma/CPP/7zip/UI lzma/CPP/7zip/UI/Client7z lzma/CPP/7zip/UI/Common lzma/CPP/7zip/UI/Console lzma/CPP/Common lzma/CPP/Windows lzma/CS lzma/CS/7zip lzma/CS/7zip/Common lzma/CS/7zip/Compress lzma/CS/7zip/Compress/LZ lzma/CS/7zip/Compress/LZMA lzma/CS/7zip/Compress/LzmaAlone lzma/CS/7zip/Compress/LzmaAlone/Properties lzma/CS/7zip/Compress/RangeCoder lzma/Java lzma/Java/SevenZip lzma/Java/SevenZip/Compression lzma/Java/SevenZip/Compression/LZ lzma/Java/SevenZip/Compression/LZMA lzma/Java/SevenZip/Compression/RangeCoder

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Tue Jan 22 22:52:36 EST 2008


Author: icculus
Date: 2008-01-22 22:52:35 -0500 (Tue, 22 Jan 2008)
New Revision: 923

Added:
   trunk/lzma/
   trunk/lzma/7zC.txt
   trunk/lzma/7zFormat.txt
   trunk/lzma/C/
   trunk/lzma/C/7zCrc.c
   trunk/lzma/C/7zCrc.h
   trunk/lzma/C/7zCrcT8.c
   trunk/lzma/C/Alloc.c
   trunk/lzma/C/Alloc.h
   trunk/lzma/C/Archive/
   trunk/lzma/C/Archive/7z/
   trunk/lzma/C/Archive/7z/7zAlloc.c
   trunk/lzma/C/Archive/7z/7zAlloc.h
   trunk/lzma/C/Archive/7z/7zBuffer.c
   trunk/lzma/C/Archive/7z/7zBuffer.h
   trunk/lzma/C/Archive/7z/7zDecode.c
   trunk/lzma/C/Archive/7z/7zDecode.h
   trunk/lzma/C/Archive/7z/7zExtract.c
   trunk/lzma/C/Archive/7z/7zExtract.h
   trunk/lzma/C/Archive/7z/7zHeader.c
   trunk/lzma/C/Archive/7z/7zHeader.h
   trunk/lzma/C/Archive/7z/7zIn.c
   trunk/lzma/C/Archive/7z/7zIn.h
   trunk/lzma/C/Archive/7z/7zItem.c
   trunk/lzma/C/Archive/7z/7zItem.h
   trunk/lzma/C/Archive/7z/7zMain.c
   trunk/lzma/C/Archive/7z/7zMethodID.c
   trunk/lzma/C/Archive/7z/7zMethodID.h
   trunk/lzma/C/Archive/7z/7z_C.dsp
   trunk/lzma/C/Archive/7z/7z_C.dsw
   trunk/lzma/C/Archive/7z/makefile
   trunk/lzma/C/Archive/7z/makefile.gcc
   trunk/lzma/C/Compress/
   trunk/lzma/C/Compress/Branch/
   trunk/lzma/C/Compress/Branch/BranchARM.c
   trunk/lzma/C/Compress/Branch/BranchARM.h
   trunk/lzma/C/Compress/Branch/BranchARMThumb.c
   trunk/lzma/C/Compress/Branch/BranchARMThumb.h
   trunk/lzma/C/Compress/Branch/BranchIA64.c
   trunk/lzma/C/Compress/Branch/BranchIA64.h
   trunk/lzma/C/Compress/Branch/BranchPPC.c
   trunk/lzma/C/Compress/Branch/BranchPPC.h
   trunk/lzma/C/Compress/Branch/BranchSPARC.c
   trunk/lzma/C/Compress/Branch/BranchSPARC.h
   trunk/lzma/C/Compress/Branch/BranchTypes.h
   trunk/lzma/C/Compress/Branch/BranchX86.c
   trunk/lzma/C/Compress/Branch/BranchX86.h
   trunk/lzma/C/Compress/Branch/BranchX86_2.c
   trunk/lzma/C/Compress/Branch/BranchX86_2.h
   trunk/lzma/C/Compress/Huffman/
   trunk/lzma/C/Compress/Huffman/HuffmanEncode.c
   trunk/lzma/C/Compress/Huffman/HuffmanEncode.h
   trunk/lzma/C/Compress/Lz/
   trunk/lzma/C/Compress/Lz/LzHash.h
   trunk/lzma/C/Compress/Lz/MatchFinder.c
   trunk/lzma/C/Compress/Lz/MatchFinder.h
   trunk/lzma/C/Compress/Lz/MatchFinderMt.c
   trunk/lzma/C/Compress/Lz/MatchFinderMt.h
   trunk/lzma/C/Compress/Lzma/
   trunk/lzma/C/Compress/Lzma/LzmaDecode.c
   trunk/lzma/C/Compress/Lzma/LzmaDecode.h
   trunk/lzma/C/Compress/Lzma/LzmaDecodeSize.c
   trunk/lzma/C/Compress/Lzma/LzmaStateDecode.c
   trunk/lzma/C/Compress/Lzma/LzmaStateDecode.h
   trunk/lzma/C/Compress/Lzma/LzmaStateTest.c
   trunk/lzma/C/Compress/Lzma/LzmaTest.c
   trunk/lzma/C/Compress/Lzma/LzmaTypes.h
   trunk/lzma/C/CpuArch.h
   trunk/lzma/C/IStream.h
   trunk/lzma/C/Sort.c
   trunk/lzma/C/Sort.h
   trunk/lzma/C/Threads.c
   trunk/lzma/C/Threads.h
   trunk/lzma/C/Types.h
   trunk/lzma/CPP/
   trunk/lzma/CPP/7zip/
   trunk/lzma/CPP/7zip/Archive/
   trunk/lzma/CPP/7zip/Archive/7z/
   trunk/lzma/CPP/7zip/Archive/7z/7z.ico
   trunk/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h
   trunk/lzma/CPP/7zip/Archive/7z/7zDecode.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zDecode.h
   trunk/lzma/CPP/7zip/Archive/7z/7zEncode.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zEncode.h
   trunk/lzma/CPP/7zip/Archive/7z/7zExtract.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h
   trunk/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h
   trunk/lzma/CPP/7zip/Archive/7z/7zHandler.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zHandler.h
   trunk/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zHeader.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zHeader.h
   trunk/lzma/CPP/7zip/Archive/7z/7zIn.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zIn.h
   trunk/lzma/CPP/7zip/Archive/7z/7zItem.h
   trunk/lzma/CPP/7zip/Archive/7z/7zOut.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zOut.h
   trunk/lzma/CPP/7zip/Archive/7z/7zProperties.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zProperties.h
   trunk/lzma/CPP/7zip/Archive/7z/7zRegister.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zSpecStream.h
   trunk/lzma/CPP/7zip/Archive/7z/7zUpdate.cpp
   trunk/lzma/CPP/7zip/Archive/7z/7zUpdate.h
   trunk/lzma/CPP/7zip/Archive/7z/StdAfx.cpp
   trunk/lzma/CPP/7zip/Archive/7z/StdAfx.h
   trunk/lzma/CPP/7zip/Archive/Archive.def
   trunk/lzma/CPP/7zip/Archive/Archive2.def
   trunk/lzma/CPP/7zip/Archive/ArchiveExports.cpp
   trunk/lzma/CPP/7zip/Archive/Common/
   trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp
   trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2.h
   trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
   trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h
   trunk/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
   trunk/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h
   trunk/lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp
   trunk/lzma/CPP/7zip/Archive/Common/DummyOutStream.h
   trunk/lzma/CPP/7zip/Archive/Common/HandlerOut.cpp
   trunk/lzma/CPP/7zip/Archive/Common/HandlerOut.h
   trunk/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
   trunk/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h
   trunk/lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp
   trunk/lzma/CPP/7zip/Archive/Common/ItemNameUtils.h
   trunk/lzma/CPP/7zip/Archive/Common/MultiStream.cpp
   trunk/lzma/CPP/7zip/Archive/Common/MultiStream.h
   trunk/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
   trunk/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h
   trunk/lzma/CPP/7zip/Archive/Common/ParseProperties.cpp
   trunk/lzma/CPP/7zip/Archive/Common/ParseProperties.h
   trunk/lzma/CPP/7zip/Archive/DllExports2.cpp
   trunk/lzma/CPP/7zip/Archive/IArchive.h
   trunk/lzma/CPP/7zip/Bundles/
   trunk/lzma/CPP/7zip/Bundles/Alone7z/
   trunk/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp
   trunk/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw
   trunk/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
   trunk/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h
   trunk/lzma/CPP/7zip/Bundles/Alone7z/makefile
   trunk/lzma/CPP/7zip/Bundles/Alone7z/resource.rc
   trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/
   trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
   trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
   trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/makefile
   trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc
   trunk/lzma/CPP/7zip/Bundles/Format7zR/
   trunk/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
   trunk/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h
   trunk/lzma/CPP/7zip/Bundles/Format7zR/makefile
   trunk/lzma/CPP/7zip/Bundles/Format7zR/resource.rc
   trunk/lzma/CPP/7zip/Common/
   trunk/lzma/CPP/7zip/Common/CreateCoder.cpp
   trunk/lzma/CPP/7zip/Common/CreateCoder.h
   trunk/lzma/CPP/7zip/Common/FilePathAutoRename.cpp
   trunk/lzma/CPP/7zip/Common/FilePathAutoRename.h
   trunk/lzma/CPP/7zip/Common/FileStreams.cpp
   trunk/lzma/CPP/7zip/Common/FileStreams.h
   trunk/lzma/CPP/7zip/Common/FilterCoder.cpp
   trunk/lzma/CPP/7zip/Common/FilterCoder.h
   trunk/lzma/CPP/7zip/Common/InBuffer.cpp
   trunk/lzma/CPP/7zip/Common/InBuffer.h
   trunk/lzma/CPP/7zip/Common/InOutTempBuffer.cpp
   trunk/lzma/CPP/7zip/Common/InOutTempBuffer.h
   trunk/lzma/CPP/7zip/Common/LimitedStreams.cpp
   trunk/lzma/CPP/7zip/Common/LimitedStreams.h
   trunk/lzma/CPP/7zip/Common/LockedStream.cpp
   trunk/lzma/CPP/7zip/Common/LockedStream.h
   trunk/lzma/CPP/7zip/Common/MethodId.cpp
   trunk/lzma/CPP/7zip/Common/MethodId.h
   trunk/lzma/CPP/7zip/Common/MethodProps.cpp
   trunk/lzma/CPP/7zip/Common/MethodProps.h
   trunk/lzma/CPP/7zip/Common/OffsetStream.cpp
   trunk/lzma/CPP/7zip/Common/OffsetStream.h
   trunk/lzma/CPP/7zip/Common/OutBuffer.cpp
   trunk/lzma/CPP/7zip/Common/OutBuffer.h
   trunk/lzma/CPP/7zip/Common/ProgressUtils.cpp
   trunk/lzma/CPP/7zip/Common/ProgressUtils.h
   trunk/lzma/CPP/7zip/Common/RegisterArc.h
   trunk/lzma/CPP/7zip/Common/RegisterCodec.h
   trunk/lzma/CPP/7zip/Common/StdAfx.h
   trunk/lzma/CPP/7zip/Common/StreamBinder.cpp
   trunk/lzma/CPP/7zip/Common/StreamBinder.h
   trunk/lzma/CPP/7zip/Common/StreamObjects.cpp
   trunk/lzma/CPP/7zip/Common/StreamObjects.h
   trunk/lzma/CPP/7zip/Common/StreamUtils.cpp
   trunk/lzma/CPP/7zip/Common/StreamUtils.h
   trunk/lzma/CPP/7zip/Common/VirtThread.cpp
   trunk/lzma/CPP/7zip/Common/VirtThread.h
   trunk/lzma/CPP/7zip/Compress/
   trunk/lzma/CPP/7zip/Compress/Branch/
   trunk/lzma/CPP/7zip/Compress/Branch/ARM.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/ARM.h
   trunk/lzma/CPP/7zip/Compress/Branch/ARMThumb.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/ARMThumb.h
   trunk/lzma/CPP/7zip/Compress/Branch/BCJ2Register.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/BCJRegister.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/BranchCoder.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/BranchCoder.h
   trunk/lzma/CPP/7zip/Compress/Branch/BranchRegister.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/IA64.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/IA64.h
   trunk/lzma/CPP/7zip/Compress/Branch/PPC.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/PPC.h
   trunk/lzma/CPP/7zip/Compress/Branch/SPARC.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/SPARC.h
   trunk/lzma/CPP/7zip/Compress/Branch/StdAfx.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/StdAfx.h
   trunk/lzma/CPP/7zip/Compress/Branch/x86.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/x86.h
   trunk/lzma/CPP/7zip/Compress/Branch/x86_2.cpp
   trunk/lzma/CPP/7zip/Compress/Branch/x86_2.h
   trunk/lzma/CPP/7zip/Compress/ByteSwap/
   trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.cpp
   trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.h
   trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwapRegister.cpp
   trunk/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.cpp
   trunk/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.h
   trunk/lzma/CPP/7zip/Compress/CodecExports.cpp
   trunk/lzma/CPP/7zip/Compress/Copy/
   trunk/lzma/CPP/7zip/Compress/Copy/CopyCoder.cpp
   trunk/lzma/CPP/7zip/Compress/Copy/CopyCoder.h
   trunk/lzma/CPP/7zip/Compress/Copy/CopyRegister.cpp
   trunk/lzma/CPP/7zip/Compress/Copy/StdAfx.cpp
   trunk/lzma/CPP/7zip/Compress/Copy/StdAfx.h
   trunk/lzma/CPP/7zip/Compress/LZ/
   trunk/lzma/CPP/7zip/Compress/LZ/LZOutWindow.cpp
   trunk/lzma/CPP/7zip/Compress/LZ/LZOutWindow.h
   trunk/lzma/CPP/7zip/Compress/LZ/StdAfx.h
   trunk/lzma/CPP/7zip/Compress/LZMA/
   trunk/lzma/CPP/7zip/Compress/LZMA/LZMA.h
   trunk/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp
   trunk/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.h
   trunk/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.cpp
   trunk/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.h
   trunk/lzma/CPP/7zip/Compress/LZMA/LZMARegister.cpp
   trunk/lzma/CPP/7zip/Compress/LZMA/StdAfx.cpp
   trunk/lzma/CPP/7zip/Compress/LZMA/StdAfx.h
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.h
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.c
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.h
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/makefile
   trunk/lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc
   trunk/lzma/CPP/7zip/Compress/RangeCoder/
   trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoder.h
   trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.cpp
   trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.h
   trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBitTree.h
   trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderOpt.h
   trunk/lzma/CPP/7zip/Compress/RangeCoder/StdAfx.h
   trunk/lzma/CPP/7zip/ICoder.h
   trunk/lzma/CPP/7zip/IDecl.h
   trunk/lzma/CPP/7zip/IPassword.h
   trunk/lzma/CPP/7zip/IProgress.h
   trunk/lzma/CPP/7zip/IStream.h
   trunk/lzma/CPP/7zip/MyVersion.h
   trunk/lzma/CPP/7zip/MyVersionInfo.rc
   trunk/lzma/CPP/7zip/PropID.h
   trunk/lzma/CPP/7zip/UI/
   trunk/lzma/CPP/7zip/UI/Client7z/
   trunk/lzma/CPP/7zip/UI/Client7z/Client7z.cpp
   trunk/lzma/CPP/7zip/UI/Client7z/Client7z.dsp
   trunk/lzma/CPP/7zip/UI/Client7z/Client7z.dsw
   trunk/lzma/CPP/7zip/UI/Client7z/StdAfx.cpp
   trunk/lzma/CPP/7zip/UI/Client7z/StdAfx.h
   trunk/lzma/CPP/7zip/UI/Client7z/makefile
   trunk/lzma/CPP/7zip/UI/Common/
   trunk/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
   trunk/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h
   trunk/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
   trunk/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h
   trunk/lzma/CPP/7zip/UI/Common/ArchiveName.cpp
   trunk/lzma/CPP/7zip/UI/Common/ArchiveName.h
   trunk/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
   trunk/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h
   trunk/lzma/CPP/7zip/UI/Common/DefaultName.cpp
   trunk/lzma/CPP/7zip/UI/Common/DefaultName.h
   trunk/lzma/CPP/7zip/UI/Common/DirItem.h
   trunk/lzma/CPP/7zip/UI/Common/EnumDirItems.cpp
   trunk/lzma/CPP/7zip/UI/Common/EnumDirItems.h
   trunk/lzma/CPP/7zip/UI/Common/ExitCode.h
   trunk/lzma/CPP/7zip/UI/Common/Extract.cpp
   trunk/lzma/CPP/7zip/UI/Common/Extract.h
   trunk/lzma/CPP/7zip/UI/Common/ExtractMode.h
   trunk/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp
   trunk/lzma/CPP/7zip/UI/Common/ExtractingFilePath.h
   trunk/lzma/CPP/7zip/UI/Common/IFileExtractCallback.h
   trunk/lzma/CPP/7zip/UI/Common/LoadCodecs.cpp
   trunk/lzma/CPP/7zip/UI/Common/LoadCodecs.h
   trunk/lzma/CPP/7zip/UI/Common/OpenArchive.cpp
   trunk/lzma/CPP/7zip/UI/Common/OpenArchive.h
   trunk/lzma/CPP/7zip/UI/Common/PropIDUtils.cpp
   trunk/lzma/CPP/7zip/UI/Common/PropIDUtils.h
   trunk/lzma/CPP/7zip/UI/Common/Property.h
   trunk/lzma/CPP/7zip/UI/Common/SetProperties.cpp
   trunk/lzma/CPP/7zip/UI/Common/SetProperties.h
   trunk/lzma/CPP/7zip/UI/Common/SortUtils.cpp
   trunk/lzma/CPP/7zip/UI/Common/SortUtils.h
   trunk/lzma/CPP/7zip/UI/Common/TempFiles.cpp
   trunk/lzma/CPP/7zip/UI/Common/TempFiles.h
   trunk/lzma/CPP/7zip/UI/Common/Update.cpp
   trunk/lzma/CPP/7zip/UI/Common/Update.h
   trunk/lzma/CPP/7zip/UI/Common/UpdateAction.cpp
   trunk/lzma/CPP/7zip/UI/Common/UpdateAction.h
   trunk/lzma/CPP/7zip/UI/Common/UpdateCallback.cpp
   trunk/lzma/CPP/7zip/UI/Common/UpdateCallback.h
   trunk/lzma/CPP/7zip/UI/Common/UpdatePair.cpp
   trunk/lzma/CPP/7zip/UI/Common/UpdatePair.h
   trunk/lzma/CPP/7zip/UI/Common/UpdateProduce.cpp
   trunk/lzma/CPP/7zip/UI/Common/UpdateProduce.h
   trunk/lzma/CPP/7zip/UI/Common/WorkDir.cpp
   trunk/lzma/CPP/7zip/UI/Common/WorkDir.h
   trunk/lzma/CPP/7zip/UI/Common/ZipRegistry.h
   trunk/lzma/CPP/7zip/UI/Console/
   trunk/lzma/CPP/7zip/UI/Console/ConsoleClose.cpp
   trunk/lzma/CPP/7zip/UI/Console/ConsoleClose.h
   trunk/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
   trunk/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h
   trunk/lzma/CPP/7zip/UI/Console/List.cpp
   trunk/lzma/CPP/7zip/UI/Console/List.h
   trunk/lzma/CPP/7zip/UI/Console/Main.cpp
   trunk/lzma/CPP/7zip/UI/Console/MainAr.cpp
   trunk/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
   trunk/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h
   trunk/lzma/CPP/7zip/UI/Console/PercentPrinter.cpp
   trunk/lzma/CPP/7zip/UI/Console/PercentPrinter.h
   trunk/lzma/CPP/7zip/UI/Console/StdAfx.cpp
   trunk/lzma/CPP/7zip/UI/Console/StdAfx.h
   trunk/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
   trunk/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h
   trunk/lzma/CPP/7zip/UI/Console/UserInputUtils.cpp
   trunk/lzma/CPP/7zip/UI/Console/UserInputUtils.h
   trunk/lzma/CPP/7zip/UI/Console/afxres.h
   trunk/lzma/CPP/Build.mak
   trunk/lzma/CPP/Common/
   trunk/lzma/CPP/Common/AutoPtr.h
   trunk/lzma/CPP/Common/Buffer.h
   trunk/lzma/CPP/Common/CRC.cpp
   trunk/lzma/CPP/Common/C_FileIO.cpp
   trunk/lzma/CPP/Common/C_FileIO.h
   trunk/lzma/CPP/Common/ComTry.h
   trunk/lzma/CPP/Common/CommandLineParser.cpp
   trunk/lzma/CPP/Common/CommandLineParser.h
   trunk/lzma/CPP/Common/Defs.h
   trunk/lzma/CPP/Common/DynamicBuffer.h
   trunk/lzma/CPP/Common/IntToString.cpp
   trunk/lzma/CPP/Common/IntToString.h
   trunk/lzma/CPP/Common/ListFileUtils.cpp
   trunk/lzma/CPP/Common/ListFileUtils.h
   trunk/lzma/CPP/Common/MyCom.h
   trunk/lzma/CPP/Common/MyException.h
   trunk/lzma/CPP/Common/MyGuidDef.h
   trunk/lzma/CPP/Common/MyInitGuid.h
   trunk/lzma/CPP/Common/MyString.cpp
   trunk/lzma/CPP/Common/MyString.h
   trunk/lzma/CPP/Common/MyUnknown.h
   trunk/lzma/CPP/Common/MyVector.cpp
   trunk/lzma/CPP/Common/MyVector.h
   trunk/lzma/CPP/Common/MyWindows.h
   trunk/lzma/CPP/Common/NewHandler.cpp
   trunk/lzma/CPP/Common/NewHandler.h
   trunk/lzma/CPP/Common/StdAfx.h
   trunk/lzma/CPP/Common/StdInStream.cpp
   trunk/lzma/CPP/Common/StdInStream.h
   trunk/lzma/CPP/Common/StdOutStream.cpp
   trunk/lzma/CPP/Common/StdOutStream.h
   trunk/lzma/CPP/Common/StringConvert.cpp
   trunk/lzma/CPP/Common/StringConvert.h
   trunk/lzma/CPP/Common/StringToInt.cpp
   trunk/lzma/CPP/Common/StringToInt.h
   trunk/lzma/CPP/Common/Types.h
   trunk/lzma/CPP/Common/UTFConvert.cpp
   trunk/lzma/CPP/Common/UTFConvert.h
   trunk/lzma/CPP/Common/Wildcard.cpp
   trunk/lzma/CPP/Common/Wildcard.h
   trunk/lzma/CPP/Windows/
   trunk/lzma/CPP/Windows/DLL.cpp
   trunk/lzma/CPP/Windows/DLL.h
   trunk/lzma/CPP/Windows/Defs.h
   trunk/lzma/CPP/Windows/Error.cpp
   trunk/lzma/CPP/Windows/Error.h
   trunk/lzma/CPP/Windows/FileDir.cpp
   trunk/lzma/CPP/Windows/FileDir.h
   trunk/lzma/CPP/Windows/FileFind.cpp
   trunk/lzma/CPP/Windows/FileFind.h
   trunk/lzma/CPP/Windows/FileIO.cpp
   trunk/lzma/CPP/Windows/FileIO.h
   trunk/lzma/CPP/Windows/FileMapping.cpp
   trunk/lzma/CPP/Windows/FileMapping.h
   trunk/lzma/CPP/Windows/FileName.cpp
   trunk/lzma/CPP/Windows/FileName.h
   trunk/lzma/CPP/Windows/Handle.h
   trunk/lzma/CPP/Windows/MemoryLock.cpp
   trunk/lzma/CPP/Windows/MemoryLock.h
   trunk/lzma/CPP/Windows/PropVariant.cpp
   trunk/lzma/CPP/Windows/PropVariant.h
   trunk/lzma/CPP/Windows/PropVariantConversions.cpp
   trunk/lzma/CPP/Windows/PropVariantConversions.h
   trunk/lzma/CPP/Windows/StdAfx.h
   trunk/lzma/CPP/Windows/Synchronization.cpp
   trunk/lzma/CPP/Windows/Synchronization.h
   trunk/lzma/CPP/Windows/System.cpp
   trunk/lzma/CPP/Windows/System.h
   trunk/lzma/CPP/Windows/Thread.h
   trunk/lzma/CPP/Windows/Time.h
   trunk/lzma/CS/
   trunk/lzma/CS/7zip/
   trunk/lzma/CS/7zip/Common/
   trunk/lzma/CS/7zip/Common/CRC.cs
   trunk/lzma/CS/7zip/Common/CommandLineParser.cs
   trunk/lzma/CS/7zip/Common/InBuffer.cs
   trunk/lzma/CS/7zip/Common/OutBuffer.cs
   trunk/lzma/CS/7zip/Compress/
   trunk/lzma/CS/7zip/Compress/LZ/
   trunk/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs
   trunk/lzma/CS/7zip/Compress/LZ/LzBinTree.cs
   trunk/lzma/CS/7zip/Compress/LZ/LzInWindow.cs
   trunk/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs
   trunk/lzma/CS/7zip/Compress/LZMA/
   trunk/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs
   trunk/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs
   trunk/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs
   trunk/lzma/CS/7zip/Compress/LzmaAlone/
   trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs
   trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj
   trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln
   trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs
   trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/
   trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs
   trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs
   trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs
   trunk/lzma/CS/7zip/Compress/RangeCoder/
   trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs
   trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs
   trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
   trunk/lzma/CS/7zip/ICoder.cs
   trunk/lzma/Java/
   trunk/lzma/Java/SevenZip/
   trunk/lzma/Java/SevenZip/CRC.java
   trunk/lzma/Java/SevenZip/Compression/
   trunk/lzma/Java/SevenZip/Compression/LZ/
   trunk/lzma/Java/SevenZip/Compression/LZ/BinTree.java
   trunk/lzma/Java/SevenZip/Compression/LZ/InWindow.java
   trunk/lzma/Java/SevenZip/Compression/LZ/OutWindow.java
   trunk/lzma/Java/SevenZip/Compression/LZMA/
   trunk/lzma/Java/SevenZip/Compression/LZMA/Base.java
   trunk/lzma/Java/SevenZip/Compression/LZMA/Decoder.java
   trunk/lzma/Java/SevenZip/Compression/LZMA/Encoder.java
   trunk/lzma/Java/SevenZip/Compression/RangeCoder/
   trunk/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java
   trunk/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java
   trunk/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java
   trunk/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java
   trunk/lzma/Java/SevenZip/ICodeProgress.java
   trunk/lzma/Java/SevenZip/LzmaAlone.java
   trunk/lzma/Java/SevenZip/LzmaBench.java
   trunk/lzma/LGPL.txt
   trunk/lzma/Methods.txt
   trunk/lzma/history.txt
   trunk/lzma/lzma.exe
   trunk/lzma/lzma.txt
Log:
Upgraded lzma sdk to 4.57.


Added: trunk/lzma/7zC.txt
===================================================================
--- trunk/lzma/7zC.txt	                        (rev 0)
+++ trunk/lzma/7zC.txt	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,237 @@
+7z ANSI-C Decoder 4.48
+----------------------
+
+7z ANSI-C Decoder 4.48 Copyright (C) 1999-2006 Igor Pavlov
+
+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
+-------
+
+Read lzma.txt for information about license.
+
+
+Files
+---------------------
+
+7zAlloc.*    - Allocate and Free
+7zBuffer.*   - Buffer structure
+7zCrc.*      - CRC32 code
+7zDecode.*   - Low level memory->memory decoding
+7zExtract.*  - High level stream->memory decoding
+7zHeader.*   - .7z format constants
+7zIn.*       - .7z archive opening
+7zItem.*     - .7z structures
+7zMain.c     - Test application
+7zMethodID.* - MethodID structure
+7zTypes.h    - Base types and constants
+
+
+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
+----------------------
+
+.7z Decoder can be compiled in one of two modes:
+
+1) Default mode. In that mode 7z Decoder will read full compressed 
+   block to RAM before decompressing.
+  
+2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read
+   compressed block by parts. And you can specify desired buffer size. 
+   So memory requirements can be reduced. But decompressing speed will 
+   be 5-10% lower and code size is slightly larger.
+
+   
+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 ISzInStream interface */
+  CArchiveDatabaseEx db;       /* 7z archive database structure */
+  ISzAlloc allocImp;           /* memory functions for main pool */
+  ISzAlloc allocTempImp;       /* memory functions for temporary pool */
+
+2) call InitCrcTable(); function to initialize CRC structures.
+
+3) call SzArDbExInit(&db); function to initialize db structures.
+
+4) call SzArchiveOpen(inStream, &db, &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.
+SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions.
+
+5) List items or Extract items
+
+  Listing code:
+  ~~~~~~~~~~~~~
+    {
+      UInt32 i;
+      for (i = 0; i < db.Database.NumFiles; i++)
+      {
+        CFileItem *f = db.Database.Files + i;
+        printf("%10d  %s\n", (int)f->Size, f->Name);
+      }
+    }
+
+  Extracting code:
+  ~~~~~~~~~~~~~~~~
+
+  SZ_RESULT SzExtract(
+    ISzInStream *inStream, 
+    CArchiveDatabaseEx *db,
+    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 SzArDbExFree(&db, allocImp.Free) to free allocated items in "db".
+
+
+
+
+Memory requirements for .7z decoding 
+------------------------------------
+
+Memory usage for Archive opening:
+  - Temporary pool:
+     - Memory for compressed .7z headers (if _LZMA_IN_CB is not defined)
+     - 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 compressed solid block (if _LZMA_IN_CB is not defined)
+     - 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. 
+  
+
+If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for 
+compressed blocks. Instead of this, you must allocate buffer with desired 
+size before calling 7z Decoder. Use 7zMain.c as example.
+
+
+
+EXIT codes
+-----------
+
+7z Decoder functions can return one of the following codes:
+
+#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)
+
+
+
+LZMA Defines
+------------
+
+_LZMA_IN_CB       - Use special callback mode for input stream to reduce memory requirements
+
+_SZ_FILE_SIZE_32  - define it if you need only support for files smaller than 4 GB
+_SZ_NO_INT_64     - define it if your compiler doesn't support long long int or __int64.
+
+_LZMA_PROB32      - it can increase LZMA decompressing speed on some 32-bit CPUs.
+
+_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/support.html

Added: trunk/lzma/7zFormat.txt
===================================================================
--- trunk/lzma/7zFormat.txt	                        (rev 0)
+++ trunk/lzma/7zFormat.txt	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,471 @@
+7z Format description (2.30 Beta 25)
+-----------------------------------
+
+This file contains description of 7z archive format. 
+7z archive can contain files compressed with any method.
+See "Methods.txt" for description for defined compressing methods.
+
+
+Format structure Overview
+-------------------------
+
+Some fields can be optional.
+
+Archive structure
+~~~~~~~~~~~~~~~~~  
+SignatureHeader
+[PackedStreams]
+[PackedStreamsForHeaders]
+[
+  Header 
+  or 
+  {
+    Packed Header
+    HeaderInfo
+  }
+]
+
+
+
+Header structure
+~~~~~~~~~~~~~~~~  
+{
+  ArchiveProperties
+  AdditionalStreams
+  {
+    PackInfo
+    {
+      PackPos
+      NumPackStreams
+      Sizes[NumPackStreams]
+      CRCs[NumPackStreams]
+    }
+    CodersInfo
+    {
+      NumFolders
+      Folders[NumFolders]
+      {
+        NumCoders
+        CodersInfo[NumCoders]
+        {
+          ID
+          NumInStreams;
+          NumOutStreams;
+          PropertiesSize
+          Properties[PropertiesSize]
+        }
+        NumBindPairs
+        BindPairsInfo[NumBindPairs]
+        {
+          InIndex;
+          OutIndex;
+        }
+        PackedIndices
+      }
+      UnPackSize[Folders][Folders.NumOutstreams]
+      CRCs[NumFolders]
+    }
+    SubStreamsInfo
+    {
+      NumUnPackStreamsInFolders[NumFolders];
+      UnPackSizes[]
+      CRCs[]
+    }
+  }
+  MainStreamsInfo
+  {
+    (Same as in AdditionalStreams)
+  }
+  FilesInfo
+  {
+    NumFiles
+    Properties[]
+    {
+      ID
+      Size
+      Data
+    }
+  }
+}
+
+HeaderInfo structure
+~~~~~~~~~~~~~~~~~~~~
+{
+  (Same as in AdditionalStreams)
+}
+
+
+
+Notes about Notation and encoding
+---------------------------------
+
+7z uses little endian encoding.
+
+7z archive format has optional headers that are marked as
+[]
+Header
+[]
+
+REAL_UINT64 means real UINT64.
+
+UINT64 means real UINT64 encoded with the following scheme:
+
+  Size of encoding sequence depends from first byte:
+  First_Byte  Extra_Bytes        Value
+  (binary)   
+  0xxxxxxx               : ( xxxxxxx           )
+  10xxxxxx    BYTE y[1]  : (  xxxxxx << (8 * 1)) + y
+  110xxxxx    BYTE y[2]  : (   xxxxx << (8 * 2)) + y
+  ...
+  1111110x    BYTE y[6]  : (       x << (8 * 6)) + y
+  11111110    BYTE y[7]  :                         y
+  11111111    BYTE y[8]  :                         y
+
+
+
+Property IDs
+------------
+
+0x00 = kEnd,
+
+0x01 = kHeader,
+
+0x02 = kArchiveProperties,
+    
+0x03 = kAdditionalStreamsInfo,
+0x04 = kMainStreamsInfo,
+0x05 = kFilesInfo,
+    
+0x06 = kPackInfo,
+0x07 = kUnPackInfo,
+0x08 = kSubStreamsInfo,
+
+0x09 = kSize,
+0x0A = kCRC,
+
+0x0B = kFolder,
+
+0x0C = kCodersUnPackSize,
+0x0D = kNumUnPackStream,
+
+0x0E = kEmptyStream,
+0x0F = kEmptyFile,
+0x10 = kAnti,
+
+0x11 = kName,
+0x12 = kCreationTime,
+0x13 = kLastAccessTime,
+0x14 = kLastWriteTime,
+0x15 = kWinAttributes,
+0x16 = kComment,
+
+0x17 = kEncodedHeader,
+
+
+7z format headers
+-----------------
+
+SignatureHeader
+~~~~~~~~~~~~~~~
+  BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
+
+  ArchiveVersion
+  {
+    BYTE Major;   // now = 0
+    BYTE Minor;   // now = 2
+  };
+
+  UINT32 StartHeaderCRC;
+
+  StartHeader
+  {
+    REAL_UINT64 NextHeaderOffset
+    REAL_UINT64 NextHeaderSize
+    UINT32 NextHeaderCRC
+  }
+
+
+...........................
+
+
+ArchiveProperties
+~~~~~~~~~~~~~~~~~
+BYTE NID::kArchiveProperties (0x02)
+for (;;)
+{
+  BYTE PropertyType;
+  if (aType == 0)
+    break;
+  UINT64 PropertySize;
+  BYTE PropertyData[PropertySize];
+}
+
+
+Digests (NumStreams)
+~~~~~~~~~~~~~~~~~~~~~
+  BYTE AllAreDefined
+  if (AllAreDefined == 0)
+  {
+    for(NumStreams)
+      BIT Defined
+  }
+  UINT32 CRCs[NumDefined]
+
+
+PackInfo
+~~~~~~~~~~~~
+  BYTE NID::kPackInfo  (0x06)
+  UINT64 PackPos
+  UINT64 NumPackStreams
+
+  []
+  BYTE NID::kSize    (0x09)
+  UINT64 PackSizes[NumPackStreams]
+  []
+
+  []
+  BYTE NID::kCRC      (0x0A)
+  PackStreamDigests[NumPackStreams]
+  []
+
+  BYTE NID::kEnd
+
+
+Folder
+~~~~~~
+  UINT64 NumCoders;
+  for (NumCoders)
+  {
+    BYTE 
+    {
+      0:3 DecompressionMethod.IDSize
+      4:
+        0 - IsSimple
+        1 - Is not simple
+      5:
+        0 - No Attributes
+        1 - There Are Attributes
+      7:
+        0 - Last Method in Alternative_Method_List
+        1 - There are more alternative methods
+    } 
+    BYTE DecompressionMethod.ID[DecompressionMethod.IDSize]
+    if (!IsSimple)
+    {
+      UINT64 NumInStreams;
+      UINT64 NumOutStreams;
+    }
+    if (DecompressionMethod[0] != 0)
+    {
+      UINT64 PropertiesSize
+      BYTE Properties[PropertiesSize]
+    }
+  }
+    
+  NumBindPairs = NumOutStreamsTotal - 1;
+
+  for (NumBindPairs)
+  {
+    UINT64 InIndex;
+    UINT64 OutIndex;
+  }
+
+  NumPackedStreams = NumInStreamsTotal - NumBindPairs;
+  if (NumPackedStreams > 1)
+    for(NumPackedStreams)
+    {
+      UINT64 Index;
+    };
+
+
+
+
+Coders Info
+~~~~~~~~~~~
+
+  BYTE NID::kUnPackInfo  (0x07)
+
+
+  BYTE NID::kFolder  (0x0B)
+  UINT64 NumFolders
+  BYTE External
+  switch(External)
+  {
+    case 0:
+      Folders[NumFolders]
+    case 1:
+      UINT64 DataStreamIndex
+  }
+
+
+  BYTE ID::kCodersUnPackSize  (0x0C)
+  for(Folders)
+    for(Folder.NumOutStreams)
+     UINT64 UnPackSize;
+
+
+  []
+  BYTE NID::kCRC   (0x0A)
+  UnPackDigests[NumFolders]
+  []
+
+  
+
+  BYTE NID::kEnd
+
+
+
+SubStreams Info
+~~~~~~~~~~~~~~
+  BYTE NID::kSubStreamsInfo; (0x08)
+
+  []
+  BYTE NID::kNumUnPackStream; (0x0D)
+  UINT64 NumUnPackStreamsInFolders[NumFolders];
+  []
+
+
+  []
+  BYTE NID::kSize  (0x09)
+  UINT64 UnPackSizes[]
+  []
+
+
+  []
+  BYTE NID::kCRC  (0x0A)
+  Digests[Number of streams with unknown CRC]
+  []
+
+  
+  BYTE NID::kEnd
+
+
+Streams Info
+~~~~~~~~~~~~
+
+  []
+  PackInfo
+  []
+
+
+  []
+  CodersInfo
+  []
+
+
+  []
+  SubStreamsInfo
+  []
+
+  BYTE NID::kEnd
+
+
+FilesInfo
+~~~~~~~~~
+  BYTE NID::kFilesInfo;  (0x05)
+  UINT64 NumFiles
+
+  for (;;)
+  {
+    BYTE PropertyType;
+    if (aType == 0)
+      break;
+
+    UINT64 Size;
+
+    switch(PropertyType)
+    {
+      kEmptyStream:   (0x0E)
+        for(NumFiles)
+          BIT IsEmptyStream
+
+      kEmptyFile:     (0x0F)
+        for(EmptyStreams)
+          BIT IsEmptyFile
+
+      kAnti:          (0x10)
+        for(EmptyStreams)
+          BIT IsAntiFile
+      
+      case kCreationTime:   (0x12)
+      case kLastAccessTime: (0x13)
+      case kLastWriteTime:  (0x14)
+        BYTE AllAreDefined
+        if (AllAreDefined == 0)
+        {
+          for(NumFiles)
+            BIT TimeDefined
+        }
+        BYTE External;
+        if(External != 0)
+          UINT64 DataIndex
+        []
+        for(Definded Items)
+          UINT32 Time
+        []
+      
+      kNames:     (0x11)
+        BYTE External;
+        if(External != 0)
+          UINT64 DataIndex
+        []
+        for(Files)
+        {
+          wchar_t Names[NameSize];
+          wchar_t 0;
+        }
+        []
+
+      kAttributes:  (0x15)
+        BYTE AllAreDefined
+        if (AllAreDefined == 0)
+        {
+          for(NumFiles)
+            BIT AttributesAreDefined
+        }
+        BYTE External;
+        if(External != 0)
+          UINT64 DataIndex
+        []
+        for(Definded Attributes)
+          UINT32 Attributes
+        []
+    }
+  }
+
+
+Header
+~~~~~~
+  BYTE NID::kHeader (0x01)
+
+  []
+  ArchiveProperties
+  []
+
+  []
+  BYTE NID::kAdditionalStreamsInfo; (0x03)
+  StreamsInfo
+  []
+
+  []
+  BYTE NID::kMainStreamsInfo;    (0x04)
+  StreamsInfo
+  []
+
+  []
+  FilesInfo
+  []
+
+  BYTE NID::kEnd
+
+
+HeaderInfo
+~~~~~~~~~~
+  []
+  BYTE NID::kEncodedHeader; (0x17)
+  StreamsInfo for Encoded Header
+  []
+
+
+---
+End of document

Added: trunk/lzma/C/7zCrc.c
===================================================================
--- trunk/lzma/C/7zCrc.c	                        (rev 0)
+++ trunk/lzma/C/7zCrc.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,32 @@
+/* 7zCrc.c */
+
+#include "7zCrc.h"
+
+#define kCrcPoly 0xEDB88320
+UInt32 g_CrcTable[256];
+
+void MY_FAST_CALL CrcGenerateTable(void)
+{
+  UInt32 i;
+  for (i = 0; i < 256; i++)
+  {
+    UInt32 r = i;
+    int j;
+    for (j = 0; j < 8; j++)
+      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
+    g_CrcTable[i] = r;
+  }
+}
+
+UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
+{
+  const Byte *p = (const Byte *)data;
+  for (; size > 0 ; size--, p++) 
+    v = CRC_UPDATE_BYTE(v, *p);
+  return v;
+}
+
+UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
+{
+  return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
+}

Added: trunk/lzma/C/7zCrc.h
===================================================================
--- trunk/lzma/C/7zCrc.h	                        (rev 0)
+++ trunk/lzma/C/7zCrc.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,21 @@
+/* 7zCrc.h */
+
+#ifndef __7Z_CRC_H
+#define __7Z_CRC_H
+
+#include <stddef.h>
+
+#include "Types.h"
+
+extern UInt32 g_CrcTable[];
+
+void MY_FAST_CALL CrcGenerateTable(void);
+
+#define CRC_INIT_VAL 0xFFFFFFFF
+#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF)
+#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);
+
+#endif

Added: trunk/lzma/C/7zCrcT8.c
===================================================================
--- trunk/lzma/C/7zCrcT8.c	                        (rev 0)
+++ trunk/lzma/C/7zCrcT8.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,40 @@
+/* 7zCrcT8.c */
+
+#include "7zCrc.h"
+
+#define kCrcPoly 0xEDB88320
+#define CRC_NUM_TABLES 8
+
+UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
+
+void MY_FAST_CALL CrcGenerateTable()
+{
+  UInt32 i;
+  for (i = 0; i < 256; i++)
+  {
+    UInt32 r = i;
+    int j;
+    for (j = 0; j < 8; j++)
+      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
+    g_CrcTable[i] = r;
+  }
+  #if CRC_NUM_TABLES > 1
+  for (; i < 256 * CRC_NUM_TABLES; i++)
+  {
+    UInt32 r = g_CrcTable[i - 256];
+    g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
+  }
+  #endif
+}
+
+UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
+
+UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
+{
+  return CrcUpdateT8(v, data, size, g_CrcTable);
+}
+
+UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
+{
+  return CrcUpdateT8(CRC_INIT_VAL, data, size, g_CrcTable) ^ 0xFFFFFFFF;
+}

Added: trunk/lzma/C/Alloc.c
===================================================================
--- trunk/lzma/C/Alloc.c	                        (rev 0)
+++ trunk/lzma/C/Alloc.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,119 @@
+/* Alloc.c */
+
+#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
+  fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++);
+  #endif
+  return malloc(size);
+}
+
+void MyFree(void *address)
+{
+  #ifdef _SZ_ALLOC_DEBUG
+  if (address != 0)
+    fprintf(stderr, "\nFree; count = %10d", --g_allocCount);
+  #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

Added: trunk/lzma/C/Alloc.h
===================================================================
--- trunk/lzma/C/Alloc.h	                        (rev 0)
+++ trunk/lzma/C/Alloc.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,29 @@
+/* Alloc.h */
+
+#ifndef __COMMON_ALLOC_H
+#define __COMMON_ALLOC_H
+
+#include <stddef.h>
+
+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
+
+#endif

Added: trunk/lzma/C/Archive/7z/7zAlloc.c
===================================================================
--- trunk/lzma/C/Archive/7z/7zAlloc.c	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zAlloc.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,70 @@
+/* 7zAlloc.c */
+
+#include <stdlib.h>
+#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(size_t size)
+{
+  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 *address)
+{
+  #ifdef _SZ_ALLOC_DEBUG
+  if (address != 0)
+  {
+    g_allocCount--;
+    fprintf(stderr, "\nFree; count = %10d", g_allocCount);
+  }
+  #endif
+  free(address);
+}
+
+void *SzAllocTemp(size_t size)
+{
+  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 *address)
+{
+  #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);
+}

Added: trunk/lzma/C/Archive/7z/7zAlloc.h
===================================================================
--- trunk/lzma/C/Archive/7z/7zAlloc.h	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zAlloc.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,20 @@
+/* 7zAlloc.h */
+
+#ifndef __7Z_ALLOC_H
+#define __7Z_ALLOC_H
+
+#include <stddef.h>
+
+typedef struct _ISzAlloc
+{
+  void *(*Alloc)(size_t size);
+  void (*Free)(void *address); /* address can be 0 */
+} ISzAlloc;
+
+void *SzAlloc(size_t size);
+void SzFree(void *address);
+
+void *SzAllocTemp(size_t size);
+void SzFreeTemp(void *address);
+
+#endif

Added: trunk/lzma/C/Archive/7z/7zBuffer.c
===================================================================
--- trunk/lzma/C/Archive/7z/7zBuffer.c	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zBuffer.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,29 @@
+/* 7zBuffer.c */
+
+#include "7zBuffer.h"
+#include "7zAlloc.h"
+
+void SzByteBufferInit(CSzByteBuffer *buffer)
+{
+  buffer->Capacity = 0;
+  buffer->Items = 0;
+}
+
+int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size))
+{
+  buffer->Capacity = newCapacity;
+  if (newCapacity == 0)
+  {
+    buffer->Items = 0;
+    return 1;
+  }
+  buffer->Items = (Byte *)allocFunc(newCapacity);
+  return (buffer->Items != 0);
+}
+
+void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *))
+{
+  freeFunc(buffer->Items);
+  buffer->Items = 0;
+  buffer->Capacity = 0;
+}

Added: trunk/lzma/C/Archive/7z/7zBuffer.h
===================================================================
--- trunk/lzma/C/Archive/7z/7zBuffer.h	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zBuffer.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,19 @@
+/* 7zBuffer.h */
+
+#ifndef __7Z_BUFFER_H
+#define __7Z_BUFFER_H
+
+#include <stddef.h>
+#include "../../Types.h"
+
+typedef struct _CSzByteBuffer
+{
+  size_t Capacity;
+  Byte *Items;
+}CSzByteBuffer;
+
+void SzByteBufferInit(CSzByteBuffer *buffer);
+int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size));
+void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *));
+
+#endif

Added: trunk/lzma/C/Archive/7z/7zDecode.c
===================================================================
--- trunk/lzma/C/Archive/7z/7zDecode.c	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zDecode.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,341 @@
+/* 7zDecode.c */
+
+#include <memory.h>
+
+#include "7zDecode.h"
+#ifdef _SZ_ONE_DIRECTORY
+#include "LzmaDecode.h"
+#else
+#include "../../Compress/Lzma/LzmaDecode.h"
+#include "../../Compress/Branch/BranchX86.h"
+#include "../../Compress/Branch/BranchX86_2.h"
+#endif
+
+#define k_Copy 0
+#define k_LZMA 0x30101
+#define k_BCJ 0x03030103
+#define k_BCJ2 0x0303011B
+
+#ifdef _LZMA_IN_CB
+
+typedef struct _CLzmaInCallbackImp
+{
+  ILzmaInCallback InCallback;
+  ISzInStream *InStream;
+  CFileSize Size;
+} CLzmaInCallbackImp;
+
+int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
+{
+  CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
+  size_t processedSize;
+  SZ_RESULT res;
+  size_t curSize = (1 << 20);
+  if (curSize > cb->Size)
+    curSize = (size_t)cb->Size;
+  *size = 0;
+  res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize);
+  *size = (SizeT)processedSize;
+  if (processedSize > curSize)
+    return (int)SZE_FAIL;
+  cb->Size -= processedSize;
+  if (res == SZ_OK)
+    return 0;
+  return (int)res;
+}
+
+#endif
+
+SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize,
+    #ifdef _LZMA_IN_CB
+    ISzInStream *inStream,
+    #else
+    const Byte *inBuffer,
+    #endif
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
+{
+  #ifdef _LZMA_IN_CB
+  CLzmaInCallbackImp lzmaCallback;
+  #else
+  SizeT inProcessed;
+  #endif
+  
+  CLzmaDecoderState state;  /* it's about 24-80 bytes structure, if int is 32-bit */
+  int result;
+  SizeT outSizeProcessedLoc;
+  
+  #ifdef _LZMA_IN_CB
+  lzmaCallback.Size = inSize;
+  lzmaCallback.InStream = inStream;
+  lzmaCallback.InCallback.Read = LzmaReadImp;
+  #endif
+  
+  if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, 
+      (unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK)
+    return SZE_FAIL;
+  
+  state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+  if (state.Probs == 0)
+    return SZE_OUTOFMEMORY;
+  
+  #ifdef _LZMA_OUT_READ
+  if (state.Properties.DictionarySize == 0)
+    state.Dictionary = 0;
+  else
+  {
+    state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
+    if (state.Dictionary == 0)
+    {
+      allocMain->Free(state.Probs);
+      return SZE_OUTOFMEMORY;
+    }
+  }
+  LzmaDecoderInit(&state);
+  #endif
+  
+  result = LzmaDecode(&state,
+  #ifdef _LZMA_IN_CB
+    &lzmaCallback.InCallback,
+  #else
+    inBuffer, (SizeT)inSize, &inProcessed,
+  #endif
+    outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
+  allocMain->Free(state.Probs);
+  #ifdef _LZMA_OUT_READ
+  allocMain->Free(state.Dictionary);
+  #endif
+  if (result == LZMA_RESULT_DATA_ERROR)
+    return SZE_DATA_ERROR;
+  if (result != LZMA_RESULT_OK)
+    return SZE_FAIL;
+  return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR;
+}
+
+#ifdef _LZMA_IN_CB
+SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer)
+{
+  while (inSize > 0)
+  {
+    void *inBuffer;
+    size_t processedSize, curSize = (1 << 18);
+    if (curSize > inSize)
+      curSize = (size_t)(inSize);
+    RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize));
+    if (processedSize == 0)
+      return SZE_DATA_ERROR;
+    if (processedSize > curSize)
+      return SZE_FAIL;
+    memcpy(outBuffer, inBuffer, processedSize);
+    outBuffer += processedSize;
+    inSize -= processedSize;
+  }
+  return SZ_OK;
+}
+#endif
+
+#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)
+
+SZ_RESULT CheckSupportedFolder(const CFolder *f)
+{
+  if (f->NumCoders < 1 || f->NumCoders > 4)
+    return SZE_NOTIMPL;
+  if (IS_UNSUPPORTED_CODER(f->Coders[0]))
+    return SZE_NOTIMPL;
+  if (f->NumCoders == 1)
+  {
+    if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
+      return SZE_NOTIMPL;
+    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 SZE_NOTIMPL;
+    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 SZE_NOTIMPL;
+    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 SZE_NOTIMPL;
+    return SZ_OK;
+  }
+  return SZE_NOTIMPL;
+}
+
+CFileSize GetSum(const CFileSize *values, UInt32 index)
+{
+  CFileSize sum = 0;
+  UInt32 i;
+  for (i = 0; i < index; i++)
+    sum += values[i];
+  return sum;
+}
+
+SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder,
+    #ifdef _LZMA_IN_CB
+    ISzInStream *inStream, CFileSize startPos,
+    #else
+    const Byte *inBuffer,
+    #endif
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain,
+    Byte *tempBuf[])
+{
+  UInt32 ci;
+  size_t tempSizes[3] = { 0, 0, 0};
+  size_t tempSize3 = 0;
+  Byte *tempBuf3 = 0;
+
+  RINOK(CheckSupportedFolder(folder));
+
+  for (ci = 0; ci < folder->NumCoders; ci++)
+  {
+    CCoderInfo *coder = &folder->Coders[ci];
+
+    if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
+    {
+      UInt32 si = 0;
+      CFileSize offset;
+      CFileSize inSize;
+      Byte *outBufCur = outBuffer;
+      size_t outSizeCur = outSize;
+      if (folder->NumCoders == 4)
+      {
+        UInt32 indices[] = { 3, 2, 0 };
+        CFileSize unpackSize = folder->UnPackSizes[ci];
+        si = indices[ci];
+        if (ci < 2)
+        {
+          Byte *temp;
+          outSizeCur = (size_t)unpackSize;
+          if (outSizeCur != unpackSize)
+            return SZE_OUTOFMEMORY;
+          temp = (Byte *)allocMain->Alloc(outSizeCur);
+          if (temp == 0 && outSizeCur != 0)
+            return SZE_OUTOFMEMORY;
+          outBufCur = tempBuf[1 - ci] = temp;
+          tempSizes[1 - ci] = outSizeCur;
+        }
+        else if (ci == 2)
+        {
+          if (unpackSize > outSize)
+            return SZE_OUTOFMEMORY;
+          tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
+          tempSize3 = outSizeCur = (size_t)unpackSize;
+        }
+        else
+          return SZE_NOTIMPL;
+      }
+      offset = GetSum(packSizes, si);
+      inSize = packSizes[si];
+      #ifdef _LZMA_IN_CB
+      RINOK(inStream->Seek(inStream, startPos + offset));
+      #endif
+
+      if (coder->MethodID == k_Copy)
+      {
+        if (inSize != outSizeCur)
+          return SZE_DATA_ERROR;
+        
+        #ifdef _LZMA_IN_CB
+        RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
+        #else
+        memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize);
+        #endif
+      }
+      else
+      {
+        SZ_RESULT res = SzDecodeLzma(coder, inSize,
+            #ifdef _LZMA_IN_CB
+            inStream,
+            #else
+            inBuffer + (size_t)offset,
+            #endif
+            outBufCur, outSizeCur, allocMain);
+        RINOK(res)
+      }
+    }
+    else if (coder->MethodID == k_BCJ)
+    {
+      UInt32 state;
+      if (ci != 1)
+        return SZE_NOTIMPL;
+      x86_Convert_Init(state);
+      x86_Convert(outBuffer, outSize, 0, &state, 0);
+    }
+    else if (coder->MethodID == k_BCJ2)
+    {
+      CFileSize offset = GetSum(packSizes, 1);
+      CFileSize s3Size = packSizes[1];
+      SZ_RESULT res;
+      if (ci != 3)
+        return SZE_NOTIMPL;
+
+      #ifdef _LZMA_IN_CB
+      RINOK(inStream->Seek(inStream, startPos + offset));
+      tempSizes[2] = (size_t)s3Size;
+      if (tempSizes[2] != s3Size)
+        return SZE_OUTOFMEMORY;
+      tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]);
+      if (tempBuf[2] == 0 && tempSizes[2] != 0)
+        return SZE_OUTOFMEMORY;
+      res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
+      RINOK(res)
+      #endif
+
+      res = x86_2_Decode(
+          tempBuf3, tempSize3, 
+          tempBuf[0], tempSizes[0], 
+          tempBuf[1], tempSizes[1], 
+          #ifdef _LZMA_IN_CB
+          tempBuf[2], tempSizes[2], 
+          #else
+          inBuffer + (size_t)offset, (size_t)s3Size, 
+          #endif
+          outBuffer, outSize);
+      RINOK(res)
+    }
+    else 
+      return SZE_NOTIMPL;
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+    #ifdef _LZMA_IN_CB
+    ISzInStream *inStream, CFileSize startPos,
+    #else
+    const Byte *inBuffer,
+    #endif
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
+{
+  Byte *tempBuf[3] = { 0, 0, 0};
+  int i;
+  SZ_RESULT res = SzDecode2(packSizes, folder,
+      #ifdef _LZMA_IN_CB
+      inStream, startPos,
+      #else
+      inBuffer,
+      #endif
+      outBuffer, outSize, allocMain, tempBuf);
+  for (i = 0; i < 3; i++)
+    allocMain->Free(tempBuf[i]);
+  return res;
+}

Added: trunk/lzma/C/Archive/7z/7zDecode.h
===================================================================
--- trunk/lzma/C/Archive/7z/7zDecode.h	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zDecode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,20 @@
+/* 7zDecode.h */
+
+#ifndef __7Z_DECODE_H
+#define __7Z_DECODE_H
+
+#include "7zItem.h"
+#include "7zAlloc.h"
+#ifdef _LZMA_IN_CB
+#include "7zIn.h"
+#endif
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+    #ifdef _LZMA_IN_CB
+    ISzInStream *stream, CFileSize startPos,
+    #else
+    const Byte *inBuffer,
+    #endif
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
+
+#endif

Added: trunk/lzma/C/Archive/7z/7zExtract.c
===================================================================
--- trunk/lzma/C/Archive/7z/7zExtract.c	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zExtract.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,119 @@
+/* 7zExtract.c */
+
+#include "7zExtract.h"
+#include "7zDecode.h"
+#include "../../7zCrc.h"
+
+SZ_RESULT SzExtract(
+    ISzInStream *inStream, 
+    CArchiveDatabaseEx *db,
+    UInt32 fileIndex,
+    UInt32 *blockIndex,
+    Byte **outBuffer, 
+    size_t *outBufferSize,
+    size_t *offset, 
+    size_t *outSizeProcessed, 
+    ISzAlloc *allocMain,
+    ISzAlloc *allocTemp)
+{
+  UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
+  SZ_RESULT res = SZ_OK;
+  *offset = 0;
+  *outSizeProcessed = 0;
+  if (folderIndex == (UInt32)-1)
+  {
+    allocMain->Free(*outBuffer);
+    *blockIndex = folderIndex;
+    *outBuffer = 0;
+    *outBufferSize = 0;
+    return SZ_OK;
+  }
+
+  if (*outBuffer == 0 || *blockIndex != folderIndex)
+  {
+    CFolder *folder = db->Database.Folders + folderIndex;
+    CFileSize unPackSizeSpec = SzFolderGetUnPackSize(folder);
+    size_t unPackSize = (size_t)unPackSizeSpec;
+    CFileSize startOffset = SzArDbGetFolderStreamPos(db, folderIndex, 0);
+    #ifndef _LZMA_IN_CB
+    Byte *inBuffer = 0;
+    size_t processedSize;
+    CFileSize packSizeSpec;
+    size_t packSize;
+    RINOK(SzArDbGetFolderFullPackSize(db, folderIndex, &packSizeSpec));
+    packSize = (size_t)packSizeSpec;
+    if (packSize != packSizeSpec)
+      return SZE_OUTOFMEMORY;
+    #endif
+    if (unPackSize != unPackSizeSpec)
+      return SZE_OUTOFMEMORY;
+    *blockIndex = folderIndex;
+    allocMain->Free(*outBuffer);
+    *outBuffer = 0;
+    
+    RINOK(inStream->Seek(inStream, startOffset));
+    
+    #ifndef _LZMA_IN_CB
+    if (packSize != 0)
+    {
+      inBuffer = (Byte *)allocTemp->Alloc(packSize);
+      if (inBuffer == 0)
+        return SZE_OUTOFMEMORY;
+    }
+    res = inStream->Read(inStream, inBuffer, packSize, &processedSize);
+    if (res == SZ_OK && processedSize != packSize)
+      res = SZE_FAIL;
+    #endif
+    if (res == SZ_OK)
+    {
+      *outBufferSize = unPackSize;
+      if (unPackSize != 0)
+      {
+        *outBuffer = (Byte *)allocMain->Alloc(unPackSize);
+        if (*outBuffer == 0)
+          res = SZE_OUTOFMEMORY;
+      }
+      if (res == SZ_OK)
+      {
+        res = SzDecode(db->Database.PackSizes + 
+          db->FolderStartPackStreamIndex[folderIndex], folder, 
+          #ifdef _LZMA_IN_CB
+          inStream, startOffset, 
+          #else
+          inBuffer, 
+          #endif
+          *outBuffer, unPackSize, allocTemp);
+        if (res == SZ_OK)
+        {
+          if (folder->UnPackCRCDefined)
+          {
+            if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC)
+              res = SZE_CRC_ERROR;
+          }
+        }
+      }
+    }
+    #ifndef _LZMA_IN_CB
+    allocTemp->Free(inBuffer);
+    #endif
+  }
+  if (res == SZ_OK)
+  {
+    UInt32 i; 
+    CFileItem *fileItem = db->Database.Files + fileIndex;
+    *offset = 0;
+    for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
+      *offset += (UInt32)db->Database.Files[i].Size;
+    *outSizeProcessed = (size_t)fileItem->Size;
+    if (*offset + *outSizeProcessed > *outBufferSize)
+      return SZE_FAIL;
+    {
+      if (fileItem->IsFileCRCDefined)
+      {
+        if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
+          res = SZE_CRC_ERROR;
+      }
+    }
+  }
+  return res;
+}

Added: trunk/lzma/C/Archive/7z/7zExtract.h
===================================================================
--- trunk/lzma/C/Archive/7z/7zExtract.h	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zExtract.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,40 @@
+/* 7zExtract.h */
+
+#ifndef __7Z_EXTRACT_H
+#define __7Z_EXTRACT_H
+
+#include "7zIn.h"
+
+/*
+  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.
+*/
+
+SZ_RESULT SzExtract(
+    ISzInStream *inStream, 
+    CArchiveDatabaseEx *db,
+    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);
+
+#endif

Added: trunk/lzma/C/Archive/7z/7zHeader.c
===================================================================
--- trunk/lzma/C/Archive/7z/7zHeader.c	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zHeader.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,5 @@
+/*  7zHeader.c */
+
+#include "7zHeader.h"
+
+Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

Added: trunk/lzma/C/Archive/7z/7zHeader.h
===================================================================
--- trunk/lzma/C/Archive/7z/7zHeader.h	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zHeader.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,55 @@
+/* 7zHeader.h */
+
+#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,
+  k7zIdCreationTime,
+  k7zIdLastAccessTime,
+  k7zIdLastWriteTime,
+  k7zIdWinAttributes,
+  k7zIdComment,
+  
+  k7zIdEncodedHeader,
+  
+  k7zIdStartPos
+};
+
+#endif

Added: trunk/lzma/C/Archive/7z/7zIn.c
===================================================================
--- trunk/lzma/C/Archive/7z/7zIn.c	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zIn.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1314 @@
+/* 7zIn.c */
+
+#include "7zIn.h"
+#include "7zDecode.h"
+#include "../../7zCrc.h"
+
+#define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; }
+
+void SzArDbExInit(CArchiveDatabaseEx *db)
+{
+  SzArchiveDatabaseInit(&db->Database);
+  db->FolderStartPackStreamIndex = 0;
+  db->PackStreamStartPositions = 0;
+  db->FolderStartFileIndex = 0;
+  db->FileIndexToFolderIndexMap = 0;
+}
+
+void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *))
+{
+  freeFunc(db->FolderStartPackStreamIndex);
+  freeFunc(db->PackStreamStartPositions);
+  freeFunc(db->FolderStartFileIndex);
+  freeFunc(db->FileIndexToFolderIndexMap);
+  SzArchiveDatabaseFree(&db->Database, freeFunc);
+  SzArDbExInit(db);
+}
+
+/*
+CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const 
+{
+  return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
+}
+
+CFileSize GetFilePackSize(int fileIndex) const
+{
+  int folderIndex = FileIndexToFolderIndexMap[fileIndex];
+  if (folderIndex >= 0)
+  {
+    const CFolder &folderInfo = Folders[folderIndex];
+    if (FolderStartFileIndex[folderIndex] == fileIndex)
+    return GetFolderFullPackSize(folderIndex);
+  }
+  return 0;
+}
+*/
+
+#define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \
+  if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; }
+
+SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
+{
+  UInt32 startPos = 0;
+  CFileSize startPosSize = 0;
+  UInt32 i;
+  UInt32 folderIndex = 0;
+  UInt32 indexInFolder = 0;
+  MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc);
+  for(i = 0; i < db->Database.NumFolders; i++)
+  {
+    db->FolderStartPackStreamIndex[i] = startPos;
+    startPos += db->Database.Folders[i].NumPackStreams;
+  }
+
+  MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc);
+
+  for(i = 0; i < db->Database.NumPackStreams; i++)
+  {
+    db->PackStreamStartPositions[i] = startPosSize;
+    startPosSize += db->Database.PackSizes[i];
+  }
+
+  MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc);
+  MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc);
+
+  for (i = 0; i < db->Database.NumFiles; i++)
+  {
+    CFileItem *file = db->Database.Files + i;
+    int emptyStream = !file->HasStream;
+    if (emptyStream && indexInFolder == 0)
+    {
+      db->FileIndexToFolderIndexMap[i] = (UInt32)-1;
+      continue;
+    }
+    if (indexInFolder == 0)
+    {
+      /*
+      v3.13 incorrectly worked with empty folders
+      v4.07: Loop for skipping empty folders
+      */
+      for (;;)
+      {
+        if (folderIndex >= db->Database.NumFolders)
+          return SZE_ARCHIVE_ERROR;
+        db->FolderStartFileIndex[folderIndex] = i;
+        if (db->Database.Folders[folderIndex].NumUnPackStreams != 0)
+          break;
+        folderIndex++;
+      }
+    }
+    db->FileIndexToFolderIndexMap[i] = folderIndex;
+    if (emptyStream)
+      continue;
+    indexInFolder++;
+    if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams)
+    {
+      folderIndex++;
+      indexInFolder = 0;
+    }
+  }
+  return SZ_OK;
+}
+
+
+CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder)
+{
+  return db->ArchiveInfo.DataStartPosition + 
+    db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder];
+}
+
+int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize)
+{
+  UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex];
+  CFolder *folder = db->Database.Folders + folderIndex;
+  CFileSize size = 0;
+  UInt32 i;
+  for (i = 0; i < folder->NumPackStreams; i++)
+  {
+    CFileSize t = size + db->Database.PackSizes[packStreamIndex + i];
+    if (t < size)
+      return SZE_FAIL;
+    size = t;
+  }
+  *resSize = size;
+  return SZ_OK;
+}
+
+
+/*
+SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector,
+    CObjectVector<CFileItem> &files, UInt64 type)
+{
+  CBoolVector boolVector;
+  RINOK(ReadBoolVector2(files.Size(), boolVector))
+
+  CStreamSwitch streamSwitch;
+  RINOK(streamSwitch.Set(this, &dataVector));
+
+  for(int i = 0; i < files.Size(); i++)
+  {
+    CFileItem &file = files[i];
+    CArchiveFileTime fileTime;
+    bool defined = boolVector[i];
+    if (defined)
+    {
+      UInt32 low, high;
+      RINOK(SzReadUInt32(low));
+      RINOK(SzReadUInt32(high));
+      fileTime.dwLowDateTime = low;
+      fileTime.dwHighDateTime = high;
+    }
+    switch(type)
+    {
+      case k7zIdCreationTime:
+        file.IsCreationTimeDefined = defined;
+        if (defined)
+          file.CreationTime = fileTime;
+        break;
+      case k7zIdLastWriteTime:
+        file.IsLastWriteTimeDefined = defined;
+        if (defined)
+          file.LastWriteTime = fileTime;
+        break;
+      case k7zIdLastAccessTime:
+        file.IsLastAccessTimeDefined = defined;
+        if (defined)
+          file.LastAccessTime = fileTime;
+        break;
+    }
+  }
+  return SZ_OK;
+}
+*/
+
+SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size)
+{
+  #ifdef _LZMA_IN_CB
+  while (size > 0)
+  {
+    void *inBufferSpec;
+    size_t processedSize;
+    const Byte *inBuffer;
+    RINOK(inStream->Read(inStream, (void **)&inBufferSpec, size, &processedSize));
+    inBuffer = (const Byte *)inBufferSpec;
+    if (processedSize == 0 || processedSize > size)
+      return SZE_FAIL;
+    size -= processedSize;
+    do
+    {
+      *data++ = *inBuffer++;
+    }
+    while (--processedSize != 0);
+  }
+  #else
+  size_t processedSize;
+  RINOK(inStream->Read(inStream, data, size, &processedSize));
+  if (processedSize != size)
+    return SZE_FAIL;
+  #endif
+  return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data)
+{
+  return SafeReadDirect(inStream, data, 1);
+}
+
+SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value, UInt32 *crc)
+{
+  int i;
+  *value = 0;
+  for (i = 0; i < 4; i++)
+  {
+    Byte b;
+    RINOK(SafeReadDirectByte(inStream, &b));
+    *value |= ((UInt32)b << (8 * i));
+    *crc = CRC_UPDATE_BYTE(*crc, b);
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value, UInt32 *crc)
+{
+  int i;
+  *value = 0;
+  for (i = 0; i < 8; i++)
+  {
+    Byte b;
+    RINOK(SafeReadDirectByte(inStream, &b));
+    *value |= ((UInt64)b << (8 * i));
+    *crc = CRC_UPDATE_BYTE(*crc, b);
+  }
+  return SZ_OK;
+}
+
+int TestSignatureCandidate(Byte *testBytes)
+{
+  size_t i;
+  for (i = 0; i < k7zSignatureSize; i++)
+    if (testBytes[i] != k7zSignature[i])
+      return 0;
+  return 1;
+}
+
+typedef struct _CSzState
+{
+  Byte *Data;
+  size_t Size;
+}CSzData;
+
+SZ_RESULT SzReadByte(CSzData *sd, Byte *b)
+{
+  if (sd->Size == 0)
+    return SZE_ARCHIVE_ERROR;
+  sd->Size--;
+  *b = *sd->Data++;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size)
+{
+  size_t i;
+  for (i = 0; i < size; i++)
+  {
+    RINOK(SzReadByte(sd, data + i));
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value)
+{
+  int i;
+  *value = 0;
+  for (i = 0; i < 4; i++)
+  {
+    Byte b;
+    RINOK(SzReadByte(sd, &b));
+    *value |= ((UInt32)(b) << (8 * i));
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value)
+{
+  Byte firstByte;
+  Byte mask = 0x80;
+  int i;
+  RINOK(SzReadByte(sd, &firstByte));
+  *value = 0;
+  for (i = 0; i < 8; i++)
+  {
+    Byte b;
+    if ((firstByte & mask) == 0)
+    {
+      UInt64 highPart = firstByte & (mask - 1);
+      *value += (highPart << (8 * i));
+      return SZ_OK;
+    }
+    RINOK(SzReadByte(sd, &b));
+    *value |= ((UInt64)b << (8 * i));
+    mask >>= 1;
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value)
+{
+  UInt64 value64;
+  RINOK(SzReadNumber(sd, &value64));
+  *value = (CFileSize)value64;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value)
+{
+  UInt64 value64;
+  RINOK(SzReadNumber(sd, &value64));
+  if (value64 >= 0x80000000)
+    return SZE_NOTIMPL;
+  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))
+    return SZE_NOTIMPL;
+  *value = (UInt32)value64;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) 
+{ 
+  return SzReadNumber(sd, value); 
+}
+
+SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size)
+{
+  if (size > sd->Size)
+    return SZE_ARCHIVE_ERROR;
+  sd->Size -= (size_t)size;
+  sd->Data += (size_t)size;
+  return SZ_OK;
+}
+
+SZ_RESULT SzSkeepData(CSzData *sd)
+{
+  UInt64 size;
+  RINOK(SzReadNumber(sd, &size));
+  return SzSkeepDataSize(sd, size);
+}
+
+SZ_RESULT SzReadArchiveProperties(CSzData *sd)
+{
+  for (;;)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdEnd)
+      break;
+    SzSkeepData(sd);
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute)
+{
+  for (;;)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if (type == attribute)
+      return SZ_OK;
+    if (type == k7zIdEnd)
+      return SZE_ARCHIVE_ERROR;
+    RINOK(SzSkeepData(sd));
+  }
+}
+
+SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+  Byte b = 0;
+  Byte mask = 0;
+  size_t i;
+  MY_ALLOC(Byte, *v, numItems, allocFunc);
+  for (i = 0; i < numItems; i++)
+  {
+    if (mask == 0)
+    {
+      RINOK(SzReadByte(sd, &b));
+      mask = 0x80;
+    }
+    (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);
+    mask >>= 1;
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+  Byte allAreDefined;
+  size_t i;
+  RINOK(SzReadByte(sd, &allAreDefined));
+  if (allAreDefined == 0)
+    return SzReadBoolVector(sd, numItems, v, allocFunc);
+  MY_ALLOC(Byte, *v, numItems, allocFunc);
+  for(i = 0; i < numItems; i++)
+    (*v)[i] = 1;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadHashDigests(
+    CSzData *sd, 
+    size_t numItems,
+    Byte **digestsDefined, 
+    UInt32 **digests, 
+    void * (*allocFunc)(size_t size))
+{
+  size_t i;
+  RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc));
+  MY_ALLOC(UInt32, *digests, numItems, allocFunc);
+  for(i = 0; i < numItems; i++)
+    if ((*digestsDefined)[i])
+    {
+      RINOK(SzReadUInt32(sd, (*digests) + i));
+    }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadPackInfo(
+    CSzData *sd, 
+    CFileSize *dataOffset,
+    UInt32 *numPackStreams,
+    CFileSize **packSizes,
+    Byte **packCRCsDefined,
+    UInt32 **packCRCs,
+    void * (*allocFunc)(size_t size))
+{
+  UInt32 i;
+  RINOK(SzReadSize(sd, dataOffset));
+  RINOK(SzReadNumber32(sd, numPackStreams));
+
+  RINOK(SzWaitAttribute(sd, k7zIdSize));
+
+  MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc);
+
+  for(i = 0; i < *numPackStreams; i++)
+  {
+    RINOK(SzReadSize(sd, (*packSizes) + i));
+  }
+
+  for (;;)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdEnd)
+      break;
+    if (type == k7zIdCRC)
+    {
+      RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); 
+      continue;
+    }
+    RINOK(SzSkeepData(sd));
+  }
+  if (*packCRCsDefined == 0)
+  {
+    MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc);
+    MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc);
+    for(i = 0; i < *numPackStreams; i++)
+    {
+      (*packCRCsDefined)[i] = 0;
+      (*packCRCs)[i] = 0;
+    }
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadSwitch(CSzData *sd)
+{
+  Byte external;
+  RINOK(SzReadByte(sd, &external));
+  return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR;
+}
+
+SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size))
+{
+  UInt32 numCoders;
+  UInt32 numBindPairs;
+  UInt32 numPackedStreams;
+  UInt32 i;
+  UInt32 numInStreams = 0;
+  UInt32 numOutStreams = 0;
+  RINOK(SzReadNumber32(sd, &numCoders));
+  folder->NumCoders = numCoders;
+
+  MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc);
+
+  for (i = 0; i < numCoders; i++)
+    SzCoderInfoInit(folder->Coders + i);
+
+  for (i = 0; i < numCoders; i++)
+  {
+    Byte mainByte;
+    CCoderInfo *coder = folder->Coders + i;
+    {
+      unsigned idSize, j;
+      Byte longID[15];
+      RINOK(SzReadByte(sd, &mainByte));
+      idSize = (unsigned)(mainByte & 0xF);
+      RINOK(SzReadBytes(sd, longID, idSize));
+      if (idSize > sizeof(coder->MethodID))
+        return SZE_NOTIMPL;
+      coder->MethodID = 0;
+      for (j = 0; j < idSize; j++)
+        coder->MethodID |= (CMethodID)longID[idSize - 1 - j] << (8 * j);
+
+      if ((mainByte & 0x10) != 0)
+      {
+        RINOK(SzReadNumber32(sd, &coder->NumInStreams));
+        RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
+      }
+      else
+      {
+        coder->NumInStreams = 1;
+        coder->NumOutStreams = 1;
+      }
+      if ((mainByte & 0x20) != 0)
+      {
+        UInt64 propertiesSize = 0;
+        RINOK(SzReadNumber(sd, &propertiesSize));
+        if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc))
+          return SZE_OUTOFMEMORY;
+        RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize));
+      }
+    }
+    while ((mainByte & 0x80) != 0)
+    {
+      RINOK(SzReadByte(sd, &mainByte));
+      RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
+      if ((mainByte & 0x10) != 0)
+      {
+        UInt32 n;
+        RINOK(SzReadNumber32(sd, &n));
+        RINOK(SzReadNumber32(sd, &n));
+      }
+      if ((mainByte & 0x20) != 0)
+      {
+        UInt64 propertiesSize = 0;
+        RINOK(SzReadNumber(sd, &propertiesSize));
+        RINOK(SzSkeepDataSize(sd, propertiesSize));
+      }
+    }
+    numInStreams += (UInt32)coder->NumInStreams;
+    numOutStreams += (UInt32)coder->NumOutStreams;
+  }
+
+  numBindPairs = numOutStreams - 1;
+  folder->NumBindPairs = numBindPairs;
+
+
+  MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc);
+
+  for (i = 0; i < numBindPairs; i++)
+  {
+    CBindPair *bindPair = folder->BindPairs + i;;
+    RINOK(SzReadNumber32(sd, &bindPair->InIndex));
+    RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); 
+  }
+
+  numPackedStreams = numInStreams - (UInt32)numBindPairs;
+
+  folder->NumPackStreams = numPackedStreams;
+  MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc);
+
+  if (numPackedStreams == 1)
+  {
+    UInt32 j;
+    UInt32 pi = 0;
+    for (j = 0; j < numInStreams; j++)
+      if (SzFolderFindBindPairForInStream(folder, j) < 0)
+      {
+        folder->PackStreams[pi++] = j;
+        break;
+      }
+  }
+  else
+    for(i = 0; i < numPackedStreams; i++)
+    {
+      RINOK(SzReadNumber32(sd, folder->PackStreams + i));
+    }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadUnPackInfo(
+    CSzData *sd, 
+    UInt32 *numFolders,
+    CFolder **folders,  /* for allocFunc */
+    void * (*allocFunc)(size_t size),
+    ISzAlloc *allocTemp)
+{
+  UInt32 i;
+  RINOK(SzWaitAttribute(sd, k7zIdFolder));
+  RINOK(SzReadNumber32(sd, numFolders));
+  {
+    RINOK(SzReadSwitch(sd));
+
+    MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc);
+
+    for(i = 0; i < *numFolders; i++)
+      SzFolderInit((*folders) + i);
+
+    for(i = 0; i < *numFolders; i++)
+    {
+      RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc));
+    }
+  }
+
+  RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize));
+
+  for(i = 0; i < *numFolders; i++)
+  {
+    UInt32 j;
+    CFolder *folder = (*folders) + i;
+    UInt32 numOutStreams = SzFolderGetNumOutStreams(folder);
+
+    MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc);
+
+    for(j = 0; j < numOutStreams; j++)
+    {
+      RINOK(SzReadSize(sd, folder->UnPackSizes + j));
+    }
+  }
+
+  for (;;)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdEnd)
+      return SZ_OK;
+    if (type == k7zIdCRC)
+    {
+      SZ_RESULT res;
+      Byte *crcsDefined = 0;
+      UInt32 *crcs = 0;
+      res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); 
+      if (res == SZ_OK)
+      {
+        for(i = 0; i < *numFolders; i++)
+        {
+          CFolder *folder = (*folders) + i;
+          folder->UnPackCRCDefined = crcsDefined[i];
+          folder->UnPackCRC = crcs[i];
+        }
+      }
+      allocTemp->Free(crcs);
+      allocTemp->Free(crcsDefined);
+      RINOK(res);
+      continue;
+    }
+    RINOK(SzSkeepData(sd));
+  }
+}
+
+SZ_RESULT SzReadSubStreamsInfo(
+    CSzData *sd, 
+    UInt32 numFolders,
+    CFolder *folders,
+    UInt32 *numUnPackStreams,
+    CFileSize **unPackSizes,
+    Byte **digestsDefined,
+    UInt32 **digests,
+    ISzAlloc *allocTemp)
+{
+  UInt64 type = 0;
+  UInt32 i;
+  UInt32 si = 0;
+  UInt32 numDigests = 0;
+
+  for(i = 0; i < numFolders; i++)
+    folders[i].NumUnPackStreams = 1;
+  *numUnPackStreams = numFolders;
+
+  for (;;)
+  {
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdNumUnPackStream)
+    {
+      *numUnPackStreams = 0;
+      for(i = 0; i < numFolders; i++)
+      {
+        UInt32 numStreams;
+        RINOK(SzReadNumber32(sd, &numStreams));
+        folders[i].NumUnPackStreams = numStreams;
+        *numUnPackStreams += numStreams;
+      }
+      continue;
+    }
+    if (type == k7zIdCRC || type == k7zIdSize)
+      break;
+    if (type == k7zIdEnd)
+      break;
+    RINOK(SzSkeepData(sd));
+  }
+
+  if (*numUnPackStreams == 0)
+  {
+    *unPackSizes = 0;
+    *digestsDefined = 0;
+    *digests = 0;
+  }
+  else
+  {
+    *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize));
+    RINOM(*unPackSizes);
+    *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte));
+    RINOM(*digestsDefined);
+    *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32));
+    RINOM(*digests);
+  }
+
+  for(i = 0; i < numFolders; i++)
+  {
+    /*
+    v3.13 incorrectly worked with empty folders
+    v4.07: we check that folder is empty
+    */
+    CFileSize sum = 0;
+    UInt32 j;
+    UInt32 numSubstreams = folders[i].NumUnPackStreams;
+    if (numSubstreams == 0)
+      continue;
+    if (type == k7zIdSize)
+    for (j = 1; j < numSubstreams; j++)
+    {
+      CFileSize size;
+      RINOK(SzReadSize(sd, &size));
+      (*unPackSizes)[si++] = size;
+      sum += size;
+    }
+    (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum;
+  }
+  if (type == k7zIdSize)
+  {
+    RINOK(SzReadID(sd, &type));
+  }
+
+  for(i = 0; i < *numUnPackStreams; i++)
+  {
+    (*digestsDefined)[i] = 0;
+    (*digests)[i] = 0;
+  }
+
+
+  for(i = 0; i < numFolders; i++)
+  {
+    UInt32 numSubstreams = folders[i].NumUnPackStreams;
+    if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
+      numDigests += numSubstreams;
+  }
+
+ 
+  si = 0;
+  for (;;)
+  {
+    if (type == k7zIdCRC)
+    {
+      int digestIndex = 0;
+      Byte *digestsDefined2 = 0; 
+      UInt32 *digests2 = 0;
+      SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc);
+      if (res == SZ_OK)
+      {
+        for (i = 0; i < numFolders; i++)
+        {
+          CFolder *folder = folders + i;
+          UInt32 numSubstreams = folder->NumUnPackStreams;
+          if (numSubstreams == 1 && folder->UnPackCRCDefined)
+          {
+            (*digestsDefined)[si] = 1;
+            (*digests)[si] = folder->UnPackCRC;
+            si++;
+          }
+          else
+          {
+            UInt32 j;
+            for (j = 0; j < numSubstreams; j++, digestIndex++)
+            {
+              (*digestsDefined)[si] = digestsDefined2[digestIndex];
+              (*digests)[si] = digests2[digestIndex];
+              si++;
+            }
+          }
+        }
+      }
+      allocTemp->Free(digestsDefined2);
+      allocTemp->Free(digests2);
+      RINOK(res);
+    }
+    else if (type == k7zIdEnd)
+      return SZ_OK;
+    else
+    {
+      RINOK(SzSkeepData(sd));
+    }
+    RINOK(SzReadID(sd, &type));
+  }
+}
+
+
+SZ_RESULT SzReadStreamsInfo(
+    CSzData *sd, 
+    CFileSize *dataOffset,
+    CArchiveDatabase *db,
+    UInt32 *numUnPackStreams,
+    CFileSize **unPackSizes, /* allocTemp */
+    Byte **digestsDefined,   /* allocTemp */
+    UInt32 **digests,        /* allocTemp */
+    void * (*allocFunc)(size_t size),
+    ISzAlloc *allocTemp)
+{
+  for (;;)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if ((UInt64)(int)type != type)
+      return SZE_FAIL;
+    switch((int)type)
+    {
+      case k7zIdEnd:
+        return SZ_OK;
+      case k7zIdPackInfo:
+      {
+        RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, 
+            &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc));
+        break;
+      }
+      case k7zIdUnPackInfo:
+      {
+        RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp));
+        break;
+      }
+      case k7zIdSubStreamsInfo:
+      {
+        RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, 
+            numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp));
+        break;
+      }
+      default:
+        return SZE_FAIL;
+    }
+  }
+}
+
+Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, 
+    void * (*allocFunc)(size_t size))
+{
+  UInt32 i;
+  for(i = 0; i < numFiles; i++)
+  {
+    UInt32 len = 0;
+    UInt32 pos = 0;
+    CFileItem *file = files + i;
+    while(pos + 2 <= sd->Size)
+    {
+      int numAdds;
+      UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+      pos += 2;
+      len++;
+      if (value == 0)
+        break;
+      if (value < 0x80)
+        continue;
+      if (value >= 0xD800 && value < 0xE000)
+      {
+        UInt32 c2;
+        if (value >= 0xDC00)
+          return SZE_ARCHIVE_ERROR;
+        if (pos + 2 > sd->Size)
+          return SZE_ARCHIVE_ERROR;
+        c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+        pos += 2;
+        if (c2 < 0xDC00 || c2 >= 0xE000)
+          return SZE_ARCHIVE_ERROR;
+        value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+      }
+      for (numAdds = 1; numAdds < 5; numAdds++)
+        if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+          break;
+      len += numAdds;
+    }
+
+    MY_ALLOC(char, file->Name, (size_t)len, allocFunc);
+
+    len = 0;
+    while(2 <= sd->Size)
+    {
+      int numAdds;
+      UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+      SzSkeepDataSize(sd, 2);
+      if (value < 0x80)
+      {
+        file->Name[len++] = (char)value;
+        if (value == 0)
+          break;
+        continue;
+      }
+      if (value >= 0xD800 && value < 0xE000)
+      {
+        UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+        SzSkeepDataSize(sd, 2);
+        value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+      }
+      for (numAdds = 1; numAdds < 5; numAdds++)
+        if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+          break;
+      file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
+      do
+      {
+        numAdds--;
+        file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
+      }
+      while(numAdds > 0);
+
+      len += numAdds;
+    }
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadHeader2(
+    CSzData *sd, 
+    CArchiveDatabaseEx *db,   /* allocMain */
+    CFileSize **unPackSizes,  /* allocTemp */
+    Byte **digestsDefined,    /* allocTemp */
+    UInt32 **digests,         /* allocTemp */
+    Byte **emptyStreamVector, /* allocTemp */
+    Byte **emptyFileVector,   /* allocTemp */
+    Byte **lwtVector,         /* allocTemp */
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp)
+{
+  UInt64 type;
+  UInt32 numUnPackStreams = 0;
+  UInt32 numFiles = 0;
+  CFileItem *files = 0;
+  UInt32 numEmptyStreams = 0;
+  UInt32 i;
+
+  RINOK(SzReadID(sd, &type));
+
+  if (type == k7zIdArchiveProperties)
+  {
+    RINOK(SzReadArchiveProperties(sd));
+    RINOK(SzReadID(sd, &type));
+  }
+ 
+ 
+  if (type == k7zIdMainStreamsInfo)
+  {
+    RINOK(SzReadStreamsInfo(sd,
+        &db->ArchiveInfo.DataStartPosition,
+        &db->Database, 
+        &numUnPackStreams,
+        unPackSizes,
+        digestsDefined,
+        digests, allocMain->Alloc, allocTemp));
+    db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader;
+    RINOK(SzReadID(sd, &type));
+  }
+
+  if (type == k7zIdEnd)
+    return SZ_OK;
+  if (type != k7zIdFilesInfo)
+    return SZE_ARCHIVE_ERROR;
+  
+  RINOK(SzReadNumber32(sd, &numFiles));
+  db->Database.NumFiles = numFiles;
+
+  MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc);
+
+  db->Database.Files = files;
+  for(i = 0; i < numFiles; i++)
+    SzFileInit(files + i);
+
+  for (;;)
+  {
+    UInt64 type;
+    UInt64 size;
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdEnd)
+      break;
+    RINOK(SzReadNumber(sd, &size));
+
+    if ((UInt64)(int)type != type)
+    {
+      RINOK(SzSkeepDataSize(sd, size));
+    }
+    else
+    switch((int)type)
+    {
+      case k7zIdName:
+      {
+        RINOK(SzReadSwitch(sd));
+        RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc))
+        break;
+      }
+      case k7zIdEmptyStream:
+      {
+        RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc));
+        numEmptyStreams = 0;
+        for (i = 0; i < numFiles; i++)
+          if ((*emptyStreamVector)[i])
+            numEmptyStreams++;
+        break;
+      }
+      case k7zIdEmptyFile:
+      {
+        RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc));
+        break;
+      }
+      case k7zIdLastWriteTime:
+      {
+        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp->Alloc));
+        RINOK(SzReadSwitch(sd));
+        for (i = 0; i < numFiles; i++)
+        {
+          CFileItem *f = &files[i];
+          Byte defined = (*lwtVector)[i];
+          f->IsLastWriteTimeDefined = defined;
+          f->LastWriteTime.Low = f->LastWriteTime.High = 0;
+          if (defined)
+          {
+            RINOK(SzReadUInt32(sd, &f->LastWriteTime.Low));
+            RINOK(SzReadUInt32(sd, &f->LastWriteTime.High));
+          }
+        }
+        break;
+      }
+      default:
+      {
+        RINOK(SzSkeepDataSize(sd, size));
+      }
+    }
+  }
+
+  {
+    UInt32 emptyFileIndex = 0;
+    UInt32 sizeIndex = 0;
+    for(i = 0; i < numFiles; i++)
+    {
+      CFileItem *file = files + i;
+      file->IsAnti = 0;
+      if (*emptyStreamVector == 0)
+        file->HasStream = 1;
+      else
+        file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);
+      if(file->HasStream)
+      {
+        file->IsDirectory = 0;
+        file->Size = (*unPackSizes)[sizeIndex];
+        file->FileCRC = (*digests)[sizeIndex];
+        file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex];
+        sizeIndex++;
+      }
+      else
+      {
+        if (*emptyFileVector == 0)
+          file->IsDirectory = 1;
+        else
+          file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
+        emptyFileIndex++;
+        file->Size = 0;
+        file->IsFileCRCDefined = 0;
+      }
+    }
+  }
+  return SzArDbExFill(db, allocMain->Alloc);
+}
+
+SZ_RESULT SzReadHeader(
+    CSzData *sd, 
+    CArchiveDatabaseEx *db, 
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp)
+{
+  CFileSize *unPackSizes = 0;
+  Byte *digestsDefined = 0;
+  UInt32 *digests = 0;
+  Byte *emptyStreamVector = 0;
+  Byte *emptyFileVector = 0;
+  Byte *lwtVector = 0;
+  SZ_RESULT res = SzReadHeader2(sd, db, 
+      &unPackSizes, &digestsDefined, &digests,
+      &emptyStreamVector, &emptyFileVector, &lwtVector, 
+      allocMain, allocTemp);
+  allocTemp->Free(unPackSizes);
+  allocTemp->Free(digestsDefined);
+  allocTemp->Free(digests);
+  allocTemp->Free(emptyStreamVector);
+  allocTemp->Free(emptyFileVector);
+  allocTemp->Free(lwtVector);
+  return res;
+} 
+
+SZ_RESULT SzReadAndDecodePackedStreams2(
+    ISzInStream *inStream, 
+    CSzData *sd,
+    CSzByteBuffer *outBuffer,
+    CFileSize baseOffset, 
+    CArchiveDatabase *db,
+    CFileSize **unPackSizes,
+    Byte **digestsDefined,
+    UInt32 **digests,
+    #ifndef _LZMA_IN_CB
+    Byte **inBuffer,
+    #endif
+    ISzAlloc *allocTemp)
+{
+
+  UInt32 numUnPackStreams = 0;
+  CFileSize dataStartPos;
+  CFolder *folder;
+  #ifndef _LZMA_IN_CB
+  CFileSize packSize = 0;
+  UInt32 i = 0;
+  #endif
+  CFileSize unPackSize;
+  SZ_RESULT res;
+
+  RINOK(SzReadStreamsInfo(sd, &dataStartPos, db,
+      &numUnPackStreams,  unPackSizes, digestsDefined, digests, 
+      allocTemp->Alloc, allocTemp));
+  
+  dataStartPos += baseOffset;
+  if (db->NumFolders != 1)
+    return SZE_ARCHIVE_ERROR;
+
+  folder = db->Folders;
+  unPackSize = SzFolderGetUnPackSize(folder);
+  
+  RINOK(inStream->Seek(inStream, dataStartPos));
+
+  #ifndef _LZMA_IN_CB
+  for (i = 0; i < db->NumPackStreams; i++)
+    packSize += db->PackSizes[i];
+
+  MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc);
+
+  RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize));
+  #endif
+
+  if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc))
+    return SZE_OUTOFMEMORY;
+  
+  res = SzDecode(db->PackSizes, folder, 
+          #ifdef _LZMA_IN_CB
+          inStream, dataStartPos, 
+          #else
+          *inBuffer, 
+          #endif
+          outBuffer->Items, (size_t)unPackSize, allocTemp);
+  RINOK(res)
+  if (folder->UnPackCRCDefined)
+    if (CrcCalc(outBuffer->Items, (size_t)unPackSize) != folder->UnPackCRC)
+      return SZE_FAIL;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadAndDecodePackedStreams(
+    ISzInStream *inStream, 
+    CSzData *sd,
+    CSzByteBuffer *outBuffer,
+    CFileSize baseOffset, 
+    ISzAlloc *allocTemp)
+{
+  CArchiveDatabase db;
+  CFileSize *unPackSizes = 0;
+  Byte *digestsDefined = 0;
+  UInt32 *digests = 0;
+  #ifndef _LZMA_IN_CB
+  Byte *inBuffer = 0;
+  #endif
+  SZ_RESULT res;
+  SzArchiveDatabaseInit(&db);
+  res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, 
+    &db, &unPackSizes, &digestsDefined, &digests, 
+    #ifndef _LZMA_IN_CB
+    &inBuffer,
+    #endif
+    allocTemp);
+  SzArchiveDatabaseFree(&db, allocTemp->Free);
+  allocTemp->Free(unPackSizes);
+  allocTemp->Free(digestsDefined);
+  allocTemp->Free(digests);
+  #ifndef _LZMA_IN_CB
+  allocTemp->Free(inBuffer);
+  #endif
+  return res;
+}
+
+SZ_RESULT SzArchiveOpen2(
+    ISzInStream *inStream, 
+    CArchiveDatabaseEx *db,
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp)
+{
+  Byte signature[k7zSignatureSize];
+  Byte version;
+  UInt32 crcFromArchive;
+  UInt64 nextHeaderOffset;
+  UInt64 nextHeaderSize;
+  UInt32 nextHeaderCRC;
+  UInt32 crc = 0;
+  CFileSize pos = 0;
+  CSzByteBuffer buffer;
+  CSzData sd;
+  SZ_RESULT res;
+
+  RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize));
+
+  if (!TestSignatureCandidate(signature))
+    return SZE_ARCHIVE_ERROR;
+
+  /*
+  db.Clear();
+  db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
+  */
+  RINOK(SafeReadDirectByte(inStream, &version));
+  if (version != k7zMajorVersion)
+    return SZE_ARCHIVE_ERROR;
+  RINOK(SafeReadDirectByte(inStream, &version));
+
+  RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive, &crc));
+
+  crc = CRC_INIT_VAL;
+  RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset, &crc));
+  RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize, &crc));
+  RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC, &crc));
+
+  pos = k7zStartHeaderSize;
+  db->ArchiveInfo.StartPositionAfterHeader = pos;
+  
+  if (CRC_GET_DIGEST(crc) != crcFromArchive)
+    return SZE_ARCHIVE_ERROR;
+
+  if (nextHeaderSize == 0)
+    return SZ_OK;
+
+  RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset)));
+
+  if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc))
+    return SZE_OUTOFMEMORY;
+
+  res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize);
+  if (res == SZ_OK)
+  {
+    res = SZE_ARCHIVE_ERROR;
+    if (CrcCalc(buffer.Items, (UInt32)nextHeaderSize) == nextHeaderCRC)
+    {
+      for (;;)
+      {
+        UInt64 type;
+        sd.Data = buffer.Items;
+        sd.Size = buffer.Capacity;
+        res = SzReadID(&sd, &type);
+        if (res != SZ_OK)
+          break;
+        if (type == k7zIdHeader)
+        {
+          res = SzReadHeader(&sd, db, allocMain, allocTemp);
+          break;
+        }
+        if (type != k7zIdEncodedHeader)
+        {
+          res = SZE_ARCHIVE_ERROR;
+          break;
+        }
+        {
+          CSzByteBuffer outBuffer;
+          res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, 
+              db->ArchiveInfo.StartPositionAfterHeader, 
+              allocTemp);
+          if (res != SZ_OK)
+          {
+            SzByteBufferFree(&outBuffer, allocTemp->Free);
+            break;
+          }
+          SzByteBufferFree(&buffer, allocTemp->Free);
+          buffer.Items = outBuffer.Items;
+          buffer.Capacity = outBuffer.Capacity;
+        }
+      }
+    }
+  }
+  SzByteBufferFree(&buffer, allocTemp->Free);
+  return res;
+}
+
+SZ_RESULT SzArchiveOpen(
+    ISzInStream *inStream, 
+    CArchiveDatabaseEx *db,
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp)
+{
+  SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp);
+  if (res != SZ_OK)
+    SzArDbExFree(db, allocMain->Free);
+  return res;
+}

Added: trunk/lzma/C/Archive/7z/7zIn.h
===================================================================
--- trunk/lzma/C/Archive/7z/7zIn.h	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zIn.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,55 @@
+/* 7zIn.h */
+
+#ifndef __7Z_IN_H
+#define __7Z_IN_H
+
+#include "7zHeader.h"
+#include "7zItem.h"
+#include "7zAlloc.h"
+ 
+typedef struct _CInArchiveInfo
+{
+  CFileSize StartPositionAfterHeader; 
+  CFileSize DataStartPosition;
+}CInArchiveInfo;
+
+typedef struct _CArchiveDatabaseEx
+{
+  CArchiveDatabase Database;
+  CInArchiveInfo ArchiveInfo;
+  UInt32 *FolderStartPackStreamIndex;
+  CFileSize *PackStreamStartPositions;
+  UInt32 *FolderStartFileIndex;
+  UInt32 *FileIndexToFolderIndexMap;
+}CArchiveDatabaseEx;
+
+void SzArDbExInit(CArchiveDatabaseEx *db);
+void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *));
+CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder);
+int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize);
+
+typedef struct _ISzInStream
+{
+  #ifdef _LZMA_IN_CB
+  SZ_RESULT (*Read)(
+      void *object,           /* pointer to ISzInStream itself */
+      void **buffer,          /* out: pointer to buffer with data */
+      size_t maxRequiredSize, /* max required size to read */
+      size_t *processedSize); /* real processed size. 
+                                 processedSize can be less than maxRequiredSize.
+                                 If processedSize == 0, then there are no more 
+                                 bytes in stream. */
+  #else
+  SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize);
+  #endif
+  SZ_RESULT (*Seek)(void *object, CFileSize pos);
+} ISzInStream;
+
+ 
+int SzArchiveOpen(
+    ISzInStream *inStream, 
+    CArchiveDatabaseEx *db,
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp);
+ 
+#endif

Added: trunk/lzma/C/Archive/7z/7zItem.c
===================================================================
--- trunk/lzma/C/Archive/7z/7zItem.c	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zItem.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,134 @@
+/* 7zItem.c */
+
+#include "7zItem.h"
+#include "7zAlloc.h"
+
+void SzCoderInfoInit(CCoderInfo *coder)
+{
+  SzByteBufferInit(&coder->Properties);
+}
+
+void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p))
+{
+  SzByteBufferFree(&coder->Properties, freeFunc);
+  SzCoderInfoInit(coder);
+}
+
+void SzFolderInit(CFolder *folder)
+{
+  folder->NumCoders = 0;
+  folder->Coders = 0;
+  folder->NumBindPairs = 0;
+  folder->BindPairs = 0;
+  folder->NumPackStreams = 0;
+  folder->PackStreams = 0;
+  folder->UnPackSizes = 0;
+  folder->UnPackCRCDefined = 0;
+  folder->UnPackCRC = 0;
+  folder->NumUnPackStreams = 0;
+}
+
+void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p))
+{
+  UInt32 i;
+  for (i = 0; i < folder->NumCoders; i++)
+    SzCoderInfoFree(&folder->Coders[i], freeFunc);
+  freeFunc(folder->Coders);
+  freeFunc(folder->BindPairs);
+  freeFunc(folder->PackStreams);
+  freeFunc(folder->UnPackSizes);
+  SzFolderInit(folder);
+}
+
+UInt32 SzFolderGetNumOutStreams(CFolder *folder)
+{
+  UInt32 result = 0;
+  UInt32 i;
+  for (i = 0; i < folder->NumCoders; i++)
+    result += folder->Coders[i].NumOutStreams;
+  return result;
+}
+
+int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex)
+{
+  UInt32 i;
+  for(i = 0; i < folder->NumBindPairs; i++)
+    if (folder->BindPairs[i].InIndex == inStreamIndex)
+      return i;
+  return -1;
+}
+
+
+int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex)
+{
+  UInt32 i;
+  for(i = 0; i < folder->NumBindPairs; i++)
+    if (folder->BindPairs[i].OutIndex == outStreamIndex)
+      return i;
+  return -1;
+}
+
+CFileSize SzFolderGetUnPackSize(CFolder *folder)
+{ 
+  int i = (int)SzFolderGetNumOutStreams(folder);
+  if (i == 0)
+    return 0;
+  for (i--; i >= 0; i--)
+    if (SzFolderFindBindPairForOutStream(folder, i) < 0)
+      return folder->UnPackSizes[i];
+  /* throw 1; */
+  return 0;
+}
+
+/*
+int FindPackStreamArrayIndex(int inStreamIndex) const
+{
+  for(int i = 0; i < PackStreams.Size(); i++)
+  if (PackStreams[i] == inStreamIndex)
+    return i;
+  return -1;
+}
+*/
+
+void SzFileInit(CFileItem *fileItem)
+{
+  fileItem->IsFileCRCDefined = 0;
+  fileItem->HasStream = 1;
+  fileItem->IsDirectory = 0;
+  fileItem->IsAnti = 0;
+  fileItem->IsLastWriteTimeDefined = 0;
+  fileItem->Name = 0;
+}
+
+void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p))
+{
+  freeFunc(fileItem->Name);
+  SzFileInit(fileItem);
+}
+
+void SzArchiveDatabaseInit(CArchiveDatabase *db)
+{
+  db->NumPackStreams = 0;
+  db->PackSizes = 0;
+  db->PackCRCsDefined = 0;
+  db->PackCRCs = 0;
+  db->NumFolders = 0;
+  db->Folders = 0;
+  db->NumFiles = 0;
+  db->Files = 0;
+}
+
+void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *))
+{
+  UInt32 i;
+  for (i = 0; i < db->NumFolders; i++)
+    SzFolderFree(&db->Folders[i], freeFunc);
+  for (i = 0; i < db->NumFiles; i++)
+    SzFileFree(&db->Files[i], freeFunc);
+  freeFunc(db->PackSizes);
+  freeFunc(db->PackCRCsDefined);
+  freeFunc(db->PackCRCs);
+  freeFunc(db->Folders);
+  freeFunc(db->Files);
+  SzArchiveDatabaseInit(db);
+}

Added: trunk/lzma/C/Archive/7z/7zItem.h
===================================================================
--- trunk/lzma/C/Archive/7z/7zItem.h	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zItem.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,95 @@
+/* 7zItem.h */
+
+#ifndef __7Z_ITEM_H
+#define __7Z_ITEM_H
+
+#include "7zMethodID.h"
+#include "7zHeader.h"
+#include "7zBuffer.h"
+
+typedef struct _CCoderInfo
+{
+  UInt32 NumInStreams;
+  UInt32 NumOutStreams;
+  CMethodID MethodID;
+  CSzByteBuffer Properties;
+}CCoderInfo;
+
+void SzCoderInfoInit(CCoderInfo *coder);
+void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p));
+
+typedef struct _CBindPair
+{
+  UInt32 InIndex;
+  UInt32 OutIndex;
+}CBindPair;
+
+typedef struct _CFolder
+{
+  UInt32 NumCoders;
+  CCoderInfo *Coders;
+  UInt32 NumBindPairs;
+  CBindPair *BindPairs;
+  UInt32 NumPackStreams; 
+  UInt32 *PackStreams;
+  CFileSize *UnPackSizes;
+  int UnPackCRCDefined;
+  UInt32 UnPackCRC;
+
+  UInt32 NumUnPackStreams;
+}CFolder;
+
+void SzFolderInit(CFolder *folder);
+CFileSize SzFolderGetUnPackSize(CFolder *folder);
+int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex);
+UInt32 SzFolderGetNumOutStreams(CFolder *folder);
+CFileSize SzFolderGetUnPackSize(CFolder *folder);
+
+typedef struct _CArchiveFileTime
+{
+  UInt32 Low;
+  UInt32 High;
+} CArchiveFileTime;
+
+typedef struct _CFileItem
+{
+  CArchiveFileTime LastWriteTime;
+  /*
+  CFileSize StartPos;
+  UInt32 Attributes; 
+  */
+  CFileSize Size;
+  UInt32 FileCRC;
+  char *Name;
+
+  Byte IsFileCRCDefined;
+  Byte HasStream;
+  Byte IsDirectory;
+  Byte IsAnti;
+  Byte IsLastWriteTimeDefined;
+  /*
+  int AreAttributesDefined;
+  int IsLastWriteTimeDefined;
+  int IsStartPosDefined;
+  */
+}CFileItem;
+
+void SzFileInit(CFileItem *fileItem);
+
+typedef struct _CArchiveDatabase
+{
+  UInt32 NumPackStreams;
+  CFileSize *PackSizes;
+  Byte *PackCRCsDefined;
+  UInt32 *PackCRCs;
+  UInt32 NumFolders;
+  CFolder *Folders;
+  UInt32 NumFiles;
+  CFileItem *Files;
+}CArchiveDatabase;
+
+void SzArchiveDatabaseInit(CArchiveDatabase *db);
+void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *));
+
+
+#endif

Added: trunk/lzma/C/Archive/7z/7zMain.c
===================================================================
--- trunk/lzma/C/Archive/7z/7zMain.c	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zMain.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,428 @@
+/* 
+7zMain.c
+Test application for 7z Decoder
+LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+#define USE_WINDOWS_FUNCTIONS
+#endif
+
+#ifdef USE_WINDOWS_FUNCTIONS
+#include <windows.h>
+#endif
+
+#include "7zIn.h"
+#include "7zExtract.h"
+
+#include "../../7zCrc.h"
+
+
+#ifdef USE_WINDOWS_FUNCTIONS
+typedef HANDLE MY_FILE_HANDLE;
+#else
+typedef FILE *MY_FILE_HANDLE;
+#endif
+
+void ConvertNumberToString(CFileSize value, char *s)
+{
+  char temp[32];
+  int pos = 0;
+  do 
+  {
+    temp[pos++] = (char)('0' + (int)(value % 10));
+    value /= 10;
+  }
+  while (value != 0);
+  do
+    *s++ = temp[--pos];
+  while(pos > 0);
+  *s = '\0';
+}
+
+#define PERIOD_4 (4 * 365 + 1)
+#define PERIOD_100 (PERIOD_4 * 25 - 1)
+#define PERIOD_400 (PERIOD_100 * 4 + 1)
+
+void ConvertFileTimeToString(CArchiveFileTime *ft, char *s)
+{
+  unsigned year, mon, day, hour, min, sec;
+  UInt64 v64 = ft->Low | ((UInt64)ft->High << 32);
+  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+  unsigned temp;
+  UInt32 v; 
+  v64 /= 10000000;
+  sec = (unsigned)(v64 % 60);
+  v64 /= 60;
+  min = (unsigned)(v64 % 60);
+  v64 /= 60;
+  hour = (unsigned)(v64 % 24);
+  v64 /= 24;
+
+  v = (UInt32)v64;
+
+  year = (unsigned)(1601 + v / PERIOD_400 * 400);
+  v %= PERIOD_400;
+
+  temp = (unsigned)(v / PERIOD_100);
+  if (temp == 4)
+    temp = 3;
+  year += temp * 100;
+  v -= temp * PERIOD_100;
+
+  temp = v / PERIOD_4;
+  if (temp == 25)
+    temp = 24;
+  year += temp * 4;
+  v -= temp * PERIOD_4;
+
+  temp = v / 365;
+  if (temp == 4)
+    temp = 3;
+  year += temp;
+  v -= temp * 365;
+
+  if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
+    ms[1] = 29;
+  for (mon = 1; mon <= 12; mon++)
+  {
+    unsigned s = ms[mon - 1];
+    if (v < s)
+      break;
+    v -= s;
+  }
+  day = (unsigned)v + 1;
+  sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec);
+}
+
+
+#ifdef USE_WINDOWS_FUNCTIONS
+/*
+   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).
+*/
+#define kChunkSizeMax (1 << 24)
+#endif
+
+size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size)
+{ 
+  if (size == 0)
+    return 0;
+  #ifdef USE_WINDOWS_FUNCTIONS
+  {
+    size_t processedSize = 0;
+    do
+    {
+      DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
+      DWORD processedLoc = 0;
+      BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL);
+      data = (void *)((unsigned char *)data + processedLoc);
+      size -= processedLoc;
+      processedSize += processedLoc;
+      if (!res || processedLoc == 0)
+        break;
+    }
+    while (size > 0);
+    return processedSize;
+  }
+  #else
+  return fread(data, 1, size, file); 
+  #endif
+}
+
+size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size)
+{ 
+  if (size == 0)
+    return 0;
+  #ifdef USE_WINDOWS_FUNCTIONS
+  {
+    size_t processedSize = 0;
+    do
+    {
+      DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
+      DWORD processedLoc = 0;
+      BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL);
+      data = (void *)((unsigned char *)data + processedLoc);
+      size -= processedLoc;
+      processedSize += processedLoc;
+      if (!res)
+        break;
+    }
+    while (size > 0);
+    return processedSize;
+  }
+  #else
+  return fwrite(data, 1, size, file); 
+  #endif
+}
+
+int MyCloseFile(MY_FILE_HANDLE file)
+{ 
+  #ifdef USE_WINDOWS_FUNCTIONS
+  return (CloseHandle(file) != FALSE) ? 0 : 1;
+  #else
+  return fclose(file); 
+  #endif
+}
+
+typedef struct _CFileInStream
+{
+  ISzInStream InStream;
+  MY_FILE_HANDLE File;
+} CFileInStream;
+
+#ifdef _LZMA_IN_CB
+
+#define kBufferSize (1 << 12)
+Byte g_Buffer[kBufferSize];
+
+SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
+{
+  CFileInStream *s = (CFileInStream *)object;
+  size_t processedSizeLoc;
+  if (maxRequiredSize > kBufferSize)
+    maxRequiredSize = kBufferSize;
+  processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize);
+  *buffer = g_Buffer;
+  if (processedSize != 0)
+    *processedSize = processedSizeLoc;
+  return SZ_OK;
+}
+
+#else
+
+SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize)
+{
+  CFileInStream *s = (CFileInStream *)object;
+  size_t processedSizeLoc = MyReadFile(s->File, buffer, size);
+  if (processedSize != 0)
+    *processedSize = processedSizeLoc;
+  return SZ_OK;
+}
+
+#endif
+
+SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
+{
+  CFileInStream *s = (CFileInStream *)object;
+
+  #ifdef USE_WINDOWS_FUNCTIONS
+  {
+    LARGE_INTEGER value;
+    value.LowPart = (DWORD)pos;
+    value.HighPart = (LONG)((UInt64)pos >> 32);
+    #ifdef _SZ_FILE_SIZE_32
+    /* VC 6.0 has bug with >> 32 shifts. */
+    value.HighPart = 0;
+    #endif
+    value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN);
+    if (value.LowPart == 0xFFFFFFFF)
+      if(GetLastError() != NO_ERROR) 
+        return SZE_FAIL;
+    return SZ_OK;
+  }
+  #else
+  int res = fseek(s->File, (long)pos, SEEK_SET);
+  if (res == 0)
+    return SZ_OK;
+  return SZE_FAIL;
+  #endif
+}
+
+void PrintError(char *sz)
+{
+  printf("\nERROR: %s\n", sz);
+}
+
+int main(int numargs, char *args[])
+{
+  CFileInStream archiveStream;
+  CArchiveDatabaseEx db;
+  SZ_RESULT res;
+  ISzAlloc allocImp;
+  ISzAlloc allocTempImp;
+
+  printf("\n7z ANSI-C Decoder 4.48  Copyright (c) 1999-2007 Igor Pavlov  2007-06-21\n");
+  if (numargs == 1)
+  {
+    printf(
+      "\nUsage: 7zDec <command> <archive_name>\n\n"
+      "<Commands>\n"
+      "  e: Extract files from archive\n"
+      "  l: List contents of archive\n"
+      "  t: Test integrity of archive\n");
+    return 0;
+  }
+  if (numargs < 3)
+  {
+    PrintError("incorrect command");
+    return 1;
+  }
+
+  archiveStream.File = 
+  #ifdef USE_WINDOWS_FUNCTIONS
+  CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ, 
+      NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (archiveStream.File == INVALID_HANDLE_VALUE)
+  #else
+  archiveStream.File = fopen(args[2], "rb");
+  if (archiveStream.File == 0)
+  #endif
+  {
+    PrintError("can not open input file");
+    return 1;
+  }
+
+  archiveStream.InStream.Read = SzFileReadImp;
+  archiveStream.InStream.Seek = SzFileSeekImp;
+
+  allocImp.Alloc = SzAlloc;
+  allocImp.Free = SzFree;
+
+  allocTempImp.Alloc = SzAllocTemp;
+  allocTempImp.Free = SzFreeTemp;
+
+  CrcGenerateTable();
+
+  SzArDbExInit(&db);
+  res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
+  if (res == SZ_OK)
+  {
+    char *command = args[1];
+    int listCommand = 0;
+    int testCommand = 0;
+    int extractCommand = 0;
+    if (strcmp(command, "l") == 0)
+      listCommand = 1;
+    if (strcmp(command, "t") == 0)
+      testCommand = 1;
+    else if (strcmp(command, "e") == 0)
+      extractCommand = 1;
+
+    if (listCommand)
+    {
+      UInt32 i;
+      for (i = 0; i < db.Database.NumFiles; i++)
+      {
+        CFileItem *f = db.Database.Files + i;
+        char s[32], t[32];
+        ConvertNumberToString(f->Size, s);
+        if (f->IsLastWriteTimeDefined)
+          ConvertFileTimeToString(&f->LastWriteTime, t);
+        else
+          strcpy(t, "                   ");
+
+        printf("%10s %s  %s\n", s, t, f->Name);
+      }
+    }
+    else if (testCommand || extractCommand)
+    {
+      UInt32 i;
+
+      /*
+      if you need cache, use these 3 variables.
+      if you use external function, you can make these variable as static.
+      */
+      UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
+      Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
+      size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */
+
+      printf("\n");
+      for (i = 0; i < db.Database.NumFiles; i++)
+      {
+        size_t offset;
+        size_t outSizeProcessed;
+        CFileItem *f = db.Database.Files + i;
+        if (f->IsDirectory)
+          printf("Directory ");
+        else
+          printf(testCommand ? 
+            "Testing   ":
+            "Extracting");
+        printf(" %s", f->Name);
+        if (f->IsDirectory)
+        {
+          printf("\n");
+          continue;
+        }
+        res = SzExtract(&archiveStream.InStream, &db, i, 
+            &blockIndex, &outBuffer, &outBufferSize, 
+            &offset, &outSizeProcessed, 
+            &allocImp, &allocTempImp);
+        if (res != SZ_OK)
+          break;
+        if (!testCommand)
+        {
+          MY_FILE_HANDLE outputHandle;
+          size_t processedSize;
+          char *fileName = f->Name;
+          size_t nameLen = strlen(f->Name);
+          for (; nameLen > 0; nameLen--)
+            if (f->Name[nameLen - 1] == '/')
+            {
+              fileName = f->Name + nameLen;
+              break;
+            }
+            
+          outputHandle = 
+          #ifdef USE_WINDOWS_FUNCTIONS
+            CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ, 
+                NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+          if (outputHandle == INVALID_HANDLE_VALUE)
+          #else
+          fopen(fileName, "wb+");
+          if (outputHandle == 0)
+          #endif
+          {
+            PrintError("can not open output file");
+            res = SZE_FAIL;
+            break;
+          }
+          processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed);
+          if (processedSize != outSizeProcessed)
+          {
+            PrintError("can not write output file");
+            res = SZE_FAIL;
+            break;
+          }
+          if (MyCloseFile(outputHandle))
+          {
+            PrintError("can not close output file");
+            res = SZE_FAIL;
+            break;
+          }
+        }
+        printf("\n");
+      }
+      allocImp.Free(outBuffer);
+    }
+    else
+    {
+      PrintError("incorrect command");
+      res = SZE_FAIL;
+    }
+  }
+  SzArDbExFree(&db, allocImp.Free);
+
+  MyCloseFile(archiveStream.File);
+  if (res == SZ_OK)
+  {
+    printf("\nEverything is Ok\n");
+    return 0;
+  }
+  if (res == (SZ_RESULT)SZE_NOTIMPL)
+    PrintError("decoder doesn't support this archive");
+  else if (res == (SZ_RESULT)SZE_OUTOFMEMORY)
+    PrintError("can not allocate memory");
+  else if (res == (SZ_RESULT)SZE_CRC_ERROR)
+    PrintError("CRC error");
+  else     
+    printf("\nERROR #%d\n", res);
+  return 1;
+}

Added: trunk/lzma/C/Archive/7z/7zMethodID.c
===================================================================
--- trunk/lzma/C/Archive/7z/7zMethodID.c	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zMethodID.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+/* 7zMethodID.c */
+
+#include "7zMethodID.h"
+
+/*
+int AreMethodsEqual(CMethodID *a1, CMethodID *a2)
+{
+  return (*a1 == *a2) ? 1 : 0;
+}
+*/

Added: trunk/lzma/C/Archive/7z/7zMethodID.h
===================================================================
--- trunk/lzma/C/Archive/7z/7zMethodID.h	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7zMethodID.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+/* 7zMethodID.h */
+
+#ifndef __7Z_METHOD_ID_H
+#define __7Z_METHOD_ID_H
+
+#include "../../Types.h"
+
+typedef UInt64 CMethodID;
+
+#endif

Added: trunk/lzma/C/Archive/7z/7z_C.dsp
===================================================================
--- trunk/lzma/C/Archive/7z/7z_C.dsp	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7z_C.dsp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,211 @@
+# Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=7z_C - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "7z_C.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "7z_C - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "7z_C - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "7z_C - Win32 Release"
+# Name "7z_C - Win32 Debug"
+# Begin Group "LZMA"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma\LzmaDecode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma\LzmaDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzma\LzmaTypes.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\7zCrc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Types.h
+# End Source File
+# End Group
+# Begin Group "Branch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchX86.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchX86.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchX86_2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchX86_2.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\7zAlloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zAlloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zBuffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zExtract.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zExtract.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zItem.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.h
+# End Source File
+# End Target
+# End Project

Added: trunk/lzma/C/Archive/7z/7z_C.dsw
===================================================================
--- trunk/lzma/C/Archive/7z/7z_C.dsw	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/7z_C.dsw	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "7z_C"=.\7z_C.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

Added: trunk/lzma/C/Archive/7z/makefile
===================================================================
--- trunk/lzma/C/Archive/7z/makefile	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/makefile	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,74 @@
+PROG = 7zDec.exe
+
+!IFDEF CPU
+LIBS = $(LIBS) bufferoverflowU.lib 
+CFLAGS = $(CFLAGS) -GS- -Zc:forScope -WX -GS- -Gy -W4 
+!ENDIF
+
+!IFNDEF O
+!IFDEF CPU
+O=$(CPU)
+!ELSE
+O=O
+!ENDIF
+!ENDIF
+
+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -D_LZMA_IN_CB
+CFLAGS_O1 = $(CFLAGS) -O1
+CFLAGS_O2 = $(CFLAGS) -O2
+
+LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF
+
+PROGPATH = $O\$(PROG)
+
+COMPL_O1   = $(CPP) $(CFLAGS_O1) $**
+COMPL_O2   = $(CPP) $(CFLAGS_O2) $**
+COMPL      = $(CPP) $(CFLAGS_O1) $**
+
+C_OBJS = \
+  $O\7zCrc.obj \
+
+
+7Z_OBJS = \
+  $O\7zAlloc.obj \
+  $O\7zBuffer.obj \
+  $O\7zDecode.obj \
+  $O\7zExtract.obj \
+  $O\7zHeader.obj \
+  $O\7zIn.obj \
+  $O\7zItem.obj \
+  $O\7zMain.obj \
+  $O\7zMethodID.obj \
+
+OBJS = \
+  $(7Z_OBJS) \
+  $O\LzmaDecode.obj \
+  $O\BranchX86.obj \
+  $O\BranchX86_2.obj \
+  $(C_OBJS) \
+
+all: $(PROGPATH) 
+
+clean:
+	-del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch 
+
+$O:
+	if not exist "$O" mkdir "$O"
+
+$(PROGPATH): $O $(OBJS)
+	link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
+
+
+$(7Z_OBJS): $(*B).c
+	$(COMPL)
+$O\LzmaDecode.obj: ../../Compress/Lzma/$(*B).c
+	$(COMPL_O2)
+
+$O\BranchX86.obj: ../../Compress/Branch/$(*B).c
+	$(COMPL_O2)
+
+$O\BranchX86_2.obj: ../../Compress/Branch/$(*B).c
+	$(COMPL_O2)
+
+$(C_OBJS): ../../$(*B).c
+	$(COMPL_O2)

Added: trunk/lzma/C/Archive/7z/makefile.gcc
===================================================================
--- trunk/lzma/C/Archive/7z/makefile.gcc	                        (rev 0)
+++ trunk/lzma/C/Archive/7z/makefile.gcc	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,55 @@
+PROG = 7zDec
+CXX = g++
+LIB = 
+RM = rm -f
+CFLAGS = -c -O2 -Wall -D_LZMA_IN_CB
+
+OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o BranchX86.o BranchX86_2.o
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+	$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
+
+7zAlloc.o: 7zAlloc.c
+	$(CXX) $(CFLAGS) 7zAlloc.c
+
+7zBuffer.o: 7zBuffer.c
+	$(CXX) $(CFLAGS) 7zBuffer.c
+
+7zCrc.o: ../../7zCrc.c
+	$(CXX) $(CFLAGS) ../../7zCrc.c
+
+7zDecode.o: 7zDecode.c
+	$(CXX) $(CFLAGS) 7zDecode.c
+
+7zExtract.o: 7zExtract.c
+	$(CXX) $(CFLAGS) 7zExtract.c
+
+7zHeader.o: 7zHeader.c
+	$(CXX) $(CFLAGS) 7zHeader.c
+
+7zIn.o: 7zIn.c
+	$(CXX) $(CFLAGS) 7zIn.c
+
+7zItem.o: 7zItem.c
+	$(CXX) $(CFLAGS) 7zItem.c
+
+7zMain.o: 7zMain.c
+	$(CXX) $(CFLAGS) 7zMain.c
+
+7zMethodID.o: 7zMethodID.c
+	$(CXX) $(CFLAGS) 7zMethodID.c
+
+LzmaDecode.o: ../../Compress/Lzma/LzmaDecode.c
+	$(CXX) $(CFLAGS) ../../Compress/Lzma/LzmaDecode.c
+
+BranchX86.o: ../../Compress/Branch/BranchX86.c
+	$(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86.c
+
+BranchX86_2.o: ../../Compress/Branch/BranchX86_2.c
+	$(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86_2.c
+
+clean:
+	-$(RM) $(PROG) $(OBJS)
+

Added: trunk/lzma/C/Compress/Branch/BranchARM.c
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchARM.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchARM.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,26 @@
+/* BranchARM.c */
+
+#include "BranchARM.h"
+
+UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+  UInt32 i;
+  for (i = 0; i + 4 <= size; i += 4)
+  {
+    if (data[i + 3] == 0xEB)
+    {
+      UInt32 dest;
+      UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]);
+      src <<= 2;
+      if (encoding)
+        dest = nowPos + i + 8 + src;
+      else
+        dest = src - (nowPos + i + 8);
+      dest >>= 2;
+      data[i + 2] = (Byte)(dest >> 16);
+      data[i + 1] = (Byte)(dest >> 8);
+      data[i + 0] = (Byte)dest;
+    }
+  }
+  return i;
+}

Added: trunk/lzma/C/Compress/Branch/BranchARM.h
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchARM.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchARM.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+/* BranchARM.h */
+
+#ifndef __BRANCH_ARM_H
+#define __BRANCH_ARM_H
+
+#include "BranchTypes.h"
+
+UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif

Added: trunk/lzma/C/Compress/Branch/BranchARMThumb.c
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchARMThumb.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchARMThumb.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,35 @@
+/* BranchARMThumb.c */
+
+#include "BranchARMThumb.h"
+
+UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+  UInt32 i;
+  for (i = 0; i + 4 <= size; i += 2)
+  {
+    if ((data[i + 1] & 0xF8) == 0xF0 && 
+        (data[i + 3] & 0xF8) == 0xF8)
+    {
+      UInt32 dest;
+      UInt32 src = 
+        ((data[i + 1] & 0x7) << 19) |
+        (data[i + 0] << 11) |
+        ((data[i + 3] & 0x7) << 8) |
+        (data[i + 2]);
+      
+      src <<= 1;
+      if (encoding)
+        dest = nowPos + i + 4 + src;
+      else
+        dest = src - (nowPos + i + 4);
+      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;
+}

Added: trunk/lzma/C/Compress/Branch/BranchARMThumb.h
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchARMThumb.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchARMThumb.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+/* BranchARMThumb.h */
+
+#ifndef __BRANCH_ARM_THUMB_H
+#define __BRANCH_ARM_THUMB_H
+
+#include "BranchTypes.h"
+
+UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif

Added: trunk/lzma/C/Compress/Branch/BranchIA64.c
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchIA64.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchIA64.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,66 @@
+/* BranchIA64.c */
+
+#include "BranchIA64.h"
+
+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 
+};
+
+UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+  UInt32 i;
+  for (i = 0; i + 16 <= 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 
+        /* &&  (instNorm & 0x3F)== 0 */
+        )
+      {
+        UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
+        UInt32 dest;
+        src |= ((UInt32)(instNorm >> 36) & 1) << 20;
+        
+        src <<= 4;
+        
+        if (encoding)
+          dest = nowPos + i + src;
+        else
+          dest = src - (nowPos + 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;
+}

Added: trunk/lzma/C/Compress/Branch/BranchIA64.h
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchIA64.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchIA64.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+/* BranchIA64.h */
+
+#ifndef __BRANCH_IA64_H
+#define __BRANCH_IA64_H
+
+#include "BranchTypes.h"
+
+UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif

Added: trunk/lzma/C/Compress/Branch/BranchPPC.c
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchPPC.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchPPC.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,36 @@
+/* BranchPPC.c */
+
+#include "BranchPPC.h"
+
+UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+  UInt32 i;
+  for (i = 0; i + 4 <= size; i += 4)
+  {
+    /* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */
+    if ((data[i] >> 2) == 0x12 && 
+    (
+      (data[i + 3] & 3) == 1 
+      /* || (data[i+3] & 3) == 3 */
+      )
+    )
+    {
+      UInt32 src = ((data[i + 0] & 3) << 24) |
+        (data[i + 1] << 16) |
+        (data[i + 2] << 8) |
+        (data[i + 3] & (~3));
+      
+      UInt32 dest;
+      if (encoding)
+        dest = nowPos + i + src;
+      else
+        dest = src - (nowPos + 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;
+}

Added: trunk/lzma/C/Compress/Branch/BranchPPC.h
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchPPC.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchPPC.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+/* BranchPPC.h */
+
+#ifndef __BRANCH_PPC_H
+#define __BRANCH_PPC_H
+
+#include "BranchTypes.h"
+
+UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif

Added: trunk/lzma/C/Compress/Branch/BranchSPARC.c
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchSPARC.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchSPARC.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,36 @@
+/* BranchSPARC.c */
+
+#include "BranchSPARC.h"
+
+UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
+{
+  UInt32 i;
+  for (i = 0; i + 4 <= 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 = nowPos + i + src;
+      else
+        dest = src - (nowPos + 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;
+}

Added: trunk/lzma/C/Compress/Branch/BranchSPARC.h
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchSPARC.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchSPARC.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+/* BranchSPARC.h */
+
+#ifndef __BRANCH_SPARC_H
+#define __BRANCH_SPARC_H
+
+#include "BranchTypes.h"
+
+UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
+
+#endif

Added: trunk/lzma/C/Compress/Branch/BranchTypes.h
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchTypes.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchTypes.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,51 @@
+/* BranchTypes.h */
+
+#ifndef __BRANCHTYPES_H
+#define __BRANCHTYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif 
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif 
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif
+
+#ifndef _7ZIP_UINT64_DEFINED
+#define _7ZIP_UINT64_DEFINED
+#ifdef _SZ_NO_INT_64
+typedef unsigned long UInt64;
+#else
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 UInt64;
+#else
+typedef unsigned long long int UInt64;
+#endif
+#endif
+#endif
+
+/* #define _LZMA_NO_SYSTEM_SIZE_T */
+/* You can use it, if you don't want <stddef.h> */
+
+#ifndef _7ZIP_SIZET_DEFINED
+#define _7ZIP_SIZET_DEFINED
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+#include <stddef.h>
+typedef size_t SizeT;
+#endif
+#endif
+
+#endif

Added: trunk/lzma/C/Compress/Branch/BranchX86.c
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchX86.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchX86.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,84 @@
+/* BranchX86.c */
+
+#include "BranchX86.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 *buffer, SizeT endPos, UInt32 nowPos, UInt32 *prevMaskMix, int encoding)
+{
+  SizeT bufferPos = 0, prevPosT;
+  UInt32 prevMask = *prevMaskMix & 0x7;
+  if (endPos < 5)
+    return 0;
+  nowPos += 5;
+  prevPosT = (SizeT)0 - 1;
+
+  for(;;)
+  {
+    Byte *p = buffer + bufferPos;
+    Byte *limit = buffer + endPos - 4;
+    for (; p < limit; p++)
+      if ((*p & 0xFE) == 0xE8)
+        break;
+    bufferPos = (SizeT)(p - buffer);
+    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 = (nowPos + (UInt32)bufferPos) + src;
+        else
+          dest = src - (nowPos + (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;
+  *prevMaskMix = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
+  return bufferPos;
+}

Added: trunk/lzma/C/Compress/Branch/BranchX86.h
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchX86.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchX86.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,12 @@
+/* BranchX86.h */
+
+#ifndef __BRANCHX86_H
+#define __BRANCHX86_H
+
+#include "BranchTypes.h"
+
+#define x86_Convert_Init(state) { state = 0; }
+
+SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *state, int encoding);
+
+#endif

Added: trunk/lzma/C/Compress/Branch/BranchX86_2.c
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchX86_2.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchX86_2.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,135 @@
+// BranchX86_2.c
+
+#include "BranchX86_2.h"
+
+#include "../../Alloc.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_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+  { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#define RC_TEST { if (Buffer == BufferLim) return BCJ2_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+ 
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+// #define UpdateBit0(p) Range = bound; *(p) = (CProb)(*(p) + ((kBitModelTotal - *(p)) >> kNumMoveBits));
+// #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) = (CProb)(*(p) - (*(p) >> kNumMoveBits));
+
+int x86_2_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; 
+  RC_INIT(buf3, size3);
+
+  if (outSize == 0)
+    return BCJ2_RESULT_OK;
+
+  for (;;)
+  {
+    Byte b;
+    CProb *prob;
+    UInt32 bound;
+
+    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;
+
+    IfBit0(prob)
+    {
+      UpdateBit0(prob)
+      prevByte = b;
+    }
+    else
+    {
+      UInt32 dest;
+      const Byte *v;
+      UpdateBit1(prob)
+      if (b == 0xE8)
+      {
+        v = buf1;
+        if (size1 < 4)
+          return BCJ2_RESULT_DATA_ERROR;
+        buf1 += 4;
+        size1 -= 4;
+      }
+      else
+      {
+        v = buf2;
+        if (size2 < 4)
+          return BCJ2_RESULT_DATA_ERROR;
+        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) ? BCJ2_RESULT_OK : BCJ2_RESULT_DATA_ERROR;
+}

Added: trunk/lzma/C/Compress/Branch/BranchX86_2.h
===================================================================
--- trunk/lzma/C/Compress/Branch/BranchX86_2.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Branch/BranchX86_2.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,28 @@
+// BranchX86_2.h
+
+#ifndef __BRANCHX86_2_H
+#define __BRANCHX86_2_H
+
+#include "BranchTypes.h"
+
+#define BCJ2_RESULT_OK 0
+#define BCJ2_RESULT_DATA_ERROR 1
+
+/*
+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).
+*/
+
+int x86_2_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);
+
+#endif

Added: trunk/lzma/C/Compress/Huffman/HuffmanEncode.c
===================================================================
--- trunk/lzma/C/Compress/Huffman/HuffmanEncode.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Huffman/HuffmanEncode.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,146 @@
+/* Compress/HuffmanEncode.c */
+
+#include "HuffmanEncode.h"
+#include "../../Sort.h"
+
+#define kMaxLen 16
+#define NUM_BITS 10
+#define MASK ((1 << NUM_BITS) - 1)
+
+#define NUM_COUNTERS 64
+
+/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */
+#define HUFFMAN_SPEED_OPT
+
+void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen)
+{
+  UInt32 num = 0;
+  /* if (maxLen > 10) maxLen = 10; */
+  {
+    UInt32 i;
+    
+    #ifdef HUFFMAN_SPEED_OPT
+    
+    UInt32 counters[NUM_COUNTERS];
+    for (i = 0; i < NUM_COUNTERS; i++) 
+      counters[i] = 0;
+    for (i = 0; i < numSymbols; i++) 
+    {
+      UInt32 freq = freqs[i];
+      counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++;
+    }
+ 
+    for (i = 1; i < NUM_COUNTERS; i++) 
+    {
+      UInt32 temp = counters[i];
+      counters[i] = num;
+      num += temp;
+    }
+
+    for (i = 0; i < numSymbols; i++) 
+    {
+      UInt32 freq = freqs[i];
+      if (freq == 0)
+        lens[i] = 0;
+      else
+        p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS);
+    }
+    counters[0] = 0;
+    HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]);
+    
+    #else
+
+    for (i = 0; i < numSymbols; i++) 
+    {
+      UInt32 freq = freqs[i];
+      if (freq == 0)
+        lens[i] = 0;
+      else
+        p[num++] = i | (freq << NUM_BITS);
+    }
+    HeapSort(p, num);
+
+    #endif
+  }
+
+  if (num < 2) 
+  {
+    int minCode = 0;
+    int maxCode = 1;
+    if (num == 1)
+    {
+      maxCode = p[0] & MASK;
+      if (maxCode == 0)
+        maxCode++;
+    }
+    p[minCode] = 0;
+    p[maxCode] = 1;
+    lens[minCode] = lens[maxCode] = 1;
+    return;
+  }
+  
+  {
+    UInt32 b, e, i;
+  
+    i = b = e = 0;
+    do 
+    {
+      UInt32 n, m, freq;
+      n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
+      freq = (p[n] & ~MASK);
+      p[n] = (p[n] & MASK) | (e << NUM_BITS);
+      m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
+      freq += (p[m] & ~MASK);
+      p[m] = (p[m] & MASK) | (e << NUM_BITS);
+      p[e] = (p[e] & MASK) | freq;
+      e++;
+    } 
+    while (num - e > 1);
+    
+    {
+      UInt32 lenCounters[kMaxLen + 1];
+      for (i = 0; i <= kMaxLen; i++) 
+        lenCounters[i] = 0;
+      
+      p[--e] &= MASK;
+      lenCounters[1] = 2;
+      while (e > 0) 
+      {
+        UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;
+        p[e] = (p[e] & MASK) | (len << NUM_BITS);
+        if (len >= maxLen) 
+          for (len = maxLen - 1; lenCounters[len] == 0; len--);
+        lenCounters[len]--;
+        lenCounters[len + 1] += 2;
+      }
+      
+      {
+        UInt32 len;
+        i = 0;
+        for (len = maxLen; len != 0; len--) 
+        {
+          UInt32 num;
+          for (num = lenCounters[len]; num != 0; num--) 
+            lens[p[i++] & MASK] = (Byte)len;
+        }
+      }
+      
+      {
+        UInt32 nextCodes[kMaxLen + 1];
+        {
+          UInt32 code = 0;
+          UInt32 len;
+          for (len = 1; len <= kMaxLen; len++) 
+            nextCodes[len] = code = (code + lenCounters[len - 1]) << 1;
+        }
+        /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */
+
+        {
+          UInt32 i;
+          for (i = 0; i < numSymbols; i++) 
+            p[i] = nextCodes[lens[i]]++;
+        }
+      }
+    }
+  }
+}

Added: trunk/lzma/C/Compress/Huffman/HuffmanEncode.h
===================================================================
--- trunk/lzma/C/Compress/Huffman/HuffmanEncode.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Huffman/HuffmanEncode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,18 @@
+/* Compress/HuffmanEncode.h */
+
+#ifndef __COMPRESS_HUFFMANENCODE_H
+#define __COMPRESS_HUFFMANENCODE_H
+
+#include "../../Types.h"
+
+/*
+Conditions:
+  num <= 1024 = 2 ^ NUM_BITS
+  Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS)
+  maxLen <= 16 = kMaxLen
+  Num_Items(p) >= HUFFMAN_TEMP_SIZE(num)
+*/
+ 
+void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
+
+#endif

Added: trunk/lzma/C/Compress/Lz/LzHash.h
===================================================================
--- trunk/lzma/C/Compress/Lz/LzHash.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Lz/LzHash.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,53 @@
+/* LzHash.h */
+
+#ifndef __C_LZHASH_H
+#define __C_LZHASH_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 = g_CrcTable[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
+
+#define HASH4_CALC { \
+  UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+  hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & p->hashMask; }
+
+#define HASH5_CALC { \
+  UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)); \
+  hashValue = (hash4Value ^ (g_CrcTable[cur[4]] << 3)) & p->hashMask; \
+  hash4Value &= (kHash4Size - 1); }
+
+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ g_CrcTable[cur[2]]) & 0xFFFF; */
+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ g_CrcTable[cur[1]]) & 0xFFFF;
+
+
+#define MT_HASH2_CALC \
+  hash2Value = (g_CrcTable[cur[0]] ^ cur[1]) & (kHash2Size - 1);
+
+#define MT_HASH3_CALC { \
+  UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
+
+#define MT_HASH4_CALC { \
+  UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & (kHash4Size - 1); }
+
+#endif

Added: trunk/lzma/C/Compress/Lz/MatchFinder.c
===================================================================
--- trunk/lzma/C/Compress/Lz/MatchFinder.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Lz/MatchFinder.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,742 @@
+/* MatchFinder.c */
+/* Please call InitCrcTable before */
+
+#include <string.h>
+
+#include "MatchFinder.h"
+#include "LzHash.h"
+
+#include "../../7zCrc.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
+
+void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+  if (!p->directInput)
+  {
+    alloc->Free(p->bufferBase);
+    p->bufferBase = 0;
+  }
+}
+
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
+
+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(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;
+}
+
+void MatchFinder_ReadBlock(CMatchFinder *p)
+{
+  if (p->streamEndWasReached || p->result != SZ_OK)
+    return;
+  for (;;)
+  {
+    Byte *dest = p->buffer + (p->streamPos - p->pos);
+    UInt32 numReadBytes;
+    UInt32 size = (UInt32)(p->bufferBase + p->blockSize - dest);
+    if (size == 0)
+      return;
+    p->result = p->stream->Read(p->stream, dest, size, &numReadBytes);
+    if (p->result != SZ_OK)
+      return;
+    if (numReadBytes == 0)
+    {
+      p->streamEndWasReached = 1;
+      return;
+    }
+    p->streamPos += numReadBytes;
+    if (p->streamPos - p->pos > p->keepSizeAfter)
+      return;
+  }
+}
+
+void MatchFinder_MoveBlock(CMatchFinder *p)
+{
+  memmove(p->bufferBase, 
+    p->buffer - p->keepSizeBefore, 
+    p->streamPos - p->pos + p->keepSizeBefore);
+  p->buffer = p->bufferBase + p->keepSizeBefore;
+}
+
+int MatchFinder_NeedMove(CMatchFinder *p)
+{
+  /* 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);
+}
+
+void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
+{
+  if (MatchFinder_NeedMove(p))
+    MatchFinder_MoveBlock(p);
+  MatchFinder_ReadBlock(p);
+}
+
+void MatchFinder_SetDefaultSettings(CMatchFinder *p)
+{
+  p->cutValue = 32;
+  p->btMode = 1;
+  p->numHashBytes = 4;
+  /* p->skipModeBits = 0; */
+  p->directInput = 0;
+  p->bigHash = 0;
+}
+
+void MatchFinder_Construct(CMatchFinder *p)
+{
+  p->bufferBase = 0;
+  p->directInput = 0;
+  p->hash = 0;
+  MatchFinder_SetDefaultSettings(p);
+}
+
+void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
+{
+  alloc->Free(p->hash);
+  p->hash = 0;
+}
+
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+  MatchFinder_FreeThisClassMemory(p, alloc);
+  LzInWindow_Free(p, alloc);
+}
+
+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(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 /* >> p->skipModeBits */) + 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 >>= p->skipModeBits; */
+        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;
+}
+
+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);
+}
+
+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;
+  }
+}
+
+void MatchFinder_Normalize(CMatchFinder *p)
+{
+  UInt32 subValue = MatchFinder_GetSubValue(p);
+  MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
+  MatchFinder_ReduceOffsets(p, subValue);
+}
+
+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);
+}
+
+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;
+      }
+    }
+  }
+}
+
+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;
+
+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;
+
+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)
+}
+
+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)
+}
+
+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)
+}
+
+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
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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;
+  }
+}

Added: trunk/lzma/C/Compress/Lz/MatchFinder.h
===================================================================
--- trunk/lzma/C/Compress/Lz/MatchFinder.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Lz/MatchFinder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,106 @@
+/* MatchFinder.h */
+
+#ifndef __MATCHFINDER_H
+#define __MATCHFINDER_H
+
+#include "../../IStream.h"
+
+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;
+  int btMode;
+  /* int skipModeBits; */
+  int bigHash;
+  UInt32 historySize;
+  UInt32 fixedHashSize;
+  UInt32 hashSizeSum;
+  UInt32 numSons;
+
+  HRes result;
+} 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);
+
+#endif

Added: trunk/lzma/C/Compress/Lz/MatchFinderMt.c
===================================================================
--- trunk/lzma/C/Compress/Lz/MatchFinderMt.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Lz/MatchFinderMt.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,806 @@
+/* MatchFinderMt.c */
+
+#ifdef _WIN32
+#define USE_ALLOCA
+#endif
+
+#ifdef USE_ALLOCA
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+
+#include "../../7zCrc.h"
+#include "LzHash.h"
+
+#include "MatchFinderMt.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;
+}
+
+HRes MtSync_Create2(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
+{
+  if (p->wasCreated)
+    return SZ_OK;
+
+  RINOK(CriticalSection_Init(&p->cs));
+  p->csWasInitialized = True;
+
+  RINOK(AutoResetEvent_CreateNotSignaled(&p->canStart));
+  RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
+  RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
+  
+  RINOK(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
+  RINOK(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
+
+  p->needStart = True;
+  
+  RINOK(Thread_Create(&p->thread, startAddress, obj));
+  p->wasCreated = True;
+  return SZ_OK;
+}
+
+HRes MtSync_Create(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
+{
+  HRes 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_GetHeads(name, v) \
+static void GetHeads ## name(const Byte *p, UInt32 pos, \
+UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \
+for (; numHeads != 0; numHeads--) { \
+const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++;  } }
+
+DEF_GetHeads(2,  (p[0] | ((UInt32)p[1] << 8)) & hashMask)
+DEF_GetHeads(3,  (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
+DEF_GetHeads(4,  (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5)) & hashMask)
+DEF_GetHeads(4b, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
+DEF_GetHeads(5,  (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5) ^ (g_CrcTable[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);
+            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
+
+#if _MSC_VER >= 1300
+#define NO_INLINE __declspec(noinline) __fastcall 
+#else
+#ifdef _MSC_VER
+#define NO_INLINE __fastcall 
+#endif
+#endif
+
+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(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 StdCall HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p);  return 0; }
+static unsigned StdCall BtThreadFunc2(void *p) 
+{ 
+  #ifdef USE_ALLOCA
+  alloca(0x180);
+  #endif
+  BtThreadFunc((CMatchFinderMt *)p); 
+  return 0; 
+}
+
+HRes 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 E_INVALIDARG;
+  if (p->hashBuf == 0)
+  {
+    p->hashBuf = (UInt32 *)alloc->Alloc((kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
+    if (p->hashBuf == 0)
+      return SZE_OUTOFMEMORY;
+    p->btBuf = p->hashBuf + kHashBufferSize;
+  }
+  keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
+  keepAddBufferAfter += kMtHashBlockSize;
+  if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
+    return SZE_OUTOFMEMORY;
+
+  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->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  do { GET_NEXT_BLOCK_IF_REQUIRED
+#define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
+#define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while(--num != 0);
+
+void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
+{ 
+  SKIP_HEADER2 { p->btNumAvailBytes--;
+  SKIP_FOOTER
+}
+
+void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
+{ 
+  SKIP_HEADER(2)
+      UInt32 hash2Value;
+      MT_HASH2_CALC
+      hash[hash2Value] = p->lzPos;
+  SKIP_FOOTER
+}
+
+void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
+{ 
+  SKIP_HEADER(3)
+      UInt32 hash2Value, hash3Value;
+      MT_HASH3_CALC
+      hash[kFix3HashSize + hash3Value] = 
+      hash[                hash2Value] = 
+        p->lzPos;
+  SKIP_FOOTER
+}
+
+/*
+void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
+{ 
+  SKIP_HEADER(4)
+      UInt32 hash2Value, hash3Value, hash4Value;
+      MT_HASH4_CALC
+      hash[kFix4HashSize + hash4Value] = 
+      hash[kFix3HashSize + hash3Value] = 
+      hash[                hash2Value] = 
+        p->lzPos;
+  SKIP_FOOTER
+}
+*/
+
+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;
+    */
+  }
+}

Added: trunk/lzma/C/Compress/Lz/MatchFinderMt.h
===================================================================
--- trunk/lzma/C/Compress/Lz/MatchFinderMt.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Lz/MatchFinderMt.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,95 @@
+/* MatchFinderMt.h */
+
+#ifndef __MATCHFINDERMT_H
+#define __MATCHFINDERMT_H
+
+#include "../../Threads.h"
+#include "MatchFinder.h"
+
+#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);
+
+typedef struct _CMatchFinderMt
+{
+  /* LZ */
+  const Byte *pointerToCurPos;
+  UInt32 *btBuf;
+  UInt32 btBufPos;
+  UInt32 btBufPosLimit;
+  UInt32 lzPos;
+  UInt32 btNumAvailBytes;
+
+  UInt32 *hash;
+  UInt32 fixedHashSize;
+  UInt32 historySize;
+
+  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);
+HRes 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);
+
+#endif

Added: trunk/lzma/C/Compress/Lzma/LzmaDecode.c
===================================================================
--- trunk/lzma/C/Compress/Lzma/LzmaDecode.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Lzma/LzmaDecode.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,584 @@
+/*
+  LzmaDecode.c
+  LZMA Decoder (optimized for Speed version)
+  
+  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+  http://www.7-zip.org/
+
+  LZMA SDK is licensed under two licenses:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  It means that you can select one of these two licenses and 
+  follow rules of that license.
+
+  SPECIAL EXCEPTION:
+  Igor Pavlov, as the author of this Code, expressly permits you to 
+  statically or dynamically link your Code (or bind by name) to the 
+  interfaces of this file without subjecting your linked Code to the 
+  terms of the CPL or GNU LGPL. Any modifications or additions 
+  to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#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_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+  { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+  { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+  BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+ 
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+  { UpdateBit0(p); mi <<= 1; A0; } else \
+  { UpdateBit1(p); mi = (mi + mi) + 1; A1; } 
+  
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)               
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+  { int i = numLevels; res = 1; \
+  do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+  res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols) 
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+  unsigned char prop0;
+  if (size < LZMA_PROPERTIES_SIZE)
+    return LZMA_RESULT_DATA_ERROR;
+  prop0 = propsData[0];
+  if (prop0 >= (9 * 5 * 5))
+    return LZMA_RESULT_DATA_ERROR;
+  {
+    for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+    for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+    propsRes->lc = prop0;
+    /*
+    unsigned char remainder = (unsigned char)(prop0 / 9);
+    propsRes->lc = prop0 % 9;
+    propsRes->pb = remainder / 5;
+    propsRes->lp = remainder % 5;
+    */
+  }
+
+  #ifdef _LZMA_OUT_READ
+  {
+    int i;
+    propsRes->DictionarySize = 0;
+    for (i = 0; i < 4; i++)
+      propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+    if (propsRes->DictionarySize == 0)
+      propsRes->DictionarySize = 1;
+  }
+  #endif
+  return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+    #ifdef _LZMA_IN_CB
+    ILzmaInCallback *InCallback,
+    #else
+    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+    #endif
+    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+  CProb *p = vs->Probs;
+  SizeT nowPos = 0;
+  Byte previousByte = 0;
+  UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+  UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+  int lc = vs->Properties.lc;
+
+  #ifdef _LZMA_OUT_READ
+  
+  UInt32 Range = vs->Range;
+  UInt32 Code = vs->Code;
+  #ifdef _LZMA_IN_CB
+  const Byte *Buffer = vs->Buffer;
+  const Byte *BufferLim = vs->BufferLim;
+  #else
+  const Byte *Buffer = inStream;
+  const Byte *BufferLim = inStream + inSize;
+  #endif
+  int state = vs->State;
+  UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+  int len = vs->RemainLen;
+  UInt32 globalPos = vs->GlobalPos;
+  UInt32 distanceLimit = vs->DistanceLimit;
+
+  Byte *dictionary = vs->Dictionary;
+  UInt32 dictionarySize = vs->Properties.DictionarySize;
+  UInt32 dictionaryPos = vs->DictionaryPos;
+
+  Byte tempDictionary[4];
+
+  #ifndef _LZMA_IN_CB
+  *inSizeProcessed = 0;
+  #endif
+  *outSizeProcessed = 0;
+  if (len == kLzmaStreamWasFinishedId)
+    return LZMA_RESULT_OK;
+
+  if (dictionarySize == 0)
+  {
+    dictionary = tempDictionary;
+    dictionarySize = 1;
+    tempDictionary[0] = vs->TempDictionary[0];
+  }
+
+  if (len == kLzmaNeedInitId)
+  {
+    {
+      UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+      UInt32 i;
+      for (i = 0; i < numProbs; i++)
+        p[i] = kBitModelTotal >> 1; 
+      rep0 = rep1 = rep2 = rep3 = 1;
+      state = 0;
+      globalPos = 0;
+      distanceLimit = 0;
+      dictionaryPos = 0;
+      dictionary[dictionarySize - 1] = 0;
+      #ifdef _LZMA_IN_CB
+      RC_INIT;
+      #else
+      RC_INIT(inStream, inSize);
+      #endif
+    }
+    len = 0;
+  }
+  while(len != 0 && nowPos < outSize)
+  {
+    UInt32 pos = dictionaryPos - rep0;
+    if (pos >= dictionarySize)
+      pos += dictionarySize;
+    outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+    if (++dictionaryPos == dictionarySize)
+      dictionaryPos = 0;
+    len--;
+  }
+  if (dictionaryPos == 0)
+    previousByte = dictionary[dictionarySize - 1];
+  else
+    previousByte = dictionary[dictionaryPos - 1];
+
+  #else /* if !_LZMA_OUT_READ */
+
+  int state = 0;
+  UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+  int len = 0;
+  const Byte *Buffer;
+  const Byte *BufferLim;
+  UInt32 Range;
+  UInt32 Code;
+
+  #ifndef _LZMA_IN_CB
+  *inSizeProcessed = 0;
+  #endif
+  *outSizeProcessed = 0;
+
+  {
+    UInt32 i;
+    UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+    for (i = 0; i < numProbs; i++)
+      p[i] = kBitModelTotal >> 1;
+  }
+  
+  #ifdef _LZMA_IN_CB
+  RC_INIT;
+  #else
+  RC_INIT(inStream, inSize);
+  #endif
+
+  #endif /* _LZMA_OUT_READ */
+
+  while(nowPos < outSize)
+  {
+    CProb *prob;
+    UInt32 bound;
+    int posState = (int)(
+        (nowPos 
+        #ifdef _LZMA_OUT_READ
+        + globalPos
+        #endif
+        )
+        & posStateMask);
+
+    prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+    IfBit0(prob)
+    {
+      int symbol = 1;
+      UpdateBit0(prob)
+      prob = p + Literal + (LZMA_LIT_SIZE * 
+        (((
+        (nowPos 
+        #ifdef _LZMA_OUT_READ
+        + globalPos
+        #endif
+        )
+        & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+      if (state >= kNumLitStates)
+      {
+        int matchByte;
+        #ifdef _LZMA_OUT_READ
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        matchByte = dictionary[pos];
+        #else
+        matchByte = outStream[nowPos - rep0];
+        #endif
+        do
+        {
+          int bit;
+          CProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & 0x100);
+          probLit = prob + 0x100 + bit + symbol;
+          RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+        }
+        while (symbol < 0x100);
+      }
+      while (symbol < 0x100)
+      {
+        CProb *probLit = prob + symbol;
+        RC_GET_BIT(probLit, symbol)
+      }
+      previousByte = (Byte)symbol;
+
+      outStream[nowPos++] = previousByte;
+      #ifdef _LZMA_OUT_READ
+      if (distanceLimit < dictionarySize)
+        distanceLimit++;
+
+      dictionary[dictionaryPos] = previousByte;
+      if (++dictionaryPos == dictionarySize)
+        dictionaryPos = 0;
+      #endif
+      if (state < 4) state = 0;
+      else if (state < 10) state -= 3;
+      else state -= 6;
+    }
+    else             
+    {
+      UpdateBit1(prob);
+      prob = p + IsRep + state;
+      IfBit0(prob)
+      {
+        UpdateBit0(prob);
+        rep3 = rep2;
+        rep2 = rep1;
+        rep1 = rep0;
+        state = state < kNumLitStates ? 0 : 3;
+        prob = p + LenCoder;
+      }
+      else
+      {
+        UpdateBit1(prob);
+        prob = p + IsRepG0 + state;
+        IfBit0(prob)
+        {
+          UpdateBit0(prob);
+          prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IfBit0(prob)
+          {
+            #ifdef _LZMA_OUT_READ
+            UInt32 pos;
+            #endif
+            UpdateBit0(prob);
+            
+            #ifdef _LZMA_OUT_READ
+            if (distanceLimit == 0)
+            #else
+            if (nowPos == 0)
+            #endif
+              return LZMA_RESULT_DATA_ERROR;
+            
+            state = state < kNumLitStates ? 9 : 11;
+            #ifdef _LZMA_OUT_READ
+            pos = dictionaryPos - rep0;
+            if (pos >= dictionarySize)
+              pos += dictionarySize;
+            previousByte = dictionary[pos];
+            dictionary[dictionaryPos] = previousByte;
+            if (++dictionaryPos == dictionarySize)
+              dictionaryPos = 0;
+            #else
+            previousByte = outStream[nowPos - rep0];
+            #endif
+            outStream[nowPos++] = previousByte;
+            #ifdef _LZMA_OUT_READ
+            if (distanceLimit < dictionarySize)
+              distanceLimit++;
+            #endif
+
+            continue;
+          }
+          else
+          {
+            UpdateBit1(prob);
+          }
+        }
+        else
+        {
+          UInt32 distance;
+          UpdateBit1(prob);
+          prob = p + IsRepG1 + state;
+          IfBit0(prob)
+          {
+            UpdateBit0(prob);
+            distance = rep1;
+          }
+          else 
+          {
+            UpdateBit1(prob);
+            prob = p + IsRepG2 + state;
+            IfBit0(prob)
+            {
+              UpdateBit0(prob);
+              distance = rep2;
+            }
+            else
+            {
+              UpdateBit1(prob);
+              distance = rep3;
+              rep3 = rep2;
+            }
+            rep2 = rep1;
+          }
+          rep1 = rep0;
+          rep0 = distance;
+        }
+        state = state < kNumLitStates ? 8 : 11;
+        prob = p + RepLenCoder;
+      }
+      {
+        int numBits, offset;
+        CProb *probLen = prob + LenChoice;
+        IfBit0(probLen)
+        {
+          UpdateBit0(probLen);
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          numBits = kLenNumLowBits;
+        }
+        else
+        {
+          UpdateBit1(probLen);
+          probLen = prob + LenChoice2;
+          IfBit0(probLen)
+          {
+            UpdateBit0(probLen);
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            numBits = kLenNumMidBits;
+          }
+          else
+          {
+            UpdateBit1(probLen);
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            numBits = kLenNumHighBits;
+          }
+        }
+        RangeDecoderBitTreeDecode(probLen, numBits, len);
+        len += offset;
+      }
+
+      if (state < 4)
+      {
+        int posSlot;
+        state += kNumLitStates;
+        prob = p + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 
+            kNumPosSlotBits);
+        RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+        if (posSlot >= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot >> 1) - 1);
+          rep0 = (2 | ((UInt32)posSlot & 1));
+          if (posSlot < kEndPosModelIndex)
+          {
+            rep0 <<= numDirectBits;
+            prob = p + SpecPos + rep0 - posSlot - 1;
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              RC_NORMALIZE
+              Range >>= 1;
+              rep0 <<= 1;
+              if (Code >= Range)
+              {
+                Code -= Range;
+                rep0 |= 1;
+              }
+            }
+            while (--numDirectBits != 0);
+            prob = p + Align;
+            rep0 <<= kNumAlignBits;
+            numDirectBits = kNumAlignBits;
+          }
+          {
+            int i = 1;
+            int mi = 1;
+            do
+            {
+              CProb *prob3 = prob + mi;
+              RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+              i <<= 1;
+            }
+            while(--numDirectBits != 0);
+          }
+        }
+        else
+          rep0 = posSlot;
+        if (++rep0 == (UInt32)(0))
+        {
+          /* it's for stream version */
+          len = kLzmaStreamWasFinishedId;
+          break;
+        }
+      }
+
+      len += kMatchMinLen;
+      #ifdef _LZMA_OUT_READ
+      if (rep0 > distanceLimit) 
+      #else
+      if (rep0 > nowPos)
+      #endif
+        return LZMA_RESULT_DATA_ERROR;
+
+      #ifdef _LZMA_OUT_READ
+      if (dictionarySize - distanceLimit > (UInt32)len)
+        distanceLimit += len;
+      else
+        distanceLimit = dictionarySize;
+      #endif
+
+      do
+      {
+        #ifdef _LZMA_OUT_READ
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        previousByte = dictionary[pos];
+        dictionary[dictionaryPos] = previousByte;
+        if (++dictionaryPos == dictionarySize)
+          dictionaryPos = 0;
+        #else
+        previousByte = outStream[nowPos - rep0];
+        #endif
+        len--;
+        outStream[nowPos++] = previousByte;
+      }
+      while(len != 0 && nowPos < outSize);
+    }
+  }
+  RC_NORMALIZE;
+
+  #ifdef _LZMA_OUT_READ
+  vs->Range = Range;
+  vs->Code = Code;
+  vs->DictionaryPos = dictionaryPos;
+  vs->GlobalPos = globalPos + (UInt32)nowPos;
+  vs->DistanceLimit = distanceLimit;
+  vs->Reps[0] = rep0;
+  vs->Reps[1] = rep1;
+  vs->Reps[2] = rep2;
+  vs->Reps[3] = rep3;
+  vs->State = state;
+  vs->RemainLen = len;
+  vs->TempDictionary[0] = tempDictionary[0];
+  #endif
+
+  #ifdef _LZMA_IN_CB
+  vs->Buffer = Buffer;
+  vs->BufferLim = BufferLim;
+  #else
+  *inSizeProcessed = (SizeT)(Buffer - inStream);
+  #endif
+  *outSizeProcessed = nowPos;
+  return LZMA_RESULT_OK;
+}

Added: trunk/lzma/C/Compress/Lzma/LzmaDecode.h
===================================================================
--- trunk/lzma/C/Compress/Lzma/LzmaDecode.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Lzma/LzmaDecode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,113 @@
+/* 
+  LzmaDecode.h
+  LZMA Decoder interface
+
+  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+  http://www.7-zip.org/
+
+  LZMA SDK is licensed under two licenses:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  It means that you can select one of these two licenses and 
+  follow rules of that license.
+
+  SPECIAL EXCEPTION:
+  Igor Pavlov, as the author of this code, expressly permits you to 
+  statically or dynamically link your code (or bind by name) to the 
+  interfaces of this file without subjecting your linked code to the 
+  terms of the CPL or GNU LGPL. Any modifications or additions 
+  to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+#include "LzmaTypes.h"
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs, 
+   but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+  int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+  int lc;
+  int lp;
+  int pb;
+  #ifdef _LZMA_OUT_READ
+  UInt32 DictionarySize;
+  #endif
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+  CLzmaProperties Properties;
+  CProb *Probs;
+
+  #ifdef _LZMA_IN_CB
+  const unsigned char *Buffer;
+  const unsigned char *BufferLim;
+  #endif
+
+  #ifdef _LZMA_OUT_READ
+  unsigned char *Dictionary;
+  UInt32 Range;
+  UInt32 Code;
+  UInt32 DictionaryPos;
+  UInt32 GlobalPos;
+  UInt32 DistanceLimit;
+  UInt32 Reps[4];
+  int State;
+  int RemainLen;
+  unsigned char TempDictionary[4];
+  #endif
+} CLzmaDecoderState;
+
+#ifdef _LZMA_OUT_READ
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
+#endif
+
+int LzmaDecode(CLzmaDecoderState *vs,
+    #ifdef _LZMA_IN_CB
+    ILzmaInCallback *inCallback,
+    #else
+    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+    #endif
+    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif

Added: trunk/lzma/C/Compress/Lzma/LzmaDecodeSize.c
===================================================================
--- trunk/lzma/C/Compress/Lzma/LzmaDecodeSize.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Lzma/LzmaDecodeSize.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,712 @@
+/*
+  LzmaDecodeSize.c
+  LZMA Decoder (optimized for Size version)
+  
+  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+  http://www.7-zip.org/
+
+  LZMA SDK is licensed under two licenses:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  It means that you can select one of these two licenses and 
+  follow rules of that license.
+
+  SPECIAL EXCEPTION:
+  Igor Pavlov, as the author of this code, expressly permits you to 
+  statically or dynamically link your code (or bind by name) to the 
+  interfaces of this file without subjecting your linked code to the 
+  terms of the CPL or GNU LGPL. Any modifications or additions 
+  to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+  const Byte *Buffer;
+  const Byte *BufferLim;
+  UInt32 Range;
+  UInt32 Code;
+  #ifdef _LZMA_IN_CB
+  ILzmaInCallback *InCallback;
+  int Result;
+  #endif
+  int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+  if (rd->Buffer == rd->BufferLim)
+  {
+    #ifdef _LZMA_IN_CB
+    SizeT size;
+    rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+    rd->BufferLim = rd->Buffer + size;
+    if (size == 0)
+    #endif
+    {
+      rd->ExtraBytes = 1;
+      return 0xFF;
+    }
+  }
+  return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd
+  #ifndef _LZMA_IN_CB
+    , const Byte *stream, SizeT bufferSize
+  #endif
+    )
+{
+  int i;
+  #ifdef _LZMA_IN_CB
+  rd->Buffer = rd->BufferLim = 0;
+  #else
+  rd->Buffer = stream;
+  rd->BufferLim = stream + bufferSize;
+  #endif
+  rd->ExtraBytes = 0;
+  rd->Code = 0;
+  rd->Range = (0xFFFFFFFF);
+  for(i = 0; i < 5; i++)
+    rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;        
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+  RC_INIT_VAR
+  UInt32 result = 0;
+  int i;
+  for (i = numTotalBits; i != 0; i--)
+  {
+    /* UInt32 t; */
+    range >>= 1;
+
+    result <<= 1;
+    if (code >= range)
+    {
+      code -= range;
+      result |= 1;
+    }
+    /*
+    t = (code - range) >> 31;
+    t &= 1;
+    code -= range & (t - 1);
+    result = (result + result) | (1 - t);
+    */
+    RC_NORMALIZE
+  }
+  RC_FLUSH_VAR
+  return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+  UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+  if (rd->Code < bound)
+  {
+    rd->Range = bound;
+    *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+    if (rd->Range < kTopValue)
+    {
+      rd->Code = (rd->Code << 8) | ReadByte;
+      rd->Range <<= 8;
+    }
+    return 0;
+  }
+  else
+  {
+    rd->Range -= bound;
+    rd->Code -= bound;
+    *prob -= (*prob) >> kNumMoveBits;
+    if (rd->Range < kTopValue)
+    {
+      rd->Code = (rd->Code << 8) | ReadByte;
+      rd->Range <<= 8;
+    }
+    return 1;
+  }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+  UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+  if (code < bound) \
+    { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+  else \
+    { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+  RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)               
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+  int mi = 1;
+  int i;
+  #ifdef _LZMA_LOC_OPT
+  RC_INIT_VAR
+  #endif
+  for(i = numLevels; i != 0; i--)
+  {
+    #ifdef _LZMA_LOC_OPT
+    CProb *prob = probs + mi;
+    RC_GET_BIT(prob, mi)
+    #else
+    mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+    #endif
+  }
+  #ifdef _LZMA_LOC_OPT
+  RC_FLUSH_VAR
+  #endif
+  return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+  int mi = 1;
+  int i;
+  int symbol = 0;
+  #ifdef _LZMA_LOC_OPT
+  RC_INIT_VAR
+  #endif
+  for(i = 0; i < numLevels; i++)
+  {
+    #ifdef _LZMA_LOC_OPT
+    CProb *prob = probs + mi;
+    RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+    #else
+    int bit = RangeDecoderBitDecode(probs + mi, rd);
+    mi = mi + mi + bit;
+    symbol |= (bit << i);
+    #endif
+  }
+  #ifdef _LZMA_LOC_OPT
+  RC_FLUSH_VAR
+  #endif
+  return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{ 
+  int symbol = 1;
+  #ifdef _LZMA_LOC_OPT
+  RC_INIT_VAR
+  #endif
+  do
+  {
+    #ifdef _LZMA_LOC_OPT
+    CProb *prob = probs + symbol;
+    RC_GET_BIT(prob, symbol)
+    #else
+    symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+    #endif
+  }
+  while (symbol < 0x100);
+  #ifdef _LZMA_LOC_OPT
+  RC_FLUSH_VAR
+  #endif
+  return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{ 
+  int symbol = 1;
+  #ifdef _LZMA_LOC_OPT
+  RC_INIT_VAR
+  #endif
+  do
+  {
+    int bit;
+    int matchBit = (matchByte >> 7) & 1;
+    matchByte <<= 1;
+    #ifdef _LZMA_LOC_OPT
+    {
+      CProb *prob = probs + 0x100 + (matchBit << 8) + symbol;
+      RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+    }
+    #else
+    bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd);
+    symbol = (symbol << 1) | bit;
+    #endif
+    if (matchBit != bit)
+    {
+      while (symbol < 0x100)
+      {
+        #ifdef _LZMA_LOC_OPT
+        CProb *prob = probs + symbol;
+        RC_GET_BIT(prob, symbol)
+        #else
+        symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+        #endif
+      }
+      break;
+    }
+  }
+  while (symbol < 0x100);
+  #ifdef _LZMA_LOC_OPT
+  RC_FLUSH_VAR
+  #endif
+  return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols) 
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+  if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+    return RangeDecoderBitTreeDecode(p + LenLow +
+        (posState << kLenNumLowBits), kLenNumLowBits, rd);
+  if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+    return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+        (posState << kLenNumMidBits), kLenNumMidBits, rd);
+  return kLenNumLowSymbols + kLenNumMidSymbols + 
+      RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+  unsigned char prop0;
+  if (size < LZMA_PROPERTIES_SIZE)
+    return LZMA_RESULT_DATA_ERROR;
+  prop0 = propsData[0];
+  if (prop0 >= (9 * 5 * 5))
+    return LZMA_RESULT_DATA_ERROR;
+  {
+    for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+    for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+    propsRes->lc = prop0;
+    /*
+    unsigned char remainder = (unsigned char)(prop0 / 9);
+    propsRes->lc = prop0 % 9;
+    propsRes->pb = remainder / 5;
+    propsRes->lp = remainder % 5;
+    */
+  }
+
+  #ifdef _LZMA_OUT_READ
+  {
+    int i;
+    propsRes->DictionarySize = 0;
+    for (i = 0; i < 4; i++)
+      propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+    if (propsRes->DictionarySize == 0)
+      propsRes->DictionarySize = 1;
+  }
+  #endif
+  return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+    #ifdef _LZMA_IN_CB
+    ILzmaInCallback *InCallback,
+    #else
+    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+    #endif
+    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+  CProb *p = vs->Probs;
+  SizeT nowPos = 0;
+  Byte previousByte = 0;
+  UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+  UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+  int lc = vs->Properties.lc;
+  CRangeDecoder rd;
+
+  #ifdef _LZMA_OUT_READ
+  
+  int state = vs->State;
+  UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+  int len = vs->RemainLen;
+  UInt32 globalPos = vs->GlobalPos;
+  UInt32 distanceLimit = vs->DistanceLimit;
+
+  Byte *dictionary = vs->Dictionary;
+  UInt32 dictionarySize = vs->Properties.DictionarySize;
+  UInt32 dictionaryPos = vs->DictionaryPos;
+
+  Byte tempDictionary[4];
+
+  rd.Range = vs->Range;
+  rd.Code = vs->Code;
+  #ifdef _LZMA_IN_CB
+  rd.InCallback = InCallback;
+  rd.Buffer = vs->Buffer;
+  rd.BufferLim = vs->BufferLim;
+  #else
+  rd.Buffer = inStream;
+  rd.BufferLim = inStream + inSize;
+  #endif
+
+  #ifndef _LZMA_IN_CB
+  *inSizeProcessed = 0;
+  #endif
+  *outSizeProcessed = 0;
+  if (len == kLzmaStreamWasFinishedId)
+    return LZMA_RESULT_OK;
+
+  if (dictionarySize == 0)
+  {
+    dictionary = tempDictionary;
+    dictionarySize = 1;
+    tempDictionary[0] = vs->TempDictionary[0];
+  }
+
+  if (len == kLzmaNeedInitId)
+  {
+    {
+      UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+      UInt32 i;
+      for (i = 0; i < numProbs; i++)
+        p[i] = kBitModelTotal >> 1; 
+      rep0 = rep1 = rep2 = rep3 = 1;
+      state = 0;
+      globalPos = 0;
+      distanceLimit = 0;
+      dictionaryPos = 0;
+      dictionary[dictionarySize - 1] = 0;
+      RangeDecoderInit(&rd
+          #ifndef _LZMA_IN_CB
+          , inStream, inSize
+          #endif
+          );
+      #ifdef _LZMA_IN_CB
+      if (rd.Result != LZMA_RESULT_OK)
+        return rd.Result;
+      #endif
+      if (rd.ExtraBytes != 0)
+        return LZMA_RESULT_DATA_ERROR;
+    }
+    len = 0;
+  }
+  while(len != 0 && nowPos < outSize)
+  {
+    UInt32 pos = dictionaryPos - rep0;
+    if (pos >= dictionarySize)
+      pos += dictionarySize;
+    outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+    if (++dictionaryPos == dictionarySize)
+      dictionaryPos = 0;
+    len--;
+  }
+  if (dictionaryPos == 0)
+    previousByte = dictionary[dictionarySize - 1];
+  else
+    previousByte = dictionary[dictionaryPos - 1];
+
+  #ifdef _LZMA_IN_CB
+  rd.Result = LZMA_RESULT_OK;
+  #endif
+  rd.ExtraBytes = 0;
+
+  #else /* if !_LZMA_OUT_READ */
+
+  int state = 0;
+  UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+  int len = 0;
+
+  #ifndef _LZMA_IN_CB
+  *inSizeProcessed = 0;
+  #endif
+  *outSizeProcessed = 0;
+
+  {
+    UInt32 i;
+    UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+    for (i = 0; i < numProbs; i++)
+      p[i] = kBitModelTotal >> 1;
+  }
+  
+  #ifdef _LZMA_IN_CB
+  rd.InCallback = InCallback;
+  #endif
+  RangeDecoderInit(&rd
+      #ifndef _LZMA_IN_CB
+      , inStream, inSize
+      #endif
+      );
+
+  #ifdef _LZMA_IN_CB
+  if (rd.Result != LZMA_RESULT_OK)
+    return rd.Result;
+  #endif
+  if (rd.ExtraBytes != 0)
+    return LZMA_RESULT_DATA_ERROR;
+
+  #endif /* _LZMA_OUT_READ */
+
+
+  while(nowPos < outSize)
+  {
+    int posState = (int)(
+        (nowPos 
+        #ifdef _LZMA_OUT_READ
+        + globalPos
+        #endif
+        )
+        & posStateMask);
+    #ifdef _LZMA_IN_CB
+    if (rd.Result != LZMA_RESULT_OK)
+      return rd.Result;
+    #endif
+    if (rd.ExtraBytes != 0)
+      return LZMA_RESULT_DATA_ERROR;
+    if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+    {
+      CProb *probs = p + Literal + (LZMA_LIT_SIZE * 
+        (((
+        (nowPos 
+        #ifdef _LZMA_OUT_READ
+        + globalPos
+        #endif
+        )
+        & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+      if (state >= kNumLitStates)
+      {
+        Byte matchByte;
+        #ifdef _LZMA_OUT_READ
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        matchByte = dictionary[pos];
+        #else
+        matchByte = outStream[nowPos - rep0];
+        #endif
+        previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+      }
+      else
+        previousByte = LzmaLiteralDecode(probs, &rd);
+      outStream[nowPos++] = previousByte;
+      #ifdef _LZMA_OUT_READ
+      if (distanceLimit < dictionarySize)
+        distanceLimit++;
+
+      dictionary[dictionaryPos] = previousByte;
+      if (++dictionaryPos == dictionarySize)
+        dictionaryPos = 0;
+      #endif
+      if (state < 4) state = 0;
+      else if (state < 10) state -= 3;
+      else state -= 6;
+    }
+    else             
+    {
+      if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+      {
+        if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+        {
+          if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+          {
+            #ifdef _LZMA_OUT_READ
+            UInt32 pos;
+            #endif
+      
+            #ifdef _LZMA_OUT_READ
+            if (distanceLimit == 0)
+            #else
+            if (nowPos == 0)
+            #endif
+              return LZMA_RESULT_DATA_ERROR;
+
+            state = state < 7 ? 9 : 11;
+            #ifdef _LZMA_OUT_READ
+            pos = dictionaryPos - rep0;
+            if (pos >= dictionarySize)
+              pos += dictionarySize;
+            previousByte = dictionary[pos];
+            dictionary[dictionaryPos] = previousByte;
+            if (++dictionaryPos == dictionarySize)
+              dictionaryPos = 0;
+            #else
+            previousByte = outStream[nowPos - rep0];
+            #endif
+            outStream[nowPos++] = previousByte;
+
+            #ifdef _LZMA_OUT_READ
+            if (distanceLimit < dictionarySize)
+              distanceLimit++;
+            #endif
+            continue;
+          }
+        }
+        else
+        {
+          UInt32 distance;
+          if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+            distance = rep1;
+          else 
+          {
+            if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+              distance = rep2;
+            else
+            {
+              distance = rep3;
+              rep3 = rep2;
+            }
+            rep2 = rep1;
+          }
+          rep1 = rep0;
+          rep0 = distance;
+        }
+        len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+        state = state < 7 ? 8 : 11;
+      }
+      else
+      {
+        int posSlot;
+        rep3 = rep2;
+        rep2 = rep1;
+        rep1 = rep0;
+        state = state < 7 ? 7 : 10;
+        len = LzmaLenDecode(p + LenCoder, &rd, posState);
+        posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 
+            kNumPosSlotBits), kNumPosSlotBits, &rd);
+        if (posSlot >= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot >> 1) - 1);
+          rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+          if (posSlot < kEndPosModelIndex)
+          {
+            rep0 += RangeDecoderReverseBitTreeDecode(
+                p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+          }
+          else
+          {
+            rep0 += RangeDecoderDecodeDirectBits(&rd, 
+                numDirectBits - kNumAlignBits) << kNumAlignBits;
+            rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+          }
+        }
+        else
+          rep0 = posSlot;
+        if (++rep0 == (UInt32)(0))
+        {
+          /* it's for stream version */
+          len = kLzmaStreamWasFinishedId;
+          break;
+        }
+      }
+
+      len += kMatchMinLen;
+      #ifdef _LZMA_OUT_READ
+      if (rep0 > distanceLimit) 
+      #else
+      if (rep0 > nowPos)
+      #endif
+        return LZMA_RESULT_DATA_ERROR;
+
+      #ifdef _LZMA_OUT_READ
+      if (dictionarySize - distanceLimit > (UInt32)len)
+        distanceLimit += len;
+      else
+        distanceLimit = dictionarySize;
+      #endif
+
+      do
+      {
+        #ifdef _LZMA_OUT_READ
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        previousByte = dictionary[pos];
+        dictionary[dictionaryPos] = previousByte;
+        if (++dictionaryPos == dictionarySize)
+          dictionaryPos = 0;
+        #else
+        previousByte = outStream[nowPos - rep0];
+        #endif
+        len--;
+        outStream[nowPos++] = previousByte;
+      }
+      while(len != 0 && nowPos < outSize);
+    }
+  }
+
+
+  #ifdef _LZMA_OUT_READ
+  vs->Range = rd.Range;
+  vs->Code = rd.Code;
+  vs->DictionaryPos = dictionaryPos;
+  vs->GlobalPos = globalPos + (UInt32)nowPos;
+  vs->DistanceLimit = distanceLimit;
+  vs->Reps[0] = rep0;
+  vs->Reps[1] = rep1;
+  vs->Reps[2] = rep2;
+  vs->Reps[3] = rep3;
+  vs->State = state;
+  vs->RemainLen = len;
+  vs->TempDictionary[0] = tempDictionary[0];
+  #endif
+
+  #ifdef _LZMA_IN_CB
+  vs->Buffer = rd.Buffer;
+  vs->BufferLim = rd.BufferLim;
+  #else
+  *inSizeProcessed = (SizeT)(rd.Buffer - inStream);
+  #endif
+  *outSizeProcessed = nowPos;
+  return LZMA_RESULT_OK;
+}

Added: trunk/lzma/C/Compress/Lzma/LzmaStateDecode.c
===================================================================
--- trunk/lzma/C/Compress/Lzma/LzmaStateDecode.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Lzma/LzmaStateDecode.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,521 @@
+/*
+  LzmaStateDecode.c
+  LZMA Decoder (State version)
+  
+  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+  http://www.7-zip.org/
+
+  LZMA SDK is licensed under two licenses:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  It means that you can select one of these two licenses and 
+  follow rules of that license.
+
+  SPECIAL EXCEPTION:
+  Igor Pavlov, as the author of this Code, expressly permits you to 
+  statically or dynamically link your Code (or bind by name) to the 
+  interfaces of this file without subjecting your linked Code to the 
+  terms of the CPL or GNU LGPL. Any modifications or additions 
+  to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaStateDecode.h"
+
+#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_INIT Code = 0; Range = 0xFFFFFFFF; \
+  { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }}
+
+#define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+  { UpdateBit0(p); mi <<= 1; A0; } else \
+  { UpdateBit1(p); mi = (mi + mi) + 1; A1; } 
+  
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)               
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+  { int i = numLevels; res = 1; \
+  do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+  res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols) 
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+/* kRequiredInBufferSize = number of required input bytes for worst case: 
+   longest match with longest distance.
+   kLzmaInBufferSize must be larger than kRequiredInBufferSize 
+   23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE)
+*/
+
+#define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8)
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+  unsigned char prop0;
+  if (size < LZMA_PROPERTIES_SIZE)
+    return LZMA_RESULT_DATA_ERROR;
+  prop0 = propsData[0];
+  if (prop0 >= (9 * 5 * 5))
+    return LZMA_RESULT_DATA_ERROR;
+  {
+    for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+    for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+    propsRes->lc = prop0;
+    /*
+    unsigned char remainder = (unsigned char)(prop0 / 9);
+    propsRes->lc = prop0 % 9;
+    propsRes->pb = remainder / 5;
+    propsRes->lp = remainder % 5;
+    */
+  }
+
+  {
+    int i;
+    propsRes->DictionarySize = 0;
+    for (i = 0; i < 4; i++)
+      propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+    if (propsRes->DictionarySize == 0)
+      propsRes->DictionarySize = 1;
+    return LZMA_RESULT_OK;
+  }
+}
+
+int LzmaDecode(
+    CLzmaDecoderState *vs,
+    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+    int finishDecoding)
+{
+  UInt32 Range = vs->Range;
+  UInt32 Code = vs->Code;
+
+  unsigned char *Buffer = vs->Buffer;
+  int BufferSize = vs->BufferSize; /* don't change it to unsigned int */
+  CProb *p = vs->Probs;
+
+  int state = vs->State;
+  unsigned char previousByte;
+  UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+  SizeT nowPos = 0;
+  UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+  UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+  int lc = vs->Properties.lc;
+  int len = vs->RemainLen;
+  UInt32 globalPos = vs->GlobalPos;
+  UInt32 distanceLimit = vs->DistanceLimit;
+
+  unsigned char *dictionary = vs->Dictionary;
+  UInt32 dictionarySize = vs->Properties.DictionarySize;
+  UInt32 dictionaryPos = vs->DictionaryPos;
+
+  unsigned char tempDictionary[4];
+
+  (*inSizeProcessed) = 0;
+  (*outSizeProcessed) = 0;
+  if (len == kLzmaStreamWasFinishedId)
+    return LZMA_RESULT_OK;
+
+  if (dictionarySize == 0)
+  {
+    dictionary = tempDictionary;
+    dictionarySize = 1;
+    tempDictionary[0] = vs->TempDictionary[0];
+  }
+
+  if (len == kLzmaNeedInitId)
+  {
+    while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+    {
+      Buffer[BufferSize++] = *inStream++;
+      (*inSizeProcessed)++;
+      inSize--;
+    }
+    if (BufferSize < 5)
+    {
+      vs->BufferSize = BufferSize;
+      return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK;
+    }
+    {
+      UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+      UInt32 i;
+      for (i = 0; i < numProbs; i++)
+        p[i] = kBitModelTotal >> 1; 
+      rep0 = rep1 = rep2 = rep3 = 1;
+      state = 0;
+      globalPos = 0;
+      distanceLimit = 0;
+      dictionaryPos = 0;
+      dictionary[dictionarySize - 1] = 0;
+      RC_INIT;
+    }
+    len = 0;
+  }
+  while(len != 0 && nowPos < outSize)
+  {
+    UInt32 pos = dictionaryPos - rep0;
+    if (pos >= dictionarySize)
+      pos += dictionarySize;
+    outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+    if (++dictionaryPos == dictionarySize)
+      dictionaryPos = 0;
+    len--;
+  }
+  if (dictionaryPos == 0)
+    previousByte = dictionary[dictionarySize - 1];
+  else
+    previousByte = dictionary[dictionaryPos - 1];
+
+  for (;;)
+  {
+    int bufferPos = (int)(Buffer - vs->Buffer);
+    if (BufferSize - bufferPos < kRequiredInBufferSize)
+    {
+      int i;
+      BufferSize -= bufferPos;
+      if (BufferSize < 0)
+        return LZMA_RESULT_DATA_ERROR;
+      for (i = 0; i < BufferSize; i++)
+        vs->Buffer[i] = Buffer[i];
+      Buffer = vs->Buffer;
+      while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+      {
+        Buffer[BufferSize++] = *inStream++;
+        (*inSizeProcessed)++;
+        inSize--;
+      }
+      if (BufferSize < kRequiredInBufferSize && !finishDecoding)
+        break;
+    }
+    if (nowPos >= outSize)
+      break;
+    {
+    CProb *prob;
+    UInt32 bound;
+    int posState = (int)((nowPos + globalPos) & posStateMask);
+
+    prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+    IfBit0(prob)
+    {
+      int symbol = 1;
+      UpdateBit0(prob)
+      prob = p + Literal + (LZMA_LIT_SIZE * 
+        ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+      if (state >= kNumLitStates)
+      {
+        int matchByte;
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        matchByte = dictionary[pos];
+        do
+        {
+          int bit;
+          CProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & 0x100);
+          probLit = prob + 0x100 + bit + symbol;
+          RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+        }
+        while (symbol < 0x100);
+      }
+      while (symbol < 0x100)
+      {
+        CProb *probLit = prob + symbol;
+        RC_GET_BIT(probLit, symbol)
+      }
+      previousByte = (unsigned char)symbol;
+
+      outStream[nowPos++] = previousByte;
+      if (distanceLimit < dictionarySize)
+        distanceLimit++;
+
+      dictionary[dictionaryPos] = previousByte;
+      if (++dictionaryPos == dictionarySize)
+        dictionaryPos = 0;
+      if (state < 4) state = 0;
+      else if (state < 10) state -= 3;
+      else state -= 6;
+    }
+    else             
+    {
+      UpdateBit1(prob);
+      prob = p + IsRep + state;
+      IfBit0(prob)
+      {
+        UpdateBit0(prob);
+        rep3 = rep2;
+        rep2 = rep1;
+        rep1 = rep0;
+        state = state < kNumLitStates ? 0 : 3;
+        prob = p + LenCoder;
+      }
+      else
+      {
+        UpdateBit1(prob);
+        prob = p + IsRepG0 + state;
+        IfBit0(prob)
+        {
+          UpdateBit0(prob);
+          prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IfBit0(prob)
+          {
+            UInt32 pos;
+            UpdateBit0(prob);
+            if (distanceLimit == 0)
+              return LZMA_RESULT_DATA_ERROR;
+            if (distanceLimit < dictionarySize)
+              distanceLimit++;
+            state = state < kNumLitStates ? 9 : 11;
+            pos = dictionaryPos - rep0;
+            if (pos >= dictionarySize)
+              pos += dictionarySize;
+            previousByte = dictionary[pos];
+            dictionary[dictionaryPos] = previousByte;
+            if (++dictionaryPos == dictionarySize)
+              dictionaryPos = 0;
+            outStream[nowPos++] = previousByte;
+            continue;
+          }
+          else
+          {
+            UpdateBit1(prob);
+          }
+        }
+        else
+        {
+          UInt32 distance;
+          UpdateBit1(prob);
+          prob = p + IsRepG1 + state;
+          IfBit0(prob)
+          {
+            UpdateBit0(prob);
+            distance = rep1;
+          }
+          else 
+          {
+            UpdateBit1(prob);
+            prob = p + IsRepG2 + state;
+            IfBit0(prob)
+            {
+              UpdateBit0(prob);
+              distance = rep2;
+            }
+            else
+            {
+              UpdateBit1(prob);
+              distance = rep3;
+              rep3 = rep2;
+            }
+            rep2 = rep1;
+          }
+          rep1 = rep0;
+          rep0 = distance;
+        }
+        state = state < kNumLitStates ? 8 : 11;
+        prob = p + RepLenCoder;
+      }
+      {
+        int numBits, offset;
+        CProb *probLen = prob + LenChoice;
+        IfBit0(probLen)
+        {
+          UpdateBit0(probLen);
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          numBits = kLenNumLowBits;
+        }
+        else
+        {
+          UpdateBit1(probLen);
+          probLen = prob + LenChoice2;
+          IfBit0(probLen)
+          {
+            UpdateBit0(probLen);
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            numBits = kLenNumMidBits;
+          }
+          else
+          {
+            UpdateBit1(probLen);
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            numBits = kLenNumHighBits;
+          }
+        }
+        RangeDecoderBitTreeDecode(probLen, numBits, len);
+        len += offset;
+      }
+
+      if (state < 4)
+      {
+        int posSlot;
+        state += kNumLitStates;
+        prob = p + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 
+            kNumPosSlotBits);
+        RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+        if (posSlot >= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot >> 1) - 1);
+          rep0 = (2 | ((UInt32)posSlot & 1));
+          if (posSlot < kEndPosModelIndex)
+          {
+            rep0 <<= numDirectBits;
+            prob = p + SpecPos + rep0 - posSlot - 1;
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              RC_NORMALIZE
+              Range >>= 1;
+              rep0 <<= 1;
+              if (Code >= Range)
+              {
+                Code -= Range;
+                rep0 |= 1;
+              }
+            }
+            while (--numDirectBits != 0);
+            prob = p + Align;
+            rep0 <<= kNumAlignBits;
+            numDirectBits = kNumAlignBits;
+          }
+          {
+            int i = 1;
+            int mi = 1;
+            do
+            {
+              CProb *prob3 = prob + mi;
+              RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+              i <<= 1;
+            }
+            while(--numDirectBits != 0);
+          }
+        }
+        else
+          rep0 = posSlot;
+        if (++rep0 == (UInt32)(0))
+        {
+          /* it's for stream version */
+          len = kLzmaStreamWasFinishedId;
+          break;
+        }
+      }
+
+      len += kMatchMinLen;
+      if (rep0 > distanceLimit) 
+        return LZMA_RESULT_DATA_ERROR;
+      if (dictionarySize - distanceLimit > (UInt32)len)
+        distanceLimit += len;
+      else
+        distanceLimit = dictionarySize;
+
+      do
+      {
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        previousByte = dictionary[pos];
+        dictionary[dictionaryPos] = previousByte;
+        if (++dictionaryPos == dictionarySize)
+          dictionaryPos = 0;
+        len--;
+        outStream[nowPos++] = previousByte;
+      }
+      while(len != 0 && nowPos < outSize);
+    }
+    }
+  }
+  RC_NORMALIZE;
+
+  BufferSize -= (int)(Buffer - vs->Buffer);
+  if (BufferSize < 0)
+    return LZMA_RESULT_DATA_ERROR;
+  {
+    int i;
+    for (i = 0; i < BufferSize; i++)
+      vs->Buffer[i] = Buffer[i];
+  }
+  vs->BufferSize = BufferSize;
+  vs->Range = Range;
+  vs->Code = Code;
+  vs->DictionaryPos = dictionaryPos;
+  vs->GlobalPos = (UInt32)(globalPos + nowPos);
+  vs->DistanceLimit = distanceLimit;
+  vs->Reps[0] = rep0;
+  vs->Reps[1] = rep1;
+  vs->Reps[2] = rep2;
+  vs->Reps[3] = rep3;
+  vs->State = state;
+  vs->RemainLen = len;
+  vs->TempDictionary[0] = tempDictionary[0];
+
+  (*outSizeProcessed) = nowPos;
+  return LZMA_RESULT_OK;
+}

Added: trunk/lzma/C/Compress/Lzma/LzmaStateDecode.h
===================================================================
--- trunk/lzma/C/Compress/Lzma/LzmaStateDecode.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Lzma/LzmaStateDecode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,96 @@
+/* 
+  LzmaStateDecode.h
+  LZMA Decoder interface (State version)
+
+  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+  http://www.7-zip.org/
+
+  LZMA SDK is licensed under two licenses:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  It means that you can select one of these two licenses and 
+  follow rules of that license.
+
+  SPECIAL EXCEPTION:
+  Igor Pavlov, as the author of this code, expressly permits you to 
+  statically or dynamically link your code (or bind by name) to the 
+  interfaces of this file without subjecting your linked code to the 
+  terms of the CPL or GNU LGPL. Any modifications or additions 
+  to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMASTATEDECODE_H
+#define __LZMASTATEDECODE_H
+
+#include "LzmaTypes.h"
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs, 
+   but memory usage will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+  int lc;
+  int lp;
+  int pb;
+  UInt32 DictionarySize;
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp)))
+
+#define kLzmaInBufferSize 64   /* don't change it. it must be larger than kRequiredInBufferSize */
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+  CLzmaProperties Properties;
+  CProb *Probs;
+  unsigned char *Dictionary;
+
+  unsigned char Buffer[kLzmaInBufferSize];
+  int BufferSize;
+
+  UInt32 Range;
+  UInt32 Code;
+  UInt32 DictionaryPos;
+  UInt32 GlobalPos;
+  UInt32 DistanceLimit;
+  UInt32 Reps[4];
+  int State;
+  int RemainLen;  /* -2: decoder needs internal initialization
+                     -1: stream was finished, 
+                      0: ok
+                    > 0: need to write RemainLen bytes as match Reps[0],
+                  */
+  unsigned char TempDictionary[4];  /* it's required when DictionarySize = 0 */
+} CLzmaDecoderState;
+
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; }
+
+/* LzmaDecode: decoding from input stream to output stream.
+  If finishDecoding != 0, then there are no more bytes in input stream
+  after inStream[inSize - 1]. */
+
+int LzmaDecode(CLzmaDecoderState *vs,
+    const unsigned char *inStream, SizeT inSize,  SizeT *inSizeProcessed,
+    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
+    int finishDecoding);
+
+#endif

Added: trunk/lzma/C/Compress/Lzma/LzmaStateTest.c
===================================================================
--- trunk/lzma/C/Compress/Lzma/LzmaStateTest.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Lzma/LzmaStateTest.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,195 @@
+/* 
+LzmaStateTest.c
+Test application for LZMA Decoder (State version)
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-02)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "LzmaStateDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+#define kInBufferSize (1 << 15)
+#define kOutBufferSize (1 << 15)
+
+unsigned char g_InBuffer[kInBufferSize];
+unsigned char g_OutBuffer[kOutBufferSize];
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+  { return fread(data, 1, size, file); }
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+  { return (MyReadFile(file, data, size) == size); }
+
+int PrintError(char *buffer, const char *message)
+{
+  sprintf(buffer + strlen(buffer), "\nError: ");
+  sprintf(buffer + strlen(buffer), message);
+  return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+  /* We use two 32-bit integers to construct 64-bit integer for file size.
+     You can remove outSizeHigh, if you don't need >= 4GB supporting,
+     or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+  UInt32 outSize = 0;
+  UInt32 outSizeHigh = 0; 
+  
+  int waitEOS = 1; 
+  /* waitEOS = 1, if there is no uncompressed size in headers, 
+   so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+  int i;
+  int res = 0;
+  CLzmaDecoderState state;  /* it's about 140 bytes structure, if int is 32-bit */
+  unsigned char properties[LZMA_PROPERTIES_SIZE];
+  SizeT inAvail = 0;
+  unsigned char *inBuffer = 0;
+
+  if (sizeof(UInt32) < 4)
+    return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+  /* Read LZMA properties for compressed stream */
+
+  if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+    return PrintError(rs, kCantReadMessage);
+
+  /* Read uncompressed size */
+  
+  for (i = 0; i < 8; i++)
+  {
+    unsigned char b;
+    if (!MyReadFileAndCheck(inFile, &b, 1))
+      return PrintError(rs, kCantReadMessage);
+    if (b != 0xFF)
+      waitEOS = 0;
+    if (i < 4)
+      outSize += (UInt32)(b) << (i * 8);
+    else
+      outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+  }
+
+  /* Decode LZMA properties and allocate memory */
+  
+  if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+    return PrintError(rs, "Incorrect stream properties");
+  state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+  if (state.Probs == 0)
+    return PrintError(rs, kCantAllocateMessage);
+  
+  if (state.Properties.DictionarySize == 0)
+    state.Dictionary = 0;
+  else
+  {
+    state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+    if (state.Dictionary == 0)
+    {
+      free(state.Probs);
+      return PrintError(rs, kCantAllocateMessage);
+    }
+  }
+  
+  /* Decompress */
+  
+  LzmaDecoderInit(&state);
+  
+  do
+  {
+    SizeT inProcessed, outProcessed;
+    int finishDecoding;
+    UInt32 outAvail = kOutBufferSize;
+    if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+      outAvail = outSize;
+    if (inAvail == 0)
+    {
+      inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize);
+      inBuffer = g_InBuffer;
+    }
+    finishDecoding = (inAvail == 0);
+    res = LzmaDecode(&state,
+        inBuffer, inAvail, &inProcessed,
+        g_OutBuffer, outAvail, &outProcessed,
+        finishDecoding);
+    if (res != 0)
+    {
+      sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+      res = 1;
+      break;
+    }
+    inAvail -= inProcessed;
+    inBuffer += inProcessed;
+    
+    if (outFile != 0)  
+      if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed)
+      {
+        PrintError(rs, kCantWriteMessage);
+        res = 1;
+        break;
+      }
+      
+    if (outSize < outProcessed)
+      outSizeHigh--;
+    outSize -= (UInt32)outProcessed;
+    outSize &= 0xFFFFFFFF;
+
+    if (outProcessed == 0 && finishDecoding)
+    {
+      if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+        res = 1;
+      break;
+    }
+  }
+  while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0  || waitEOS);
+
+  free(state.Dictionary);
+  free(state.Probs);
+  return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+  FILE *inFile = 0;
+  FILE *outFile = 0;
+  int res;
+
+  sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov  2005-08-02\n");
+  if (numArgs < 2 || numArgs > 3)
+  {
+    sprintf(rs + strlen(rs), "\nUsage:  lzmadec file.lzma [outFile]\n");
+    return 1;
+  }
+
+  inFile = fopen(args[1], "rb");
+  if (inFile == 0)
+    return PrintError(rs, "Can not open input file");
+
+  if (numArgs > 2)
+  {
+    outFile = fopen(args[2], "wb+");
+    if (outFile == 0)
+      return PrintError(rs, "Can not open output file");
+  }
+
+  res = main3(inFile, outFile, rs);
+
+  if (outFile != 0)
+    fclose(outFile);
+  fclose(inFile);
+  return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+  char rs[800] = { 0 };
+  int res = main2(numArgs, args, rs);
+  printf(rs);
+  return res;
+}

Added: trunk/lzma/C/Compress/Lzma/LzmaTest.c
===================================================================
--- trunk/lzma/C/Compress/Lzma/LzmaTest.c	                        (rev 0)
+++ trunk/lzma/C/Compress/Lzma/LzmaTest.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,342 @@
+/* 
+LzmaTest.c
+Test application for LZMA Decoder
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.26 (2005-08-05)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "LzmaDecode.h"
+
+const char *kCantReadMessage = "Can not read input file";
+const char *kCantWriteMessage = "Can not write output file";
+const char *kCantAllocateMessage = "Can not allocate memory";
+
+size_t MyReadFile(FILE *file, void *data, size_t size)
+{ 
+  if (size == 0)
+    return 0;
+  return fread(data, 1, size, file); 
+}
+
+int MyReadFileAndCheck(FILE *file, void *data, size_t size)
+  { return (MyReadFile(file, data, size) == size);} 
+
+size_t MyWriteFile(FILE *file, const void *data, size_t size)
+{ 
+  if (size == 0)
+    return 0;
+  return fwrite(data, 1, size, file); 
+}
+
+int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)
+  { return (MyWriteFile(file, data, size) == size); }
+
+#ifdef _LZMA_IN_CB
+#define kInBufferSize (1 << 15)
+typedef struct _CBuffer
+{
+  ILzmaInCallback InCallback;
+  FILE *File;
+  unsigned char Buffer[kInBufferSize];
+} CBuffer;
+
+int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
+{
+  CBuffer *b = (CBuffer *)object;
+  *buffer = b->Buffer;
+  *size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize);
+  return LZMA_RESULT_OK;
+}
+CBuffer g_InBuffer;
+
+#endif
+
+#ifdef _LZMA_OUT_READ
+#define kOutBufferSize (1 << 15)
+unsigned char g_OutBuffer[kOutBufferSize];
+#endif
+
+int PrintError(char *buffer, const char *message)
+{
+  sprintf(buffer + strlen(buffer), "\nError: ");
+  sprintf(buffer + strlen(buffer), message);
+  return 1;
+}
+
+int main3(FILE *inFile, FILE *outFile, char *rs)
+{
+  /* We use two 32-bit integers to construct 64-bit integer for file size.
+     You can remove outSizeHigh, if you don't need >= 4GB supporting,
+     or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
+  UInt32 outSize = 0;
+  UInt32 outSizeHigh = 0;
+  #ifndef _LZMA_OUT_READ
+  SizeT outSizeFull;
+  unsigned char *outStream;
+  #endif
+  
+  int waitEOS = 1; 
+  /* waitEOS = 1, if there is no uncompressed size in headers, 
+   so decoder will wait EOS (End of Stream Marker) in compressed stream */
+
+  #ifndef _LZMA_IN_CB
+  SizeT compressedSize;
+  unsigned char *inStream;
+  #endif
+
+  CLzmaDecoderState state;  /* it's about 24-80 bytes structure, if int is 32-bit */
+  unsigned char properties[LZMA_PROPERTIES_SIZE];
+
+  int res;
+
+  #ifdef _LZMA_IN_CB
+  g_InBuffer.File = inFile;
+  #endif
+
+  if (sizeof(UInt32) < 4)
+    return PrintError(rs, "LZMA decoder needs correct UInt32");
+
+  #ifndef _LZMA_IN_CB
+  {
+    long length;
+    fseek(inFile, 0, SEEK_END);
+    length = ftell(inFile);
+    fseek(inFile, 0, SEEK_SET);
+    if ((long)(SizeT)length != length)
+      return PrintError(rs, "Too big compressed stream");
+    compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
+  }
+  #endif
+
+  /* Read LZMA properties for compressed stream */
+
+  if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
+    return PrintError(rs, kCantReadMessage);
+
+  /* Read uncompressed size */
+
+  {
+    int i;
+    for (i = 0; i < 8; i++)
+    {
+      unsigned char b;
+      if (!MyReadFileAndCheck(inFile, &b, 1))
+        return PrintError(rs, kCantReadMessage);
+      if (b != 0xFF)
+        waitEOS = 0;
+      if (i < 4)
+        outSize += (UInt32)(b) << (i * 8);
+      else
+        outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
+    }
+    
+    #ifndef _LZMA_OUT_READ
+    if (waitEOS)
+      return PrintError(rs, "Stream with EOS marker is not supported");
+    outSizeFull = (SizeT)outSize;
+    if (sizeof(SizeT) >= 8)
+      outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
+    else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
+      return PrintError(rs, "Too big uncompressed stream");
+    #endif
+  }
+
+  /* Decode LZMA properties and allocate memory */
+  
+  if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+    return PrintError(rs, "Incorrect stream properties");
+  state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+
+  #ifdef _LZMA_OUT_READ
+  if (state.Properties.DictionarySize == 0)
+    state.Dictionary = 0;
+  else
+    state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+  #else
+  if (outSizeFull == 0)
+    outStream = 0;
+  else
+    outStream = (unsigned char *)malloc(outSizeFull);
+  #endif
+
+  #ifndef _LZMA_IN_CB
+  if (compressedSize == 0)
+    inStream = 0;
+  else
+    inStream = (unsigned char *)malloc(compressedSize);
+  #endif
+
+  if (state.Probs == 0 
+    #ifdef _LZMA_OUT_READ
+    || (state.Dictionary == 0 && state.Properties.DictionarySize != 0)
+    #else
+    || (outStream == 0 && outSizeFull != 0)
+    #endif
+    #ifndef _LZMA_IN_CB
+    || (inStream == 0 && compressedSize != 0)
+    #endif
+    )
+  {
+    free(state.Probs);
+    #ifdef _LZMA_OUT_READ
+    free(state.Dictionary);
+    #else
+    free(outStream);
+    #endif
+    #ifndef _LZMA_IN_CB
+    free(inStream);
+    #endif
+    return PrintError(rs, kCantAllocateMessage);
+  }
+
+  /* Decompress */
+
+  #ifdef _LZMA_IN_CB
+  g_InBuffer.InCallback.Read = LzmaReadCompressed;
+  #else
+  if (!MyReadFileAndCheck(inFile, inStream, compressedSize))
+    return PrintError(rs, kCantReadMessage);
+  #endif
+
+  #ifdef _LZMA_OUT_READ
+  {
+    #ifndef _LZMA_IN_CB
+    SizeT inAvail = compressedSize;
+    const unsigned char *inBuffer = inStream;
+    #endif
+    LzmaDecoderInit(&state);
+    do
+    {
+      #ifndef _LZMA_IN_CB
+      SizeT inProcessed;
+      #endif
+      SizeT outProcessed;
+      SizeT outAvail = kOutBufferSize;
+      if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
+        outAvail = (SizeT)outSize;
+      res = LzmaDecode(&state,
+        #ifdef _LZMA_IN_CB
+        &g_InBuffer.InCallback,
+        #else
+        inBuffer, inAvail, &inProcessed,
+        #endif
+        g_OutBuffer, outAvail, &outProcessed);
+      if (res != 0)
+      {
+        sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+        res = 1;
+        break;
+      }
+      #ifndef _LZMA_IN_CB
+      inAvail -= inProcessed;
+      inBuffer += inProcessed;
+      #endif
+      
+      if (outFile != 0)  
+        if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed))
+        {
+          PrintError(rs, kCantWriteMessage);
+          res = 1;
+          break;
+        }
+        
+      if (outSize < outProcessed)
+        outSizeHigh--;
+      outSize -= (UInt32)outProcessed;
+      outSize &= 0xFFFFFFFF;
+        
+      if (outProcessed == 0)
+      {
+        if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
+          res = 1;
+        break;
+      }
+    }
+    while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0  || waitEOS);
+  }
+
+  #else
+  {
+    #ifndef _LZMA_IN_CB
+    SizeT inProcessed;
+    #endif
+    SizeT outProcessed;
+    res = LzmaDecode(&state,
+      #ifdef _LZMA_IN_CB
+      &g_InBuffer.InCallback,
+      #else
+      inStream, compressedSize, &inProcessed,
+      #endif
+      outStream, outSizeFull, &outProcessed);
+    if (res != 0)
+    {
+      sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
+      res = 1;
+    }
+    else if (outFile != 0)
+    {
+      if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed))
+      {
+        PrintError(rs, kCantWriteMessage);
+        res = 1;
+      }
+    }
+  }
+  #endif
+
+  free(state.Probs);
+  #ifdef _LZMA_OUT_READ
+  free(state.Dictionary);
+  #else
+  free(outStream);
+  #endif
+  #ifndef _LZMA_IN_CB
+  free(inStream);
+  #endif
+  return res;
+}
+
+int main2(int numArgs, const char *args[], char *rs)
+{
+  FILE *inFile = 0;
+  FILE *outFile = 0;
+  int res;
+
+  sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov  2005-08-05\n");
+  if (numArgs < 2 || numArgs > 3)
+  {
+    sprintf(rs + strlen(rs), "\nUsage:  lzmadec file.lzma [outFile]\n");
+    return 1;
+  }
+
+  inFile = fopen(args[1], "rb");
+  if (inFile == 0)
+    return PrintError(rs, "Can not open input file");
+
+  if (numArgs > 2)
+  {
+    outFile = fopen(args[2], "wb+");
+    if (outFile == 0)
+      return PrintError(rs, "Can not open output file");
+  }
+
+  res = main3(inFile, outFile, rs);
+
+  if (outFile != 0)
+    fclose(outFile);
+  fclose(inFile);
+  return res;
+}
+
+int main(int numArgs, const char *args[])
+{
+  char rs[800] = { 0 };
+  int res = main2(numArgs, args, rs);
+  printf(rs);
+  return res;
+}

Added: trunk/lzma/C/Compress/Lzma/LzmaTypes.h
===================================================================
--- trunk/lzma/C/Compress/Lzma/LzmaTypes.h	                        (rev 0)
+++ trunk/lzma/C/Compress/Lzma/LzmaTypes.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,45 @@
+/* 
+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
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif 
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif 
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif 
+
+/* #define _LZMA_NO_SYSTEM_SIZE_T */
+/* You can use it, if you don't want <stddef.h> */
+
+#ifndef _7ZIP_SIZET_DEFINED
+#define _7ZIP_SIZET_DEFINED
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+#include <stddef.h>
+typedef size_t SizeT;
+#endif
+#endif
+
+#endif

Added: trunk/lzma/C/CpuArch.h
===================================================================
--- trunk/lzma/C/CpuArch.h	                        (rev 0)
+++ trunk/lzma/C/CpuArch.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,18 @@
+/* CpuArch.h */
+
+#ifndef __CPUARCH_H
+#define __CPUARCH_H
+
+/* 
+LITTLE_ENDIAN_UNALIGN means:
+  1) CPU is LITTLE_ENDIAN
+  2) it's allowed to make unaligned memory accesses
+if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know 
+about these properties of platform.
+*/
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
+#define LITTLE_ENDIAN_UNALIGN
+#endif
+
+#endif

Added: trunk/lzma/C/IStream.h
===================================================================
--- trunk/lzma/C/IStream.h	                        (rev 0)
+++ trunk/lzma/C/IStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,19 @@
+/* IStream.h */
+
+#ifndef __C_ISTREAM_H
+#define __C_ISTREAM_H
+
+#include "Types.h"
+
+typedef struct _ISeqInStream
+{
+  HRes (*Read)(void *object, void *data, UInt32 size, UInt32 *processedSize);
+} ISeqInStream;
+
+typedef struct _ISzAlloc
+{
+  void *(*Alloc)(size_t size);
+  void (*Free)(void *address); /* address can be 0 */
+} ISzAlloc;
+
+#endif

Added: trunk/lzma/C/Sort.c
===================================================================
--- trunk/lzma/C/Sort.c	                        (rev 0)
+++ trunk/lzma/C/Sort.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,92 @@
+/* Sort.c */
+
+#include "Sort.h"
+
+#define HeapSortDown(p, k, size, temp) \
+  { for (;;) { \
+    UInt32 s = (k << 1); \
+    if (s > size) break; \
+    if (s < size && p[s + 1] > p[s]) s++; \
+    if (temp >= p[s]) break; \
+    p[k] = p[s]; k = s; \
+  } p[k] = temp; }
+
+void HeapSort(UInt32 *p, UInt32 size)
+{
+  if (size <= 1)
+    return;
+  p--;
+  {
+    UInt32 i = size / 2;
+    do
+    {
+      UInt32 temp = p[i];
+      UInt32 k = i;
+      HeapSortDown(p, k, size, temp)
+    }
+    while(--i != 0);
+  }
+  /*
+  do
+  {
+    UInt32 k = 1;
+    UInt32 temp = p[size];
+    p[size--] = p[1];
+    HeapSortDown(p, k, size, temp)
+  }
+  while (size > 1);
+  */
+  while (size > 3)
+  {
+    UInt32 temp = p[size];
+    UInt32 k = (p[3] > p[2]) ? 3 : 2;
+    p[size--] = p[1];
+    p[1] = p[k]; 
+    HeapSortDown(p, k, size, temp)
+  }
+  {
+    UInt32 temp = p[size];
+    p[size] = p[1];
+    if (size > 2 && p[2] < temp)
+    {
+      p[1] = p[2];
+      p[2] = temp;
+    }
+    else
+      p[1] = temp;
+  }
+}
+
+/*
+#define HeapSortRefDown(p, vals, n, size, temp) \
+  { UInt32 k = n; UInt32 val = vals[temp]; for (;;) { \
+    UInt32 s = (k << 1); \
+    if (s > size) break; \
+    if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \
+    if (val >= vals[p[s]]) break; \
+    p[k] = p[s]; k = s; \
+  } p[k] = temp; }
+
+void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size)
+{
+  if (size <= 1)
+    return;
+  p--;
+  {
+    UInt32 i = size / 2;
+    do
+    {
+      UInt32 temp = p[i];
+      HeapSortRefDown(p, vals, i, size, temp);
+    }
+    while(--i != 0);
+  }
+  do
+  {
+    UInt32 temp = p[size];
+    p[size--] = p[1];
+    HeapSortRefDown(p, vals, 1, size, temp);
+  }
+  while (size > 1);
+}
+*/
\ No newline at end of file

Added: trunk/lzma/C/Sort.h
===================================================================
--- trunk/lzma/C/Sort.h	                        (rev 0)
+++ trunk/lzma/C/Sort.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,11 @@
+/* Sort.h */
+
+#ifndef __7Z_Sort_H
+#define __7Z_Sort_H
+
+#include "Types.h"
+
+void HeapSort(UInt32 *p, UInt32 size);
+/* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */
+
+#endif

Added: trunk/lzma/C/Threads.c
===================================================================
--- trunk/lzma/C/Threads.c	                        (rev 0)
+++ trunk/lzma/C/Threads.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,106 @@
+/* Threads.c */
+
+#include "Threads.h"
+#include <process.h>
+
+HRes GetError()
+{
+  DWORD res = GetLastError();
+  return (res) ? (HRes)(res) : SZE_FAIL;
+}
+
+HRes BoolToHRes(int v) { return v ? SZ_OK : GetError(); }
+HRes BOOLToHRes(BOOL v) { return v ? SZ_OK : GetError(); }
+
+HRes MyCloseHandle(HANDLE *h)
+{
+  if (*h != NULL)
+    if (!CloseHandle(*h))
+      return GetError();
+  *h = NULL;
+  return SZ_OK;
+}
+
+HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter)
+{ 
+  unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
+  thread->handle = 
+    /* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */
+    (HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId);
+    /* maybe we must use errno here, but probably GetLastError() is also OK. */
+  return BoolToHRes(thread->handle != 0);
+}
+
+HRes WaitObject(HANDLE h)
+{
+  return (HRes)WaitForSingleObject(h, INFINITE); 
+}
+
+HRes Thread_Wait(CThread *thread)
+{
+  if (thread->handle == NULL)
+    return 1;
+  return WaitObject(thread->handle); 
+}
+
+HRes Thread_Close(CThread *thread)
+{
+  return MyCloseHandle(&thread->handle);
+}
+
+HRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled)
+{
+  p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL);
+  return BoolToHRes(p->handle != 0);
+}
+
+HRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled)
+  { return Event_Create(p, TRUE, initialSignaled); }
+HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) 
+  { return ManualResetEvent_Create(p, 0); }
+
+HRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled)
+  { return Event_Create(p, FALSE, initialSignaled); }
+HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) 
+  { return AutoResetEvent_Create(p, 0); }
+
+HRes Event_Set(CEvent *p) { return BOOLToHRes(SetEvent(p->handle)); }
+HRes Event_Reset(CEvent *p) { return BOOLToHRes(ResetEvent(p->handle)); }
+HRes Event_Wait(CEvent *p) { return WaitObject(p->handle); }
+HRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); }
+
+
+HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount)
+{
+  p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL);
+  return BoolToHRes(p->handle != 0);
+}
+
+HRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) 
+{ 
+  return BOOLToHRes(ReleaseSemaphore(p->handle, releaseCount, previousCount)); 
+}
+HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount)
+{
+  return Semaphore_Release(p, (LONG)releaseCount, NULL);
+}
+HRes Semaphore_Release1(CSemaphore *p)
+{
+  return Semaphore_ReleaseN(p, 1);
+}
+
+HRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); }
+HRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); }
+
+HRes CriticalSection_Init(CCriticalSection *p)
+{
+  /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
+  __try 
+  { 
+    InitializeCriticalSection(p); 
+    /* InitializeCriticalSectionAndSpinCount(p, 0); */
+  }  
+  __except (EXCEPTION_EXECUTE_HANDLER) { return SZE_OUTOFMEMORY; }
+  return SZ_OK;
+}
+

Added: trunk/lzma/C/Threads.h
===================================================================
--- trunk/lzma/C/Threads.h	                        (rev 0)
+++ trunk/lzma/C/Threads.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,69 @@
+/* Threads.h */
+
+#ifndef __7Z_THRESDS_H
+#define __7Z_THRESDS_H
+
+#include <windows.h>
+
+#include "Types.h"
+
+typedef struct _CThread
+{
+  HANDLE handle;
+} CThread;
+
+#define Thread_Construct(thread) (thread)->handle = NULL
+#define Thread_WasCreated(thread) ((thread)->handle != NULL)
+ 
+typedef unsigned THREAD_FUNC_RET_TYPE;
+#define THREAD_FUNC_CALL_TYPE StdCall
+#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
+
+HRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter);
+HRes Thread_Wait(CThread *thread);
+HRes Thread_Close(CThread *thread);
+
+typedef struct _CEvent
+{
+  HANDLE handle;
+} CEvent;
+
+typedef CEvent CAutoResetEvent;
+typedef CEvent CManualResetEvent;
+
+#define Event_Construct(event) (event)->handle = NULL
+#define Event_IsCreated(event) ((event)->handle != NULL)
+
+HRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled);
+HRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event);
+HRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled);
+HRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event);
+HRes Event_Set(CEvent *event);
+HRes Event_Reset(CEvent *event);
+HRes Event_Wait(CEvent *event);
+HRes Event_Close(CEvent *event);
+
+
+typedef struct _CSemaphore
+{
+  HANDLE handle;
+} CSemaphore;
+
+#define Semaphore_Construct(p) (p)->handle = NULL
+
+HRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount);
+HRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
+HRes Semaphore_Release1(CSemaphore *p);
+HRes Semaphore_Wait(CSemaphore *p);
+HRes Semaphore_Close(CSemaphore *p);
+
+
+typedef CRITICAL_SECTION CCriticalSection;
+
+HRes CriticalSection_Init(CCriticalSection *p);
+#define CriticalSection_Delete(p) DeleteCriticalSection(p)
+#define CriticalSection_Enter(p) EnterCriticalSection(p)
+#define CriticalSection_Leave(p) LeaveCriticalSection(p)
+
+#endif
+

Added: trunk/lzma/C/Types.h
===================================================================
--- trunk/lzma/C/Types.h	                        (rev 0)
+++ trunk/lzma/C/Types.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,100 @@
+/* 7zTypes.h */
+
+#ifndef __C_TYPES_H
+#define __C_TYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif 
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif 
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif 
+
+#ifndef _7ZIP_INT32_DEFINED
+#define _7ZIP_INT32_DEFINED
+#ifdef _LZMA_INT32_IS_ULONG
+typedef long Int32;
+#else
+typedef int Int32;
+#endif
+#endif 
+
+/* #define _SZ_NO_INT_64 */
+/* define it your compiler doesn't support long long int */
+
+#ifndef _7ZIP_UINT64_DEFINED
+#define _7ZIP_UINT64_DEFINED
+#ifdef _SZ_NO_INT_64
+typedef unsigned long UInt64;
+#else
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 UInt64;
+#else
+typedef unsigned long long int UInt64;
+#endif
+#endif
+#endif
+
+
+/* #define _SZ_FILE_SIZE_32 */
+/* You can define _SZ_FILE_SIZE_32, if you don't need support for files larger than 4 GB*/
+
+#ifndef CFileSize
+#ifdef _SZ_FILE_SIZE_32
+typedef UInt32 CFileSize; 
+#else
+typedef UInt64 CFileSize; 
+#endif
+#endif
+
+#define SZ_RESULT int
+
+typedef int HRes;
+#define RES_OK (0)
+
+#define SZ_OK (0)
+#define SZE_DATA_ERROR (1)
+#define SZE_CRC_ERROR (3)
+#define SZE_ARCHIVE_ERROR (6)
+
+#define SZE_OUTOFMEMORY (0x8007000EL)
+#define SZE_NOTIMPL (0x80004001L)
+#define SZE_FAIL (0x80004005L)
+#define SZE_INVALIDARG (0x80070057L)
+
+
+#ifndef RINOK
+#define RINOK(x) { HRes __result_ = (x); if(__result_ != 0) return __result_; }
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+#ifdef _MSC_VER
+#define StdCall __stdcall 
+#else
+#define StdCall
+#endif
+
+#if _MSC_VER >= 1300
+#define MY_FAST_CALL __declspec(noinline) __fastcall 
+#elif defined( _MSC_VER)
+#define MY_FAST_CALL __fastcall 
+#else
+#define MY_FAST_CALL
+#endif
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7z.ico
===================================================================
(Binary files differ)


Property changes on: trunk/lzma/CPP/7zip/Archive/7z/7z.ico
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zCompressionMode.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// CompressionMethod.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zCompressionMode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,50 @@
+// 7zCompressionMode.h
+
+#ifndef __7Z_COMPRESSION_MODE_H
+#define __7Z_COMPRESSION_MODE_H
+
+#include "../../../Common/MyString.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "../../Common/MethodProps.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CMethodFull: public CMethod
+{
+  UInt32 NumInStreams;
+  UInt32 NumOutStreams;
+  bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+};
+
+struct CBind
+{
+  UInt32 InCoder;
+  UInt32 InStream;
+  UInt32 OutCoder;
+  UInt32 OutStream;
+};
+
+struct CCompressionMethodMode
+{
+  CObjectVector<CMethodFull> Methods;
+  CRecordVector<CBind> Binds;
+  #ifdef COMPRESS_MT
+  UInt32 NumThreads;
+  #endif
+  bool PasswordIsDefined;
+  UString Password;
+
+  bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
+  CCompressionMethodMode(): PasswordIsDefined(false)
+      #ifdef COMPRESS_MT
+      , NumThreads(1) 
+      #endif
+  {}
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zDecode.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zDecode.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zDecode.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,330 @@
+// 7zDecode.cpp
+
+#include "StdAfx.h"
+
+#include "7zDecode.h"
+
+#include "../../IPassword.h"
+#include "../../Common/LockedStream.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/CreateCoder.h"
+#include "../../Common/FilterCoder.h"
+
+namespace NArchive {
+namespace N7z {
+
+static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
+    CBindInfoEx &bindInfo)
+{
+  bindInfo.Clear();
+  int i;
+  for (i = 0; i < folder.BindPairs.Size(); i++)
+  {
+    NCoderMixer::CBindPair bindPair;
+    bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
+    bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
+    bindInfo.BindPairs.Add(bindPair);
+  }
+  UInt32 outStreamIndex = 0;
+  for (i = 0; i < folder.Coders.Size(); i++)
+  {
+    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+    const CCoderInfo &coderInfo = folder.Coders[i];
+    coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
+    coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
+    bindInfo.Coders.Add(coderStreamsInfo);
+    bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);
+    for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
+      if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
+        bindInfo.OutStreams.Add(outStreamIndex);
+  }
+  for (i = 0; i < folder.PackStreams.Size(); i++)
+    bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
+}
+
+static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1, 
+    const NCoderMixer::CCoderStreamsInfo &a2)
+{
+  return (a1.NumInStreams == a2.NumInStreams) &&
+    (a1.NumOutStreams == a2.NumOutStreams);
+}
+
+static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
+{
+  return (a1.InIndex == a2.InIndex) &&
+    (a1.OutIndex == a2.OutIndex);
+}
+
+static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
+{
+  if (a1.Coders.Size() != a2.Coders.Size())
+    return false;
+  int i;
+  for (i = 0; i < a1.Coders.Size(); i++)
+    if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
+      return false;
+  if (a1.BindPairs.Size() != a2.BindPairs.Size())
+    return false;
+  for (i = 0; i < a1.BindPairs.Size(); i++)
+    if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
+      return false;
+  for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
+    if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
+      return false;
+  if (a1.InStreams.Size() != a2.InStreams.Size())
+    return false;
+  if (a1.OutStreams.Size() != a2.OutStreams.Size())
+    return false;
+  return true;
+}
+
+CDecoder::CDecoder(bool multiThread)
+{
+  #ifndef _ST_MODE
+  multiThread = true;
+  #endif
+  _multiThread = multiThread;
+  _bindInfoExPrevIsDefined = false;
+}
+
+HRESULT CDecoder::Decode(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    IInStream *inStream,
+    UInt64 startPos,
+    const UInt64 *packSizes,
+    const CFolder &folderInfo, 
+    ISequentialOutStream *outStream,
+    ICompressProgressInfo *compressProgress
+    #ifndef _NO_CRYPTO
+    , ICryptoGetTextPassword *getTextPassword
+    #endif
+    #ifdef COMPRESS_MT
+    , bool mtMode, UInt32 numThreads
+    #endif
+    )
+{
+  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
+  
+  CLockedInStream lockedInStream;
+  lockedInStream.Init(inStream);
+  
+  for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
+  {
+    CLockedSequentialInStreamImp *lockedStreamImpSpec = new 
+        CLockedSequentialInStreamImp;
+    CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
+    lockedStreamImpSpec->Init(&lockedInStream, startPos);
+    startPos += packSizes[j];
+    
+    CLimitedSequentialInStream *streamSpec = new 
+        CLimitedSequentialInStream;
+    CMyComPtr<ISequentialInStream> inStream = streamSpec;
+    streamSpec->SetStream(lockedStreamImp);
+    streamSpec->Init(packSizes[j]);
+    inStreams.Add(inStream);
+  }
+  
+  int numCoders = folderInfo.Coders.Size();
+  
+  CBindInfoEx bindInfo;
+  ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
+  bool createNewCoders;
+  if (!_bindInfoExPrevIsDefined)
+    createNewCoders = true;
+  else
+    createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
+  if (createNewCoders)
+  {
+    int i;
+    _decoders.Clear();
+    // _decoders2.Clear();
+    
+    _mixerCoder.Release();
+
+    if (_multiThread)
+    {
+      _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
+      _mixerCoder = _mixerCoderMTSpec;
+      _mixerCoderCommon = _mixerCoderMTSpec;
+    }
+    else
+    {
+      #ifdef _ST_MODE
+      _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
+      _mixerCoder = _mixerCoderSTSpec;
+      _mixerCoderCommon = _mixerCoderSTSpec;
+      #endif
+    }
+    RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
+    
+    for (i = 0; i < numCoders; i++)
+    {
+      const CCoderInfo &coderInfo = folderInfo.Coders[i];
+
+  
+      CMyComPtr<ICompressCoder> decoder;
+      CMyComPtr<ICompressCoder2> decoder2;
+      RINOK(CreateCoder(
+          EXTERNAL_CODECS_LOC_VARS
+          coderInfo.MethodID, decoder, decoder2, false));
+      CMyComPtr<IUnknown> decoderUnknown;
+      if (coderInfo.IsSimpleCoder())
+      {
+        if (decoder == 0)
+          return E_NOTIMPL;
+
+        decoderUnknown = (IUnknown *)decoder;
+        
+        if (_multiThread)
+          _mixerCoderMTSpec->AddCoder(decoder);
+        #ifdef _ST_MODE
+        else
+          _mixerCoderSTSpec->AddCoder(decoder, false);
+        #endif
+      }
+      else
+      {
+        if (decoder2 == 0)
+          return E_NOTIMPL;
+        decoderUnknown = (IUnknown *)decoder2;
+        if (_multiThread)
+          _mixerCoderMTSpec->AddCoder2(decoder2);
+        #ifdef _ST_MODE
+        else
+          _mixerCoderSTSpec->AddCoder2(decoder2, false);
+        #endif
+      }
+      _decoders.Add(decoderUnknown);
+      #ifdef EXTERNAL_CODECS
+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
+      decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+      if (setCompressCodecsInfo)
+      {
+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
+      }
+      #endif
+    }
+    _bindInfoExPrev = bindInfo;
+    _bindInfoExPrevIsDefined = true;
+  }
+  int i;
+  _mixerCoderCommon->ReInit();
+  
+  UInt32 packStreamIndex = 0, unPackStreamIndex = 0;
+  UInt32 coderIndex = 0;
+  // UInt32 coder2Index = 0;
+  
+  for (i = 0; i < numCoders; i++)
+  {
+    const CCoderInfo &coderInfo = folderInfo.Coders[i];
+    CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
+    
+    {
+      CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
+      decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+      if (setDecoderProperties)
+      {
+        const CByteBuffer &properties = coderInfo.Properties;
+        size_t size = properties.GetCapacity();
+        if (size > 0xFFFFFFFF)
+          return E_NOTIMPL;
+        if (size > 0)
+        {
+          RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size));
+        }
+      }
+    }
+
+    #ifdef COMPRESS_MT
+    if (mtMode)
+    {
+      CMyComPtr<ICompressSetCoderMt> setCoderMt;
+      decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+      if (setCoderMt)
+      {
+        RINOK(setCoderMt->SetNumberOfThreads(numThreads));
+      }
+    }
+    #endif
+
+    #ifndef _NO_CRYPTO
+    {
+      CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+      decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+      if (cryptoSetPassword)
+      {
+        if (getTextPassword == 0)
+          return E_FAIL;
+        CMyComBSTR password;
+        RINOK(getTextPassword->CryptoGetTextPassword(&password));
+        CByteBuffer buffer;
+        UString unicodePassword(password);
+        const UInt32 sizeInBytes = unicodePassword.Length() * 2;
+        buffer.SetCapacity(sizeInBytes);
+        for (int i = 0; i < unicodePassword.Length(); i++)
+        {
+          wchar_t c = unicodePassword[i];
+          ((Byte *)buffer)[i * 2] = (Byte)c;
+          ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+        }
+        RINOK(cryptoSetPassword->CryptoSetPassword(
+          (const Byte *)buffer, sizeInBytes));
+      }
+    }
+    #endif
+
+    coderIndex++;
+    
+    UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
+    UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
+    CRecordVector<const UInt64 *> packSizesPointers;
+    CRecordVector<const UInt64 *> unPackSizesPointers;
+    packSizesPointers.Reserve(numInStreams);
+    unPackSizesPointers.Reserve(numOutStreams);
+    UInt32 j;
+    for (j = 0; j < numOutStreams; j++, unPackStreamIndex++)
+      unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]);
+    
+    for (j = 0; j < numInStreams; j++, packStreamIndex++)
+    {
+      int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
+      if (bindPairIndex >= 0)
+        packSizesPointers.Add(
+        &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
+      else
+      {
+        int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
+        if (index < 0)
+          return E_FAIL;
+        packSizesPointers.Add(&packSizes[index]);
+      }
+    }
+    
+    _mixerCoderCommon->SetCoderInfo(i, 
+        &packSizesPointers.Front(), 
+        &unPackSizesPointers.Front());
+  }
+  UInt32 mainCoder, temp;
+  bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
+
+  if (_multiThread)
+    _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
+  /*
+  else
+    _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
+  */
+  
+  if (numCoders == 0)
+    return 0;
+  CRecordVector<ISequentialInStream *> inStreamPointers;
+  inStreamPointers.Reserve(inStreams.Size());
+  for (i = 0; i < inStreams.Size(); i++)
+    inStreamPointers.Add(inStreams[i]);
+  ISequentialOutStream *outStreamPointer = outStream;
+  return _mixerCoder->Code(&inStreamPointers.Front(), NULL, 
+    inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zDecode.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zDecode.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zDecode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,68 @@
+// 7zDecode.h
+
+#ifndef __7Z_DECODE_H
+#define __7Z_DECODE_H
+
+#include "../../IStream.h"
+#include "../../IPassword.h"
+
+#include "../Common/CoderMixer2.h"
+#include "../Common/CoderMixer2MT.h"
+#ifdef _ST_MODE
+#include "../Common/CoderMixer2ST.h"
+#endif
+
+#include "../../Common/CreateCoder.h"
+
+#include "7zItem.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CBindInfoEx: public NCoderMixer::CBindInfo
+{
+  CRecordVector<CMethodId> CoderMethodIDs;
+  void Clear()
+  {
+    CBindInfo::Clear();
+    CoderMethodIDs.Clear();
+  }
+};
+
+class CDecoder
+{
+  bool _bindInfoExPrevIsDefined;
+  CBindInfoEx _bindInfoExPrev;
+  
+  bool _multiThread;
+  #ifdef _ST_MODE
+  NCoderMixer::CCoderMixer2ST *_mixerCoderSTSpec;
+  #endif
+  NCoderMixer::CCoderMixer2MT *_mixerCoderMTSpec;
+  NCoderMixer::CCoderMixer2 *_mixerCoderCommon;
+  
+  CMyComPtr<ICompressCoder2> _mixerCoder;
+  CObjectVector<CMyComPtr<IUnknown> > _decoders;
+  // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;
+public:
+  CDecoder(bool multiThread);
+  HRESULT Decode(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      IInStream *inStream,
+      UInt64 startPos,
+      const UInt64 *packSizes,
+      const CFolder &folder, 
+      ISequentialOutStream *outStream,
+      ICompressProgressInfo *compressProgress
+      #ifndef _NO_CRYPTO
+      , ICryptoGetTextPassword *getTextPasswordSpec
+      #endif
+      #ifdef COMPRESS_MT
+      , bool mtMode, UInt32 numThreads
+      #endif
+      );
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zEncode.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zEncode.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zEncode.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,453 @@
+// Encode.cpp
+
+#include "StdAfx.h"
+
+#include "7zEncode.h"
+#include "7zSpecStream.h"
+
+#include "../../IPassword.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/InOutTempBuffer.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/CreateCoder.h"
+#include "../../Common/FilterCoder.h"
+
+static const UInt64 k_AES = 0x06F10701;
+static const UInt64 k_BCJ  = 0x03030103;
+static const UInt64 k_BCJ2 = 0x0303011B;
+
+namespace NArchive {
+namespace N7z {
+
+static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,
+    const CRecordVector<CMethodId> decompressionMethods,
+    CFolder &folder)
+{
+  folder.Coders.Clear();
+  // bindInfo.CoderMethodIDs.Clear();
+  // folder.OutStreams.Clear();
+  folder.PackStreams.Clear();
+  folder.BindPairs.Clear();
+  int i;
+  for (i = 0; i < bindInfo.BindPairs.Size(); i++)
+  {
+    CBindPair bindPair;
+    bindPair.InIndex = bindInfo.BindPairs[i].InIndex;
+    bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;
+    folder.BindPairs.Add(bindPair);
+  }
+  for (i = 0; i < bindInfo.Coders.Size(); i++)
+  {
+    CCoderInfo coderInfo;
+    const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
+    coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
+    coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
+    coderInfo.MethodID = decompressionMethods[i];
+    folder.Coders.Add(coderInfo);
+  }
+  for (i = 0; i < bindInfo.InStreams.Size(); i++)
+    folder.PackStreams.Add(bindInfo.InStreams[i]);
+}
+
+HRESULT CEncoder::CreateMixerCoder(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    const UInt64 *inSizeForReduce)
+{
+  _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
+  _mixerCoder = _mixerCoderSpec;
+  RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
+  for (int i = 0; i < _options.Methods.Size(); i++)
+  {
+    const CMethodFull &methodFull = _options.Methods[i];
+    _codersInfo.Add(CCoderInfo());
+    CCoderInfo &encodingInfo = _codersInfo.Back();
+    encodingInfo.MethodID = methodFull.Id;
+    CMyComPtr<ICompressCoder> encoder;
+    CMyComPtr<ICompressCoder2> encoder2;
+    
+
+    RINOK(CreateCoder(
+        EXTERNAL_CODECS_LOC_VARS
+        methodFull.Id, encoder, encoder2, true));
+
+    if (!encoder && !encoder2)
+      return E_FAIL;
+
+    CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;
+   
+    #ifdef COMPRESS_MT
+    {
+      CMyComPtr<ICompressSetCoderMt> setCoderMt;
+      encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+      if (setCoderMt)
+      {
+        RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));
+      }
+    }
+    #endif
+        
+
+    RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));
+
+    /*
+    CMyComPtr<ICryptoResetSalt> resetSalt;
+    encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
+    if (resetSalt != NULL)
+    {
+      resetSalt->ResetSalt();
+    }
+    */
+
+    #ifdef EXTERNAL_CODECS
+    CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
+    encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+    if (setCompressCodecsInfo)
+    {
+      RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
+    }
+    #endif
+    
+    CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+    encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+
+    if (cryptoSetPassword)
+    {
+      CByteBuffer buffer;
+      const UInt32 sizeInBytes = _options.Password.Length() * 2;
+      buffer.SetCapacity(sizeInBytes);
+      for (int i = 0; i < _options.Password.Length(); i++)
+      {
+        wchar_t c = _options.Password[i];
+        ((Byte *)buffer)[i * 2] = (Byte)c;
+        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+      }
+      RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
+    }
+
+    if (encoder)
+      _mixerCoderSpec->AddCoder(encoder);
+    else
+      _mixerCoderSpec->AddCoder2(encoder2);
+  }
+  return S_OK;
+}
+
+HRESULT CEncoder::Encode(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    ISequentialInStream *inStream,
+    const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+    CFolder &folderItem,
+    ISequentialOutStream *outStream,
+    CRecordVector<UInt64> &packSizes,
+    ICompressProgressInfo *compressProgress)
+{
+  RINOK(EncoderConstr());
+
+  if (_mixerCoderSpec == NULL)
+  {
+    RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
+  }
+  _mixerCoderSpec->ReInit();
+  // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
+
+  CObjectVector<CInOutTempBuffer> inOutTempBuffers;
+  CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
+  CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
+  int numMethods = _bindInfo.Coders.Size();
+  int i;
+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+  {
+    inOutTempBuffers.Add(CInOutTempBuffer());
+    inOutTempBuffers.Back().Create();
+    inOutTempBuffers.Back().InitWriting();
+  }
+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+  {
+    CSequentialOutTempBufferImp *tempBufferSpec = 
+        new CSequentialOutTempBufferImp;
+    CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
+    tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
+    tempBuffers.Add(tempBuffer);
+    tempBufferSpecs.Add(tempBufferSpec);
+  }
+
+  for (i = 0; i < numMethods; i++)
+    _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
+
+  if (_bindInfo.InStreams.IsEmpty())
+    return E_FAIL;
+  UInt32 mainCoderIndex, mainStreamIndex;
+  _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
+  
+  if (inStreamSize != NULL)
+  {
+    CRecordVector<const UInt64 *> sizePointers;
+    for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
+      if (i == mainStreamIndex)
+        sizePointers.Add(inStreamSize);
+      else
+        sizePointers.Add(NULL);
+    _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
+  }
+
+  
+  // UInt64 outStreamStartPos;
+  // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
+  
+  CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = 
+      new CSequentialInStreamSizeCount2;
+  CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
+  CSequentialOutStreamSizeCount *outStreamSizeCountSpec = 
+      new CSequentialOutStreamSizeCount;
+  CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
+
+  inStreamSizeCountSpec->Init(inStream);
+  outStreamSizeCountSpec->SetStream(outStream);
+  outStreamSizeCountSpec->Init();
+
+  CRecordVector<ISequentialInStream *> inStreamPointers;
+  CRecordVector<ISequentialOutStream *> outStreamPointers;
+  inStreamPointers.Add(inStreamSizeCount);
+  outStreamPointers.Add(outStreamSizeCount);
+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+    outStreamPointers.Add(tempBuffers[i - 1]);
+
+  for (i = 0; i < _codersInfo.Size(); i++)
+  {
+    CCoderInfo &encodingInfo = _codersInfo[i];
+    
+    CMyComPtr<ICryptoResetInitVector> resetInitVector;
+    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
+    if (resetInitVector != NULL)
+    {
+      resetInitVector->ResetInitVector();
+    }
+
+    CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
+    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+    if (writeCoderProperties != NULL)
+    {
+      CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
+      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+      outStreamSpec->Init();
+      writeCoderProperties->WriteCoderProperties(outStream);
+      size_t size = outStreamSpec->GetSize();
+      encodingInfo.Properties.SetCapacity(size);
+      memmove(encodingInfo.Properties, outStreamSpec->GetBuffer(), size);
+    }
+  }
+
+  UInt32 progressIndex = mainCoderIndex;
+
+  for (i = 0; i < _codersInfo.Size(); i++)
+  {
+    const CCoderInfo &e = _codersInfo[i];
+    if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size())
+      progressIndex = i + 1;
+  }
+
+  _mixerCoderSpec->SetProgressCoderIndex(progressIndex);
+  
+  RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
+    &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
+  
+  ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods,
+      folderItem);
+  
+  packSizes.Add(outStreamSizeCountSpec->GetSize());
+  
+  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+  {
+    CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
+    inOutTempBuffer.FlushWrite();
+    inOutTempBuffer.InitReading();
+    inOutTempBuffer.WriteToStream(outStream);
+    packSizes.Add(inOutTempBuffer.GetDataSize());
+  }
+  
+  for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
+  {
+    int binder = _bindInfo.FindBinderForInStream(
+        _bindReverseConverter->DestOutToSrcInMap[i]);
+    UInt64 streamSize;
+    if (binder < 0)
+      streamSize = inStreamSizeCountSpec->GetSize();
+    else
+      streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
+    folderItem.UnPackSizes.Add(streamSize);
+  }
+  for (i = numMethods - 1; i >= 0; i--)
+    folderItem.Coders[numMethods - 1 - i].Properties = _codersInfo[i].Properties;
+  return S_OK;
+}
+
+
+CEncoder::CEncoder(const CCompressionMethodMode &options):
+  _bindReverseConverter(0),
+  _constructed(false)
+{
+  if (options.IsEmpty())
+    throw 1;
+
+  _options = options;
+  _mixerCoderSpec = NULL;
+}
+
+HRESULT CEncoder::EncoderConstr()
+{
+  if (_constructed)
+    return S_OK;
+  if (_options.Methods.IsEmpty())
+  {
+    // it has only password method;
+    if (!_options.PasswordIsDefined)
+      throw 1;
+    if (!_options.Binds.IsEmpty())
+      throw 1;
+    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+    CMethodFull method;
+    
+    method.NumInStreams = 1;
+    method.NumOutStreams = 1;
+    coderStreamsInfo.NumInStreams = 1;
+    coderStreamsInfo.NumOutStreams = 1;
+    method.Id = k_AES;
+    
+    _options.Methods.Add(method);
+    _bindInfo.Coders.Add(coderStreamsInfo);
+  
+    _bindInfo.InStreams.Add(0);
+    _bindInfo.OutStreams.Add(0);
+  }
+  else
+  {
+
+  UInt32 numInStreams = 0, numOutStreams = 0;
+  int i;
+  for (i = 0; i < _options.Methods.Size(); i++)
+  {
+    const CMethodFull &methodFull = _options.Methods[i];
+    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+    coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
+    coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
+    if (_options.Binds.IsEmpty())
+    {
+      if (i < _options.Methods.Size() - 1)
+      {
+        NCoderMixer::CBindPair bindPair;
+        bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
+        bindPair.OutIndex = numOutStreams;
+        _bindInfo.BindPairs.Add(bindPair);
+      }
+      else
+        _bindInfo.OutStreams.Insert(0, numOutStreams);
+      for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
+        _bindInfo.OutStreams.Add(numOutStreams + j);
+    }
+    
+    numInStreams += coderStreamsInfo.NumInStreams;
+    numOutStreams += coderStreamsInfo.NumOutStreams;
+
+    _bindInfo.Coders.Add(coderStreamsInfo);
+  }
+
+  if (!_options.Binds.IsEmpty())
+  {
+    for (i = 0; i < _options.Binds.Size(); i++)
+    {
+      NCoderMixer::CBindPair bindPair;
+      const CBind &bind = _options.Binds[i];
+      bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
+      bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
+      _bindInfo.BindPairs.Add(bindPair);
+    }
+    for (i = 0; i < (int)numOutStreams; i++)
+      if (_bindInfo.FindBinderForOutStream(i) == -1)
+        _bindInfo.OutStreams.Add(i);
+  }
+
+  for (i = 0; i < (int)numInStreams; i++)
+    if (_bindInfo.FindBinderForInStream(i) == -1)
+      _bindInfo.InStreams.Add(i);
+
+  if (_bindInfo.InStreams.IsEmpty())
+    throw 1; // this is error
+
+  // Make main stream first in list
+  int inIndex = _bindInfo.InStreams[0];
+  for (;;)
+  {
+    UInt32 coderIndex, coderStreamIndex;
+    _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
+    UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
+    int binder = _bindInfo.FindBinderForOutStream(outIndex);
+    if (binder >= 0)
+    {
+      inIndex = _bindInfo.BindPairs[binder].InIndex;
+      continue;
+    }
+    for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
+      if (_bindInfo.OutStreams[i] == outIndex)
+      {
+        _bindInfo.OutStreams.Delete(i);
+        _bindInfo.OutStreams.Insert(0, outIndex);
+        break;
+      }
+    break;
+  }
+
+  if (_options.PasswordIsDefined)
+  {
+    int numCryptoStreams = _bindInfo.OutStreams.Size();
+
+    for (i = 0; i < numCryptoStreams; i++)
+    {
+      NCoderMixer::CBindPair bindPair;
+      bindPair.InIndex = numInStreams + i;
+      bindPair.OutIndex = _bindInfo.OutStreams[i];
+      _bindInfo.BindPairs.Add(bindPair);
+    }
+    _bindInfo.OutStreams.Clear();
+
+    /*
+    if (numCryptoStreams == 0)
+      numCryptoStreams = 1;
+    */
+
+    for (i = 0; i < numCryptoStreams; i++)
+    {
+      NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
+      CMethodFull method;
+      method.NumInStreams = 1;
+      method.NumOutStreams = 1;
+      coderStreamsInfo.NumInStreams = method.NumOutStreams;
+      coderStreamsInfo.NumOutStreams = method.NumInStreams;
+      method.Id = k_AES;
+
+      _options.Methods.Add(method);
+      _bindInfo.Coders.Add(coderStreamsInfo);
+      _bindInfo.OutStreams.Add(numOutStreams + i);
+    }
+  }
+
+  }
+
+  for (int i = _options.Methods.Size() - 1; i >= 0; i--)
+  {
+    const CMethodFull &methodFull = _options.Methods[i];
+    _decompressionMethods.Add(methodFull.Id);
+  }
+
+  _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);
+  _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
+  _constructed = true;
+  return S_OK;
+}
+
+CEncoder::~CEncoder()
+{
+  delete _bindReverseConverter;
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zEncode.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zEncode.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zEncode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,55 @@
+// 7zEncode.h
+
+#ifndef __7Z_ENCODE_H
+#define __7Z_ENCODE_H
+
+// #include "../../Common/StreamObjects.h"
+
+#include "7zCompressionMode.h"
+
+#include "../Common/CoderMixer2.h"
+#include "../Common/CoderMixer2MT.h"
+#ifdef _ST_MODE
+#include "../Common/CoderMixer2ST.h"
+#endif
+#include "7zItem.h"
+
+#include "../../Common/CreateCoder.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CEncoder
+{
+  NCoderMixer::CCoderMixer2MT *_mixerCoderSpec;
+  CMyComPtr<ICompressCoder2> _mixerCoder;
+
+  CObjectVector<CCoderInfo> _codersInfo;
+
+  CCompressionMethodMode _options;
+  NCoderMixer::CBindInfo _bindInfo;
+  NCoderMixer::CBindInfo _decompressBindInfo;
+  NCoderMixer::CBindReverseConverter *_bindReverseConverter;
+  CRecordVector<CMethodId> _decompressionMethods;
+
+  HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS
+      const UInt64 *inSizeForReduce);
+
+  bool _constructed;
+public:
+  CEncoder(const CCompressionMethodMode &options);
+  ~CEncoder();
+  HRESULT EncoderConstr();
+  HRESULT Encode(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      ISequentialInStream *inStream,
+      const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+      CFolder &folderItem,
+      ISequentialOutStream *outStream,
+      CRecordVector<UInt64> &packSizes,
+      ICompressProgressInfo *compressProgress);
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zExtract.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zExtract.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zExtract.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,269 @@
+// 7zExtract.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zFolderOutStream.h"
+#include "7zDecode.h"
+// #include "7z1Decode.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CExtractFolderInfo
+{
+  #ifdef _7Z_VOL
+  int VolumeIndex;
+  #endif
+  CNum FileIndex;
+  CNum FolderIndex;
+  CBoolVector ExtractStatuses;
+  UInt64 UnPackSize;
+  CExtractFolderInfo(
+    #ifdef _7Z_VOL
+    int volumeIndex, 
+    #endif
+    CNum fileIndex, CNum folderIndex): 
+    #ifdef _7Z_VOL
+    VolumeIndex(volumeIndex),
+    #endif
+    FileIndex(fileIndex),
+    FolderIndex(folderIndex), 
+    UnPackSize(0) 
+  {
+    if (fileIndex != kNumNoIndex)
+    {
+      ExtractStatuses.Reserve(1);
+      ExtractStatuses.Add(true);
+    }
+  };
+};
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+    Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
+{
+  COM_TRY_BEGIN
+  bool testMode = (testModeSpec != 0);
+  CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+  UInt64 importantTotalUnPacked = 0;
+
+  bool allFilesMode = (numItems == UInt32(-1));
+  if (allFilesMode)
+    numItems = 
+    #ifdef _7Z_VOL
+    _refs.Size();
+    #else
+    _database.Files.Size();
+    #endif
+
+  if(numItems == 0)
+    return S_OK;
+
+  /*
+  if(_volumes.Size() != 1)
+    return E_FAIL;
+  const CVolume &volume = _volumes.Front();
+  const CArchiveDatabaseEx &_database = volume.Database;
+  IInStream *_inStream = volume.Stream;
+  */
+  
+  CObjectVector<CExtractFolderInfo> extractFolderInfoVector;
+  for(UInt32 ii = 0; ii < numItems; ii++)
+  {
+    // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];
+    UInt32 ref2Index = allFilesMode ? ii : indices[ii];
+    // const CRef2 &ref2 = _refs[ref2Index];
+
+    // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
+    {
+      #ifdef _7Z_VOL
+      // const CRef &ref = ref2.Refs[ri];
+      const CRef &ref = _refs[ref2Index];
+
+      int volumeIndex = ref.VolumeIndex;
+      const CVolume &volume = _volumes[volumeIndex];
+      const CArchiveDatabaseEx &database = volume.Database;
+      UInt32 fileIndex = ref.ItemIndex;
+      #else
+      const CArchiveDatabaseEx &database = _database;
+      UInt32 fileIndex = ref2Index;
+      #endif
+
+      CNum folderIndex = database.FileIndexToFolderIndexMap[fileIndex];
+      if (folderIndex == kNumNoIndex)
+      {
+        extractFolderInfoVector.Add(CExtractFolderInfo(
+            #ifdef _7Z_VOL
+            volumeIndex, 
+            #endif
+            fileIndex, kNumNoIndex));
+        continue;
+      }
+      if (extractFolderInfoVector.IsEmpty() || 
+        folderIndex != extractFolderInfoVector.Back().FolderIndex 
+        #ifdef _7Z_VOL
+        || volumeIndex != extractFolderInfoVector.Back().VolumeIndex
+        #endif
+        )
+      {
+        extractFolderInfoVector.Add(CExtractFolderInfo(
+            #ifdef _7Z_VOL
+            volumeIndex, 
+            #endif
+            kNumNoIndex, folderIndex));
+        const CFolder &folderInfo = database.Folders[folderIndex];
+        UInt64 unPackSize = folderInfo.GetUnPackSize();
+        importantTotalUnPacked += unPackSize;
+        extractFolderInfoVector.Back().UnPackSize = unPackSize;
+      }
+      
+      CExtractFolderInfo &efi = extractFolderInfoVector.Back();
+      
+      // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
+      CNum startIndex = database.FolderStartFileIndex[folderIndex];
+      for (CNum index = efi.ExtractStatuses.Size();
+          index <= fileIndex - startIndex; index++)
+      {
+        // UInt64 unPackSize = _database.Files[startIndex + index].UnPackSize;
+        // Count partial_folder_size
+        // efi.UnPackSize += unPackSize;
+        // importantTotalUnPacked += unPackSize;
+        efi.ExtractStatuses.Add(index == fileIndex - startIndex);
+      }
+    }
+  }
+
+  extractCallback->SetTotal(importantTotalUnPacked);
+
+  CDecoder decoder(
+    #ifdef _ST_MODE
+    false
+    #else
+    true
+    #endif
+    );
+  // CDecoder1 decoder;
+
+  UInt64 currentTotalPacked = 0;
+  UInt64 currentTotalUnPacked = 0;
+  UInt64 totalFolderUnPacked;
+  UInt64 totalFolderPacked;
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(extractCallback, false);
+
+  for(int i = 0; i < extractFolderInfoVector.Size(); i++, 
+      currentTotalUnPacked += totalFolderUnPacked,
+      currentTotalPacked += totalFolderPacked)
+  {
+    lps->OutSize = currentTotalUnPacked;
+    lps->InSize = currentTotalPacked;
+    RINOK(lps->SetCur());
+    
+    const CExtractFolderInfo &efi = extractFolderInfoVector[i];
+    totalFolderUnPacked = efi.UnPackSize;
+
+    totalFolderPacked = 0;
+
+    CFolderOutStream *folderOutStream = new CFolderOutStream;
+    CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
+
+    #ifdef _7Z_VOL
+    const CVolume &volume = _volumes[efi.VolumeIndex];
+    const CArchiveDatabaseEx &database = volume.Database;
+    #else
+    const CArchiveDatabaseEx &database = _database;
+    #endif
+
+    CNum startIndex;
+    if (efi.FileIndex != kNumNoIndex)
+      startIndex = efi.FileIndex;
+    else
+      startIndex = database.FolderStartFileIndex[efi.FolderIndex];
+
+
+    HRESULT result = folderOutStream->Init(&database, 
+        #ifdef _7Z_VOL
+        volume.StartRef2Index, 
+        #else
+        0,
+        #endif
+        startIndex, 
+        &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0);
+
+    RINOK(result);
+
+    if (efi.FileIndex != kNumNoIndex)
+      continue;
+
+    CNum folderIndex = efi.FolderIndex;
+    const CFolder &folderInfo = database.Folders[folderIndex];
+
+    totalFolderPacked = _database.GetFolderFullPackSize(folderIndex);
+
+    CNum packStreamIndex = database.FolderStartPackStreamIndex[folderIndex];
+    UInt64 folderStartPackPos = database.GetFolderStreamPos(folderIndex, 0);
+
+    #ifndef _NO_CRYPTO
+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+    if (extractCallback)
+      extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+    #endif
+
+    try
+    {
+      HRESULT result = decoder.Decode(
+          EXTERNAL_CODECS_VARS
+          #ifdef _7Z_VOL
+          volume.Stream,
+          #else
+          _inStream,
+          #endif
+          folderStartPackPos, 
+          &database.PackSizes[packStreamIndex],
+          folderInfo,
+          outStream,
+          progress
+          #ifndef _NO_CRYPTO
+          , getTextPassword
+          #endif
+          #ifdef COMPRESS_MT
+          , true, _numThreads
+          #endif
+          );
+
+      if (result == S_FALSE)
+      {
+        RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
+        continue;
+      }
+      if (result == E_NOTIMPL)
+      {
+        RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+        continue;
+      }
+      if (result != S_OK)
+        return result;
+      if (folderOutStream->WasWritingFinished() != S_OK)
+      {
+        RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
+        continue;
+      }
+    }
+    catch(...)
+    {
+      RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
+      continue;
+    }
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zFolderInStream.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,130 @@
+// 7zFolderInStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zFolderInStream.h"
+
+namespace NArchive {
+namespace N7z {
+
+CFolderInStream::CFolderInStream()
+{
+  _inStreamWithHashSpec = new CSequentialInStreamWithCRC;
+  _inStreamWithHash = _inStreamWithHashSpec;
+}
+
+void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, 
+    const UInt32 *fileIndices, UInt32 numFiles)
+{
+  _updateCallback = updateCallback;
+  _numFiles = numFiles;
+  _fileIndex = 0;
+  _fileIndices = fileIndices;
+  Processed.Clear();
+  CRCs.Clear();
+  Sizes.Clear();
+  _fileIsOpen = false;
+  _currentSizeIsDefined = false;
+}
+
+HRESULT CFolderInStream::OpenStream()
+{
+  _filePos = 0;
+  while (_fileIndex < _numFiles)
+  {
+    _currentSizeIsDefined = false;
+    CMyComPtr<ISequentialInStream> stream;
+    HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
+    if (result != S_OK && result != S_FALSE)
+      return result;
+    _fileIndex++;
+    _inStreamWithHashSpec->SetStream(stream);
+    _inStreamWithHashSpec->Init();
+    if (!stream)
+    {
+      RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+      Sizes.Add(0);
+      Processed.Add(result == S_OK);
+      AddDigest();
+      continue;
+    }
+    CMyComPtr<IStreamGetSize> streamGetSize;
+    if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK)
+    {
+      if(streamGetSize)
+      {
+        _currentSizeIsDefined = true;
+        RINOK(streamGetSize->GetSize(&_currentSize));
+      }
+    }
+
+    _fileIsOpen = true;
+    return S_OK;
+  }
+  return S_OK;
+}
+
+void CFolderInStream::AddDigest()
+{
+  CRCs.Add(_inStreamWithHashSpec->GetCRC());
+}
+
+HRESULT CFolderInStream::CloseStream()
+{
+  RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+  _inStreamWithHashSpec->ReleaseStream();
+  _fileIsOpen = false;
+  Processed.Add(true);
+  Sizes.Add(_filePos);
+  AddDigest();
+  return S_OK;
+}
+
+STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize = 0;
+  while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0)
+  {
+    if (_fileIsOpen)
+    {
+      UInt32 localProcessedSize;
+      RINOK(_inStreamWithHash->Read(
+          ((Byte *)data) + realProcessedSize, size, &localProcessedSize));
+      if (localProcessedSize == 0)
+      {
+        RINOK(CloseStream());
+        continue;
+      }
+      realProcessedSize += localProcessedSize;
+      _filePos += localProcessedSize;
+      size -= localProcessedSize;
+      break;
+    }
+    else
+    {
+      RINOK(OpenStream());
+    }
+  }
+  if (processedSize != 0)
+    *processedSize = realProcessedSize;
+  return S_OK;
+}
+
+STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
+{
+  *value = 0;
+  int subStreamIndex = (int)subStream;
+  if (subStreamIndex < 0 || subStream > Sizes.Size())
+    return E_FAIL;
+  if (subStreamIndex < Sizes.Size())
+  {
+    *value= Sizes[subStreamIndex];
+    return S_OK;
+  }
+  if (!_currentSizeIsDefined)
+    return S_FALSE;
+  *value = _currentSize;
+  return S_OK;
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zFolderInStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,66 @@
+// 7z/FolderInStream.h
+
+#ifndef __7Z_FOLDERINSTREAM_H
+#define __7Z_FOLDERINSTREAM_H
+
+#include "7zItem.h"
+#include "7zHeader.h"
+
+#include "../IArchive.h"
+#include "../Common/InStreamWithCRC.h"
+#include "../../IStream.h"
+#include "../../ICoder.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CFolderInStream: 
+  public ISequentialInStream,
+  public ICompressGetSubStreamSize,
+  public CMyUnknownImp
+{
+public:
+
+  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+
+  CFolderInStream();
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+private:
+  CSequentialInStreamWithCRC *_inStreamWithHashSpec;
+  CMyComPtr<ISequentialInStream> _inStreamWithHash;
+  CMyComPtr<IArchiveUpdateCallback> _updateCallback;
+
+  bool _currentSizeIsDefined;
+  UInt64 _currentSize;
+
+  bool _fileIsOpen;
+  UInt64 _filePos;
+
+  const UInt32 *_fileIndices;
+  UInt32 _numFiles;
+  UInt32 _fileIndex;
+
+  HRESULT OpenStream();
+  HRESULT CloseStream();
+  void AddDigest();
+public:
+  void Init(IArchiveUpdateCallback *updateCallback, 
+      const UInt32 *fileIndices, UInt32 numFiles);
+  CRecordVector<bool> Processed;
+  CRecordVector<UInt32> CRCs;
+  CRecordVector<UInt64> Sizes;
+  UInt64 GetFullSize() const
+  {
+    UInt64 size = 0;
+    for (int i = 0; i < Sizes.Size(); i++)      
+      size += Sizes[i];
+    return size;
+  }
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,165 @@
+// 7zFolderOutStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zFolderOutStream.h"
+
+namespace NArchive {
+namespace N7z {
+
+CFolderOutStream::CFolderOutStream()
+{
+  _outStreamWithHashSpec = new COutStreamWithCRC;
+  _outStreamWithHash = _outStreamWithHashSpec;
+}
+
+HRESULT CFolderOutStream::Init(
+    const CArchiveDatabaseEx *archiveDatabase,
+    UInt32 ref2Offset,
+    UInt32 startIndex,
+    const CBoolVector *extractStatuses, 
+    IArchiveExtractCallback *extractCallback,
+    bool testMode,
+    bool checkCrc)
+{
+  _archiveDatabase = archiveDatabase;
+  _ref2Offset = ref2Offset;
+  _startIndex = startIndex;
+
+  _extractStatuses = extractStatuses;
+  _extractCallback = extractCallback;
+  _testMode = testMode;
+
+  _checkCrc = checkCrc;
+
+  _currentIndex = 0;
+  _fileIsOpen = false;
+  return WriteEmptyFiles();
+}
+
+HRESULT CFolderOutStream::OpenFile()
+{
+  Int32 askMode;
+  if((*_extractStatuses)[_currentIndex])
+    askMode = _testMode ? 
+        NArchive::NExtract::NAskMode::kTest :
+        NArchive::NExtract::NAskMode::kExtract;
+  else
+    askMode = NArchive::NExtract::NAskMode::kSkip;
+  CMyComPtr<ISequentialOutStream> realOutStream;
+
+  UInt32 index = _startIndex + _currentIndex;
+  RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
+
+  _outStreamWithHashSpec->SetStream(realOutStream);
+  _outStreamWithHashSpec->Init(_checkCrc);
+  if (askMode == NArchive::NExtract::NAskMode::kExtract &&
+      (!realOutStream)) 
+  {
+    const CFileItem &fileInfo = _archiveDatabase->Files[index];
+    if (!fileInfo.IsAnti && !fileInfo.IsDirectory)
+      askMode = NArchive::NExtract::NAskMode::kSkip;
+  }
+  return _extractCallback->PrepareOperation(askMode);
+}
+
+HRESULT CFolderOutStream::WriteEmptyFiles()
+{
+  for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
+  {
+    UInt32 index = _startIndex + _currentIndex;
+    const CFileItem &fileInfo = _archiveDatabase->Files[index];
+    if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0)
+      return S_OK;
+    RINOK(OpenFile());
+    RINOK(_extractCallback->SetOperationResult(
+        NArchive::NExtract::NOperationResult::kOK));
+    _outStreamWithHashSpec->ReleaseStream();
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CFolderOutStream::Write(const void *data, 
+    UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize = 0;
+  while(_currentIndex < _extractStatuses->Size())
+  {
+    if (_fileIsOpen)
+    {
+      UInt32 index = _startIndex + _currentIndex;
+      const CFileItem &fileInfo = _archiveDatabase->Files[index];
+      UInt64 fileSize = fileInfo.UnPackSize;
+      
+      UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos, 
+          UInt64(size - realProcessedSize));
+      
+      UInt32 processedSizeLocal;
+      RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, 
+            numBytesToWrite, &processedSizeLocal));
+
+      _filePos += processedSizeLocal;
+      realProcessedSize += processedSizeLocal;
+      if (_filePos == fileSize)
+      {
+        bool digestsAreEqual;
+        if (fileInfo.IsFileCRCDefined && _checkCrc)
+          digestsAreEqual = fileInfo.FileCRC == _outStreamWithHashSpec->GetCRC();
+        else
+          digestsAreEqual = true;
+
+        RINOK(_extractCallback->SetOperationResult(
+            digestsAreEqual ? 
+            NArchive::NExtract::NOperationResult::kOK :
+            NArchive::NExtract::NOperationResult::kCRCError));
+        _outStreamWithHashSpec->ReleaseStream();
+        _fileIsOpen = false;
+        _currentIndex++;
+      }
+      if (realProcessedSize == size)
+      {
+        if (processedSize != NULL)
+          *processedSize = realProcessedSize;
+        return WriteEmptyFiles();
+      }
+    }
+    else
+    {
+      RINOK(OpenFile());
+      _fileIsOpen = true;
+      _filePos = 0;
+    }
+  }
+  if (processedSize != NULL)
+    *processedSize = size;
+  return S_OK;
+}
+
+HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
+{
+  while(_currentIndex < _extractStatuses->Size())
+  {
+    if (_fileIsOpen)
+    {
+      RINOK(_extractCallback->SetOperationResult(resultEOperationResult));
+      _outStreamWithHashSpec->ReleaseStream();
+      _fileIsOpen = false;
+      _currentIndex++;
+    }
+    else
+    {
+      RINOK(OpenFile());
+      _fileIsOpen = true;
+    }
+  }
+  return S_OK;
+}
+
+HRESULT CFolderOutStream::WasWritingFinished()
+{
+  if (_currentIndex == _extractStatuses->Size())
+    return S_OK;
+  return E_FAIL;
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zFolderOutStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,60 @@
+// 7zFolderOutStream.h
+
+#ifndef __7Z_FOLDEROUTSTREAM_H
+#define __7Z_FOLDEROUTSTREAM_H
+
+#include "7zIn.h"
+
+#include "../../IStream.h"
+#include "../IArchive.h"
+#include "../Common/OutStreamWithCRC.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CFolderOutStream: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP
+  
+  CFolderOutStream();
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+private:
+
+  COutStreamWithCRC *_outStreamWithHashSpec;
+  CMyComPtr<ISequentialOutStream> _outStreamWithHash;
+  const CArchiveDatabaseEx *_archiveDatabase;
+  const CBoolVector *_extractStatuses;
+  UInt32 _startIndex;
+  UInt32 _ref2Offset;
+  int _currentIndex;
+  // UInt64 _currentDataPos;
+  CMyComPtr<IArchiveExtractCallback> _extractCallback;
+  bool _testMode;
+
+  bool _fileIsOpen;
+
+  bool _checkCrc;
+  UInt64 _filePos;
+
+  HRESULT OpenFile();
+  HRESULT WriteEmptyFiles();
+public:
+  HRESULT Init(
+      const CArchiveDatabaseEx *archiveDatabase,
+      UInt32 ref2Offset,
+      UInt32 startIndex,
+      const CBoolVector *extractStatuses, 
+      IArchiveExtractCallback *extractCallback,
+      bool testMode,
+      bool checkCrc);
+  HRESULT FlushCorrupted(Int32 resultEOperationResult);
+  HRESULT WasWritingFinished();
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zHandler.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zHandler.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zHandler.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,793 @@
+// 7zHandler.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zProperties.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Windows/Defs.h"
+
+#include "../Common/ItemNameUtils.h"
+#ifdef _7Z_VOL
+#include "../Common/MultiStream.h"
+#endif
+
+#ifdef __7Z_SET_PROPERTIES
+#ifdef EXTRACT_ONLY
+#include "../Common/ParseProperties.h"
+#endif
+#endif
+
+#ifdef COMPRESS_MT
+#include "../../../Windows/System.h"
+#endif
+
+using namespace NWindows;
+
+extern UString ConvertMethodIdToString(UInt64 id);
+
+namespace NArchive {
+namespace N7z {
+
+CHandler::CHandler()
+{
+  _crcSize = 4;
+
+  #ifdef EXTRACT_ONLY
+  #ifdef COMPRESS_MT
+  _numThreads = NWindows::NSystem::GetNumberOfProcessors();
+  #endif
+  #else
+  Init();
+  #endif
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+  *numItems = 
+  #ifdef _7Z_VOL
+  _refs.Size();
+  #else
+  *numItems = _database.Files.Size();
+  #endif
+  return S_OK;
+}
+
+#ifdef _SFX
+
+IMP_IInArchive_ArcProps_NO
+
+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
+{
+  return E_NOTIMPL;
+}
+
+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,     
+      BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
+{
+  return E_NOTIMPL;
+}
+
+
+#else
+
+STATPROPSTG kArcProps[] = 
+{
+  { NULL, kpidMethod, VT_BSTR},
+  { NULL, kpidSolid, VT_BOOL},
+  { NULL, kpidNumBlocks, VT_UI4}
+};
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case kpidMethod:
+    {
+      UString resString;
+      CRecordVector<UInt64> ids;
+      int i;
+      for (i = 0; i < _database.Folders.Size(); i++)
+      {
+        const CFolder &f = _database.Folders[i];
+        for (int j = f.Coders.Size() - 1; j >= 0; j--)
+          ids.AddToUniqueSorted(f.Coders[j].MethodID);
+      }
+
+      for (i = 0; i < ids.Size(); i++)
+      {
+        UInt64 id = ids[i];
+        UString methodName;
+        /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);
+        if (methodName.IsEmpty())
+          methodName = ConvertMethodIdToString(id);
+        if (!resString.IsEmpty())
+          resString += L' ';
+        resString += methodName;
+      }
+      prop = resString; 
+      break;
+    }
+    case kpidSolid: prop = _database.IsSolid(); break;
+    case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+IMP_IInArchive_ArcProps
+
+#endif
+
+static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop)
+{
+  if (timeDefined)
+    prop = unixTime;
+}
+
+#ifndef _SFX
+
+static UString ConvertUInt32ToString(UInt32 value)
+{
+  wchar_t buffer[32];
+  ConvertUInt64ToString(value, buffer);
+  return buffer;
+}
+
+static UString GetStringForSizeValue(UInt32 value)
+{
+  for (int i = 31; i >= 0; i--)
+    if ((UInt32(1) << i) == value)
+      return ConvertUInt32ToString(i);
+  UString result;
+  if (value % (1 << 20) == 0)
+  {
+    result += ConvertUInt32ToString(value >> 20);
+    result += L"m";
+  }
+  else if (value % (1 << 10) == 0)
+  {
+    result += ConvertUInt32ToString(value >> 10);
+    result += L"k";
+  }
+  else
+  {
+    result += ConvertUInt32ToString(value);
+    result += L"b";
+  }
+  return result;
+}
+
+static const UInt64 k_Copy = 0x0;
+static const UInt64 k_LZMA  = 0x030101;
+static const UInt64 k_PPMD  = 0x030401;
+
+static wchar_t GetHex(Byte value)
+{
+  return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
+}
+static inline UString GetHex2(Byte value)
+{
+  UString result;
+  result += GetHex((Byte)(value >> 4));
+  result += GetHex((Byte)(value & 0xF));
+  return result;
+}
+
+#endif
+
+static const UInt64 k_AES  = 0x06F10701;
+
+#ifndef _SFX
+static inline UInt32 GetUInt32FromMemLE(const Byte *p)
+{
+  return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
+}
+#endif
+
+bool CHandler::IsEncrypted(UInt32 index2) const
+{
+  CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+  if (folderIndex != kNumNoIndex)
+  {
+    const CFolder &folderInfo = _database.Folders[folderIndex];
+    for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
+      if (folderInfo.Coders[i].MethodID == k_AES)
+        return true;
+  }
+  return false;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NWindows::NCOM::CPropVariant prop;
+  
+  /*
+  const CRef2 &ref2 = _refs[index];
+  if (ref2.Refs.IsEmpty())
+    return E_FAIL;
+  const CRef &ref = ref2.Refs.Front();
+  */
+  
+  #ifdef _7Z_VOL
+  const CRef &ref = _refs[index];
+  const CVolume &volume = _volumes[ref.VolumeIndex];
+  const CArchiveDatabaseEx &_database = volume.Database;
+  UInt32 index2 = ref.ItemIndex;
+  const CFileItem &item = _database.Files[index2];
+  #else
+  const CFileItem &item = _database.Files[index];
+  UInt32 index2 = index;
+  #endif
+
+  switch(propID)
+  {
+    case kpidPath:
+    {
+      if (!item.Name.IsEmpty())
+        prop = NItemName::GetOSName(item.Name);
+      break;
+    }
+    case kpidIsFolder:
+      prop = item.IsDirectory;
+      break;
+    case kpidSize:
+    {
+      prop = item.UnPackSize;
+      // prop = ref2.UnPackSize;
+      break;
+    }
+    case kpidPosition:
+    {
+      /*
+      if (ref2.Refs.Size() > 1)
+        prop = ref2.StartPos;
+      else
+      */
+        if (item.IsStartPosDefined)
+          prop = item.StartPos;
+      break;
+    }
+    case kpidPackedSize:
+    {
+      // prop = ref2.PackSize;
+      {
+        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+        if (folderIndex != kNumNoIndex)
+        {
+          if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2)
+            prop = _database.GetFolderFullPackSize(folderIndex);
+          /*
+          else
+            prop = (UInt64)0;
+          */
+        }
+        else
+          prop = (UInt64)0;
+      }
+      break;
+    }
+    case kpidLastAccessTime:
+      MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop);
+      break;
+    case kpidCreationTime:
+      MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop);
+      break;
+    case kpidLastWriteTime:
+      MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop);
+      break;
+    case kpidAttributes:
+      if (item.AreAttributesDefined)
+        prop = item.Attributes;
+      break;
+    case kpidCRC:
+      if (item.IsFileCRCDefined)
+        prop = item.FileCRC;
+      break;
+    case kpidEncrypted:
+    {
+      prop = IsEncrypted(index2);
+      break;
+    }
+    #ifndef _SFX
+    case kpidMethod:
+      {
+        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+        if (folderIndex != kNumNoIndex)
+        {
+          const CFolder &folderInfo = _database.Folders[folderIndex];
+          UString methodsString;
+          for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
+          {
+            const CCoderInfo &coderInfo = folderInfo.Coders[i];
+            if (!methodsString.IsEmpty())
+              methodsString += L' ';
+
+            {
+              UString methodName;
+              bool methodIsKnown = FindMethod(
+                  EXTERNAL_CODECS_VARS 
+                  coderInfo.MethodID, methodName);
+
+              if (methodIsKnown)
+              {
+                methodsString += methodName;
+                if (coderInfo.MethodID == k_LZMA)
+                {
+                  if (coderInfo.Properties.GetCapacity() >= 5)
+                  {
+                    methodsString += L":";
+                    UInt32 dicSize = GetUInt32FromMemLE(
+                      ((const Byte *)coderInfo.Properties + 1));
+                    methodsString += GetStringForSizeValue(dicSize);
+                  }
+                }
+                else if (coderInfo.MethodID == k_PPMD)
+                {
+                  if (coderInfo.Properties.GetCapacity() >= 5)
+                  {
+                    Byte order = *(const Byte *)coderInfo.Properties;
+                    methodsString += L":o";
+                    methodsString += ConvertUInt32ToString(order);
+                    methodsString += L":mem";
+                    UInt32 dicSize = GetUInt32FromMemLE(
+                      ((const Byte *)coderInfo.Properties + 1));
+                    methodsString += GetStringForSizeValue(dicSize);
+                  }
+                }
+                else if (coderInfo.MethodID == k_AES)
+                {
+                  if (coderInfo.Properties.GetCapacity() >= 1)
+                  {
+                    methodsString += L":";
+                    const Byte *data = (const Byte *)coderInfo.Properties;
+                    Byte firstByte = *data++;
+                    UInt32 numCyclesPower = firstByte & 0x3F;
+                    methodsString += ConvertUInt32ToString(numCyclesPower);
+                    /*
+                    if ((firstByte & 0xC0) != 0)
+                    {
+                      methodsString += L":";
+                      return S_OK;
+                      UInt32 saltSize = (firstByte >> 7) & 1;
+                      UInt32 ivSize = (firstByte >> 6) & 1;
+                      if (coderInfo.Properties.GetCapacity() >= 2)
+                      {
+                        Byte secondByte = *data++;
+                        saltSize += (secondByte >> 4);
+                        ivSize += (secondByte & 0x0F);
+                      }
+                    }
+                    */
+                  }
+                }
+                else
+                {
+                  if (coderInfo.Properties.GetCapacity() > 0)
+                  {
+                    methodsString += L":[";
+                    for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++)
+                    {
+                      if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity())
+                      {
+                        methodsString += L"..";
+                        break;
+                      }
+                      else
+                        methodsString += GetHex2(coderInfo.Properties[bi]);
+                    }
+                    methodsString += L"]";
+                  }
+                }
+              }
+              else
+              {
+                methodsString += ConvertMethodIdToString(coderInfo.MethodID);
+              }
+            }
+          }
+          prop = methodsString;
+        }
+      }
+      break;
+    case kpidBlock:
+      {
+        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+        if (folderIndex != kNumNoIndex)
+          prop = (UInt32)folderIndex;
+      }
+      break;
+    case kpidPackedSize0:
+    case kpidPackedSize1:
+    case kpidPackedSize2:
+    case kpidPackedSize3:
+    case kpidPackedSize4:
+      {
+        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+        if (folderIndex != kNumNoIndex)
+        {
+          const CFolder &folderInfo = _database.Folders[folderIndex];
+          if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
+              folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
+          {
+            prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
+          }
+          else
+            prop = (UInt64)0;
+        }
+        else
+          prop = (UInt64)0;
+      }
+      break;
+    #endif
+    case kpidIsAnti:
+      prop = item.IsAnti;
+      break;
+  }
+  prop.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+#ifdef _7Z_VOL
+
+static const wchar_t *kExt = L"7z";
+static const wchar_t *kAfterPart = L".7z";
+
+class CVolumeName
+{
+  bool _first;
+  UString _unchangedPart;
+  UString _changedPart;    
+  UString _afterPart;    
+public:
+  bool InitName(const UString &name)
+  {
+    _first = true;
+    int dotPos = name.ReverseFind('.');
+    UString basePart = name;
+    if (dotPos >= 0)
+    {
+      UString ext = name.Mid(dotPos + 1);
+      if (ext.CompareNoCase(kExt)==0 || 
+        ext.CompareNoCase(L"EXE") == 0)
+      {
+        _afterPart = kAfterPart;
+        basePart = name.Left(dotPos);
+      }
+    }
+
+    int numLetters = 1;
+    bool splitStyle = false;
+    if (basePart.Right(numLetters) == L"1")
+    {
+      while (numLetters < basePart.Length())
+      {
+        if (basePart[basePart.Length() - numLetters - 1] != '0')
+          break;
+        numLetters++;
+      }
+    }
+    else 
+      return false;
+    _unchangedPart = basePart.Left(basePart.Length() - numLetters);
+    _changedPart = basePart.Right(numLetters);
+    return true;
+  }
+
+  UString GetNextName()
+  {
+    UString newName; 
+    // if (_newStyle || !_first)
+    {
+      int i;
+      int numLetters = _changedPart.Length();
+      for (i = numLetters - 1; i >= 0; i--)
+      {
+        wchar_t c = _changedPart[i];
+        if (c == L'9')
+        {
+          c = L'0';
+          newName = c + newName;
+          if (i == 0)
+            newName = UString(L'1') + newName;
+          continue;
+        }
+        c++;
+        newName = UString(c) + newName;
+        i--;
+        for (; i >= 0; i--)
+          newName = _changedPart[i] + newName;
+        break;
+      }
+      _changedPart = newName;
+    }
+    _first = false;
+    return _unchangedPart + _changedPart + _afterPart;
+  }
+};
+
+#endif
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+    const UInt64 *maxCheckStartPosition, 
+    IArchiveOpenCallback *openArchiveCallback)
+{
+  COM_TRY_BEGIN
+  Close();
+  #ifndef _SFX
+  _fileInfoPopIDs.Clear();
+  #endif
+  try
+  {
+    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
+    #ifdef _7Z_VOL
+    CVolumeName seqName;
+
+    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+    #endif
+
+    #ifndef _NO_CRYPTO
+    CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+    if (openArchiveCallback)
+    {
+      openArchiveCallbackTemp.QueryInterface(
+          IID_ICryptoGetTextPassword, &getTextPassword);
+    }
+    #endif
+    #ifdef _7Z_VOL
+    if (openArchiveCallback)
+    {
+      openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
+    }
+    for (;;)
+    {
+      CMyComPtr<IInStream> inStream;
+      if (!_volumes.IsEmpty())
+      {
+        if (!openVolumeCallback)
+          break;
+        if(_volumes.Size() == 1)
+        {
+          UString baseName;
+          {
+            NCOM::CPropVariant prop;
+            RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
+            if (prop.vt != VT_BSTR)
+              break;
+            baseName = prop.bstrVal;
+          }
+          seqName.InitName(baseName);
+        }
+
+        UString fullName = seqName.GetNextName();
+        HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);
+        if (result == S_FALSE)
+          break;
+        if (result != S_OK)
+          return result;
+        if (!stream)
+          break;
+      }
+      else
+        inStream = stream;
+
+      CInArchive archive;
+      RINOK(archive.Open(inStream, maxCheckStartPosition));
+
+      _volumes.Add(CVolume());
+      CVolume &volume = _volumes.Back();
+      CArchiveDatabaseEx &database = volume.Database;
+      volume.Stream = inStream;
+      volume.StartRef2Index = _refs.Size();
+
+      HRESULT result = archive.ReadDatabase(database
+          #ifndef _NO_CRYPTO
+          , getTextPassword
+          #endif
+          );
+      if (result != S_OK)
+      {
+        _volumes.Clear();
+        return result;
+      }
+      database.Fill();
+      for(int i = 0; i < database.Files.Size(); i++)
+      {
+        CRef refNew;
+        refNew.VolumeIndex = _volumes.Size() - 1;
+        refNew.ItemIndex = i;
+        _refs.Add(refNew);
+        /*
+        const CFileItem &file = database.Files[i];
+        int j;
+        */
+        /*
+        for (j = _refs.Size() - 1; j >= 0; j--)
+        {
+          CRef2 &ref2 = _refs[j];
+          const CRef &ref = ref2.Refs.Back();
+          const CVolume &volume2 = _volumes[ref.VolumeIndex];
+          const CArchiveDatabaseEx &database2 = volume2.Database;
+          const CFileItem &file2 = database2.Files[ref.ItemIndex];
+          if (file2.Name.CompareNoCase(file.Name) == 0)
+          {
+            if (!file.IsStartPosDefined)
+              continue;
+            if (file.StartPos != ref2.StartPos + ref2.UnPackSize)
+              continue;
+            ref2.Refs.Add(refNew);
+            break;
+          }
+        }
+        */
+        /*
+        j = -1;
+        if (j < 0)
+        {
+          CRef2 ref2New;
+          ref2New.Refs.Add(refNew);
+          j = _refs.Add(ref2New);
+        }
+        CRef2 &ref2 = _refs[j];
+        ref2.UnPackSize += file.UnPackSize;
+        ref2.PackSize += database.GetFilePackSize(i);
+        if (ref2.Refs.Size() == 1 && file.IsStartPosDefined)
+          ref2.StartPos = file.StartPos;
+        */
+      }
+      if (database.Files.Size() != 1)
+        break;
+      const CFileItem &file = database.Files.Front();
+      if (!file.IsStartPosDefined)
+        break;
+    }
+    #else
+    CInArchive archive;
+    RINOK(archive.Open(stream, maxCheckStartPosition));
+    HRESULT result = archive.ReadDatabase(
+      EXTERNAL_CODECS_VARS
+      _database
+      #ifndef _NO_CRYPTO
+      , getTextPassword
+      #endif
+      );
+    RINOK(result);
+    _database.Fill();
+    _inStream = stream;
+    #endif
+  }
+  catch(...)
+  {
+    Close();
+    return S_FALSE;
+  }
+  // _inStream = stream;
+  #ifndef _SFX
+  FillPopIDs();
+  #endif
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+  COM_TRY_BEGIN
+  #ifdef _7Z_VOL
+  _volumes.Clear();
+  _refs.Clear();
+  #else
+  _inStream.Release();
+  _database.Clear();
+  #endif
+  return S_OK;
+  COM_TRY_END
+}
+
+#ifdef _7Z_VOL
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+  if (index != 0)
+    return E_INVALIDARG;
+  *stream = 0;
+  CMultiStream *streamSpec = new CMultiStream;
+  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+  
+  UInt64 pos = 0;
+  const UString *fileName;
+  for (int i = 0; i < _refs.Size(); i++)
+  {
+    const CRef &ref = _refs[i];
+    const CVolume &volume = _volumes[ref.VolumeIndex];
+    const CArchiveDatabaseEx &database = volume.Database;
+    const CFileItem &file = database.Files[ref.ItemIndex];
+    if (i == 0)
+      fileName = &file.Name;
+    else
+      if (fileName->Compare(file.Name) != 0)
+        return S_FALSE;
+    if (!file.IsStartPosDefined)
+      return S_FALSE;
+    if (file.StartPos != pos)
+      return S_FALSE;
+    CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex];
+    if (folderIndex == kNumNoIndex)
+    {
+      if (file.UnPackSize != 0)
+        return E_FAIL;
+      continue;
+    }
+    if (database.NumUnPackStreamsVector[folderIndex] != 1)
+      return S_FALSE;
+    const CFolder &folder = database.Folders[folderIndex];
+    if (folder.Coders.Size() != 1)
+      return S_FALSE;
+    const CCoderInfo &coder = folder.Coders.Front();
+    if (coder.NumInStreams != 1 || coder.NumOutStreams != 1)
+      return S_FALSE;
+    if (coder.MethodID != k_Copy)
+      return S_FALSE;
+
+    pos += file.UnPackSize;
+    CMultiStream::CSubStreamInfo subStreamInfo;
+    subStreamInfo.Stream = volume.Stream;
+    subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0);
+    subStreamInfo.Size = file.UnPackSize;
+    streamSpec->Streams.Add(subStreamInfo);
+  }
+  streamSpec->Init();
+  *stream = streamTemp.Detach();
+  return S_OK;
+}
+#endif
+
+
+#ifdef __7Z_SET_PROPERTIES
+#ifdef EXTRACT_ONLY
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+  COM_TRY_BEGIN
+  #ifdef COMPRESS_MT
+  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
+  _numThreads = numProcessors;
+  #endif
+
+  for (int i = 0; i < numProperties; i++)
+  {
+    UString name = names[i];
+    name.MakeUpper();
+    if (name.IsEmpty())
+      return E_INVALIDARG;
+    const PROPVARIANT &value = values[i];
+    UInt32 number;
+    int index = ParseStringToUInt32(name, number);
+    if (index == 0)
+    {
+      if(name.Left(2).CompareNoCase(L"MT") == 0)
+      {
+        #ifdef COMPRESS_MT
+        RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
+        #endif
+        continue;
+      }
+      else
+        return E_INVALIDARG;
+    }
+  }
+  return S_OK;
+  COM_TRY_END
+}  
+
+#endif
+#endif
+
+IMPL_ISetCompressCodecsInfo
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zHandler.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zHandler.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zHandler.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,146 @@
+// 7z/Handler.h
+
+#ifndef __7Z_HANDLER_H
+#define __7Z_HANDLER_H
+
+#include "../../ICoder.h"
+#include "../IArchive.h"
+#include "7zIn.h"
+
+#include "7zCompressionMode.h"
+
+#include "../../Common/CreateCoder.h"
+
+#ifndef EXTRACT_ONLY
+#include "../Common/HandlerOut.h"
+#endif
+
+namespace NArchive {
+namespace N7z {
+
+#ifdef _7Z_VOL
+struct CRef
+{
+  int VolumeIndex;
+  int ItemIndex;
+};
+
+struct CVolume
+{
+  int StartRef2Index;
+  CMyComPtr<IInStream> Stream;
+  CArchiveDatabaseEx Database;
+};
+#endif
+
+#ifndef __7Z_SET_PROPERTIES
+
+#ifdef EXTRACT_ONLY
+#ifdef COMPRESS_MT
+#define __7Z_SET_PROPERTIES
+#endif
+#else 
+#define __7Z_SET_PROPERTIES
+#endif
+
+#endif
+
+
+class CHandler: 
+  #ifndef EXTRACT_ONLY
+  public NArchive::COutHandler,
+  #endif
+  public IInArchive,
+  #ifdef _7Z_VOL
+  public IInArchiveGetStream,
+  #endif
+  #ifdef __7Z_SET_PROPERTIES
+  public ISetProperties, 
+  #endif
+  #ifndef EXTRACT_ONLY
+  public IOutArchive, 
+  #endif
+  PUBLIC_ISetCompressCodecsInfo
+  public CMyUnknownImp
+{
+public:
+  MY_QUERYINTERFACE_BEGIN2(IInArchive)
+  #ifdef _7Z_VOL
+  MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
+  #endif
+  #ifdef __7Z_SET_PROPERTIES
+  MY_QUERYINTERFACE_ENTRY(ISetProperties)
+  #endif
+  #ifndef EXTRACT_ONLY
+  MY_QUERYINTERFACE_ENTRY(IOutArchive)
+  #endif
+  QUERY_ENTRY_ISetCompressCodecsInfo
+  MY_QUERYINTERFACE_END
+  MY_ADDREF_RELEASE
+
+  INTERFACE_IInArchive(;)
+
+  #ifdef _7Z_VOL
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);  
+  #endif
+
+  #ifdef __7Z_SET_PROPERTIES
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
+  #endif
+
+  #ifndef EXTRACT_ONLY
+  INTERFACE_IOutArchive(;)
+  #endif
+
+  DECL_ISetCompressCodecsInfo
+
+  CHandler();
+
+private:
+  #ifdef _7Z_VOL
+  CObjectVector<CVolume> _volumes;
+  CObjectVector<CRef> _refs;
+  #else
+  CMyComPtr<IInStream> _inStream;
+  NArchive::N7z::CArchiveDatabaseEx _database;
+  #endif
+
+  #ifdef EXTRACT_ONLY
+  
+  #ifdef COMPRESS_MT
+  UInt32 _numThreads;
+  #endif
+
+  UInt32 _crcSize;
+
+  #else
+  
+  CRecordVector<CBind> _binds;
+
+  HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback);
+
+  HRESULT SetCompressionMethod(CCompressionMethodMode &method,
+      CObjectVector<COneMethodInfo> &methodsInfo
+      #ifdef COMPRESS_MT
+      , UInt32 numThreads
+      #endif
+      );
+
+  HRESULT SetCompressionMethod(
+      CCompressionMethodMode &method,
+      CCompressionMethodMode &headerMethod);
+
+  #endif
+
+  bool IsEncrypted(UInt32 index2) const;
+  #ifndef _SFX
+
+  CRecordVector<UInt64> _fileInfoPopIDs;
+  void FillPopIDs();
+
+  #endif
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zHandlerOut.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,464 @@
+// 7zHandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zOut.h"
+#include "7zUpdate.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/StringToInt.h"
+#include "../../IPassword.h"
+#include "../../ICoder.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "../Common/ParseProperties.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace N7z {
+
+static const wchar_t *kLZMAMethodName = L"LZMA";
+static const wchar_t *kCopyMethod = L"Copy";
+static const wchar_t *kDefaultMethodName = kLZMAMethodName;
+
+static const UInt32 kLzmaAlgorithmX5 = 1;
+static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
+static const UInt32 kDictionaryForHeaders = 1 << 20;
+static const UInt32 kNumFastBytesForHeaders = 273;
+static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;
+
+static inline bool IsCopyMethod(const UString &methodName)
+  { return (methodName.CompareNoCase(kCopyMethod) == 0); }
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+  *type = NFileTimeType::kWindows;
+  return S_OK;
+}
+
+HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode,
+    IArchiveUpdateCallback *updateCallback)
+{
+  CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
+  if (!getTextPassword)
+  {
+    CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback);
+    udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
+  }
+  
+  if (getTextPassword)
+  {
+    CMyComBSTR password;
+    Int32 passwordIsDefined;
+    RINOK(getTextPassword->CryptoGetTextPassword2(
+        &passwordIsDefined, &password));
+    methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
+    if (methodMode.PasswordIsDefined)
+      methodMode.Password = password;
+  }
+  else
+    methodMode.PasswordIsDefined = false;
+  return S_OK;
+}
+
+HRESULT CHandler::SetCompressionMethod(
+    CCompressionMethodMode &methodMode,
+    CCompressionMethodMode &headerMethod)
+{
+  HRESULT res = SetCompressionMethod(methodMode, _methods
+  #ifdef COMPRESS_MT
+  , _numThreads
+  #endif
+  );
+  RINOK(res);
+  methodMode.Binds = _binds;
+
+  if (_compressHeaders)
+  {
+    // headerMethod.Methods.Add(methodMode.Methods.Back());
+
+    CObjectVector<COneMethodInfo> headerMethodInfoVector;
+    COneMethodInfo oneMethodInfo;
+    oneMethodInfo.MethodName = kLZMAMethodName;
+    {
+      CProp property;
+      property.Id = NCoderPropID::kMatchFinder;
+      property.Value = kLzmaMatchFinderForHeaders;
+      oneMethodInfo.Properties.Add(property);
+    }
+    {
+      CProp property;
+      property.Id = NCoderPropID::kAlgorithm;
+      property.Value = kAlgorithmForHeaders;
+      oneMethodInfo.Properties.Add(property);
+    }
+    {
+      CProp property;
+      property.Id = NCoderPropID::kNumFastBytes;
+      property.Value = UInt32(kNumFastBytesForHeaders);
+      oneMethodInfo.Properties.Add(property);
+    }
+    {
+      CProp property;
+      property.Id = NCoderPropID::kDictionarySize;
+      property.Value = UInt32(kDictionaryForHeaders);
+      oneMethodInfo.Properties.Add(property);
+    }
+    headerMethodInfoVector.Add(oneMethodInfo);
+    HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector
+      #ifdef COMPRESS_MT
+      ,1
+      #endif
+    );
+    RINOK(res);
+  }
+  return S_OK;
+}
+
+HRESULT CHandler::SetCompressionMethod(
+    CCompressionMethodMode &methodMode,
+    CObjectVector<COneMethodInfo> &methodsInfo
+    #ifdef COMPRESS_MT
+    , UInt32 numThreads
+    #endif
+    )
+{
+  UInt32 level = _level;
+  
+  if (methodsInfo.IsEmpty())
+  {
+    COneMethodInfo oneMethodInfo;
+    oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);
+    methodsInfo.Add(oneMethodInfo);
+  }
+
+  bool needSolid = false;
+  for(int i = 0; i < methodsInfo.Size(); i++)
+  {
+    COneMethodInfo &oneMethodInfo = methodsInfo[i];
+    SetCompressionMethod2(oneMethodInfo
+      #ifdef COMPRESS_MT
+      , numThreads
+      #endif
+      );
+
+    if (!IsCopyMethod(oneMethodInfo.MethodName))
+      needSolid = true;
+
+    CMethodFull methodFull;
+
+    if (!FindMethod(
+        EXTERNAL_CODECS_VARS
+        oneMethodInfo.MethodName, methodFull.Id, methodFull.NumInStreams, methodFull.NumOutStreams))
+      return E_INVALIDARG;
+    methodFull.Properties = oneMethodInfo.Properties;
+    methodMode.Methods.Add(methodFull);
+
+    if (!_numSolidBytesDefined)
+    {
+      for (int j = 0; j < methodFull.Properties.Size(); j++)
+      {
+        const CProp &prop = methodFull.Properties[j];
+        if ((prop.Id == NCoderPropID::kDictionarySize || 
+             prop.Id == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)
+        {
+          _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;
+          const UInt64 kMinSize = (1 << 24);
+          if (_numSolidBytes < kMinSize)
+            _numSolidBytes = kMinSize;
+          _numSolidBytesDefined = true;
+          break;
+        }
+      }
+    }
+  }
+
+  if (!needSolid && !_numSolidBytesDefined)
+  {
+    _numSolidBytesDefined = true;
+    _numSolidBytes  = 0;
+  }
+  return S_OK;
+}
+
+static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, CArchiveFileTime &filetime, bool &filetimeIsDefined)
+{
+  filetimeIsDefined = false;
+  NCOM::CPropVariant propVariant;
+  RINOK(updateCallback->GetProperty(index, propID, &propVariant));
+  if (propVariant.vt == VT_FILETIME)
+  {
+    filetime = propVariant.filetime;
+    filetimeIsDefined = true;
+  }
+  else if (propVariant.vt != VT_EMPTY)
+    return E_INVALIDARG;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+    IArchiveUpdateCallback *updateCallback)
+{
+  COM_TRY_BEGIN
+
+  const CArchiveDatabaseEx *database = 0;
+  #ifdef _7Z_VOL
+  if(_volumes.Size() > 1)
+    return E_FAIL;
+  const CVolume *volume = 0;
+  if (_volumes.Size() == 1)
+  {
+    volume = &_volumes.Front();
+    database = &volume->Database;
+  }
+  #else
+  if (_inStream != 0)
+    database = &_database;
+  #endif
+
+  // CRecordVector<bool> compressStatuses;
+  CObjectVector<CUpdateItem> updateItems;
+  // CRecordVector<UInt32> copyIndices;
+  
+  // CMyComPtr<IUpdateCallback2> updateCallback2;
+  // updateCallback->QueryInterface(&updateCallback2);
+
+  for(UInt32 i = 0; i < numItems; i++)
+  {
+    Int32 newData;
+    Int32 newProperties;
+    UInt32 indexInArchive;
+    if (!updateCallback)
+      return E_FAIL;
+    RINOK(updateCallback->GetUpdateItemInfo(i,
+        &newData, &newProperties, &indexInArchive));
+    CUpdateItem updateItem;
+    updateItem.NewProperties = IntToBool(newProperties);
+    updateItem.NewData = IntToBool(newData);
+    updateItem.IndexInArchive = indexInArchive;
+    updateItem.IndexInClient = i;
+    updateItem.IsAnti = false;
+    updateItem.Size = 0;
+
+    if (updateItem.IndexInArchive != -1)
+    {
+      const CFileItem &fileItem = database->Files[updateItem.IndexInArchive];
+      updateItem.Name = fileItem.Name;
+      updateItem.IsDirectory = fileItem.IsDirectory;
+      updateItem.Size = fileItem.UnPackSize;
+      updateItem.IsAnti = fileItem.IsAnti;
+      
+      updateItem.CreationTime = fileItem.CreationTime;
+      updateItem.IsCreationTimeDefined = fileItem.IsCreationTimeDefined;
+      updateItem.LastWriteTime = fileItem.LastWriteTime;
+      updateItem.IsLastWriteTimeDefined = fileItem.IsLastWriteTimeDefined;
+      updateItem.LastAccessTime = fileItem.LastAccessTime;
+      updateItem.IsLastAccessTimeDefined = fileItem.IsLastAccessTimeDefined;
+    }
+
+    if (updateItem.NewProperties)
+    {
+      bool nameIsDefined;
+      bool folderStatusIsDefined;
+      {
+        NCOM::CPropVariant propVariant;
+        RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant));
+        if (propVariant.vt == VT_EMPTY)
+          updateItem.AttributesAreDefined = false;
+        else if (propVariant.vt != VT_UI4)
+          return E_INVALIDARG;
+        else
+        {
+          updateItem.Attributes = propVariant.ulVal;
+          updateItem.AttributesAreDefined = true;
+        }
+      }
+      
+      RINOK(GetTime(updateCallback, i, kpidCreationTime, updateItem.CreationTime, updateItem.IsCreationTimeDefined));
+      RINOK(GetTime(updateCallback, i, kpidLastWriteTime, updateItem.LastWriteTime , updateItem.IsLastWriteTimeDefined));
+      RINOK(GetTime(updateCallback, i, kpidLastAccessTime, updateItem.LastAccessTime, updateItem.IsLastAccessTimeDefined));
+
+      {
+        NCOM::CPropVariant propVariant;
+        RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant));
+        if (propVariant.vt == VT_EMPTY)
+          nameIsDefined = false;
+        else if (propVariant.vt != VT_BSTR)
+          return E_INVALIDARG;
+        else
+        {
+          updateItem.Name = NItemName::MakeLegalName(propVariant.bstrVal);
+          nameIsDefined = true;
+        }
+      }
+      {
+        NCOM::CPropVariant propVariant;
+        RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant));
+        if (propVariant.vt == VT_EMPTY)
+          folderStatusIsDefined = false;
+        else if (propVariant.vt != VT_BOOL)
+          return E_INVALIDARG;
+        else
+        {
+          updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE);
+          folderStatusIsDefined = true;
+        }
+      }
+
+      {
+        NCOM::CPropVariant propVariant;
+        RINOK(updateCallback->GetProperty(i, kpidIsAnti, &propVariant));
+        if (propVariant.vt == VT_EMPTY)
+          updateItem.IsAnti = false;
+        else if (propVariant.vt != VT_BOOL)
+          return E_INVALIDARG;
+        else
+          updateItem.IsAnti = (propVariant.boolVal != VARIANT_FALSE);
+      }
+
+      if (updateItem.IsAnti)
+      {
+        updateItem.AttributesAreDefined = false;
+
+        updateItem.IsCreationTimeDefined = false;
+        updateItem.IsLastWriteTimeDefined = false;
+        updateItem.IsLastAccessTimeDefined = false;
+        
+        updateItem.Size = 0;
+      }
+
+      if (!folderStatusIsDefined && updateItem.AttributesAreDefined)
+        updateItem.SetDirectoryStatusFromAttributes();
+    }
+
+    if (updateItem.NewData)
+    {
+      NCOM::CPropVariant propVariant;
+      RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant));
+      if (propVariant.vt != VT_UI8)
+        return E_INVALIDARG;
+      updateItem.Size = (UInt64)propVariant.uhVal.QuadPart;
+      if (updateItem.Size != 0 && updateItem.IsAnti)
+        return E_INVALIDARG;
+    }
+    updateItems.Add(updateItem);
+  }
+
+  CCompressionMethodMode methodMode, headerMethod;
+  RINOK(SetCompressionMethod(methodMode, headerMethod));
+  #ifdef COMPRESS_MT
+  methodMode.NumThreads = _numThreads;
+  headerMethod.NumThreads = 1;
+  #endif
+
+  RINOK(SetPassword(methodMode, updateCallback));
+
+  bool compressMainHeader = _compressHeaders;  // check it
+
+  if (methodMode.PasswordIsDefined)
+  {
+    compressMainHeader = true; 
+    if(_encryptHeaders)
+      RINOK(SetPassword(headerMethod, updateCallback));
+  }
+
+  if (numItems < 2)
+    compressMainHeader = false;
+
+  CUpdateOptions options;
+  options.Method = &methodMode;
+  options.HeaderMethod = (_compressHeaders || 
+      (methodMode.PasswordIsDefined && _encryptHeaders)) ? 
+      &headerMethod : 0;
+  options.UseFilters = _level != 0 && _autoFilter;
+  options.MaxFilter = _level >= 8;
+
+  options.HeaderOptions.CompressMainHeader = compressMainHeader;
+  options.HeaderOptions.WriteModified = WriteModified;
+  options.HeaderOptions.WriteCreated = WriteCreated;
+  options.HeaderOptions.WriteAccessed = WriteAccessed;
+  
+  options.NumSolidFiles = _numSolidFiles;
+  options.NumSolidBytes = _numSolidBytes;
+  options.SolidExtension = _solidExtension;
+  options.RemoveSfxBlock = _removeSfxBlock;
+  options.VolumeMode = _volumeMode;
+  return Update(
+      EXTERNAL_CODECS_VARS
+      #ifdef _7Z_VOL
+      volume ? volume->Stream: 0, 
+      volume ? database: 0, 
+      #else
+      _inStream, 
+      database,
+      #endif
+      updateItems, outStream, updateCallback, options);
+  COM_TRY_END
+}
+
+static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)
+{
+  stream = 0;
+  int index = ParseStringToUInt32(srcString, coder);
+  if (index == 0)
+    return E_INVALIDARG;
+  srcString.Delete(0, index);
+  if (srcString[0] == 'S')
+  {
+    srcString.Delete(0);
+    int index = ParseStringToUInt32(srcString, stream);
+    if (index == 0)
+      return E_INVALIDARG;
+    srcString.Delete(0, index);
+  }
+  return S_OK;
+}
+
+static HRESULT GetBindInfo(UString &srcString, CBind &bind)
+{
+  RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));
+  if (srcString[0] != ':')
+    return E_INVALIDARG;
+  srcString.Delete(0);
+  RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));
+  if (!srcString.IsEmpty())
+    return E_INVALIDARG;
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+  COM_TRY_BEGIN
+  _binds.Clear();
+  BeforeSetProperty();
+
+  for (int i = 0; i < numProperties; i++)
+  {
+    UString name = names[i];
+    name.MakeUpper();
+    if (name.IsEmpty())
+      return E_INVALIDARG;
+
+    const PROPVARIANT &value = values[i];
+
+    if (name[0] == 'B')
+    {
+      name.Delete(0);
+      CBind bind;
+      RINOK(GetBindInfo(name, bind));
+      _binds.Add(bind);
+      continue;
+    }
+
+    RINOK(SetProperty(name, value));
+  }
+
+  return S_OK;
+  COM_TRY_END
+}  
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zHeader.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zHeader.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zHeader.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,27 @@
+// 7z/Header.cpp
+
+#include "StdAfx.h"
+#include "7zHeader.h"
+
+namespace NArchive {
+namespace N7z {
+
+Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
+#ifdef _7Z_VOL
+Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};
+#endif
+
+class SignatureInitializer
+{
+public:
+  SignatureInitializer() 
+  { 
+    kSignature[0]--; 
+    #ifdef _7Z_VOL
+    kFinishSignature[0]--;
+    #endif
+  };
+} g_SignatureInitializer;
+
+}}
+

Added: trunk/lzma/CPP/7zip/Archive/7z/7zHeader.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zHeader.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zHeader.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,96 @@
+// 7z/7zHeader.h
+
+#ifndef __7Z_HEADER_H
+#define __7Z_HEADER_H
+
+#include "../../../Common/Types.h"
+
+namespace NArchive {
+namespace N7z {
+
+const int kSignatureSize = 6;
+extern Byte kSignature[kSignatureSize];
+
+// #define _7Z_VOL
+// 7z-MultiVolume is not finished yet.
+// It can work already, but I still do not like some 
+// things of that new multivolume format.
+// So please keep it commented.
+
+#ifdef _7Z_VOL
+extern Byte kFinishSignature[kSignatureSize];
+#endif
+
+struct CArchiveVersion
+{
+  Byte Major;
+  Byte Minor;
+};
+
+const Byte kMajorVersion = 0;
+
+struct CStartHeader
+{
+  UInt64 NextHeaderOffset;
+  UInt64 NextHeaderSize;
+  UInt32 NextHeaderCRC;
+};
+
+const UInt32 kStartHeaderSize = 20;
+
+#ifdef _7Z_VOL
+struct CFinishHeader: public CStartHeader
+{
+  UInt64 ArchiveStartOffset;  // data offset from end if that struct
+  UInt64 AdditionalStartBlockSize; // start  signature & start header size
+};
+
+const UInt32 kFinishHeaderSize = kStartHeaderSize + 16;
+#endif
+
+namespace NID
+{
+  enum EEnum
+  {
+    kEnd,
+
+    kHeader,
+
+    kArchiveProperties,
+    
+    kAdditionalStreamsInfo,
+    kMainStreamsInfo,
+    kFilesInfo,
+    
+    kPackInfo,
+    kUnPackInfo,
+    kSubStreamsInfo,
+
+    kSize,
+    kCRC,
+
+    kFolder,
+
+    kCodersUnPackSize,
+    kNumUnPackStream,
+
+    kEmptyStream,
+    kEmptyFile,
+    kAnti,
+
+    kName,
+    kCreationTime,
+    kLastAccessTime,
+    kLastWriteTime,
+    kWinAttributes,
+    kComment,
+
+    kEncodedHeader,
+
+    kStartPos
+  };
+}
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zIn.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zIn.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zIn.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1206 @@
+// 7zIn.cpp
+
+#include "StdAfx.h"
+
+#include "7zIn.h"
+#include "7zDecode.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+extern "C" 
+{ 
+#include "../../../../C/7zCrc.h"
+}
+
+// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader 
+#ifndef _SFX
+#define FORMAT_7Z_RECOVERY
+#endif
+
+namespace NArchive {
+namespace N7z {
+
+class CInArchiveException {};
+
+static void ThrowException() { throw CInArchiveException(); }
+static inline void ThrowEndOfData()   { ThrowException(); }
+static inline void ThrowUnsupported() { ThrowException(); }
+static inline void ThrowIncorrect()   { ThrowException(); }
+static inline void ThrowUnsupportedVersion() { ThrowException(); }
+
+/*
+class CInArchiveException
+{
+public:
+  enum CCauseType
+  {
+    kUnsupportedVersion = 0,
+    kUnsupported,
+    kIncorrect, 
+    kEndOfData,
+  } Cause;
+  CInArchiveException(CCauseType cause): Cause(cause) {};
+};
+
+static void ThrowException(CInArchiveException::CCauseType c) { throw CInArchiveException(c); }
+static void ThrowEndOfData()   { ThrowException(CInArchiveException::kEndOfData); }
+static void ThrowUnsupported() { ThrowException(CInArchiveException::kUnsupported); }
+static void ThrowIncorrect()   { ThrowException(CInArchiveException::kIncorrect); }
+static void ThrowUnsupportedVersion() { ThrowException(CInArchiveException::kUnsupportedVersion); }
+*/
+
+class CStreamSwitch
+{
+  CInArchive *_archive;
+  bool _needRemove;
+public:
+  CStreamSwitch(): _needRemove(false) {}
+  ~CStreamSwitch() { Remove(); }
+  void Remove();
+  void Set(CInArchive *archive, const Byte *data, size_t size);
+  void Set(CInArchive *archive, const CByteBuffer &byteBuffer);
+  void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);
+};
+
+void CStreamSwitch::Remove()
+{
+  if (_needRemove)
+  {
+    _archive->DeleteByteStream();
+    _needRemove = false;
+  }
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size)
+{
+  Remove();
+  _archive = archive;
+  _archive->AddByteStream(data, size);
+  _needRemove = true;
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)
+{
+  Set(archive, byteBuffer, byteBuffer.GetCapacity());
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)
+{
+  Remove();
+  Byte external = archive->ReadByte();
+  if (external != 0)
+  {
+    int dataIndex = (int)archive->ReadNum();
+    if (dataIndex < 0 || dataIndex >= dataVector->Size())
+      ThrowIncorrect();
+    Set(archive, (*dataVector)[dataIndex]);
+  }
+}
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
+#define SZ_LITTLE_ENDIAN_UNALIGN
+#endif
+
+#ifdef SZ_LITTLE_ENDIAN_UNALIGN
+static inline UInt16 GetUInt16FromMem(const Byte *p) { return *(const UInt16 *)p; }
+static inline UInt32 GetUInt32FromMem(const Byte *p) { return *(const UInt32 *)p; }
+static inline UInt64 GetUInt64FromMem(const Byte *p) { return *(const UInt64 *)p; }
+#else
+static inline UInt16 GetUInt16FromMem(const Byte *p) { return p[0] | ((UInt16)p[1] << 8); }
+static inline UInt32 GetUInt32FromMem(const Byte *p) { return p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); }
+static inline UInt64 GetUInt64FromMem(const Byte *p) { return GetUInt32FromMem(p) | ((UInt64)GetUInt32FromMem(p + 4) << 32); }
+#endif
+
+Byte CInByte2::ReadByte()
+{
+  if (_pos >= _size)
+    ThrowEndOfData();
+  return _buffer[_pos++];
+}
+
+void CInByte2::ReadBytes(Byte *data, size_t size)
+{
+  if (size > _size - _pos)
+    ThrowEndOfData();
+  for (size_t i = 0; i < size; i++)
+    data[i] = _buffer[_pos++];
+}
+
+void CInByte2::SkeepData(UInt64 size)
+{
+  if (size > _size - _pos)
+    ThrowEndOfData();
+}
+
+void CInByte2::SkeepData()
+{
+  SkeepData(ReadNumber());
+}
+
+UInt64 CInByte2::ReadNumber()
+{
+  if (_pos >= _size)
+    ThrowEndOfData();
+  Byte firstByte = _buffer[_pos++];
+  Byte mask = 0x80;
+  UInt64 value = 0;
+  for (int i = 0; i < 8; i++)
+  {
+    if ((firstByte & mask) == 0)
+    {
+      UInt64 highPart = firstByte & (mask - 1);
+      value += (highPart << (i * 8));
+      return value;
+    }
+    if (_pos >= _size)
+      ThrowEndOfData();
+    value |= ((UInt64)_buffer[_pos++] << (8 * i));
+    mask >>= 1;
+  }
+  return value;
+}
+
+CNum CInByte2::ReadNum()
+{ 
+  UInt64 value = ReadNumber(); 
+  if (value > kNumMax)
+    ThrowUnsupported();
+  return (CNum)value;
+}
+
+UInt32 CInByte2::ReadUInt32()
+{
+  if (_pos + 4 > _size)
+    ThrowEndOfData();
+  UInt32 res = GetUInt32FromMem(_buffer + _pos);
+  _pos += 4;
+  return res;
+}
+
+UInt64 CInByte2::ReadUInt64()
+{
+  if (_pos + 8 > _size)
+    ThrowEndOfData();
+  UInt64 res = GetUInt64FromMem(_buffer + _pos);
+  _pos += 8;
+  return res;
+}
+
+void CInByte2::ReadString(UString &s)
+{
+  const Byte *buf = _buffer + _pos;
+  size_t rem = (_size - _pos) / 2 * 2;
+  {
+    size_t i;
+    for (i = 0; i < rem; i += 2)
+      if (buf[i] == 0 && buf[i + 1] == 0)
+        break;
+    if (i == rem)
+      ThrowEndOfData();
+    rem = i;
+  }
+  int len = (int)(rem / 2);
+  if (len < 0 || (size_t)len * 2 != rem)
+    ThrowUnsupported();
+  wchar_t *p = s.GetBuffer(len);
+  int i;
+  for (i = 0; i < len; i++, buf += 2) 
+    p[i] = (wchar_t)GetUInt16FromMem(buf);
+  p[i] = 0;
+  s.ReleaseBuffer(len);
+  _pos += rem + 2;
+}
+
+static inline bool TestSignatureCandidate(const Byte *p)
+{
+  for (int i = 0; i < kSignatureSize; i++)
+    if (p[i] != kSignature[i])
+      return false;
+  return (p[0x1A] == 0 && p[0x1B] == 0);
+}
+
+HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+  UInt32 processedSize; 
+  RINOK(ReadStream(stream, _header, kHeaderSize, &processedSize));
+  if (processedSize != kHeaderSize)
+    return S_FALSE;
+  if (TestSignatureCandidate(_header))
+    return S_OK;
+
+  CByteBuffer byteBuffer;
+  const UInt32 kBufferSize = (1 << 16);
+  byteBuffer.SetCapacity(kBufferSize);
+  Byte *buffer = byteBuffer;
+  UInt32 numPrevBytes = kHeaderSize - 1;
+  memcpy(buffer, _header + 1, numPrevBytes);
+  UInt64 curTestPos = _arhiveBeginStreamPosition + 1;
+  for (;;)
+  {
+    if (searchHeaderSizeLimit != NULL)
+      if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit)
+        break;
+    UInt32 numReadBytes = kBufferSize - numPrevBytes;
+    RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize));
+    UInt32 numBytesInBuffer = numPrevBytes + processedSize;
+    if (numBytesInBuffer < kHeaderSize)
+      break;
+    UInt32 numTests = numBytesInBuffer - kHeaderSize + 1;
+    for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)
+    { 
+      if (TestSignatureCandidate(buffer + pos))
+      {
+        memcpy(_header, buffer + pos, kHeaderSize);
+        _arhiveBeginStreamPosition = curTestPos;
+        return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL);
+      }
+    }
+    numPrevBytes = numBytesInBuffer - numTests;
+    memmove(buffer, buffer + numTests, numPrevBytes);
+  }
+  return S_FALSE;
+}
+
+// S_FALSE means that file is not archive
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+  Close();
+  RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))
+  RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));
+  _stream = stream;
+  return S_OK;
+}
+  
+void CInArchive::Close()
+{
+  _stream.Release();
+}
+
+void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
+{
+  for (;;)
+  {
+    if (ReadID() == NID::kEnd)
+      break;
+    SkeepData();
+  }
+}
+
+void CInArchive::GetNextFolderItem(CFolder &folder)
+{
+  CNum numCoders = ReadNum();
+
+  folder.Coders.Clear();
+  folder.Coders.Reserve((int)numCoders);
+  CNum numInStreams = 0;
+  CNum numOutStreams = 0;
+  CNum i;
+  for (i = 0; i < numCoders; i++)
+  {
+    folder.Coders.Add(CCoderInfo());
+    CCoderInfo &coder = folder.Coders.Back();
+
+    {
+      Byte mainByte = ReadByte();
+      int idSize = (mainByte & 0xF);
+      Byte longID[15];
+      ReadBytes(longID, idSize);
+      if (idSize > 8)
+        ThrowUnsupported();
+      UInt64 id = 0;
+      for (int j = 0; j < idSize; j++)
+        id |= (UInt64)longID[idSize - 1 - j] << (8 * j);
+      coder.MethodID = id;
+
+      if ((mainByte & 0x10) != 0)
+      {
+        coder.NumInStreams = ReadNum();
+        coder.NumOutStreams = ReadNum();
+      }
+      else
+      {
+        coder.NumInStreams = 1;
+        coder.NumOutStreams = 1;
+      }
+      if ((mainByte & 0x20) != 0)
+      {
+        CNum propertiesSize = ReadNum();
+        coder.Properties.SetCapacity((size_t)propertiesSize);
+        ReadBytes((Byte *)coder.Properties, (size_t)propertiesSize);
+      }
+      if ((mainByte & 0x80) != 0)
+        ThrowUnsupported();
+    }
+    numInStreams += coder.NumInStreams;
+    numOutStreams += coder.NumOutStreams;
+  }
+
+  CNum numBindPairs;
+  numBindPairs = numOutStreams - 1;
+  folder.BindPairs.Clear();
+  folder.BindPairs.Reserve(numBindPairs);
+  for (i = 0; i < numBindPairs; i++)
+  {
+    CBindPair bindPair;
+    bindPair.InIndex = ReadNum();
+    bindPair.OutIndex = ReadNum(); 
+    folder.BindPairs.Add(bindPair);
+  }
+
+  CNum numPackedStreams = numInStreams - numBindPairs;
+  folder.PackStreams.Reserve(numPackedStreams);
+  if (numPackedStreams == 1)
+  {
+    for (CNum j = 0; j < numInStreams; j++)
+      if (folder.FindBindPairForInStream(j) < 0)
+      {
+        folder.PackStreams.Add(j);
+        break;
+      }
+  }
+  else
+    for(i = 0; i < numPackedStreams; i++)
+      folder.PackStreams.Add(ReadNum());
+}
+
+void CInArchive::WaitAttribute(UInt64 attribute)
+{
+  for (;;)
+  {
+    UInt64 type = ReadID();
+    if (type == attribute)
+      return;
+    if (type == NID::kEnd)
+      ThrowIncorrect();
+    SkeepData();
+  }
+}
+
+void CInArchive::ReadHashDigests(int numItems,
+    CRecordVector<bool> &digestsDefined, 
+    CRecordVector<UInt32> &digests)
+{
+  ReadBoolVector2(numItems, digestsDefined);
+  digests.Clear();
+  digests.Reserve(numItems);
+  for(int i = 0; i < numItems; i++)
+  {
+    UInt32 crc = 0;
+    if (digestsDefined[i])
+      crc = ReadUInt32();
+    digests.Add(crc);
+  }
+}
+
+void CInArchive::ReadPackInfo(
+    UInt64 &dataOffset,
+    CRecordVector<UInt64> &packSizes,
+    CRecordVector<bool> &packCRCsDefined,
+    CRecordVector<UInt32> &packCRCs)
+{
+  dataOffset = ReadNumber();
+  CNum numPackStreams = ReadNum();
+
+  WaitAttribute(NID::kSize);
+  packSizes.Clear();
+  packSizes.Reserve(numPackStreams);
+  for (CNum i = 0; i < numPackStreams; i++)
+    packSizes.Add(ReadNumber());
+
+  UInt64 type;
+  for (;;)
+  {
+    type = ReadID();
+    if (type == NID::kEnd)
+      break;
+    if (type == NID::kCRC)
+    {
+      ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); 
+      continue;
+    }
+    SkeepData();
+  }
+  if (packCRCsDefined.IsEmpty())
+  {
+    packCRCsDefined.Reserve(numPackStreams);
+    packCRCsDefined.Clear();
+    packCRCs.Reserve(numPackStreams);
+    packCRCs.Clear();
+    for(CNum i = 0; i < numPackStreams; i++)
+    {
+      packCRCsDefined.Add(false);
+      packCRCs.Add(0);
+    }
+  }
+}
+
+void CInArchive::ReadUnPackInfo(
+    const CObjectVector<CByteBuffer> *dataVector,
+    CObjectVector<CFolder> &folders)
+{
+  WaitAttribute(NID::kFolder);
+  CNum numFolders = ReadNum();
+
+  {
+    CStreamSwitch streamSwitch;
+    streamSwitch.Set(this, dataVector);
+    folders.Clear();
+    folders.Reserve(numFolders);
+    for(CNum i = 0; i < numFolders; i++)
+    {
+      folders.Add(CFolder());
+      GetNextFolderItem(folders.Back());
+    }
+  }
+
+  WaitAttribute(NID::kCodersUnPackSize);
+
+  CNum i;
+  for (i = 0; i < numFolders; i++)
+  {
+    CFolder &folder = folders[i];
+    CNum numOutStreams = folder.GetNumOutStreams();
+    folder.UnPackSizes.Reserve(numOutStreams);
+    for (CNum j = 0; j < numOutStreams; j++)
+      folder.UnPackSizes.Add(ReadNumber());
+  }
+
+  for (;;)
+  {
+    UInt64 type = ReadID();
+    if (type == NID::kEnd)
+      return;
+    if (type == NID::kCRC)
+    {
+      CRecordVector<bool> crcsDefined;
+      CRecordVector<UInt32> crcs;
+      ReadHashDigests(numFolders, crcsDefined, crcs); 
+      for(i = 0; i < numFolders; i++)
+      {
+        CFolder &folder = folders[i];
+        folder.UnPackCRCDefined = crcsDefined[i];
+        folder.UnPackCRC = crcs[i];
+      }
+      continue;
+    }
+    SkeepData();
+  }
+}
+
+void CInArchive::ReadSubStreamsInfo(
+    const CObjectVector<CFolder> &folders,
+    CRecordVector<CNum> &numUnPackStreamsInFolders,
+    CRecordVector<UInt64> &unPackSizes,
+    CRecordVector<bool> &digestsDefined, 
+    CRecordVector<UInt32> &digests)
+{
+  numUnPackStreamsInFolders.Clear();
+  numUnPackStreamsInFolders.Reserve(folders.Size());
+  UInt64 type;
+  for (;;)
+  {
+    type = ReadID();
+    if (type == NID::kNumUnPackStream)
+    {
+      for(int i = 0; i < folders.Size(); i++)
+        numUnPackStreamsInFolders.Add(ReadNum());
+      continue;
+    }
+    if (type == NID::kCRC || type == NID::kSize)
+      break;
+    if (type == NID::kEnd)
+      break;
+    SkeepData();
+  }
+
+  if (numUnPackStreamsInFolders.IsEmpty())
+    for(int i = 0; i < folders.Size(); i++)
+      numUnPackStreamsInFolders.Add(1);
+
+  int i;
+  for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
+  {
+    // v3.13 incorrectly worked with empty folders
+    // v4.07: we check that folder is empty
+    CNum numSubstreams = numUnPackStreamsInFolders[i];
+    if (numSubstreams == 0)
+      continue;
+    UInt64 sum = 0;
+    for (CNum j = 1; j < numSubstreams; j++)
+      if (type == NID::kSize)
+      {
+        UInt64 size = ReadNumber();
+        unPackSizes.Add(size);
+        sum += size;
+      }
+    unPackSizes.Add(folders[i].GetUnPackSize() - sum);
+  }
+  if (type == NID::kSize)
+    type = ReadID();
+
+  int numDigests = 0;
+  int numDigestsTotal = 0;
+  for(i = 0; i < folders.Size(); i++)
+  {
+    CNum numSubstreams = numUnPackStreamsInFolders[i];
+    if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
+      numDigests += numSubstreams;
+    numDigestsTotal += numSubstreams;
+  }
+
+  for (;;)
+  {
+    if (type == NID::kCRC)
+    {
+      CRecordVector<bool> digestsDefined2; 
+      CRecordVector<UInt32> digests2;
+      ReadHashDigests(numDigests, digestsDefined2, digests2);
+      int digestIndex = 0;
+      for (i = 0; i < folders.Size(); i++)
+      {
+        CNum numSubstreams = numUnPackStreamsInFolders[i];
+        const CFolder &folder = folders[i];
+        if (numSubstreams == 1 && folder.UnPackCRCDefined)
+        {
+          digestsDefined.Add(true);
+          digests.Add(folder.UnPackCRC);
+        }
+        else
+          for (CNum j = 0; j < numSubstreams; j++, digestIndex++)
+          {
+            digestsDefined.Add(digestsDefined2[digestIndex]);
+            digests.Add(digests2[digestIndex]);
+          }
+      }
+    }
+    else if (type == NID::kEnd)
+    {
+      if (digestsDefined.IsEmpty())
+      {
+        digestsDefined.Clear();
+        digests.Clear();
+        for (int i = 0; i < numDigestsTotal; i++)
+        {
+          digestsDefined.Add(false);
+          digests.Add(0);
+        }
+      }
+      return;
+    }
+    else
+      SkeepData();
+    type = ReadID();
+  }
+}
+
+void CInArchive::ReadStreamsInfo(
+    const CObjectVector<CByteBuffer> *dataVector,
+    UInt64 &dataOffset,
+    CRecordVector<UInt64> &packSizes,
+    CRecordVector<bool> &packCRCsDefined,
+    CRecordVector<UInt32> &packCRCs,
+    CObjectVector<CFolder> &folders,
+    CRecordVector<CNum> &numUnPackStreamsInFolders,
+    CRecordVector<UInt64> &unPackSizes,
+    CRecordVector<bool> &digestsDefined, 
+    CRecordVector<UInt32> &digests)
+{
+  for (;;)
+  {
+    UInt64 type = ReadID();
+    if (type > ((UInt32)1 << 30))
+      ThrowIncorrect();
+    switch((UInt32)type)
+    {
+      case NID::kEnd:
+        return;
+      case NID::kPackInfo:
+      {
+        ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs);
+        break;
+      }
+      case NID::kUnPackInfo:
+      {
+        ReadUnPackInfo(dataVector, folders);
+        break;
+      }
+      case NID::kSubStreamsInfo:
+      {
+        ReadSubStreamsInfo(folders, numUnPackStreamsInFolders,
+            unPackSizes, digestsDefined, digests);
+        break;
+      }
+      default:
+        ThrowIncorrect();
+    }
+  }
+}
+
+void CInArchive::ReadBoolVector(int numItems, CBoolVector &v)
+{
+  v.Clear();
+  v.Reserve(numItems);
+  Byte b = 0;
+  Byte mask = 0;
+  for(int i = 0; i < numItems; i++)
+  {
+    if (mask == 0)
+    {
+      b = ReadByte();
+      mask = 0x80;
+    }
+    v.Add((b & mask) != 0);
+    mask >>= 1;
+  }
+}
+
+void CInArchive::ReadBoolVector2(int numItems, CBoolVector &v)
+{
+  Byte allAreDefined = ReadByte();
+  if (allAreDefined == 0)
+  {
+    ReadBoolVector(numItems, v);
+    return;
+  }
+  v.Clear();
+  v.Reserve(numItems);
+  for (int i = 0; i < numItems; i++)
+    v.Add(true);
+}
+
+void CInArchive::ReadTime(const CObjectVector<CByteBuffer> &dataVector,
+    CObjectVector<CFileItem> &files, UInt32 type)
+{
+  CBoolVector boolVector;
+  ReadBoolVector2(files.Size(), boolVector);
+
+  CStreamSwitch streamSwitch;
+  streamSwitch.Set(this, &dataVector);
+
+  for(int i = 0; i < files.Size(); i++)
+  {
+    CFileItem &file = files[i];
+    CArchiveFileTime fileTime;
+    fileTime.dwLowDateTime = 0;
+    fileTime.dwHighDateTime = 0;
+    bool defined = boolVector[i];
+    if (defined)
+    {
+      fileTime.dwLowDateTime = ReadUInt32();
+      fileTime.dwHighDateTime = ReadUInt32();
+    }
+    switch(type)
+    {
+      case NID::kCreationTime:
+        file.IsCreationTimeDefined = defined;
+        if (defined)
+          file.CreationTime = fileTime;
+        break;
+      case NID::kLastWriteTime:
+        file.IsLastWriteTimeDefined = defined;
+        if (defined)
+          file.LastWriteTime = fileTime;
+        break;
+      case NID::kLastAccessTime:
+        file.IsLastAccessTimeDefined = defined;
+        if (defined)
+          file.LastAccessTime = fileTime;
+        break;
+    }
+  }
+}
+
+HRESULT CInArchive::ReadAndDecodePackedStreams(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    UInt64 baseOffset, 
+    UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector
+    #ifndef _NO_CRYPTO
+    , ICryptoGetTextPassword *getTextPassword
+    #endif
+    )
+{
+  CRecordVector<UInt64> packSizes;
+  CRecordVector<bool> packCRCsDefined;
+  CRecordVector<UInt32> packCRCs;
+  CObjectVector<CFolder> folders;
+  
+  CRecordVector<CNum> numUnPackStreamsInFolders;
+  CRecordVector<UInt64> unPackSizes;
+  CRecordVector<bool> digestsDefined;
+  CRecordVector<UInt32> digests;
+  
+  ReadStreamsInfo(NULL, 
+    dataOffset,
+    packSizes, 
+    packCRCsDefined, 
+    packCRCs, 
+    folders,
+    numUnPackStreamsInFolders,
+    unPackSizes,
+    digestsDefined, 
+    digests);
+  
+  // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader;
+  
+  CNum packIndex = 0;
+  CDecoder decoder(
+    #ifdef _ST_MODE
+    false
+    #else
+    true
+    #endif
+    );
+  UInt64 dataStartPos = baseOffset + dataOffset;
+  for(int i = 0; i < folders.Size(); i++)
+  {
+    const CFolder &folder = folders[i];
+    dataVector.Add(CByteBuffer());
+    CByteBuffer &data = dataVector.Back();
+    UInt64 unPackSize64 = folder.GetUnPackSize();
+    size_t unPackSize = (size_t)unPackSize64;
+    if (unPackSize != unPackSize64)
+      ThrowUnsupported();
+    data.SetCapacity(unPackSize);
+    
+    CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2;
+    CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+    outStreamSpec->Init(data, unPackSize);
+    
+    HRESULT result = decoder.Decode(
+      EXTERNAL_CODECS_LOC_VARS
+      _stream, dataStartPos, 
+      &packSizes[packIndex], folder, outStream, NULL
+      #ifndef _NO_CRYPTO
+      , getTextPassword
+      #endif
+      #ifdef COMPRESS_MT
+      , false, 1
+      #endif
+      );
+    RINOK(result);
+    
+    if (folder.UnPackCRCDefined)
+      if (CrcCalc(data, unPackSize) != folder.UnPackCRC)
+        ThrowIncorrect();
+      for (int j = 0; j < folder.PackStreams.Size(); j++)
+        dataStartPos += packSizes[packIndex++];
+  }
+  return S_OK;
+}
+
+HRESULT CInArchive::ReadHeader(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    CArchiveDatabaseEx &database
+    #ifndef _NO_CRYPTO
+    , ICryptoGetTextPassword *getTextPassword
+    #endif
+    )
+{
+  UInt64 type = ReadID();
+
+  if (type == NID::kArchiveProperties)
+  {
+    ReadArchiveProperties(database.ArchiveInfo);
+    type = ReadID();
+  }
+ 
+  CObjectVector<CByteBuffer> dataVector;
+  
+  if (type == NID::kAdditionalStreamsInfo)
+  {
+    HRESULT result = ReadAndDecodePackedStreams(
+        EXTERNAL_CODECS_LOC_VARS
+        database.ArchiveInfo.StartPositionAfterHeader, 
+        database.ArchiveInfo.DataStartPosition2,
+        dataVector
+        #ifndef _NO_CRYPTO
+        , getTextPassword
+        #endif
+        );
+    RINOK(result);
+    database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader;
+    type = ReadID();
+  }
+
+  CRecordVector<UInt64> unPackSizes;
+  CRecordVector<bool> digestsDefined;
+  CRecordVector<UInt32> digests;
+  
+  if (type == NID::kMainStreamsInfo)
+  {
+    ReadStreamsInfo(&dataVector,
+        database.ArchiveInfo.DataStartPosition,
+        database.PackSizes, 
+        database.PackCRCsDefined, 
+        database.PackCRCs, 
+        database.Folders,
+        database.NumUnPackStreamsVector,
+        unPackSizes,
+        digestsDefined,
+        digests);
+    database.ArchiveInfo.DataStartPosition += database.ArchiveInfo.StartPositionAfterHeader;
+    type = ReadID();
+  }
+  else
+  {
+    for(int i = 0; i < database.Folders.Size(); i++)
+    {
+      database.NumUnPackStreamsVector.Add(1);
+      CFolder &folder = database.Folders[i];
+      unPackSizes.Add(folder.GetUnPackSize());
+      digestsDefined.Add(folder.UnPackCRCDefined);
+      digests.Add(folder.UnPackCRC);
+    }
+  }
+
+  database.Files.Clear();
+
+  if (type == NID::kEnd)
+    return S_OK;
+  if (type != NID::kFilesInfo)
+    ThrowIncorrect();
+  
+  CNum numFiles = ReadNum();
+  database.Files.Reserve(numFiles);
+  CNum i;
+  for(i = 0; i < numFiles; i++)
+    database.Files.Add(CFileItem());
+
+  database.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize);
+  if (!database.PackSizes.IsEmpty())
+    database.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo);
+  if (numFiles > 0  && !digests.IsEmpty())
+    database.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC);
+
+  CBoolVector emptyStreamVector;
+  emptyStreamVector.Reserve((int)numFiles);
+  for(i = 0; i < numFiles; i++)
+    emptyStreamVector.Add(false);
+  CBoolVector emptyFileVector;
+  CBoolVector antiFileVector;
+  CNum numEmptyStreams = 0;
+
+  for (;;)
+  {
+    UInt64 type = ReadID();
+    if (type == NID::kEnd)
+      break;
+    UInt64 size = ReadNumber();
+    bool isKnownType = true;
+    if (type > ((UInt32)1 << 30))
+      isKnownType = false;
+    else switch((UInt32)type)
+    {
+      case NID::kName:
+      {
+        CStreamSwitch streamSwitch;
+        streamSwitch.Set(this, &dataVector);
+        for(int i = 0; i < database.Files.Size(); i++)
+          _inByteBack->ReadString(database.Files[i].Name);
+        break;
+      }
+      case NID::kWinAttributes:
+      {
+        CBoolVector boolVector;
+        ReadBoolVector2(database.Files.Size(), boolVector);
+        CStreamSwitch streamSwitch;
+        streamSwitch.Set(this, &dataVector);
+        for(i = 0; i < numFiles; i++)
+        {
+          CFileItem &file = database.Files[i];
+          file.AreAttributesDefined = boolVector[i];
+          if (file.AreAttributesDefined)
+            file.Attributes = ReadUInt32();
+        }
+        break;
+      }
+      case NID::kStartPos:
+      {
+        CBoolVector boolVector;
+        ReadBoolVector2(database.Files.Size(), boolVector);
+        CStreamSwitch streamSwitch;
+        streamSwitch.Set(this, &dataVector);
+        for(i = 0; i < numFiles; i++)
+        {
+          CFileItem &file = database.Files[i];
+          file.IsStartPosDefined = boolVector[i];
+          if (file.IsStartPosDefined)
+            file.StartPos = ReadUInt64();
+        }
+        break;
+      }
+      case NID::kEmptyStream:
+      {
+        ReadBoolVector(numFiles, emptyStreamVector);
+        for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)
+          if (emptyStreamVector[i])
+            numEmptyStreams++;
+        emptyFileVector.Reserve(numEmptyStreams);
+        antiFileVector.Reserve(numEmptyStreams);
+        for (i = 0; i < numEmptyStreams; i++)
+        {
+          emptyFileVector.Add(false);
+          antiFileVector.Add(false);
+        }
+        break;
+      }
+      case NID::kEmptyFile:
+      {
+        ReadBoolVector(numEmptyStreams, emptyFileVector);
+        break;
+      }
+      case NID::kAnti:
+      {
+        ReadBoolVector(numEmptyStreams, antiFileVector);
+        break;
+      }
+      case NID::kCreationTime:
+      case NID::kLastWriteTime:
+      case NID::kLastAccessTime:
+      {
+        ReadTime(dataVector, database.Files, (UInt32)type);
+        break;
+      }
+      default:
+        isKnownType = false;
+    }
+    if (isKnownType)
+      database.ArchiveInfo.FileInfoPopIDs.Add(type);
+    else
+      SkeepData(size);
+  }
+
+  CNum emptyFileIndex = 0;
+  CNum sizeIndex = 0;
+  for(i = 0; i < numFiles; i++)
+  {
+    CFileItem &file = database.Files[i];
+    file.HasStream = !emptyStreamVector[i];
+    if(file.HasStream)
+    {
+      file.IsDirectory = false;
+      file.IsAnti = false;
+      file.UnPackSize = unPackSizes[sizeIndex];
+      file.FileCRC = digests[sizeIndex];
+      file.IsFileCRCDefined = digestsDefined[sizeIndex];
+      sizeIndex++;
+    }
+    else
+    {
+      file.IsDirectory = !emptyFileVector[emptyFileIndex];
+      file.IsAnti = antiFileVector[emptyFileIndex];
+      emptyFileIndex++;
+      file.UnPackSize = 0;
+      file.IsFileCRCDefined = false;
+    }
+  }
+  return S_OK;
+}
+
+
+void CArchiveDatabaseEx::FillFolderStartPackStream()
+{
+  FolderStartPackStreamIndex.Clear();
+  FolderStartPackStreamIndex.Reserve(Folders.Size());
+  CNum startPos = 0;
+  for(int i = 0; i < Folders.Size(); i++)
+  {
+    FolderStartPackStreamIndex.Add(startPos);
+    startPos += (CNum)Folders[i].PackStreams.Size();
+  }
+}
+
+void CArchiveDatabaseEx::FillStartPos()
+{
+  PackStreamStartPositions.Clear();
+  PackStreamStartPositions.Reserve(PackSizes.Size());
+  UInt64 startPos = 0;
+  for(int i = 0; i < PackSizes.Size(); i++)
+  {
+    PackStreamStartPositions.Add(startPos);
+    startPos += PackSizes[i];
+  }
+}
+
+void CArchiveDatabaseEx::FillFolderStartFileIndex()
+{
+  FolderStartFileIndex.Clear();
+  FolderStartFileIndex.Reserve(Folders.Size());
+  FileIndexToFolderIndexMap.Clear();
+  FileIndexToFolderIndexMap.Reserve(Files.Size());
+  
+  int folderIndex = 0;
+  CNum indexInFolder = 0;
+  for (int i = 0; i < Files.Size(); i++)
+  {
+    const CFileItem &file = Files[i];
+    bool emptyStream = !file.HasStream;
+    if (emptyStream && indexInFolder == 0)
+    {
+      FileIndexToFolderIndexMap.Add(kNumNoIndex);
+      continue;
+    }
+    if (indexInFolder == 0)
+    {
+      // v3.13 incorrectly worked with empty folders
+      // v4.07: Loop for skipping empty folders
+      for (;;)
+      {
+        if (folderIndex >= Folders.Size())
+          ThrowIncorrect();
+        FolderStartFileIndex.Add(i); // check it
+        if (NumUnPackStreamsVector[folderIndex] != 0)
+          break;
+        folderIndex++;
+      }
+    }
+    FileIndexToFolderIndexMap.Add(folderIndex);
+    if (emptyStream)
+      continue;
+    indexInFolder++;
+    if (indexInFolder >= NumUnPackStreamsVector[folderIndex])
+    {
+      folderIndex++;
+      indexInFolder = 0;
+    }
+  }
+}
+
+HRESULT CInArchive::ReadDatabase2(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    CArchiveDatabaseEx &database
+    #ifndef _NO_CRYPTO
+    , ICryptoGetTextPassword *getTextPassword
+    #endif
+    )
+{
+  database.Clear();
+  database.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
+
+  database.ArchiveInfo.Version.Major = _header[6];
+  database.ArchiveInfo.Version.Minor = _header[7];
+
+  if (database.ArchiveInfo.Version.Major != kMajorVersion)
+    ThrowUnsupportedVersion();
+
+  UInt32 crcFromArchive = GetUInt32FromMem(_header + 8);
+  UInt64 nextHeaderOffset = GetUInt64FromMem(_header + 0xC);
+  UInt64 nextHeaderSize = GetUInt64FromMem(_header + 0x14);
+  UInt32 nextHeaderCRC =  GetUInt32FromMem(_header + 0x1C);
+  UInt32 crc = CrcCalc(_header + 0xC, 20);
+
+  #ifdef FORMAT_7Z_RECOVERY
+  if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
+  {
+    UInt64 cur, cur2;
+    RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));
+    const int kCheckSize = 500;
+    Byte buf[kCheckSize];
+    RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2));
+    int checkSize = kCheckSize;
+    if (cur2 - cur < kCheckSize)
+      checkSize = (int)(cur2 - cur);
+    RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2));
+    
+    UInt32 realProcessedSize;
+    RINOK(_stream->Read(buf, (UInt32)kCheckSize, &realProcessedSize));
+
+    int i;
+    for (i = (int)realProcessedSize - 2; i >= 0; i--)
+      if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04)
+        break;
+    if (i < 0)
+      return S_FALSE;
+    nextHeaderSize = realProcessedSize - i;
+    nextHeaderOffset = cur2 - cur + i;
+    nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
+    RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));
+  }
+  #endif
+
+  #ifdef FORMAT_7Z_RECOVERY
+  crcFromArchive = crc;
+  #endif
+
+  database.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;
+
+  if (crc != crcFromArchive)
+    ThrowIncorrect();
+
+  if (nextHeaderSize == 0)
+    return S_OK;
+
+  if (nextHeaderSize > (UInt64)0xFFFFFFFF)
+    return S_FALSE;
+
+  RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));
+
+  CByteBuffer buffer2;
+  buffer2.SetCapacity((size_t)nextHeaderSize);
+
+  UInt32 realProcessedSize;
+  RINOK(_stream->Read(buffer2, (UInt32)nextHeaderSize, &realProcessedSize));
+  if (realProcessedSize != (UInt32)nextHeaderSize)
+    return S_FALSE;
+  if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC)
+    ThrowIncorrect();
+  
+  CStreamSwitch streamSwitch;
+  streamSwitch.Set(this, buffer2);
+  
+  CObjectVector<CByteBuffer> dataVector;
+  
+  for (;;)
+  {
+    UInt64 type = ReadID();
+    if (type == NID::kHeader)
+      break;
+    if (type != NID::kEncodedHeader)
+      ThrowIncorrect();
+    HRESULT result = ReadAndDecodePackedStreams(
+        EXTERNAL_CODECS_LOC_VARS
+        database.ArchiveInfo.StartPositionAfterHeader, 
+        database.ArchiveInfo.DataStartPosition2,
+        dataVector
+        #ifndef _NO_CRYPTO
+        , getTextPassword
+        #endif
+        );
+    RINOK(result);
+    if (dataVector.Size() == 0)
+      return S_OK;
+    if (dataVector.Size() > 1)
+      ThrowIncorrect();
+    streamSwitch.Remove();
+    streamSwitch.Set(this, dataVector.Front());
+  }
+
+  return ReadHeader(
+    EXTERNAL_CODECS_LOC_VARS
+    database
+    #ifndef _NO_CRYPTO
+    , getTextPassword
+    #endif
+    );
+}
+
+HRESULT CInArchive::ReadDatabase(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    CArchiveDatabaseEx &database
+    #ifndef _NO_CRYPTO
+    , ICryptoGetTextPassword *getTextPassword
+    #endif
+    )
+{
+  try
+  {
+    return ReadDatabase2(
+      EXTERNAL_CODECS_LOC_VARS database
+      #ifndef _NO_CRYPTO
+      , getTextPassword
+      #endif
+      );
+  }
+  catch(CInArchiveException &) { return S_FALSE; }
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zIn.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zIn.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zIn.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,235 @@
+// 7zIn.h
+
+#ifndef __7Z_IN_H
+#define __7Z_IN_H
+
+#include "../../../Common/MyCom.h"
+#include "../../IStream.h"
+#include "../../IPassword.h"
+#include "../../Common/CreateCoder.h"
+#include "../../Common/InBuffer.h"
+
+#include "7zItem.h"
+ 
+namespace NArchive {
+namespace N7z {
+  
+struct CInArchiveInfo
+{
+  CArchiveVersion Version;
+  UInt64 StartPosition;
+  UInt64 StartPositionAfterHeader;
+  UInt64 DataStartPosition;
+  UInt64 DataStartPosition2;
+  CRecordVector<UInt64> FileInfoPopIDs;
+  void Clear()
+  {
+    FileInfoPopIDs.Clear();
+  }
+};
+
+struct CArchiveDatabaseEx: public CArchiveDatabase
+{
+  CInArchiveInfo ArchiveInfo;
+  CRecordVector<UInt64> PackStreamStartPositions;
+  CRecordVector<CNum> FolderStartPackStreamIndex;
+  CRecordVector<CNum> FolderStartFileIndex;
+  CRecordVector<CNum> FileIndexToFolderIndexMap;
+
+  void Clear()
+  {
+    CArchiveDatabase::Clear();
+    ArchiveInfo.Clear();
+    PackStreamStartPositions.Clear();
+    FolderStartPackStreamIndex.Clear();
+    FolderStartFileIndex.Clear();
+    FileIndexToFolderIndexMap.Clear();
+  }
+
+  void FillFolderStartPackStream();
+  void FillStartPos();
+  void FillFolderStartFileIndex();
+
+  void Fill()
+  {
+    FillFolderStartPackStream();
+    FillStartPos();
+    FillFolderStartFileIndex();
+  }
+  
+  UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const
+  {
+    return ArchiveInfo.DataStartPosition +
+        PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] + indexInFolder];
+  }
+  
+  UInt64 GetFolderFullPackSize(int folderIndex) const 
+  {
+    CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];
+    const CFolder &folder = Folders[folderIndex];
+    UInt64 size = 0;
+    for (int i = 0; i < folder.PackStreams.Size(); i++)
+      size += PackSizes[packStreamIndex + i];
+    return size;
+  }
+  
+  UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const 
+  {
+    return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
+  }
+
+  UInt64 GetFilePackSize(CNum fileIndex) const
+  {
+    CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
+    if (folderIndex != kNumNoIndex)
+      if (FolderStartFileIndex[folderIndex] == fileIndex)
+        return GetFolderFullPackSize(folderIndex);
+    return 0;
+  }
+};
+
+class CInByte2
+{
+  const Byte *_buffer;
+  size_t _size;
+  size_t _pos;
+public:
+  void Init(const Byte *buffer, size_t size)
+  {
+    _buffer = buffer;
+    _size = size;
+    _pos = 0;
+  }
+  Byte ReadByte();
+  void ReadBytes(Byte *data, size_t size);
+  void SkeepData(UInt64 size);
+  void SkeepData();
+  UInt64 ReadNumber();
+  CNum ReadNum();
+  UInt32 ReadUInt32();
+  UInt64 ReadUInt64();
+  void ReadString(UString &s);
+};
+
+class CStreamSwitch;
+
+const UInt32 kHeaderSize = 32;
+
+class CInArchive
+{
+  friend class CStreamSwitch;
+
+  CMyComPtr<IInStream> _stream;
+
+  CObjectVector<CInByte2> _inByteVector;
+  CInByte2 *_inByteBack;
+ 
+  UInt64 _arhiveBeginStreamPosition;
+
+  Byte _header[kHeaderSize];
+
+  void AddByteStream(const Byte *buffer, size_t size)
+  {
+    _inByteVector.Add(CInByte2());
+    _inByteBack = &_inByteVector.Back();
+    _inByteBack->Init(buffer, size);
+  }
+  
+  void DeleteByteStream()
+  {
+    _inByteVector.DeleteBack();
+    if (!_inByteVector.IsEmpty())
+      _inByteBack = &_inByteVector.Back();
+  }
+
+private:
+  HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);
+  
+  void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }
+  Byte ReadByte() { return _inByteBack->ReadByte(); }
+  UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }
+  CNum ReadNum() { return _inByteBack->ReadNum(); }
+  UInt64 ReadID() { return _inByteBack->ReadNumber(); }
+  UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
+  UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
+  void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); }
+  void SkeepData() { _inByteBack->SkeepData(); }
+  void WaitAttribute(UInt64 attribute);
+
+  void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
+  void GetNextFolderItem(CFolder &itemInfo);
+  void ReadHashDigests(int numItems,
+      CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests);
+  
+  void ReadPackInfo(
+      UInt64 &dataOffset,
+      CRecordVector<UInt64> &packSizes,
+      CRecordVector<bool> &packCRCsDefined,
+      CRecordVector<UInt32> &packCRCs);
+  
+  void ReadUnPackInfo(
+      const CObjectVector<CByteBuffer> *dataVector,
+      CObjectVector<CFolder> &folders);
+  
+  void ReadSubStreamsInfo(
+      const CObjectVector<CFolder> &folders,
+      CRecordVector<CNum> &numUnPackStreamsInFolders,
+      CRecordVector<UInt64> &unPackSizes,
+      CRecordVector<bool> &digestsDefined, 
+      CRecordVector<UInt32> &digests);
+
+  void ReadStreamsInfo(
+      const CObjectVector<CByteBuffer> *dataVector,
+      UInt64 &dataOffset,
+      CRecordVector<UInt64> &packSizes,
+      CRecordVector<bool> &packCRCsDefined,
+      CRecordVector<UInt32> &packCRCs,
+      CObjectVector<CFolder> &folders,
+      CRecordVector<CNum> &numUnPackStreamsInFolders,
+      CRecordVector<UInt64> &unPackSizes,
+      CRecordVector<bool> &digestsDefined, 
+      CRecordVector<UInt32> &digests);
+
+
+  void ReadBoolVector(int numItems, CBoolVector &v);
+  void ReadBoolVector2(int numItems, CBoolVector &v);
+  void ReadTime(const CObjectVector<CByteBuffer> &dataVector,
+      CObjectVector<CFileItem> &files, UInt32 type);
+  HRESULT ReadAndDecodePackedStreams(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      UInt64 baseOffset, UInt64 &dataOffset,
+      CObjectVector<CByteBuffer> &dataVector
+      #ifndef _NO_CRYPTO
+      , ICryptoGetTextPassword *getTextPassword
+      #endif
+      );
+  HRESULT ReadHeader(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      CArchiveDatabaseEx &database
+      #ifndef _NO_CRYPTO
+      ,ICryptoGetTextPassword *getTextPassword
+      #endif
+      );
+  HRESULT ReadDatabase2(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      CArchiveDatabaseEx &database 
+      #ifndef _NO_CRYPTO
+      ,ICryptoGetTextPassword *getTextPassword
+      #endif
+      );
+public:
+  HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
+  void Close();
+
+  HRESULT ReadDatabase(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      CArchiveDatabaseEx &database 
+      #ifndef _NO_CRYPTO
+      ,ICryptoGetTextPassword *getTextPassword
+      #endif
+      );
+};
+  
+}}
+  
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zItem.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zItem.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zItem.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,184 @@
+// 7zItem.h
+
+#ifndef __7Z_ITEM_H
+#define __7Z_ITEM_H
+
+#include "../../../Common/Buffer.h"
+#include "../../../Common/MyString.h"
+#include "../../Common/MethodId.h"
+#include "7zHeader.h"
+
+namespace NArchive {
+namespace N7z {
+
+typedef UInt32 CNum;
+const CNum kNumMax     = 0x7FFFFFFF;
+const CNum kNumNoIndex = 0xFFFFFFFF;
+
+struct CCoderInfo
+{
+  CMethodId MethodID;
+  CByteBuffer Properties;
+  CNum NumInStreams;
+  CNum NumOutStreams;
+  bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+};
+
+struct CBindPair
+{
+  CNum InIndex;
+  CNum OutIndex;
+};
+
+struct CFolder
+{
+  CObjectVector<CCoderInfo> Coders;
+  CRecordVector<CBindPair> BindPairs;
+  CRecordVector<CNum> PackStreams;
+  CRecordVector<UInt64> UnPackSizes;
+  UInt32 UnPackCRC;
+  bool UnPackCRCDefined;
+
+  CFolder(): UnPackCRCDefined(false) {}
+
+  UInt64 GetUnPackSize() const // test it
+  { 
+    if (UnPackSizes.IsEmpty())
+      return 0;
+    for (int i = UnPackSizes.Size() - 1; i >= 0; i--)
+      if (FindBindPairForOutStream(i) < 0)
+        return UnPackSizes[i];
+    throw 1;
+  }
+
+  CNum GetNumOutStreams() const
+  {
+    CNum result = 0;
+    for (int i = 0; i < Coders.Size(); i++)
+      result += Coders[i].NumOutStreams;
+    return result;
+  }
+
+  int FindBindPairForInStream(CNum inStreamIndex) const
+  {
+    for(int i = 0; i < BindPairs.Size(); i++)
+      if (BindPairs[i].InIndex == inStreamIndex)
+        return i;
+    return -1;
+  }
+  int FindBindPairForOutStream(CNum outStreamIndex) const
+  {
+    for(int i = 0; i < BindPairs.Size(); i++)
+      if (BindPairs[i].OutIndex == outStreamIndex)
+        return i;
+    return -1;
+  }
+  int FindPackStreamArrayIndex(CNum inStreamIndex) const
+  {
+    for(int i = 0; i < PackStreams.Size(); i++)
+      if (PackStreams[i] == inStreamIndex)
+        return i;
+    return -1;
+  }
+};
+
+typedef FILETIME CArchiveFileTime;
+
+class CFileItem
+{
+public:
+  CArchiveFileTime CreationTime;
+  CArchiveFileTime LastWriteTime;
+  CArchiveFileTime LastAccessTime;
+  UInt64 UnPackSize;
+  UInt64 StartPos;
+  UInt32 Attributes;
+  UInt32 FileCRC;
+  UString Name;
+
+  bool HasStream; // Test it !!! it means that there is 
+                  // stream in some folder. It can be empty stream
+  bool IsDirectory;
+  bool IsAnti;
+  bool IsFileCRCDefined;
+  bool AreAttributesDefined;
+  bool IsCreationTimeDefined;
+  bool IsLastWriteTimeDefined;
+  bool IsLastAccessTimeDefined;
+  bool IsStartPosDefined;
+
+  /*
+  const bool HasStream() const { 
+      return !IsDirectory && !IsAnti && UnPackSize != 0; }
+  */
+  CFileItem(): 
+    HasStream(true),
+    IsDirectory(false),
+    IsAnti(false),
+    IsFileCRCDefined(false),
+    AreAttributesDefined(false), 
+    IsCreationTimeDefined(false), 
+    IsLastWriteTimeDefined(false), 
+    IsLastAccessTimeDefined(false),
+    IsStartPosDefined(false)
+      {}
+  void SetAttributes(UInt32 attributes) 
+  { 
+    AreAttributesDefined = true;
+    Attributes = attributes;
+  }
+  void SetCreationTime(const CArchiveFileTime &creationTime) 
+  { 
+    IsCreationTimeDefined = true;
+    CreationTime = creationTime;
+  }
+  void SetLastWriteTime(const CArchiveFileTime &lastWriteTime) 
+  {
+    IsLastWriteTimeDefined = true;
+    LastWriteTime = lastWriteTime;
+  }
+  void SetLastAccessTime(const CArchiveFileTime &lastAccessTime) 
+  { 
+    IsLastAccessTimeDefined = true;
+    LastAccessTime = lastAccessTime;
+  }
+};
+
+struct CArchiveDatabase
+{
+  CRecordVector<UInt64> PackSizes;
+  CRecordVector<bool> PackCRCsDefined;
+  CRecordVector<UInt32> PackCRCs;
+  CObjectVector<CFolder> Folders;
+  CRecordVector<CNum> NumUnPackStreamsVector;
+  CObjectVector<CFileItem> Files;
+  void Clear()
+  {
+    PackSizes.Clear();
+    PackCRCsDefined.Clear();
+    PackCRCs.Clear();
+    Folders.Clear();
+    NumUnPackStreamsVector.Clear();
+    Files.Clear();
+  }
+  bool IsEmpty() const
+  {
+    return (PackSizes.IsEmpty() && 
+      PackCRCsDefined.IsEmpty() && 
+      PackCRCs.IsEmpty() && 
+      Folders.IsEmpty() && 
+      NumUnPackStreamsVector.IsEmpty() && 
+      Files.IsEmpty());
+  }
+  bool IsSolid() const
+  {
+    for (int i = 0; i < NumUnPackStreamsVector.Size(); i++)
+      if (NumUnPackStreamsVector[i] > 1)
+        return true;
+    return false;
+  }
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zOut.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zOut.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zOut.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1026 @@
+// 7zOut.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/AutoPtr.h"
+#include "../../Common/StreamObjects.h"
+
+#include "7zOut.h"
+
+extern "C" 
+{ 
+#include "../../../../C/7zCrc.h"
+}
+
+static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)
+{
+  while (size > 0)
+  {
+    UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);
+    UInt32 processedSize;
+    RINOK(stream->Write(data, curSize, &processedSize));
+    if(processedSize == 0)
+      return E_FAIL;
+    data = (const void *)((const Byte *)data + processedSize);
+    size -= processedSize;
+  }
+  return S_OK;
+}
+
+namespace NArchive {
+namespace N7z {
+
+HRESULT COutArchive::WriteDirect(const void *data, UInt32 size)
+{
+  return ::WriteBytes(SeqStream, data, size);
+}
+
+UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 value)
+{
+  for (int i = 0; i < 4; i++, value >>= 8)
+    crc = CRC_UPDATE_BYTE(crc, (Byte)value);
+  return crc;
+}
+
+UInt32 CrcUpdateUInt64(UInt32 crc, UInt64 value)
+{
+  for (int i = 0; i < 8; i++, value >>= 8)
+    crc = CRC_UPDATE_BYTE(crc, (Byte)value);
+  return crc;
+}
+
+HRESULT COutArchive::WriteDirectUInt32(UInt32 value)
+{
+  for (int i = 0; i < 4; i++)
+  {
+    RINOK(WriteDirectByte((Byte)value));
+    value >>= 8;
+  }
+  return S_OK;
+}
+
+HRESULT COutArchive::WriteDirectUInt64(UInt64 value)
+{
+  for (int i = 0; i < 8; i++)
+  {
+    RINOK(WriteDirectByte((Byte)value));
+    value >>= 8;
+  }
+  return S_OK;
+}
+
+HRESULT COutArchive::WriteSignature()
+{
+  RINOK(WriteDirect(kSignature, kSignatureSize));
+  RINOK(WriteDirectByte(kMajorVersion));
+  return WriteDirectByte(2);
+}
+
+#ifdef _7Z_VOL
+HRESULT COutArchive::WriteFinishSignature()
+{
+  RINOK(WriteDirect(kFinishSignature, kSignatureSize));
+  CArchiveVersion av;
+  av.Major = kMajorVersion;
+  av.Minor = 2;
+  RINOK(WriteDirectByte(av.Major));
+  return WriteDirectByte(av.Minor);
+}
+#endif
+
+HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
+{
+  UInt32 crc = CRC_INIT_VAL;
+  crc = CrcUpdateUInt64(crc, h.NextHeaderOffset);
+  crc = CrcUpdateUInt64(crc, h.NextHeaderSize);
+  crc = CrcUpdateUInt32(crc, h.NextHeaderCRC);
+  RINOK(WriteDirectUInt32(CRC_GET_DIGEST(crc)));
+  RINOK(WriteDirectUInt64(h.NextHeaderOffset));
+  RINOK(WriteDirectUInt64(h.NextHeaderSize));
+  return WriteDirectUInt32(h.NextHeaderCRC);
+}
+
+#ifdef _7Z_VOL
+HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
+{
+  CCRC crc;
+  crc.UpdateUInt64(h.NextHeaderOffset);
+  crc.UpdateUInt64(h.NextHeaderSize);
+  crc.UpdateUInt32(h.NextHeaderCRC);
+  crc.UpdateUInt64(h.ArchiveStartOffset);
+  crc.UpdateUInt64(h.AdditionalStartBlockSize);
+  RINOK(WriteDirectUInt32(crc.GetDigest()));
+  RINOK(WriteDirectUInt64(h.NextHeaderOffset));
+  RINOK(WriteDirectUInt64(h.NextHeaderSize));
+  RINOK(WriteDirectUInt32(h.NextHeaderCRC));
+  RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
+  return WriteDirectUInt64(h.AdditionalStartBlockSize);
+}
+#endif
+
+HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)
+{
+  Close();
+  #ifdef _7Z_VOL
+  // endMarker = false;
+  _endMarker = endMarker;
+  #endif
+  SeqStream = stream;
+  if (!endMarker)
+  {
+    SeqStream.QueryInterface(IID_IOutStream, &Stream);
+    if (!Stream)
+    {
+      return E_NOTIMPL;
+      // endMarker = true;
+    }
+  }
+  #ifdef _7Z_VOL
+  if (endMarker)
+  {
+    /*
+    CStartHeader sh;
+    sh.NextHeaderOffset = (UInt32)(Int32)-1;
+    sh.NextHeaderSize = (UInt32)(Int32)-1;
+    sh.NextHeaderCRC = 0;
+    WriteStartHeader(sh);
+    */
+  }
+  else
+  #endif
+  {
+    if (!Stream)
+      return E_FAIL;
+    RINOK(WriteSignature());
+    RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));
+  }
+  return S_OK;
+}
+
+void COutArchive::Close()
+{
+  SeqStream.Release();
+  Stream.Release();
+}
+
+HRESULT COutArchive::SkeepPrefixArchiveHeader()
+{
+  #ifdef _7Z_VOL
+  if (_endMarker)
+    return S_OK;
+  #endif
+  return Stream->Seek(24, STREAM_SEEK_CUR, NULL);
+}
+
+HRESULT COutArchive::WriteBytes(const void *data, size_t size)
+{
+  if (_mainMode)
+  {
+    if (_dynamicMode)
+      _dynamicBuffer.Write(data, size);
+    else
+      _outByte.WriteBytes(data, size);
+    _crc = CrcUpdate(_crc, data, size);
+  }
+  else
+  {
+    if (_countMode)
+      _countSize += size;
+    else
+      RINOK(_outByte2.Write(data, size));
+  }
+  return S_OK;
+}
+
+HRESULT COutArchive::WriteBytes(const CByteBuffer &data)
+{
+  return WriteBytes(data, data.GetCapacity());
+}
+
+HRESULT COutArchive::WriteByte(Byte b)
+{
+  return WriteBytes(&b, 1);
+}
+
+HRESULT COutArchive::WriteUInt32(UInt32 value)
+{
+  for (int i = 0; i < 4; i++)
+  {
+    RINOK(WriteByte((Byte)value));
+    value >>= 8;
+  }
+  return S_OK;
+}
+
+HRESULT COutArchive::WriteNumber(UInt64 value)
+{
+  Byte firstByte = 0;
+  Byte mask = 0x80;
+  int i;
+  for (i = 0; i < 8; i++)
+  {
+    if (value < ((UInt64(1) << ( 7  * (i + 1)))))
+    {
+      firstByte |= Byte(value >> (8 * i));
+      break;
+    }
+    firstByte |= mask;
+    mask >>= 1;
+  }
+  RINOK(WriteByte(firstByte));
+  for (;i > 0; i--)
+  {
+    RINOK(WriteByte((Byte)value));
+    value >>= 8;
+  }
+  return S_OK;
+}
+
+#ifdef _7Z_VOL
+static UInt32 GetBigNumberSize(UInt64 value)
+{
+  int i;
+  for (i = 0; i < 8; i++)
+    if (value < ((UInt64(1) << ( 7  * (i + 1)))))
+      break;
+  return 1 + i;
+}
+
+UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)
+{
+  UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
+  if (nameLength != 0)
+  {
+    nameLength = (nameLength + 1) * 2;
+    result += nameLength + GetBigNumberSize(nameLength) + 2;
+  }
+  if (props)
+  {
+    result += 20;
+  }
+  if (result >= 128)
+    result++;
+  result += kSignatureSize + 2 + kFinishHeaderSize;
+  return result;
+}
+
+UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
+{
+  UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
+  int testSize;
+  if (volSize > headersSizeBase)
+    testSize = volSize - headersSizeBase;
+  else
+    testSize = 1;
+  UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);
+  UInt64 pureSize = 1;
+  if (volSize > headersSize)
+    pureSize = volSize - headersSize;
+  return pureSize;
+}
+#endif
+
+HRESULT COutArchive::WriteFolder(const CFolder &folder)
+{
+  RINOK(WriteNumber(folder.Coders.Size()));
+  int i;
+  for (i = 0; i < folder.Coders.Size(); i++)
+  {
+    const CCoderInfo &coder = folder.Coders[i];
+    {
+      size_t propertiesSize = coder.Properties.GetCapacity();
+      
+      UInt64 id = coder.MethodID; 
+      int idSize;
+      for (idSize = 1; idSize < sizeof(id); idSize++)
+        if ((id >> (8 * idSize)) == 0)
+          break;
+      BYTE longID[15];
+      for (int t = idSize - 1; t >= 0 ; t--, id >>= 8)
+        longID[t] = (Byte)(id & 0xFF);
+      Byte b;
+      b = (Byte)(idSize & 0xF);
+      bool isComplex = !coder.IsSimpleCoder();
+      b |= (isComplex ? 0x10 : 0);
+      b |= ((propertiesSize != 0) ? 0x20 : 0 );
+      RINOK(WriteByte(b));
+      RINOK(WriteBytes(longID, idSize));
+      if (isComplex)
+      {
+        RINOK(WriteNumber(coder.NumInStreams));
+        RINOK(WriteNumber(coder.NumOutStreams));
+      }
+      if (propertiesSize == 0)
+        continue;
+      RINOK(WriteNumber(propertiesSize));
+      RINOK(WriteBytes(coder.Properties, propertiesSize));
+    }
+  }
+  for (i = 0; i < folder.BindPairs.Size(); i++)
+  {
+    const CBindPair &bindPair = folder.BindPairs[i];
+    RINOK(WriteNumber(bindPair.InIndex));
+    RINOK(WriteNumber(bindPair.OutIndex));
+  }
+  if (folder.PackStreams.Size() > 1)
+    for (i = 0; i < folder.PackStreams.Size(); i++)
+    {
+      RINOK(WriteNumber(folder.PackStreams[i]));
+    }
+  return S_OK;
+}
+
+HRESULT COutArchive::WriteBoolVector(const CBoolVector &boolVector)
+{
+  Byte b = 0;
+  Byte mask = 0x80;
+  for(int i = 0; i < boolVector.Size(); i++)
+  {
+    if (boolVector[i])
+      b |= mask;
+    mask >>= 1;
+    if (mask == 0)
+    {
+      RINOK(WriteByte(b));
+      mask = 0x80;
+      b = 0;
+    }
+  }
+  if (mask != 0x80)
+  {
+    RINOK(WriteByte(b));
+  }
+  return S_OK;
+}
+
+
+HRESULT COutArchive::WriteHashDigests(
+    const CRecordVector<bool> &digestsDefined,
+    const CRecordVector<UInt32> &digests)
+{
+  int numDefined = 0;
+  int i;
+  for(i = 0; i < digestsDefined.Size(); i++)
+    if (digestsDefined[i])
+      numDefined++;
+  if (numDefined == 0)
+    return S_OK;
+
+  RINOK(WriteByte(NID::kCRC));
+  if (numDefined == digestsDefined.Size())
+  {
+    RINOK(WriteByte(1));
+  }
+  else
+  {
+    RINOK(WriteByte(0));
+    RINOK(WriteBoolVector(digestsDefined));
+  }
+  for(i = 0; i < digests.Size(); i++)
+  {
+    if(digestsDefined[i])
+      RINOK(WriteUInt32(digests[i]));
+  }
+  return S_OK;
+}
+
+HRESULT COutArchive::WritePackInfo(
+    UInt64 dataOffset,
+    const CRecordVector<UInt64> &packSizes,
+    const CRecordVector<bool> &packCRCsDefined,
+    const CRecordVector<UInt32> &packCRCs)
+{
+  if (packSizes.IsEmpty())
+    return S_OK;
+  RINOK(WriteByte(NID::kPackInfo));
+  RINOK(WriteNumber(dataOffset));
+  RINOK(WriteNumber(packSizes.Size()));
+  RINOK(WriteByte(NID::kSize));
+  for(int i = 0; i < packSizes.Size(); i++)
+    RINOK(WriteNumber(packSizes[i]));
+
+  RINOK(WriteHashDigests(packCRCsDefined, packCRCs));
+  
+  return WriteByte(NID::kEnd);
+}
+
+HRESULT COutArchive::WriteUnPackInfo(const CObjectVector<CFolder> &folders)
+{
+  if (folders.IsEmpty())
+    return S_OK;
+
+  RINOK(WriteByte(NID::kUnPackInfo));
+
+  RINOK(WriteByte(NID::kFolder));
+  RINOK(WriteNumber(folders.Size()));
+  {
+    RINOK(WriteByte(0));
+    for(int i = 0; i < folders.Size(); i++)
+      RINOK(WriteFolder(folders[i]));
+  }
+  
+  RINOK(WriteByte(NID::kCodersUnPackSize));
+  int i;
+  for(i = 0; i < folders.Size(); i++)
+  {
+    const CFolder &folder = folders[i];
+    for (int j = 0; j < folder.UnPackSizes.Size(); j++)
+      RINOK(WriteNumber(folder.UnPackSizes[j]));
+  }
+
+  CRecordVector<bool> unPackCRCsDefined;
+  CRecordVector<UInt32> unPackCRCs;
+  for(i = 0; i < folders.Size(); i++)
+  {
+    const CFolder &folder = folders[i];
+    unPackCRCsDefined.Add(folder.UnPackCRCDefined);
+    unPackCRCs.Add(folder.UnPackCRC);
+  }
+  RINOK(WriteHashDigests(unPackCRCsDefined, unPackCRCs));
+
+  return WriteByte(NID::kEnd);
+}
+
+HRESULT COutArchive::WriteSubStreamsInfo(
+    const CObjectVector<CFolder> &folders,
+    const CRecordVector<CNum> &numUnPackStreamsInFolders,
+    const CRecordVector<UInt64> &unPackSizes,
+    const CRecordVector<bool> &digestsDefined,
+    const CRecordVector<UInt32> &digests)
+{
+  RINOK(WriteByte(NID::kSubStreamsInfo));
+
+  int i;
+  for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
+  {
+    if (numUnPackStreamsInFolders[i] != 1)
+    {
+      RINOK(WriteByte(NID::kNumUnPackStream));
+      for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
+        RINOK(WriteNumber(numUnPackStreamsInFolders[i]));
+      break;
+    }
+  }
+ 
+
+  bool needFlag = true;
+  CNum index = 0;
+  for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
+    for (CNum j = 0; j < numUnPackStreamsInFolders[i]; j++)
+    {
+      if (j + 1 != numUnPackStreamsInFolders[i])
+      {
+        if (needFlag)
+          RINOK(WriteByte(NID::kSize));
+        needFlag = false;
+        RINOK(WriteNumber(unPackSizes[index]));
+      }
+      index++;
+    }
+
+  CRecordVector<bool> digestsDefined2;
+  CRecordVector<UInt32> digests2;
+
+  int digestIndex = 0;
+  for (i = 0; i < folders.Size(); i++)
+  {
+    int numSubStreams = (int)numUnPackStreamsInFolders[i];
+    if (numSubStreams == 1 && folders[i].UnPackCRCDefined)
+      digestIndex++;
+    else
+      for (int j = 0; j < numSubStreams; j++, digestIndex++)
+      {
+        digestsDefined2.Add(digestsDefined[digestIndex]);
+        digests2.Add(digests[digestIndex]);
+      }
+  }
+  RINOK(WriteHashDigests(digestsDefined2, digests2));
+  return WriteByte(NID::kEnd);
+}
+
+HRESULT COutArchive::WriteTime(
+    const CObjectVector<CFileItem> &files, Byte type)
+{
+  /////////////////////////////////////////////////
+  // CreationTime
+  CBoolVector boolVector;
+  boolVector.Reserve(files.Size());
+  bool thereAreDefined = false;
+  bool allDefined = true;
+  int i;
+  for(i = 0; i < files.Size(); i++)
+  {
+    const CFileItem &item = files[i];
+    bool defined;
+    switch(type)
+    {
+      case NID::kCreationTime:
+        defined = item.IsCreationTimeDefined;
+        break;
+      case NID::kLastWriteTime:
+        defined = item.IsLastWriteTimeDefined;
+        break;
+      case NID::kLastAccessTime:
+        defined = item.IsLastAccessTimeDefined;
+        break;
+      default:
+        throw 1;
+    }
+    boolVector.Add(defined);
+    thereAreDefined = (thereAreDefined || defined);
+    allDefined = (allDefined && defined);
+  }
+  if (!thereAreDefined)
+    return S_OK;
+  RINOK(WriteByte(type));
+  size_t dataSize = 1 + 1;
+    dataSize += files.Size() * 8;
+  if (allDefined)
+  {
+    RINOK(WriteNumber(dataSize));
+    WriteByte(1);
+  }
+  else
+  {
+    RINOK(WriteNumber(1 + (boolVector.Size() + 7) / 8 + dataSize));
+    WriteByte(0);
+    RINOK(WriteBoolVector(boolVector));
+  }
+  RINOK(WriteByte(0));
+  for(i = 0; i < files.Size(); i++)
+  {
+    if (boolVector[i])
+    {
+      const CFileItem &item = files[i];
+      CArchiveFileTime timeValue;
+      timeValue.dwLowDateTime = 0;
+      timeValue.dwHighDateTime = 0;
+      switch(type)
+      {
+        case NID::kCreationTime:
+          timeValue = item.CreationTime;
+          break;
+        case NID::kLastWriteTime:
+          timeValue = item.LastWriteTime;
+          break;
+        case NID::kLastAccessTime:
+          timeValue = item.LastAccessTime;
+          break;
+      }
+      RINOK(WriteUInt32(timeValue.dwLowDateTime));
+      RINOK(WriteUInt32(timeValue.dwHighDateTime));
+    }
+  }
+  return S_OK;
+}
+
+HRESULT COutArchive::EncodeStream(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    CEncoder &encoder, const Byte *data, size_t dataSize,
+    CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
+{
+  CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp;
+  CMyComPtr<ISequentialInStream> stream = streamSpec;
+  streamSpec->Init(data, dataSize);
+  CFolder folderItem;
+  folderItem.UnPackCRCDefined = true;
+  folderItem.UnPackCRC = CrcCalc(data, dataSize);
+  UInt64 dataSize64 = dataSize;
+  RINOK(encoder.Encode(
+      EXTERNAL_CODECS_LOC_VARS
+      stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL))
+  folders.Add(folderItem);
+  return S_OK;
+}
+
+HRESULT COutArchive::EncodeStream(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    CEncoder &encoder, const CByteBuffer &data, 
+    CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
+{
+  return EncodeStream(
+      EXTERNAL_CODECS_LOC_VARS
+      encoder, data, data.GetCapacity(), packSizes, folders);
+}
+
+static void WriteUInt32ToBuffer(Byte *data, UInt32 value)
+{
+  for (int i = 0; i < 4; i++)
+  {
+    *data++ = (Byte)value;
+    value >>= 8;
+  }
+}
+
+static void WriteUInt64ToBuffer(Byte *data, UInt64 value)
+{
+  for (int i = 0; i < 8; i++)
+  {
+    *data++ = (Byte)value;
+    value >>= 8;
+  }
+}
+
+
+HRESULT COutArchive::WriteHeader(
+    const CArchiveDatabase &database,
+    const CHeaderOptions &headerOptions,
+    UInt64 &headerOffset)
+{
+  int i;
+  
+  /////////////////////////////////
+  // Names
+
+  CNum numDefinedNames = 0;
+  size_t namesDataSize = 0;
+  for(i = 0; i < database.Files.Size(); i++)
+  {
+    const UString &name = database.Files[i].Name;
+    if (!name.IsEmpty())
+      numDefinedNames++;
+    namesDataSize += (name.Length() + 1) * 2;
+  }
+
+  CByteBuffer namesData;
+  if (numDefinedNames > 0)
+  {
+    namesData.SetCapacity((size_t)namesDataSize);
+    size_t pos = 0;
+    for(int i = 0; i < database.Files.Size(); i++)
+    {
+      const UString &name = database.Files[i].Name;
+      for (int t = 0; t < name.Length(); t++)
+      {
+        wchar_t c = name[t];
+        namesData[pos++] = Byte(c);
+        namesData[pos++] = Byte(c >> 8);
+      }
+      namesData[pos++] = 0;
+      namesData[pos++] = 0;
+    }
+  }
+
+  /////////////////////////////////
+  // Write Attributes
+  CBoolVector attributesBoolVector;
+  attributesBoolVector.Reserve(database.Files.Size());
+  int numDefinedAttributes = 0;
+  for(i = 0; i < database.Files.Size(); i++)
+  {
+    bool defined = database.Files[i].AreAttributesDefined;
+    attributesBoolVector.Add(defined);
+    if (defined)
+      numDefinedAttributes++;
+  }
+
+  CByteBuffer attributesData;
+  if (numDefinedAttributes > 0)
+  {
+    attributesData.SetCapacity(numDefinedAttributes * 4);
+    size_t pos = 0;
+    for(i = 0; i < database.Files.Size(); i++)
+    {
+      const CFileItem &file = database.Files[i];
+      if (file.AreAttributesDefined)
+      {
+        WriteUInt32ToBuffer(attributesData + pos, file.Attributes);
+        pos += 4;
+      }
+    }
+  }
+
+  /////////////////////////////////
+  // Write StartPos
+  CBoolVector startsBoolVector;
+  startsBoolVector.Reserve(database.Files.Size());
+  int numDefinedStarts = 0;
+  for(i = 0; i < database.Files.Size(); i++)
+  {
+    bool defined = database.Files[i].IsStartPosDefined;
+    startsBoolVector.Add(defined);
+    if (defined)
+      numDefinedStarts++;
+  }
+
+  CByteBuffer startsData;
+  if (numDefinedStarts > 0)
+  {
+    startsData.SetCapacity(numDefinedStarts * 8);
+    size_t pos = 0;
+    for(i = 0; i < database.Files.Size(); i++)
+    {
+      const CFileItem &file = database.Files[i];
+      if (file.IsStartPosDefined)
+      {
+        WriteUInt64ToBuffer(startsData + pos, file.StartPos);
+        pos += 8;
+      }
+    }
+  }
+  
+  /////////////////////////////////
+  // Write Last Write Time
+  // /*
+  CNum numDefinedLastWriteTimes = 0;
+  for(i = 0; i < database.Files.Size(); i++)
+    if (database.Files[i].IsLastWriteTimeDefined)
+      numDefinedLastWriteTimes++;
+
+  if (numDefinedLastWriteTimes > 0)
+  {
+    CByteBuffer lastWriteTimeData;
+    lastWriteTimeData.SetCapacity(numDefinedLastWriteTimes * 8);
+    size_t pos = 0;
+    for(i = 0; i < database.Files.Size(); i++)
+    {
+      const CFileItem &file = database.Files[i];
+      if (file.IsLastWriteTimeDefined)
+      {
+        WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwLowDateTime);
+        pos += 4;
+        WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwHighDateTime);
+        pos += 4;
+      }
+    }
+  }
+  // */
+  
+
+  UInt64 packedSize = 0;
+  for(i = 0; i < database.PackSizes.Size(); i++)
+    packedSize += database.PackSizes[i];
+
+  headerOffset = packedSize;
+
+  _mainMode = true;
+
+  _outByte.SetStream(SeqStream);
+  _outByte.Init();
+  _crc = CRC_INIT_VAL;
+
+
+  RINOK(WriteByte(NID::kHeader));
+
+  // Archive Properties
+
+  if (database.Folders.Size() > 0)
+  {
+    RINOK(WriteByte(NID::kMainStreamsInfo));
+    RINOK(WritePackInfo(0, database.PackSizes, 
+        database.PackCRCsDefined,
+        database.PackCRCs));
+
+    RINOK(WriteUnPackInfo(database.Folders));
+
+    CRecordVector<UInt64> unPackSizes;
+    CRecordVector<bool> digestsDefined;
+    CRecordVector<UInt32> digests;
+    for (i = 0; i < database.Files.Size(); i++)
+    {
+      const CFileItem &file = database.Files[i];
+      if (!file.HasStream)
+        continue;
+      unPackSizes.Add(file.UnPackSize);
+      digestsDefined.Add(file.IsFileCRCDefined);
+      digests.Add(file.FileCRC);
+    }
+
+    RINOK(WriteSubStreamsInfo(
+        database.Folders,
+        database.NumUnPackStreamsVector,
+        unPackSizes,
+        digestsDefined,
+        digests));
+    RINOK(WriteByte(NID::kEnd));
+  }
+
+  if (database.Files.IsEmpty())
+  {
+    RINOK(WriteByte(NID::kEnd));
+    return _outByte.Flush();
+  }
+
+  RINOK(WriteByte(NID::kFilesInfo));
+  RINOK(WriteNumber(database.Files.Size()));
+
+  CBoolVector emptyStreamVector;
+  emptyStreamVector.Reserve(database.Files.Size());
+  int numEmptyStreams = 0;
+  for(i = 0; i < database.Files.Size(); i++)
+    if (database.Files[i].HasStream)
+      emptyStreamVector.Add(false);
+    else
+    {
+      emptyStreamVector.Add(true);
+      numEmptyStreams++;
+    }
+  if (numEmptyStreams > 0)
+  {
+    RINOK(WriteByte(NID::kEmptyStream));
+    RINOK(WriteNumber((emptyStreamVector.Size() + 7) / 8));
+    RINOK(WriteBoolVector(emptyStreamVector));
+
+    CBoolVector emptyFileVector, antiVector;
+    emptyFileVector.Reserve(numEmptyStreams);
+    antiVector.Reserve(numEmptyStreams);
+    CNum numEmptyFiles = 0, numAntiItems = 0;
+    for(i = 0; i < database.Files.Size(); i++)
+    {
+      const CFileItem &file = database.Files[i];
+      if (!file.HasStream)
+      {
+        emptyFileVector.Add(!file.IsDirectory);
+        if (!file.IsDirectory)
+          numEmptyFiles++;
+        antiVector.Add(file.IsAnti);
+        if (file.IsAnti)
+          numAntiItems++;
+      }
+    }
+
+    if (numEmptyFiles > 0)
+    {
+      RINOK(WriteByte(NID::kEmptyFile));
+      RINOK(WriteNumber((emptyFileVector.Size() + 7) / 8));
+      RINOK(WriteBoolVector(emptyFileVector));
+    }
+
+    if (numAntiItems > 0)
+    {
+      RINOK(WriteByte(NID::kAnti));
+      RINOK(WriteNumber((antiVector.Size() + 7) / 8));
+      RINOK(WriteBoolVector(antiVector));
+    }
+  }
+
+  if (numDefinedNames > 0)
+  {
+    /////////////////////////////////////////////////
+    RINOK(WriteByte(NID::kName));
+    {
+      RINOK(WriteNumber(1 + namesData.GetCapacity()));
+      RINOK(WriteByte(0));
+      RINOK(WriteBytes(namesData));
+    }
+
+  }
+
+  if (headerOptions.WriteCreated)
+  {
+    RINOK(WriteTime(database.Files, NID::kCreationTime));
+  }
+  if (headerOptions.WriteModified)
+  {
+    RINOK(WriteTime(database.Files, NID::kLastWriteTime));
+  }
+  if (headerOptions.WriteAccessed)
+  {
+    RINOK(WriteTime(database.Files, NID::kLastAccessTime));
+  }
+
+  if (numDefinedAttributes > 0)
+  {
+    RINOK(WriteByte(NID::kWinAttributes));
+    size_t size = 2;
+    if (numDefinedAttributes != database.Files.Size())
+      size += (attributesBoolVector.Size() + 7) / 8 + 1;
+      size += attributesData.GetCapacity();
+
+    RINOK(WriteNumber(size));
+    if (numDefinedAttributes == database.Files.Size())
+    {
+      RINOK(WriteByte(1));
+    }
+    else
+    {
+      RINOK(WriteByte(0));
+      RINOK(WriteBoolVector(attributesBoolVector));
+    }
+
+    {
+      RINOK(WriteByte(0));
+      RINOK(WriteBytes(attributesData));
+    }
+  }
+
+  if (numDefinedStarts > 0)
+  {
+    RINOK(WriteByte(NID::kStartPos));
+    size_t size = 2;
+    if (numDefinedStarts != database.Files.Size())
+      size += (startsBoolVector.Size() + 7) / 8 + 1;
+      size += startsData.GetCapacity();
+
+    RINOK(WriteNumber(size));
+    if (numDefinedStarts == database.Files.Size())
+    {
+      RINOK(WriteByte(1));
+    }
+    else
+    {
+      RINOK(WriteByte(0));
+      RINOK(WriteBoolVector(startsBoolVector));
+    }
+
+    {
+      RINOK(WriteByte(0));
+      RINOK(WriteBytes(startsData));
+    }
+  }
+
+  RINOK(WriteByte(NID::kEnd)); // for files
+  RINOK(WriteByte(NID::kEnd)); // for headers
+
+  return _outByte.Flush();
+}
+
+HRESULT COutArchive::WriteDatabase(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    const CArchiveDatabase &database,
+    const CCompressionMethodMode *options, 
+    const CHeaderOptions &headerOptions)
+{
+  UInt64 headerOffset;
+  UInt32 headerCRC;
+  UInt64 headerSize;
+  if (database.IsEmpty())
+  {
+    headerSize = 0;
+    headerOffset = 0;
+    headerCRC = CrcCalc(0, 0);
+  }
+  else
+  {
+    _dynamicBuffer.Init();
+    _dynamicMode = false;
+
+    if (options != 0)
+      if (options->IsEmpty())
+        options = 0;
+    if (options != 0)
+      if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
+        _dynamicMode = true;
+    RINOK(WriteHeader(database, headerOptions, headerOffset));
+
+    if (_dynamicMode)
+    {
+      CCompressionMethodMode encryptOptions;
+      encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
+      encryptOptions.Password = options->Password;
+      CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
+      CRecordVector<UInt64> packSizes;
+      CObjectVector<CFolder> folders;
+      RINOK(EncodeStream(
+          EXTERNAL_CODECS_LOC_VARS
+          encoder, _dynamicBuffer, 
+          _dynamicBuffer.GetSize(), packSizes, folders));
+      _dynamicMode = false;
+      _mainMode = true;
+      
+      _outByte.SetStream(SeqStream);
+      _outByte.Init();
+      _crc = CRC_INIT_VAL;
+      
+      if (folders.Size() == 0)
+        throw 1;
+
+      RINOK(WriteID(NID::kEncodedHeader));
+      RINOK(WritePackInfo(headerOffset, packSizes, 
+        CRecordVector<bool>(), CRecordVector<UInt32>()));
+      RINOK(WriteUnPackInfo(folders));
+      RINOK(WriteByte(NID::kEnd));
+      for (int i = 0; i < packSizes.Size(); i++)
+        headerOffset += packSizes[i];
+      RINOK(_outByte.Flush());
+    }
+    headerCRC = CRC_GET_DIGEST(_crc);
+    headerSize = _outByte.GetProcessedSize();
+  }
+  #ifdef _7Z_VOL
+  if (_endMarker)
+  {
+    CFinishHeader h;
+    h.NextHeaderSize = headerSize;
+    h.NextHeaderCRC = headerCRC;
+    h.NextHeaderOffset = 
+        UInt64(0) - (headerSize + 
+        4 + kFinishHeaderSize);
+    h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
+    h.AdditionalStartBlockSize = 0;
+    RINOK(WriteFinishHeader(h));
+    return WriteFinishSignature();
+  }
+  else
+  #endif
+  {
+    CStartHeader h;
+    h.NextHeaderSize = headerSize;
+    h.NextHeaderCRC = headerCRC;
+    h.NextHeaderOffset = headerOffset;
+    RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
+    return WriteStartHeader(h);
+  }
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zOut.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zOut.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zOut.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,193 @@
+// 7z/Out.h
+
+#ifndef __7Z_OUT_H
+#define __7Z_OUT_H
+
+#include "7zHeader.h"
+#include "7zItem.h"
+#include "7zCompressionMode.h"
+#include "7zEncode.h"
+
+#include "../../Common/OutBuffer.h"
+#include "../../../Common/DynamicBuffer.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CWriteBufferLoc
+{
+  Byte *_data;
+  size_t _size;
+  size_t _pos;
+public:
+  CWriteBufferLoc(): _size(0), _pos(0) {}
+  void Init(Byte *data, size_t size)  
+  { 
+    _pos = 0;
+    _data = data;
+    _size = size; 
+  }
+  HRESULT Write(const void *data, size_t size)
+  {
+    if (_pos + size > _size)
+      return E_FAIL;
+    memmove(_data + _pos, data, size);
+    _pos += size;
+    return S_OK; 
+  }
+};
+
+class CWriteDynamicBuffer
+{
+  CByteDynamicBuffer _buffer;
+  size_t _pos;
+public:
+  CWriteDynamicBuffer(): _pos(0) {}
+  void Init()  
+  { 
+    _pos = 0;
+  }
+  void Write(const void *data, size_t size)
+  {
+    if (_pos + size > _buffer.GetCapacity())
+      _buffer.EnsureCapacity(_pos + size);
+    memmove(((Byte *)_buffer) +_pos, data, size);
+    _pos += size;
+  }
+  operator Byte *() { return (Byte *)_buffer; };
+  operator const Byte *() const { return (const Byte *)_buffer; };
+  size_t GetSize() const { return _pos; }
+};
+
+struct CHeaderOptions
+{
+  // bool UseAdditionalHeaderStreams;
+  bool CompressMainHeader;
+  bool WriteModified;
+  bool WriteCreated;
+  bool WriteAccessed;
+
+  CHeaderOptions(): 
+      // UseAdditionalHeaderStreams(false), 
+      CompressMainHeader(true),
+      WriteModified(true),
+      WriteCreated(false),
+      WriteAccessed(false) {} 
+};
+
+class COutArchive
+{
+  UInt64 _prefixHeaderPos;
+
+  HRESULT WriteDirect(const void *data, UInt32 size);
+  HRESULT WriteDirectByte(Byte b) { return WriteDirect(&b, 1); }
+  HRESULT WriteDirectUInt32(UInt32 value);
+  HRESULT WriteDirectUInt64(UInt64 value);
+  
+  HRESULT WriteBytes(const void *data, size_t size);
+  HRESULT WriteBytes(const CByteBuffer &data);
+  HRESULT WriteByte(Byte b);
+  HRESULT WriteUInt32(UInt32 value);
+  HRESULT WriteNumber(UInt64 value);
+  HRESULT WriteID(UInt64 value) { return WriteNumber(value); }
+
+  HRESULT WriteFolder(const CFolder &folder);
+  HRESULT WriteFileHeader(const CFileItem &itemInfo);
+  HRESULT WriteBoolVector(const CBoolVector &boolVector);
+  HRESULT WriteHashDigests(
+      const CRecordVector<bool> &digestsDefined,
+      const CRecordVector<UInt32> &hashDigests);
+
+  HRESULT WritePackInfo(
+      UInt64 dataOffset,
+      const CRecordVector<UInt64> &packSizes,
+      const CRecordVector<bool> &packCRCsDefined,
+      const CRecordVector<UInt32> &packCRCs);
+
+  HRESULT WriteUnPackInfo(const CObjectVector<CFolder> &folders);
+
+  HRESULT WriteSubStreamsInfo(
+      const CObjectVector<CFolder> &folders,
+      const CRecordVector<CNum> &numUnPackStreamsInFolders,
+      const CRecordVector<UInt64> &unPackSizes,
+      const CRecordVector<bool> &digestsDefined,
+      const CRecordVector<UInt32> &hashDigests);
+
+  /*
+  HRESULT WriteStreamsInfo(
+      UInt64 dataOffset,
+      const CRecordVector<UInt64> &packSizes,
+      const CRecordVector<bool> &packCRCsDefined,
+      const CRecordVector<UInt32> &packCRCs,
+      bool externalFolders,
+      UInt64 externalFoldersStreamIndex,
+      const CObjectVector<CFolder> &folders,
+      const CRecordVector<CNum> &numUnPackStreamsInFolders,
+      const CRecordVector<UInt64> &unPackSizes,
+      const CRecordVector<bool> &digestsDefined,
+      const CRecordVector<UInt32> &hashDigests);
+  */
+
+
+  HRESULT WriteTime(const CObjectVector<CFileItem> &files, Byte type);
+
+  HRESULT EncodeStream(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      CEncoder &encoder, const Byte *data, size_t dataSize,
+      CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);
+  HRESULT EncodeStream(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      CEncoder &encoder, const CByteBuffer &data, 
+      CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);
+  HRESULT WriteHeader(
+      const CArchiveDatabase &database,
+      const CHeaderOptions &headerOptions,
+      UInt64 &headerOffset);
+  
+  bool _mainMode;
+
+  bool _dynamicMode;
+
+  bool _countMode;
+  size_t _countSize;
+  COutBuffer _outByte;
+  CWriteBufferLoc _outByte2;
+  CWriteDynamicBuffer _dynamicBuffer;
+  UInt32 _crc;
+
+  #ifdef _7Z_VOL
+  bool _endMarker;
+  #endif
+
+  HRESULT WriteSignature();
+  #ifdef _7Z_VOL
+  HRESULT WriteFinishSignature();
+  #endif
+  HRESULT WriteStartHeader(const CStartHeader &h);
+  #ifdef _7Z_VOL
+  HRESULT WriteFinishHeader(const CFinishHeader &h);
+  #endif
+  CMyComPtr<IOutStream> Stream;
+public:
+
+  COutArchive() { _outByte.Create(1 << 16); }
+  CMyComPtr<ISequentialOutStream> SeqStream;
+  HRESULT Create(ISequentialOutStream *stream, bool endMarker);
+  void Close();
+  HRESULT SkeepPrefixArchiveHeader();
+  HRESULT WriteDatabase(
+      DECL_EXTERNAL_CODECS_LOC_VARS
+      const CArchiveDatabase &database,
+      const CCompressionMethodMode *options, 
+      const CHeaderOptions &headerOptions);
+
+  #ifdef _7Z_VOL
+  static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);
+  static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);
+  #endif
+
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zProperties.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zProperties.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zProperties.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,162 @@
+// 7zProperties.cpp
+
+#include "StdAfx.h"
+
+#include "7zProperties.h"
+#include "7zHeader.h"
+#include "7zHandler.h"
+
+// #define _MULTI_PACK
+
+namespace NArchive {
+namespace N7z {
+
+struct CPropMap
+{
+  UInt64 FilePropID;
+  STATPROPSTG StatPROPSTG;
+};
+
+CPropMap kPropMap[] = 
+{
+  { NID::kName, NULL, kpidPath, VT_BSTR},
+  { NID::kSize, NULL, kpidSize, VT_UI8},
+  { NID::kPackInfo, NULL, kpidPackedSize, VT_UI8},
+  
+  #ifdef _MULTI_PACK
+  { 100, L"Pack0", kpidPackedSize0, VT_UI8},
+  { 101, L"Pack1", kpidPackedSize1, VT_UI8},
+  { 102, L"Pack2", kpidPackedSize2, VT_UI8},
+  { 103, L"Pack3", kpidPackedSize3, VT_UI8},
+  { 104, L"Pack4", kpidPackedSize4, VT_UI8},
+  #endif
+
+  { NID::kCreationTime, NULL, kpidCreationTime, VT_FILETIME},
+  { NID::kLastWriteTime, NULL, kpidLastWriteTime, VT_FILETIME},
+  { NID::kLastAccessTime, NULL, kpidLastAccessTime, VT_FILETIME},
+  { NID::kWinAttributes, NULL, kpidAttributes, VT_UI4},
+  { NID::kStartPos, NULL, kpidPosition, VT_UI4},
+
+  { NID::kCRC, NULL, kpidCRC, VT_UI4},
+  
+  { NID::kAnti, NULL, kpidIsAnti, VT_BOOL},
+  // { 97, NULL, kpidSolid, VT_BOOL},
+  #ifndef _SFX
+  { 98, NULL, kpidMethod, VT_BSTR},
+  { 99, NULL, kpidBlock, VT_UI4}
+  #endif
+};
+
+static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]);
+
+static int FindPropInMap(UInt64 filePropID)
+{
+  for (int i = 0; i < kPropMapSize; i++)
+    if (kPropMap[i].FilePropID == filePropID)
+      return i;
+  return -1;
+}
+
+static void CopyOneItem(CRecordVector<UInt64> &src, 
+    CRecordVector<UInt64> &dest, UInt32 item)
+{
+  for (int i = 0; i < src.Size(); i++)
+    if (src[i] == item)
+    {
+      dest.Add(item);
+      src.Delete(i);
+      return;
+    }
+}
+
+static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)
+{
+  for (int i = 0; i < src.Size(); i++)
+    if (src[i] == item)
+    {
+      src.Delete(i);
+      return;
+    }
+}
+
+static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)
+{
+  for (int i = 0; i < dest.Size(); i++)
+    if (dest[i] == item)
+    {
+      dest.Delete(i);
+      break;
+    }
+  dest.Insert(0, item);
+}
+
+void CHandler::FillPopIDs()
+{ 
+  _fileInfoPopIDs.Clear();
+
+  #ifdef _7Z_VOL
+  if(_volumes.Size() < 1)
+    return;
+  const CVolume &volume = _volumes.Front();
+  const CArchiveDatabaseEx &_database = volume.Database;
+  #endif
+
+  CRecordVector<UInt64> fileInfoPopIDs = _database.ArchiveInfo.FileInfoPopIDs;
+
+  RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
+  RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
+
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName);
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti);
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize);
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo);
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCreationTime);
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastWriteTime);
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastAccessTime);
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes);
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC);
+  CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment);
+  _fileInfoPopIDs += fileInfoPopIDs; 
+ 
+  #ifndef _SFX
+  _fileInfoPopIDs.Add(98);
+  _fileInfoPopIDs.Add(99);
+  #endif
+  #ifdef _MULTI_PACK
+  _fileInfoPopIDs.Add(100);
+  _fileInfoPopIDs.Add(101);
+  _fileInfoPopIDs.Add(102);
+  _fileInfoPopIDs.Add(103);
+  _fileInfoPopIDs.Add(104);
+  #endif
+
+  #ifndef _SFX
+  InsertToHead(_fileInfoPopIDs, NID::kLastWriteTime);
+  InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
+  InsertToHead(_fileInfoPopIDs, NID::kSize);
+  InsertToHead(_fileInfoPopIDs, NID::kName);
+  #endif
+}
+
+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)
+{
+  *numProperties = _fileInfoPopIDs.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index,     
+      BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+  if((int)index >= _fileInfoPopIDs.Size())
+    return E_INVALIDARG;
+  int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);
+  if (indexInMap == -1)
+    return E_INVALIDARG;
+  const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;
+  *propID = srcItem.propid;
+  *varType = srcItem.vt;
+  *name = 0;
+  return S_OK;
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zProperties.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zProperties.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zProperties.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,22 @@
+// 7zProperties.h
+
+#ifndef __7Z_PROPERTIES_H
+#define __7Z_PROPERTIES_H
+
+#include "../../PropID.h"
+
+namespace NArchive {
+namespace N7z {
+
+enum
+{
+  kpidPackedSize0 = kpidUserDefined,
+  kpidPackedSize1, 
+  kpidPackedSize2,
+  kpidPackedSize3,
+  kpidPackedSize4
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zRegister.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zRegister.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zRegister.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,18 @@
+// 7zRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "7zHandler.h"
+static IInArchive *CreateArc() { return new NArchive::N7z::CHandler;  }
+#ifndef EXTRACT_ONLY
+static IOutArchive *CreateArcOut() { return new NArchive::N7z::CHandler;  }
+#else
+#define CreateArcOut 0
+#endif
+
+static CArcInfo g_ArcInfo =
+  { L"7z", L"7z", 0, 7, {'7' + 1 , 'z', 0xBC, 0xAF, 0x27, 0x1C}, 6, false, CreateArc, CreateArcOut };
+
+REGISTER_ARC_DEC_SIG(7z)

Added: trunk/lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zSpecStream.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// 7zSpecStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zSpecStream.h"
+
+STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize;
+  HRESULT result = _stream->Read(data, size, &realProcessedSize);
+  _size += realProcessedSize;
+  if (processedSize != 0)
+    *processedSize = realProcessedSize;
+  return result; 
+}
+
+STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(
+    UInt64 subStream, UInt64 *value)
+{
+  if (_getSubStreamSize == NULL)
+    return E_NOTIMPL;
+  return  _getSubStreamSize->GetSubStreamSize(subStream, value);
+}
+

Added: trunk/lzma/CPP/7zip/Archive/7z/7zSpecStream.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zSpecStream.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zSpecStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,35 @@
+// 7zSpecStream.h
+
+#ifndef __7Z_SPEC_STREAM_H
+#define __7Z_SPEC_STREAM_H
+
+#include "../../IStream.h"
+#include "../../ICoder.h"
+#include "../../../Common/MyCom.h"
+
+class CSequentialInStreamSizeCount2: 
+  public ISequentialInStream,
+  public ICompressGetSubStreamSize,
+  public CMyUnknownImp
+{
+  CMyComPtr<ISequentialInStream> _stream;
+  CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;
+  UInt64 _size;
+public:
+  void Init(ISequentialInStream *stream)
+  {
+    _stream = stream;
+    _getSubStreamSize = 0;
+    _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
+    _size = 0;
+  }
+  UInt64 GetSize() const { return _size; }
+
+  MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/7zUpdate.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zUpdate.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zUpdate.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1029 @@
+// UpdateMain.cpp
+
+#include "StdAfx.h"
+
+#include "7zUpdate.h"
+#include "7zFolderInStream.h"
+#include "7zEncode.h"
+#include "7zHandler.h"
+#include "7zOut.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/LimitedStreams.h"
+#include "../Common/ItemNameUtils.h"
+
+namespace NArchive {
+namespace N7z {
+
+static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";
+static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;
+static const UInt32 kAlgorithmForBCJ2_LZMA = 1;
+static const UInt32 kNumFastBytesForBCJ2_LZMA = 64;
+
+static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, 
+    UInt64 position, UInt64 size, ICompressProgressInfo *progress)
+{
+  RINOK(inStream->Seek(position, STREAM_SEEK_SET, 0));
+  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+  CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
+  streamSpec->SetStream(inStream);
+  streamSpec->Init(size);
+
+  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+  RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
+  return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);
+}
+
+static int GetReverseSlashPos(const UString &name)
+{
+  int slashPos = name.ReverseFind(L'/');
+  #ifdef _WIN32
+  int slash1Pos = name.ReverseFind(L'\\');
+  slashPos = MyMax(slashPos, slash1Pos);
+  #endif
+  return slashPos;
+}
+
+int CUpdateItem::GetExtensionPos() const
+{
+  int slashPos = GetReverseSlashPos(Name);
+  int dotPos = Name.ReverseFind(L'.');
+  if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
+    return Name.Length();
+  return dotPos + 1;
+}
+
+UString CUpdateItem::GetExtension() const
+{
+  return Name.Mid(GetExtensionPos());
+}
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)
+{
+  size_t c1 = a1.GetCapacity();
+  size_t c2 = a2.GetCapacity();
+  RINOZ(MyCompare(c1, c2));
+  for (size_t i = 0; i < c1; i++)
+    RINOZ(MyCompare(a1[i], a2[i]));
+  return 0;
+}
+
+static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
+{
+  RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams));
+  RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams));
+  RINOZ(MyCompare(c1.MethodID, c2.MethodID));
+  return CompareBuffers(c1.Properties, c2.Properties);
+}
+
+static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)
+{
+  RINOZ(MyCompare(b1.InIndex, b2.InIndex));
+  return MyCompare(b1.OutIndex, b2.OutIndex);
+}
+
+static int CompareFolders(const CFolder &f1, const CFolder &f2)
+{
+  int s1 = f1.Coders.Size();
+  int s2 = f2.Coders.Size();
+  RINOZ(MyCompare(s1, s2));
+  int i;
+  for (i = 0; i < s1; i++)
+    RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
+  s1 = f1.BindPairs.Size();
+  s2 = f2.BindPairs.Size();
+  RINOZ(MyCompare(s1, s2));
+  for (i = 0; i < s1; i++)
+    RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
+  return 0;
+}
+
+static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
+{
+  return MyStringCompareNoCase(f1.Name, f2.Name);
+}
+
+static int CompareFolderRefs(const int *p1, const int *p2, void *param)
+{
+  int i1 = *p1;
+  int i2 = *p2;
+  const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;
+  RINOZ(CompareFolders(
+      db.Folders[i1],
+      db.Folders[i2]));
+  RINOZ(MyCompare(
+      db.NumUnPackStreamsVector[i1],
+      db.NumUnPackStreamsVector[i2]));
+  if (db.NumUnPackStreamsVector[i1] == 0)
+    return 0;
+  return CompareFiles(
+      db.Files[db.FolderStartFileIndex[i1]],
+      db.Files[db.FolderStartFileIndex[i2]]);
+}
+
+////////////////////////////////////////////////////////////
+
+static int CompareEmptyItems(const int *p1, const int *p2, void *param)
+{
+  const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
+  const CUpdateItem &u1 = updateItems[*p1];
+  const CUpdateItem &u2 = updateItems[*p2];
+  if (u1.IsDirectory != u2.IsDirectory)
+    return (u1.IsDirectory) ? 1 : -1;
+  if (u1.IsDirectory)
+  {
+    if (u1.IsAnti != u2.IsAnti)
+      return (u1.IsAnti ? 1 : -1);
+    int n = MyStringCompareNoCase(u1.Name, u2.Name);
+    return -n;
+  }
+  if (u1.IsAnti != u2.IsAnti)
+    return (u1.IsAnti ? 1 : -1);
+  return MyStringCompareNoCase(u1.Name, u2.Name);
+}
+
+static const char *g_Exts = 
+  " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo" 
+  " zip jar ear war msi"
+  " 3gp avi mov mpeg mpg mpe wmv"
+  " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"
+  " swf "
+  " chm hxi hxs"
+  " gif jpeg jpg jp2 png tiff  bmp ico psd psp"
+  " awg ps eps cgm dxf svg vrml wmf emf ai md"
+  " cad dwg pps key sxi"
+  " max 3ds"
+  " iso bin nrg mdf img pdi tar cpio xpi"
+  " vfd vhd vud vmc vsv"
+  " vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
+  " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" 
+  " f77 f f90 f95"
+  " asm sql manifest dep "
+  " mak clw csproj vcproj sln dsp dsw "
+  " class "
+  " bat cmd"
+  " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
+  " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"
+  " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"
+  " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"
+  " abw afp cwk lwp wpd wps wpt wrf wri"
+  " abf afm bdf fon mgf otf pcf pfa snf ttf"
+  " dbf mdb nsf ntf wdb db fdb gdb"
+  " exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
+  " pdb pch idb ncb opt";
+
+int GetExtIndex(const char *ext)
+{
+  int extIndex = 1;
+  const char *p = g_Exts;
+  for (;;)
+  {
+    char c = *p++;
+    if (c == 0)
+      return extIndex;
+    if (c == ' ')
+      continue;
+    int pos = 0;
+    for (;;)
+    {
+      char c2 = ext[pos++];
+      if (c2 == 0 && (c == 0 || c == ' '))
+        return extIndex;
+      if (c != c2)
+        break;
+      c = *p++;
+    }
+    extIndex++;
+    for (;;)
+    {
+      if (c == 0)
+        return extIndex;
+      if (c == ' ')
+        break;
+      c = *p++;
+    }
+  }
+}
+
+struct CRefItem
+{
+  UInt32 Index;
+  const CUpdateItem *UpdateItem;
+  UInt32 ExtensionPos;
+  UInt32 NamePos;
+  int ExtensionIndex;
+  CRefItem(UInt32 index, const CUpdateItem &updateItem, bool sortByType):
+    Index(index),
+    UpdateItem(&updateItem),
+    ExtensionPos(0),
+    NamePos(0),
+    ExtensionIndex(0)
+  {
+    if (sortByType)
+    {
+      int slashPos = GetReverseSlashPos(updateItem.Name);
+      NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0);
+      int dotPos = updateItem.Name.ReverseFind(L'.');
+      if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
+        ExtensionPos = updateItem.Name.Length();
+      else 
+      {
+        ExtensionPos = dotPos + 1;
+        UString us = updateItem.Name.Mid(ExtensionPos);
+        if (!us.IsEmpty())
+        {
+          us.MakeLower();
+          int i;
+          AString s;
+          for (i = 0; i < us.Length(); i++)
+          {
+            wchar_t c = us[i];
+            if (c >= 0x80)
+              break;
+            s += (char)c;
+          }
+          if (i == us.Length())
+            ExtensionIndex = GetExtIndex(s);
+          else
+            ExtensionIndex = 0;
+        }
+      }
+    }
+  }
+};
+
+static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)
+{
+  const CRefItem &a1 = *p1;
+  const CRefItem &a2 = *p2;
+  const CUpdateItem &u1 = *a1.UpdateItem;
+  const CUpdateItem &u2 = *a2.UpdateItem;
+  int n;
+  if (u1.IsDirectory != u2.IsDirectory)
+    return (u1.IsDirectory) ? 1 : -1;
+  if (u1.IsDirectory)
+  {
+    if (u1.IsAnti != u2.IsAnti)
+      return (u1.IsAnti ? 1 : -1);
+    n = MyStringCompareNoCase(u1.Name, u2.Name);
+    return -n;
+  }
+  bool sortByType = *(bool *)param;
+  if (sortByType)
+  {
+    RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex))
+    RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));
+    RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));
+    if (u1.IsLastWriteTimeDefined && u2.IsLastWriteTimeDefined)
+      RINOZ(CompareFileTime(&u1.LastWriteTime, &u2.LastWriteTime));
+    RINOZ(MyCompare(u1.Size, u2.Size))
+  }
+  return MyStringCompareNoCase(u1.Name, u2.Name);
+}
+
+struct CSolidGroup
+{
+  CCompressionMethodMode Method;
+  CRecordVector<UInt32> Indices;
+};
+
+static wchar_t *g_ExeExts[] =
+{
+  L"dll",
+  L"exe",
+  L"ocx",
+  L"sfx",
+  L"sys"
+};
+
+static bool IsExeFile(const UString &ext)
+{
+  for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++)
+    if (ext.CompareNoCase(g_ExeExts[i]) == 0)
+      return true;
+  return false;
+}
+
+static const UInt64 k_LZMA  = 0x030101;
+static const UInt64 k_BCJ   = 0x03030103;
+static const UInt64 k_BCJ2  = 0x0303011B;
+
+static bool GetMethodFull(UInt64 methodID, 
+    UInt32 numInStreams, CMethodFull &methodResult)
+{
+  methodResult.Id = methodID;
+  methodResult.NumInStreams = numInStreams;
+  methodResult.NumOutStreams = 1;
+  return true;
+}
+
+static bool MakeExeMethod(const CCompressionMethodMode &method, 
+    bool bcj2Filter, CCompressionMethodMode &exeMethod)
+{
+  exeMethod = method;
+  if (bcj2Filter)
+  {
+    CMethodFull methodFull;
+    if (!GetMethodFull(k_BCJ2, 4, methodFull))
+      return false;
+    exeMethod.Methods.Insert(0, methodFull);
+    if (!GetMethodFull(k_LZMA, 1, methodFull))
+      return false;
+    {
+      CProp property;
+      property.Id = NCoderPropID::kAlgorithm;
+      property.Value = kAlgorithmForBCJ2_LZMA;
+      methodFull.Properties.Add(property);
+    }
+    {
+      CProp property;
+      property.Id = NCoderPropID::kMatchFinder;
+      property.Value = kMatchFinderForBCJ2_LZMA;
+      methodFull.Properties.Add(property);
+    }
+    {
+      CProp property;
+      property.Id = NCoderPropID::kDictionarySize;
+      property.Value = kDictionaryForBCJ2_LZMA;
+      methodFull.Properties.Add(property);
+    }
+    {
+      CProp property;
+      property.Id = NCoderPropID::kNumFastBytes;
+      property.Value = kNumFastBytesForBCJ2_LZMA;
+      methodFull.Properties.Add(property);
+    }
+
+    exeMethod.Methods.Add(methodFull);
+    exeMethod.Methods.Add(methodFull);
+    CBind bind;
+
+    bind.OutCoder = 0;
+    bind.InStream = 0;
+
+    bind.InCoder = 1;
+    bind.OutStream = 0;
+    exeMethod.Binds.Add(bind);
+
+    bind.InCoder = 2;
+    bind.OutStream = 1;
+    exeMethod.Binds.Add(bind);
+
+    bind.InCoder = 3;
+    bind.OutStream = 2;
+    exeMethod.Binds.Add(bind);
+  }
+  else
+  {
+    CMethodFull methodFull;
+    if (!GetMethodFull(k_BCJ, 1, methodFull))
+      return false;
+    exeMethod.Methods.Insert(0, methodFull);
+    CBind bind;
+    bind.OutCoder = 0;
+    bind.InStream = 0;
+    bind.InCoder = 1;
+    bind.OutStream = 0;
+    exeMethod.Binds.Add(bind);
+  }
+  return true;
+}   
+
+static void SplitFilesToGroups(
+    const CCompressionMethodMode &method, 
+    bool useFilters, bool maxFilter,
+    const CObjectVector<CUpdateItem> &updateItems,
+    CObjectVector<CSolidGroup> &groups)
+{
+  if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
+    useFilters = false;
+  groups.Clear();
+  groups.Add(CSolidGroup());
+  groups.Add(CSolidGroup());
+  CSolidGroup &generalGroup = groups[0];
+  CSolidGroup &exeGroup = groups[1];
+  generalGroup.Method = method;
+  int i;
+  for (i = 0; i < updateItems.Size(); i++)
+  {
+    const CUpdateItem &updateItem = updateItems[i];
+    if (!updateItem.NewData)
+      continue;
+    if (!updateItem.HasStream())
+      continue;
+    if (useFilters)
+    {
+      const UString name = updateItem.Name;
+      int dotPos = name.ReverseFind(L'.');
+      if (dotPos >= 0)
+      {
+        UString ext = name.Mid(dotPos + 1);
+        if (IsExeFile(ext))
+        {
+          exeGroup.Indices.Add(i);
+          continue;
+        }
+      }
+    }
+    generalGroup.Indices.Add(i);
+  }
+  if (exeGroup.Indices.Size() > 0)
+    if (!MakeExeMethod(method, maxFilter, exeGroup.Method))
+      exeGroup.Method = method;
+  for (i = 0; i < groups.Size();)
+    if (groups[i].Indices.Size() == 0)
+      groups.Delete(i);
+    else
+      i++;
+}
+
+static void FromUpdateItemToFileItem(const CUpdateItem &updateItem, 
+    CFileItem &file)
+{
+  file.Name = NItemName::MakeLegalName(updateItem.Name);
+  if (updateItem.AttributesAreDefined)
+    file.SetAttributes(updateItem.Attributes);
+  
+  if (updateItem.IsCreationTimeDefined)
+    file.SetCreationTime(updateItem.CreationTime);
+  if (updateItem.IsLastWriteTimeDefined)
+    file.SetLastWriteTime(updateItem.LastWriteTime);
+  if (updateItem.IsLastAccessTimeDefined)
+    file.SetLastAccessTime(updateItem.LastAccessTime);
+  
+  file.UnPackSize = updateItem.Size;
+  file.IsDirectory = updateItem.IsDirectory;
+  file.IsAnti = updateItem.IsAnti;
+  file.HasStream = updateItem.HasStream();
+}
+
+static HRESULT Update2(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    IInStream *inStream,
+    const CArchiveDatabaseEx *database,
+    const CObjectVector<CUpdateItem> &updateItems,
+    ISequentialOutStream *seqOutStream,
+    IArchiveUpdateCallback *updateCallback,
+    const CUpdateOptions &options)
+{
+  UInt64 numSolidFiles = options.NumSolidFiles;
+  if (numSolidFiles == 0)
+    numSolidFiles = 1;
+  /*
+  CMyComPtr<IOutStream> outStream;
+  RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
+  if (!outStream)
+    return E_NOTIMPL;
+  */
+
+  UInt64 startBlockSize = database != 0 ? database->ArchiveInfo.StartPosition: 0;
+  if (startBlockSize > 0 && !options.RemoveSfxBlock)
+  {
+    RINOK(WriteRange(inStream, seqOutStream, 0, startBlockSize, NULL));
+  }
+
+  CRecordVector<int> fileIndexToUpdateIndexMap;
+  if (database != 0)
+  {
+    fileIndexToUpdateIndexMap.Reserve(database->Files.Size());
+    for (int i = 0; i < database->Files.Size(); i++)
+      fileIndexToUpdateIndexMap.Add(-1);
+  }
+  int i;
+  for(i = 0; i < updateItems.Size(); i++)
+  {
+    int index = updateItems[i].IndexInArchive;
+    if (index != -1)
+      fileIndexToUpdateIndexMap[index] = i;
+  }
+
+  CRecordVector<int> folderRefs;
+  if (database != 0)
+  {
+    for(i = 0; i < database->Folders.Size(); i++)
+    {
+      CNum indexInFolder = 0;
+      CNum numCopyItems = 0;
+      CNum numUnPackStreams = database->NumUnPackStreamsVector[i];
+      for (CNum fileIndex = database->FolderStartFileIndex[i];
+      indexInFolder < numUnPackStreams; fileIndex++)
+      {
+        if (database->Files[fileIndex].HasStream)
+        {
+          indexInFolder++;
+          int updateIndex = fileIndexToUpdateIndexMap[fileIndex];
+          if (updateIndex >= 0)
+            if (!updateItems[updateIndex].NewData)
+              numCopyItems++;
+        }
+      }
+      if (numCopyItems != numUnPackStreams && numCopyItems != 0)
+        return E_NOTIMPL; // It needs repacking !!!
+      if (numCopyItems > 0)
+        folderRefs.Add(i);
+    }
+    folderRefs.Sort(CompareFolderRefs, (void *)database);
+  }
+
+  CArchiveDatabase newDatabase;
+
+  ////////////////////////////
+
+  COutArchive archive;
+  RINOK(archive.Create(seqOutStream, false));
+  RINOK(archive.SkeepPrefixArchiveHeader());
+  UInt64 complexity = 0;
+  for(i = 0; i < folderRefs.Size(); i++)
+    complexity += database->GetFolderFullPackSize(folderRefs[i]);
+  UInt64 inSizeForReduce = 0;
+  for(i = 0; i < updateItems.Size(); i++)
+  {
+    const CUpdateItem &updateItem = updateItems[i];
+    if (updateItem.NewData)
+    {
+      complexity += updateItem.Size;
+      if (numSolidFiles == 1)
+      {
+        if (updateItem.Size > inSizeForReduce)
+          inSizeForReduce = updateItem.Size;
+      }
+      else
+        inSizeForReduce += updateItem.Size;
+    }
+  }
+  RINOK(updateCallback->SetTotal(complexity));
+  complexity = 0;
+  RINOK(updateCallback->SetCompleted(&complexity));
+
+
+  CLocalProgress *lps = new CLocalProgress;
+  CMyComPtr<ICompressProgressInfo> progress = lps;
+  lps->Init(updateCallback, true);
+
+  /////////////////////////////////////////
+  // Write Copy Items
+
+  for(i = 0; i < folderRefs.Size(); i++)
+  {
+    int folderIndex = folderRefs[i];
+    
+    lps->ProgressOffset = complexity;
+    UInt64 packSize = database->GetFolderFullPackSize(folderIndex);
+    RINOK(WriteRange(inStream, archive.SeqStream,
+        database->GetFolderStreamPos(folderIndex, 0), packSize, progress));
+    complexity += packSize;
+    
+    const CFolder &folder = database->Folders[folderIndex];
+    CNum startIndex = database->FolderStartPackStreamIndex[folderIndex];
+    for (int j = 0; j < folder.PackStreams.Size(); j++)
+    {
+      newDatabase.PackSizes.Add(database->PackSizes[startIndex + j]);
+      // newDatabase.PackCRCsDefined.Add(database.PackCRCsDefined[startIndex + j]);
+      // newDatabase.PackCRCs.Add(database.PackCRCs[startIndex + j]);
+    }
+    newDatabase.Folders.Add(folder);
+
+    CNum numUnPackStreams = database->NumUnPackStreamsVector[folderIndex];
+    newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
+
+    CNum indexInFolder = 0;
+    for (CNum fi = database->FolderStartFileIndex[folderIndex];
+        indexInFolder < numUnPackStreams; fi++)
+    {
+      CFileItem file = database->Files[fi];
+      if (file.HasStream)
+      {
+        indexInFolder++;
+        int updateIndex = fileIndexToUpdateIndexMap[fi];
+        if (updateIndex >= 0)
+        {
+          const CUpdateItem &updateItem = updateItems[updateIndex];
+          if (updateItem.NewProperties)
+          {
+            CFileItem file2;
+            FromUpdateItemToFileItem(updateItem, file2);
+            file2.UnPackSize = file.UnPackSize;
+            file2.FileCRC = file.FileCRC;
+            file2.IsFileCRCDefined = file.IsFileCRCDefined;
+            file2.HasStream = file.HasStream;
+            file = file2;
+          }
+        }
+        newDatabase.Files.Add(file);
+      }
+    }
+  }
+
+  /////////////////////////////////////////
+  // Compress New Files
+
+  CObjectVector<CSolidGroup> groups;
+  SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter, 
+      updateItems, groups);
+
+  const UInt32 kMinReduceSize = (1 << 16);
+  if (inSizeForReduce < kMinReduceSize)
+    inSizeForReduce = kMinReduceSize;
+
+  for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++)
+  {
+    const CSolidGroup &group = groups[groupIndex];
+    int numFiles = group.Indices.Size();
+    if (numFiles == 0)
+      continue;
+    CRecordVector<CRefItem> refItems;
+    refItems.Reserve(numFiles);
+    bool sortByType = (numSolidFiles > 1);
+    for (i = 0; i < numFiles; i++)
+      refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType));
+    refItems.Sort(CompareUpdateItems, (void *)&sortByType);
+    
+    CRecordVector<UInt32> indices;
+    indices.Reserve(numFiles);
+
+    for (i = 0; i < numFiles; i++)
+    {
+      UInt32 index = refItems[i].Index;
+      indices.Add(index);
+      /*
+      const CUpdateItem &updateItem = updateItems[index];
+      CFileItem file;
+      if (updateItem.NewProperties)
+        FromUpdateItemToFileItem(updateItem, file);
+      else
+        file = database.Files[updateItem.IndexInArchive];
+      if (file.IsAnti || file.IsDirectory)
+        return E_FAIL;
+      newDatabase.Files.Add(file);
+      */
+    }
+    
+    CEncoder encoder(group.Method);
+
+    for (i = 0; i < numFiles;)
+    {
+      UInt64 totalSize = 0;
+      int numSubFiles;
+      UString prevExtension;
+      for (numSubFiles = 0; i + numSubFiles < numFiles && 
+          numSubFiles < numSolidFiles; numSubFiles++)
+      {
+        const CUpdateItem &updateItem = updateItems[indices[i + numSubFiles]];
+        totalSize += updateItem.Size;
+        if (totalSize > options.NumSolidBytes)
+          break;
+        if (options.SolidExtension)
+        {
+          UString ext = updateItem.GetExtension();
+          if (numSubFiles == 0)
+            prevExtension = ext;
+          else
+            if (ext.CompareNoCase(prevExtension) != 0)
+              break;
+        }
+      }
+      if (numSubFiles < 1)
+        numSubFiles = 1;
+
+      CFolderInStream *inStreamSpec = new CFolderInStream;
+      CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
+      inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
+      
+      CFolder folderItem;
+
+      int startPackIndex = newDatabase.PackSizes.Size();
+      RINOK(encoder.Encode(
+          EXTERNAL_CODECS_LOC_VARS
+          solidInStream, NULL, &inSizeForReduce, folderItem, 
+          archive.SeqStream, newDatabase.PackSizes, progress));
+
+      for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
+        lps->OutSize += newDatabase.PackSizes[startPackIndex];
+
+      lps->InSize += folderItem.GetUnPackSize();
+      // for()
+      // newDatabase.PackCRCsDefined.Add(false);
+      // newDatabase.PackCRCs.Add(0);
+      
+      newDatabase.Folders.Add(folderItem);
+      
+      CNum numUnPackStreams = 0;
+      for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
+      {
+        const CUpdateItem &updateItem = updateItems[indices[i + subIndex]];
+        CFileItem file;
+        if (updateItem.NewProperties)
+          FromUpdateItemToFileItem(updateItem, file);
+        else
+          file = database->Files[updateItem.IndexInArchive];
+        if (file.IsAnti || file.IsDirectory)
+          return E_FAIL;
+        
+        /*
+        CFileItem &file = newDatabase.Files[
+              startFileIndexInDatabase + i + subIndex];
+        */
+        if (!inStreamSpec->Processed[subIndex])
+        {
+          continue;
+          // file.Name += L".locked";
+        }
+
+        file.FileCRC = inStreamSpec->CRCs[subIndex];
+        file.UnPackSize = inStreamSpec->Sizes[subIndex];
+        if (file.UnPackSize != 0)
+        {
+          file.IsFileCRCDefined = true;
+          file.HasStream = true;
+          numUnPackStreams++;
+        }
+        else
+        {
+          file.IsFileCRCDefined = false;
+          file.HasStream = false;
+        }
+        newDatabase.Files.Add(file);
+      }
+      // numUnPackStreams = 0 is very bad case for locked files
+      // v3.13 doesn't understand it.
+      newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
+      i += numSubFiles;
+    }
+  }
+
+  {
+    /////////////////////////////////////////
+    // Write Empty Files & Folders
+    
+    CRecordVector<int> emptyRefs;
+    for(i = 0; i < updateItems.Size(); i++)
+    {
+      const CUpdateItem &updateItem = updateItems[i];
+      if (updateItem.NewData)
+      {
+        if (updateItem.HasStream())
+          continue;
+      }
+      else
+        if (updateItem.IndexInArchive != -1)
+          if (database->Files[updateItem.IndexInArchive].HasStream)
+            continue;
+      emptyRefs.Add(i);
+    }
+    emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
+    for(i = 0; i < emptyRefs.Size(); i++)
+    {
+      const CUpdateItem &updateItem = updateItems[emptyRefs[i]];
+      CFileItem file;
+      if (updateItem.NewProperties)
+        FromUpdateItemToFileItem(updateItem, file);
+      else
+        file = database->Files[updateItem.IndexInArchive];
+      newDatabase.Files.Add(file);
+    }
+  }
+    
+  /*
+  if (newDatabase.Files.Size() != updateItems.Size())
+    return E_FAIL;
+  */
+
+  return archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS
+      newDatabase, options.HeaderMethod, options.HeaderOptions);
+}
+
+#ifdef _7Z_VOL
+
+static const UInt64 k_Copy = 0x0;
+
+static HRESULT WriteVolumeHeader(COutArchive &archive, CFileItem &file, const CUpdateOptions &options)
+{
+  CCoderInfo coder;
+  coder.NumInStreams = coder.NumOutStreams = 1;
+  coder.MethodID = k_Copy;
+  
+  CFolder folder;
+  folder.Coders.Add(coder);
+  folder.PackStreams.Add(0);
+  
+  CNum numUnPackStreams = 0;
+  if (file.UnPackSize != 0)
+  {
+    file.IsFileCRCDefined = true;
+    file.HasStream = true;
+    numUnPackStreams++;
+  }
+  else
+  {
+    throw 1;
+    file.IsFileCRCDefined = false;
+    file.HasStream = false;
+  }
+  folder.UnPackSizes.Add(file.UnPackSize);
+  
+  CArchiveDatabase newDatabase;
+  newDatabase.Files.Add(file);
+  newDatabase.Folders.Add(folder);
+  newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
+  newDatabase.PackSizes.Add(file.UnPackSize);
+  newDatabase.PackCRCsDefined.Add(false);
+  newDatabase.PackCRCs.Add(file.FileCRC);
+  
+  return archive.WriteDatabase(newDatabase, 
+      options.HeaderMethod, 
+      false, 
+      false);
+}
+
+HRESULT UpdateVolume(
+    IInStream *inStream,
+    const CArchiveDatabaseEx *database,
+    CObjectVector<CUpdateItem> &updateItems,
+    ISequentialOutStream *seqOutStream,
+    IArchiveUpdateCallback *updateCallback,
+    const CUpdateOptions &options)
+{
+  if (updateItems.Size() != 1)
+    return E_NOTIMPL;
+
+  CMyComPtr<IArchiveUpdateCallback2> volumeCallback;
+  RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback));
+  if (!volumeCallback)
+    return E_NOTIMPL;
+
+  CMyComPtr<ISequentialInStream> fileStream;
+  HRESULT result = updateCallback->GetStream(0, &fileStream);
+  if (result != S_OK && result != S_FALSE)
+    return result;
+  if (result == S_FALSE)
+    return E_FAIL;
+  
+  CFileItem file;
+  
+  const CUpdateItem &updateItem = updateItems[0];
+  if (updateItem.NewProperties)
+    FromUpdateItemToFileItem(updateItem, file);
+  else
+    file = database->Files[updateItem.IndexInArchive];
+  if (file.IsAnti || file.IsDirectory)
+    return E_FAIL;
+
+  UInt64 complexity = 0;
+  file.IsStartPosDefined = true;
+  file.StartPos = 0;
+  for (UInt64 volumeIndex = 0; true; volumeIndex++)
+  { 
+    UInt64 volSize;
+    RINOK(volumeCallback->GetVolumeSize(volumeIndex, &volSize));
+    UInt64 pureSize = COutArchive::GetVolPureSize(volSize, file.Name.Length(), true);
+    CMyComPtr<ISequentialOutStream> volumeStream;
+    RINOK(volumeCallback->GetVolumeStream(volumeIndex, &volumeStream));
+   
+    COutArchive archive;
+    RINOK(archive.Create(volumeStream, true));
+    RINOK(archive.SkeepPrefixArchiveHeader());
+        
+    CSequentialInStreamWithCRC *inCrcStreamSpec = new CSequentialInStreamWithCRC;
+    CMyComPtr<ISequentialInStream> inCrcStream = inCrcStreamSpec;
+    inCrcStreamSpec->Init(fileStream);
+
+    RINOK(WriteRange(inCrcStream, volumeStream, pureSize, updateCallback, complexity));
+    file.UnPackSize = inCrcStreamSpec->GetSize();
+    if (file.UnPackSize == 0)
+      break;
+    file.FileCRC = inCrcStreamSpec->GetCRC();
+    RINOK(WriteVolumeHeader(archive, file, options));
+    file.StartPos += file.UnPackSize;
+    if (file.UnPackSize < pureSize)
+      break;
+  }
+  return S_OK;
+}
+
+class COutVolumeStream: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  int _volIndex;
+  UInt64 _volSize;
+  UInt64 _curPos;
+  CMyComPtr<ISequentialOutStream> _volumeStream;
+  COutArchive _archive;
+  CCRC _crc;
+
+public:
+  MY_UNKNOWN_IMP
+
+  CFileItem _file;
+  CUpdateOptions _options;
+  CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+  void Init(IArchiveUpdateCallback2 *volumeCallback, 
+      const UString &name)  
+  { 
+    _file.Name = name;
+    _file.IsStartPosDefined = true;
+    _file.StartPos = 0;
+    
+    VolumeCallback = volumeCallback;
+    _volIndex = 0;
+    _volSize = 0;
+  }
+  
+  HRESULT Flush();
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+HRESULT COutVolumeStream::Flush()
+{
+  if (_volumeStream)
+  {
+    _file.UnPackSize = _curPos;
+    _file.FileCRC = _crc.GetDigest();
+    RINOK(WriteVolumeHeader(_archive, _file, _options));
+    _archive.Close();
+    _volumeStream.Release();
+    _file.StartPos += _file.UnPackSize;
+  }
+  return S_OK;
+}
+
+STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  if(processedSize != NULL)
+    *processedSize = 0;
+  while(size > 0)
+  {
+    if (!_volumeStream)
+    {
+      RINOK(VolumeCallback->GetVolumeSize(_volIndex, &_volSize));
+      RINOK(VolumeCallback->GetVolumeStream(_volIndex, &_volumeStream));
+      _volIndex++;
+      _curPos = 0;
+      RINOK(_archive.Create(_volumeStream, true));
+      RINOK(_archive.SkeepPrefixArchiveHeader());
+      _crc.Init();
+      continue;
+    }
+    UInt64 pureSize = COutArchive::GetVolPureSize(_volSize, _file.Name.Length());
+    UInt32 curSize = (UInt32)MyMin(UInt64(size), pureSize - _curPos);
+
+    _crc.Update(data, curSize);
+    UInt32 realProcessed;
+    RINOK(_volumeStream->Write(data, curSize, &realProcessed))
+    data = (void *)((Byte *)data + realProcessed);
+    size -= realProcessed;
+    if(processedSize != NULL)
+      *processedSize += realProcessed;
+    _curPos += realProcessed;
+    if (realProcessed != curSize && realProcessed == 0)
+      return E_FAIL;
+    if (_curPos == pureSize)
+    {
+      RINOK(Flush());
+    }
+  }
+  return S_OK;
+}
+
+#endif
+
+HRESULT Update(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    IInStream *inStream,
+    const CArchiveDatabaseEx *database,
+    const CObjectVector<CUpdateItem> &updateItems,
+    ISequentialOutStream *seqOutStream,
+    IArchiveUpdateCallback *updateCallback,
+    const CUpdateOptions &options)
+{
+  #ifdef _7Z_VOL
+  if (seqOutStream)
+  #endif
+    return Update2(
+        EXTERNAL_CODECS_LOC_VARS
+        inStream, database, updateItems,
+        seqOutStream, updateCallback, options);
+  #ifdef _7Z_VOL
+  if (options.VolumeMode)
+    return UpdateVolume(inStream, database, updateItems,
+      seqOutStream, updateCallback, options);
+  COutVolumeStream *volStreamSpec = new COutVolumeStream;
+  CMyComPtr<ISequentialOutStream> volStream = volStreamSpec;
+  CMyComPtr<IArchiveUpdateCallback2> volumeCallback;
+  RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback));
+  if (!volumeCallback)
+    return E_NOTIMPL;
+  volStreamSpec->Init(volumeCallback, L"a.7z");
+  volStreamSpec->_options = options;
+  RINOK(Update2(inStream, database, updateItems,
+    volStream, updateCallback, options));
+  return volStreamSpec->Flush();
+  #endif
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/7z/7zUpdate.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/7zUpdate.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/7zUpdate.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,80 @@
+// 7zUpdate.h
+
+#ifndef __7Z_UPDATE_H
+#define __7Z_UPDATE_H
+
+#include "7zIn.h"
+#include "7zOut.h"
+#include "7zCompressionMode.h"
+
+#include "../IArchive.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CUpdateItem
+{
+  bool NewData;
+  bool NewProperties;
+  int IndexInArchive;
+  int IndexInClient;
+  
+  UInt32 Attributes;
+  FILETIME CreationTime;
+  FILETIME LastWriteTime;
+  FILETIME LastAccessTime;
+
+  UInt64 Size;
+  UString Name;
+  
+  bool IsAnti;
+  bool IsDirectory;
+
+  bool IsCreationTimeDefined;
+  bool IsLastWriteTimeDefined;
+  bool IsLastAccessTimeDefined;
+  bool AttributesAreDefined;
+
+  bool HasStream() const 
+    { return !IsDirectory && !IsAnti && Size != 0; }
+  CUpdateItem():  
+      IsAnti(false), 
+      AttributesAreDefined(false), 
+      IsCreationTimeDefined(false), 
+      IsLastWriteTimeDefined(false), 
+      IsLastAccessTimeDefined(false)
+      {}
+  void SetDirectoryStatusFromAttributes()
+    { IsDirectory = ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); };
+
+  int GetExtensionPos() const;
+  UString GetExtension() const;
+};
+
+struct CUpdateOptions
+{
+  const CCompressionMethodMode *Method;
+  const CCompressionMethodMode *HeaderMethod;
+  bool UseFilters;
+  bool MaxFilter;
+
+  CHeaderOptions HeaderOptions;
+
+  UInt64 NumSolidFiles;
+  UInt64 NumSolidBytes;
+  bool SolidExtension;
+  bool RemoveSfxBlock;
+  bool VolumeMode;
+};
+
+HRESULT Update(
+    DECL_EXTERNAL_CODECS_LOC_VARS
+    IInStream *inStream,
+    const CArchiveDatabaseEx *database,
+    const CObjectVector<CUpdateItem> &updateItems,
+    ISequentialOutStream *seqOutStream,
+    IArchiveUpdateCallback *updateCallback,
+    const CUpdateOptions &options);
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/7z/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Archive/7z/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/7z/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/7z/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/Archive.def
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Archive.def	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Archive.def	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,6 @@
+EXPORTS
+  CreateObject PRIVATE
+  GetHandlerProperty PRIVATE
+  GetNumberOfFormats PRIVATE
+  GetHandlerProperty2 PRIVATE
+  CreateObject PRIVATE

Added: trunk/lzma/CPP/7zip/Archive/Archive2.def
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Archive2.def	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Archive2.def	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+EXPORTS
+  CreateObject PRIVATE
+  GetHandlerProperty PRIVATE
+  GetNumberOfFormats PRIVATE
+  GetHandlerProperty2 PRIVATE
+  CreateObject PRIVATE
+  GetNumberOfMethods PRIVATE
+  GetMethodProperty PRIVATE
+  SetLargePageMode PRIVATE

Added: trunk/lzma/CPP/7zip/Archive/ArchiveExports.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/ArchiveExports.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/ArchiveExports.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,130 @@
+// ArchiveExports.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/ComTry.h"
+#include "../../Common/Types.h"
+#include "../../Windows/PropVariant.h"
+#include "../Common/RegisterArc.h"
+
+#include "IArchive.h"
+#include "../ICoder.h"
+#include "../IPassword.h"
+
+static const unsigned int kNumArcsMax = 32;
+static unsigned int g_NumArcs = 0;
+static const CArcInfo *g_Arcs[kNumArcsMax]; 
+void RegisterArc(const CArcInfo *arcInfo) 
+{ 
+  if (g_NumArcs < kNumArcsMax)
+    g_Arcs[g_NumArcs++] = arcInfo; 
+}
+
+DEFINE_GUID(CLSID_CArchiveHandler, 
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
+
+#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])
+
+static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)
+{
+  if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
+    value->vt = VT_BSTR;
+  return S_OK;
+}
+
+static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
+{
+  return SetPropString((const char *)&guid, sizeof(GUID), value);
+}
+
+int FindFormatCalssId(const GUID *clsID)
+{
+  GUID cls = *clsID;
+  CLS_ARC_ID_ITEM(cls) = 0;
+  if (cls != CLSID_CArchiveHandler)
+    return -1;
+  Byte id = CLS_ARC_ID_ITEM(*clsID);
+  for (UInt32 i = 0; i < g_NumArcs; i++)
+    if (g_Arcs[i]->ClassId == id)
+      return i;
+  return -1;
+}
+
+STDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)
+{
+  COM_TRY_BEGIN
+  {
+    int needIn = (*iid == IID_IInArchive);
+    int needOut = (*iid == IID_IOutArchive);
+    if (!needIn && !needOut)
+      return E_NOINTERFACE;
+    int formatIndex = FindFormatCalssId(clsid);
+    if (formatIndex < 0)
+      return CLASS_E_CLASSNOTAVAILABLE;
+    
+    const CArcInfo &arc = *g_Arcs[formatIndex];
+    if (needIn)
+    {
+      *outObject = arc.CreateInArchive();
+      ((IInArchive *)*outObject)->AddRef();
+    }
+    else
+    {
+      if (!arc.CreateOutArchive)
+        return CLASS_E_CLASSNOTAVAILABLE;
+      *outObject = arc.CreateOutArchive();
+      ((IOutArchive *)*outObject)->AddRef();
+    }
+  }
+  COM_TRY_END
+  return S_OK;
+}
+
+STDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)
+{
+  if (formatIndex >= g_NumArcs)
+    return E_INVALIDARG;
+  const CArcInfo &arc = *g_Arcs[formatIndex];
+  NWindows::NCOM::CPropVariant prop;
+  switch(propID)
+  {
+    case NArchive::kName:
+      prop = arc.Name;
+      break;
+    case NArchive::kClassID:
+    {
+      GUID clsId = CLSID_CArchiveHandler;
+      CLS_ARC_ID_ITEM(clsId) = arc.ClassId;
+      return SetPropGUID(clsId, value);
+    }
+    case NArchive::kExtension:
+      if (arc.Ext != 0)
+        prop = arc.Ext;
+      break;
+    case NArchive::kAddExtension:
+      if (arc.AddExt != 0)
+        prop = arc.AddExt;
+      break;
+    case NArchive::kUpdate:
+      prop = (bool)(arc.CreateOutArchive != 0);
+      break;
+    case NArchive::kKeepName:
+      prop = arc.KeepName;
+      break;
+    case NArchive::kStartSignature:
+      return SetPropString((const char *)arc.Signature, arc.SignatureSize, value);
+  }
+  prop.Detach(value);
+  return S_OK;
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+  return GetHandlerProperty2(0, propID, value);
+}
+
+STDAPI GetNumberOfFormats(UINT32 *numFormats)
+{
+  *numFormats = g_NumArcs;
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,121 @@
+// CoderMixer2.cpp
+
+#include "StdAfx.h"
+
+#include "CoderMixer2.h"
+
+namespace NCoderMixer {
+
+CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
+  _srcBindInfo(srcBindInfo)
+{
+  srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);
+
+  UInt32  j;
+  for (j = 0; j < NumSrcInStreams; j++)
+  {
+    _srcInToDestOutMap.Add(0);
+    DestOutToSrcInMap.Add(0);
+  }
+  for (j = 0; j < _numSrcOutStreams; j++)
+  {
+    _srcOutToDestInMap.Add(0);
+    _destInToSrcOutMap.Add(0);
+  }
+
+  UInt32 destInOffset = 0;
+  UInt32 destOutOffset = 0;
+  UInt32 srcInOffset = NumSrcInStreams;
+  UInt32 srcOutOffset = _numSrcOutStreams;
+
+  for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)
+  {
+    const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i];
+
+    srcInOffset -= srcCoderInfo.NumInStreams;
+    srcOutOffset -= srcCoderInfo.NumOutStreams;
+    
+    UInt32 j;
+    for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)
+    {
+      UInt32 index = srcInOffset + j;
+      _srcInToDestOutMap[index] = destOutOffset;
+      DestOutToSrcInMap[destOutOffset] = index;
+    }
+    for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)
+    {
+      UInt32 index = srcOutOffset + j;
+      _srcOutToDestInMap[index] = destInOffset;
+      _destInToSrcOutMap[destInOffset] = index;
+    }
+  }
+}
+
+void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
+{
+  destBindInfo.Coders.Clear();
+  destBindInfo.BindPairs.Clear();
+  destBindInfo.InStreams.Clear();
+  destBindInfo.OutStreams.Clear();
+
+  int i;
+  for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--)
+  {
+    const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];
+    CCoderStreamsInfo destCoderInfo;
+    destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;
+    destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;
+    destBindInfo.Coders.Add(destCoderInfo);
+  }
+  for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--)
+  {
+    const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];
+    CBindPair destBindPair;
+    destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];
+    destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];
+    destBindInfo.BindPairs.Add(destBindPair);
+  }
+  for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)
+    destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);
+  for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)
+    destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
+}
+
+CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): 
+    NumInStreams(numInStreams),
+    NumOutStreams(numOutStreams)
+{
+  InSizes.Reserve(NumInStreams);
+  InSizePointers.Reserve(NumInStreams);
+  OutSizePointers.Reserve(NumOutStreams);
+  OutSizePointers.Reserve(NumOutStreams);
+}
+
+static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, 
+    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
+{
+  sizes.Clear();
+  sizePointers.Clear();
+  for(UInt32 i = 0; i < numItems; i++)
+  {
+    if (srcSizes == 0 || srcSizes[i] == NULL)
+    {
+      sizes.Add(0);
+      sizePointers.Add(NULL);
+    }
+    else
+    {
+      sizes.Add(*srcSizes[i]);
+      sizePointers.Add(&sizes.Back());
+    }
+  }
+}
+
+void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes,
+      const UInt64 **outSizes)
+{
+  SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
+  SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
+}
+
+}  

Added: trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,174 @@
+// CoderMixer2.h
+
+#ifndef __CODER_MIXER2_H
+#define __CODER_MIXER2_H
+
+#include "../../../Common/MyVector.h"
+#include "../../../Common/Types.h"
+#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+
+namespace NCoderMixer {
+
+struct CBindPair
+{
+  UInt32 InIndex;
+  UInt32 OutIndex;
+};
+
+struct CCoderStreamsInfo
+{
+  UInt32 NumInStreams;
+  UInt32 NumOutStreams;
+};
+
+struct CBindInfo
+{
+  CRecordVector<CCoderStreamsInfo> Coders;
+  CRecordVector<CBindPair> BindPairs;
+  CRecordVector<UInt32> InStreams;
+  CRecordVector<UInt32> OutStreams;
+
+  void Clear()
+  {
+    Coders.Clear();
+    BindPairs.Clear();
+    InStreams.Clear();
+    OutStreams.Clear();
+  }
+
+  /*
+  UInt32 GetCoderStartOutStream(UInt32 coderIndex) const
+  {
+    UInt32 numOutStreams = 0;
+    for (UInt32 i = 0; i < coderIndex; i++)
+      numOutStreams += Coders[i].NumOutStreams;
+    return numOutStreams;
+  }
+  */
+
+
+  void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const
+  {
+    numInStreams = 0;
+    numOutStreams = 0;
+    for (int i = 0; i < Coders.Size(); i++)
+    {
+      const CCoderStreamsInfo &coderStreamsInfo = Coders[i];
+      numInStreams += coderStreamsInfo.NumInStreams;
+      numOutStreams += coderStreamsInfo.NumOutStreams;
+    }
+  }
+
+  int FindBinderForInStream(UInt32 inStream) const
+  {
+    for (int i = 0; i < BindPairs.Size(); i++)
+      if (BindPairs[i].InIndex == inStream)
+        return i;
+    return -1;
+  }
+  int FindBinderForOutStream(UInt32 outStream) const
+  {
+    for (int i = 0; i < BindPairs.Size(); i++)
+      if (BindPairs[i].OutIndex == outStream)
+        return i;
+    return -1;
+  }
+
+  UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const
+  {
+    UInt32 streamIndex = 0;
+    for (UInt32 i = 0; i < coderIndex; i++)
+      streamIndex += Coders[i].NumInStreams;
+    return streamIndex;
+  }
+
+  UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const
+  {
+    UInt32 streamIndex = 0;
+    for (UInt32 i = 0; i < coderIndex; i++)
+      streamIndex += Coders[i].NumOutStreams;
+    return streamIndex;
+  }
+
+
+  void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, 
+      UInt32 &coderStreamIndex) const
+  {
+    for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
+    {
+      UInt32 curSize = Coders[coderIndex].NumInStreams;
+      if (streamIndex < curSize)
+      {
+        coderStreamIndex = streamIndex;
+        return;
+      }
+      streamIndex -= curSize;
+    }
+    throw 1;
+  }
+  void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, 
+      UInt32 &coderStreamIndex) const
+  {
+    for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
+    {
+      UInt32 curSize = Coders[coderIndex].NumOutStreams;
+      if (streamIndex < curSize)
+      {
+        coderStreamIndex = streamIndex;
+        return;
+      }
+      streamIndex -= curSize;
+    }
+    throw 1;
+  }
+};
+
+class CBindReverseConverter
+{
+  UInt32 _numSrcOutStreams;
+  NCoderMixer::CBindInfo _srcBindInfo;
+  CRecordVector<UInt32> _srcInToDestOutMap;
+  CRecordVector<UInt32> _srcOutToDestInMap;
+  CRecordVector<UInt32> _destInToSrcOutMap;
+public:
+  UInt32 NumSrcInStreams;
+  CRecordVector<UInt32> DestOutToSrcInMap;
+
+  CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo);
+  void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo);
+};
+
+struct CCoderInfo2
+{
+  CMyComPtr<ICompressCoder> Coder;
+  CMyComPtr<ICompressCoder2> Coder2;
+  UInt32 NumInStreams;
+  UInt32 NumOutStreams;
+
+  CRecordVector<UInt64> InSizes;
+  CRecordVector<UInt64> OutSizes;
+  CRecordVector<const UInt64 *> InSizePointers;
+  CRecordVector<const UInt64 *> OutSizePointers;
+
+  CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams);
+  void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
+
+  HRESULT QueryInterface(REFGUID iid, void** pp) const
+  {
+    IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
+    return p->QueryInterface(iid, pp);
+  }
+};
+
+class CCoderMixer2
+{
+public:
+  virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0;
+  virtual void ReInit() = 0;
+  virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;
+};
+
+}
+#endif
+

Added: trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,228 @@
+// CoderMixer2MT.cpp
+
+#include "StdAfx.h"
+
+#include "CoderMixer2MT.h"
+
+namespace NCoderMixer {
+
+CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): 
+    CCoderInfo2(numInStreams, numOutStreams)
+{
+  InStreams.Reserve(NumInStreams);
+  InStreamPointers.Reserve(NumInStreams);
+  OutStreams.Reserve(NumOutStreams);
+  OutStreamPointers.Reserve(NumOutStreams);
+}
+
+void CCoder2::Execute() { Code(NULL); }
+
+void CCoder2::Code(ICompressProgressInfo *progress)
+{
+  InStreamPointers.Clear();
+  OutStreamPointers.Clear();
+  UInt32 i;
+  for (i = 0; i < NumInStreams; i++)
+  {
+    if (InSizePointers[i] != NULL)
+      InSizePointers[i] = &InSizes[i];
+    InStreamPointers.Add((ISequentialInStream *)InStreams[i]);
+  }
+  for (i = 0; i < NumOutStreams; i++)
+  {
+    if (OutSizePointers[i] != NULL)
+      OutSizePointers[i] = &OutSizes[i];
+    OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]);
+  }
+  if (Coder)
+    Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], 
+        InSizePointers[0], OutSizePointers[0], progress);
+  else
+    Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams,
+      &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress);
+  {
+    int i;
+    for (i = 0; i < InStreams.Size(); i++)
+      InStreams[i].Release();
+    for (i = 0; i < OutStreams.Size(); i++)
+      OutStreams[i].Release();
+  }
+}
+
+static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, 
+    CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
+{
+  sizes.Clear();
+  sizePointers.Clear();
+  for(UInt32 i = 0; i < numItems; i++)
+  {
+    if (srcSizes == 0 || srcSizes[i] == NULL)
+    {
+      sizes.Add(0);
+      sizePointers.Add(NULL);
+    }
+    else
+    {
+      sizes.Add(*srcSizes[i]);
+      sizePointers.Add(&sizes.Back());
+    }
+  }
+}
+
+
+void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes)
+{
+  SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
+  SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
+}
+
+//////////////////////////////////////
+// CCoderMixer2MT
+
+HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
+{  
+  _bindInfo = bindInfo; 
+  _streamBinders.Clear();
+  for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
+  {
+    _streamBinders.Add(CStreamBinder());
+    RINOK(_streamBinders.Back().CreateEvents());
+  }
+  return S_OK;
+}
+
+void CCoderMixer2MT::AddCoderCommon()
+{
+  const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()];
+  CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams);
+  _coders.Add(threadCoderInfo);
+}
+
+void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
+{
+  AddCoderCommon();
+  _coders.Back().Coder = coder;
+}
+
+void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
+{
+  AddCoderCommon();
+  _coders.Back().Coder2 = coder;
+}
+
+
+void CCoderMixer2MT::ReInit()
+{
+  for(int i = 0; i < _streamBinders.Size(); i++)
+    _streamBinders[i].ReInit();
+}
+
+
+HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) 
+{
+  /*
+  if (_coders.Size() != _bindInfo.Coders.Size())
+    throw 0;
+  */
+  int i;
+  for(i = 0; i < _coders.Size(); i++)
+  {
+    CCoder2 &coderInfo = _coders[i];
+    const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
+    coderInfo.InStreams.Clear();
+    UInt32 j;
+    for(j = 0; j < coderStreamsInfo.NumInStreams; j++)
+      coderInfo.InStreams.Add(NULL);
+    coderInfo.OutStreams.Clear();
+    for(j = 0; j < coderStreamsInfo.NumOutStreams; j++)
+      coderInfo.OutStreams.Add(NULL);
+  }
+
+  for(i = 0; i < _bindInfo.BindPairs.Size(); i++)
+  {
+    const CBindPair &bindPair = _bindInfo.BindPairs[i];
+    UInt32 inCoderIndex, inCoderStreamIndex;
+    UInt32 outCoderIndex, outCoderStreamIndex;
+    _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
+    _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
+
+    _streamBinders[i].CreateStreams(
+        &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
+        &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
+  }
+
+  for(i = 0; i < _bindInfo.InStreams.Size(); i++)
+  {
+    UInt32 inCoderIndex, inCoderStreamIndex;
+    _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
+    _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
+  }
+  
+  for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
+  {
+    UInt32 outCoderIndex, outCoderStreamIndex;
+    _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
+    _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
+  }
+  return S_OK;
+}
+
+HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code)
+{
+  for (int i = 0; i < _coders.Size(); i++)
+    if (_coders[i].Result == code)
+      return code;
+  return S_OK;
+}
+
+STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
+      const UInt64 ** /* inSizes */, 
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams, 
+      const UInt64 ** /* outSizes */,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
+      numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
+    return E_INVALIDARG;
+
+  Init(inStreams, outStreams);
+
+  int i;
+  for (i = 0; i < _coders.Size(); i++)
+    if (i != _progressCoderIndex)
+    {
+      RINOK(_coders[i].Create());
+    }
+
+  for (i = 0; i < _coders.Size(); i++)
+    if (i != _progressCoderIndex)
+      _coders[i].Start();
+
+  _coders[_progressCoderIndex].Code(progress);
+
+  for (i = 0; i < _coders.Size(); i++)
+    if (i != _progressCoderIndex)
+      _coders[i].WaitFinish();
+
+  RINOK(ReturnIfError(E_ABORT));
+  RINOK(ReturnIfError(E_OUTOFMEMORY));
+  RINOK(ReturnIfError(S_FALSE));
+
+  for (i = 0; i < _coders.Size(); i++)
+  {
+    HRESULT result = _coders[i].Result;
+    if (result != S_OK && result != E_FAIL)
+      return result;
+  }
+  for (i = 0; i < _coders.Size(); i++)
+  {
+    HRESULT result = _coders[i].Result;
+    if (result != S_OK)
+      return result;
+  }
+  return S_OK;
+}
+
+}  

Added: trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/CoderMixer2MT.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,80 @@
+// CoderMixer2MT.h
+
+#ifndef __CODER_MIXER2_MT_H
+#define __CODER_MIXER2_MT_H
+
+#include "CoderMixer2.h"
+#include "../../../Common/MyCom.h"
+#include "../../Common/StreamBinder.h"
+#include "../../Common/VirtThread.h"
+
+namespace NCoderMixer {
+
+struct CCoder2: public CCoderInfo2, public CVirtThread
+{
+  HRESULT Result;
+  CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
+  CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
+  CRecordVector<ISequentialInStream*> InStreamPointers;
+  CRecordVector<ISequentialOutStream*> OutStreamPointers;
+
+  CCoder2(UInt32 numInStreams, UInt32 numOutStreams);
+  void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
+  virtual void Execute();
+  void Code(ICompressProgressInfo *progress);
+};
+
+
+/*
+  SetBindInfo()
+  for each coder
+    AddCoder[2]()
+  SetProgressIndex(UInt32 coderIndex);
+ 
+  for each file
+  {
+    ReInit()
+    for each coder
+      SetCoderInfo  
+    Code
+  }
+*/
+
+class CCoderMixer2MT:
+  public ICompressCoder2,
+  public CCoderMixer2,
+  public CMyUnknownImp
+{
+  CBindInfo _bindInfo;
+  CObjectVector<CStreamBinder> _streamBinders;
+  int _progressCoderIndex;
+
+  void AddCoderCommon();
+  HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams);
+  HRESULT ReturnIfError(HRESULT code);
+public:
+  CObjectVector<CCoder2> _coders;
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Code)(ISequentialInStream **inStreams,
+      const UInt64 **inSizes, 
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams, 
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress);
+
+  HRESULT SetBindInfo(const CBindInfo &bindInfo);
+  void AddCoder(ICompressCoder *coder);
+  void AddCoder2(ICompressCoder2 *coder);
+  void SetProgressCoderIndex(int coderIndex) {  _progressCoderIndex = coderIndex; }
+
+  void ReInit();
+  void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
+    {  _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
+  UInt64 GetWriteProcessedSize(UInt32 binderIndex) const
+    {  return _streamBinders[binderIndex].ProcessedSize; }
+};
+
+}
+#endif

Added: trunk/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,15 @@
+// CrossThreadProgress.cpp
+
+#include "StdAfx.h"
+
+#include "CrossThreadProgress.h"
+
+STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+  InSize = inSize;
+  OutSize = outSize;
+  ProgressEvent.Set();
+  WaitEvent.Lock();
+  return Result;
+}
+

Added: trunk/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/CrossThreadProgress.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,37 @@
+// CrossThreadProgress.h
+
+#ifndef __CROSSTHREADPROGRESS_H
+#define __CROSSTHREADPROGRESS_H
+
+#include "../../ICoder.h"
+#include "../../../Windows/Synchronization.h"
+#include "../../../Common/MyCom.h"
+
+class CCrossThreadProgress: 
+  public ICompressProgressInfo,
+  public CMyUnknownImp
+{
+public:
+  const UInt64 *InSize;
+  const UInt64 *OutSize;
+  HRESULT Result;
+  NWindows::NSynchronization::CAutoResetEvent ProgressEvent;
+  NWindows::NSynchronization::CAutoResetEvent WaitEvent;
+
+  HRes Create()
+  {
+    RINOK(ProgressEvent.CreateIfNotCreated());
+    return WaitEvent.CreateIfNotCreated();
+  }
+  void Init()
+  {
+    ProgressEvent.Reset();
+    WaitEvent.Reset();
+  }
+
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/DummyOutStream.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,22 @@
+// DummyOutStream.cpp
+
+#include "StdAfx.h"
+
+#include "DummyOutStream.h"
+
+STDMETHODIMP CDummyOutStream::Write(const void *data,  UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize;
+  HRESULT result;
+  if(!_stream)
+  {
+    realProcessedSize = size;
+    result = S_OK;
+  }
+  else
+    result = _stream->Write(data, size, &realProcessedSize);
+  _size += realProcessedSize;
+  if(processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return result;
+}

Added: trunk/lzma/CPP/7zip/Archive/Common/DummyOutStream.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/DummyOutStream.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/DummyOutStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,23 @@
+// DummyOutStream.h
+
+#ifndef __DUMMYOUTSTREAM_H
+#define __DUMMYOUTSTREAM_H
+
+#include "../../IStream.h"
+#include "Common/MyCom.h"
+
+class CDummyOutStream: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<ISequentialOutStream> _stream;
+  UInt64 _size;
+public:
+  void SetStream(ISequentialOutStream *outStream) { _stream = outStream; }
+  void Init() { _size = 0; }
+  MY_UNKNOWN_IMP
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  UInt64 GetSize() const { return _size; }
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/Common/HandlerOut.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/HandlerOut.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/HandlerOut.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,618 @@
+// HandlerOutCommon.cpp
+
+#include "StdAfx.h"
+
+#include "HandlerOut.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Common/StringToInt.h"
+#include "../../ICoder.h"
+#include "../Common/ParseProperties.h"
+
+#ifdef COMPRESS_MT
+#include "../../../Windows/System.h"
+#endif
+
+using namespace NWindows;
+
+namespace NArchive {
+
+static const wchar_t *kCopyMethod = L"Copy";
+static const wchar_t *kLZMAMethodName = L"LZMA";
+static const wchar_t *kLZMA2MethodName = L"LZMA2";
+static const wchar_t *kBZip2MethodName = L"BZip2";
+static const wchar_t *kPpmdMethodName = L"PPMd";
+static const wchar_t *kDeflateMethodName = L"Deflate";
+static const wchar_t *kDeflate64MethodName = L"Deflate64";
+
+static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
+static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
+
+static const UInt32 kLzmaAlgoX1 = 0;
+static const UInt32 kLzmaAlgoX5 = 1;
+
+static const UInt32 kLzmaDicSizeX1 = 1 << 16;
+static const UInt32 kLzmaDicSizeX3 = 1 << 20;
+static const UInt32 kLzmaDicSizeX5 = 1 << 24;
+static const UInt32 kLzmaDicSizeX7 = 1 << 25;
+static const UInt32 kLzmaDicSizeX9 = 1 << 26;
+
+static const UInt32 kLzmaFastBytesX1 = 32;
+static const UInt32 kLzmaFastBytesX7 = 64;
+
+static const UInt32 kPpmdMemSizeX1 = (1 << 22);
+static const UInt32 kPpmdMemSizeX5 = (1 << 24);
+static const UInt32 kPpmdMemSizeX7 = (1 << 26);
+static const UInt32 kPpmdMemSizeX9 = (192 << 20);
+
+static const UInt32 kPpmdOrderX1 = 4;
+static const UInt32 kPpmdOrderX5 = 6;
+static const UInt32 kPpmdOrderX7 = 16;
+static const UInt32 kPpmdOrderX9 = 32;
+
+static const UInt32 kDeflateAlgoX1 = 0;
+static const UInt32 kDeflateAlgoX5 = 1;
+
+static const UInt32 kDeflateFastBytesX1 = 32;
+static const UInt32 kDeflateFastBytesX7 = 64;
+static const UInt32 kDeflateFastBytesX9 = 128;
+
+static const UInt32 kDeflatePassesX1 = 1;
+static const UInt32 kDeflatePassesX7 = 3;
+static const UInt32 kDeflatePassesX9 = 10;
+
+static const UInt32 kBZip2NumPassesX1 = 1;
+static const UInt32 kBZip2NumPassesX7 = 2;
+static const UInt32 kBZip2NumPassesX9 = 7;
+
+static const UInt32 kBZip2DicSizeX1 = 100000;
+static const UInt32 kBZip2DicSizeX3 = 500000;
+static const UInt32 kBZip2DicSizeX5 = 900000;
+
+static const wchar_t *kDefaultMethodName = kLZMAMethodName;
+
+static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
+static const UInt32 kDictionaryForHeaders = 1 << 20;
+static const UInt32 kNumFastBytesForHeaders = 273;
+static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;
+
+static bool AreEqual(const UString &methodName, const wchar_t *s)
+  { return (methodName.CompareNoCase(s) == 0); }
+
+static inline bool IsLZMAMethod(const UString &methodName)
+{ 
+  return 
+    AreEqual(methodName, kLZMAMethodName) || 
+    AreEqual(methodName, kLZMA2MethodName); 
+}
+
+static inline bool IsBZip2Method(const UString &methodName)
+  { return AreEqual(methodName, kBZip2MethodName); }
+
+static inline bool IsPpmdMethod(const UString &methodName)
+  { return AreEqual(methodName, kPpmdMethodName); }
+
+static inline bool IsDeflateMethod(const UString &methodName)
+{ 
+  return 
+    AreEqual(methodName, kDeflateMethodName) || 
+    AreEqual(methodName, kDeflate64MethodName); 
+}
+
+struct CNameToPropID
+{
+  PROPID PropID;
+  VARTYPE VarType;
+  const wchar_t *Name;
+};
+
+CNameToPropID g_NameToPropID[] = 
+{
+  { NCoderPropID::kOrder, VT_UI4, L"O" },
+  { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
+  { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
+  { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },
+  { NCoderPropID::kEndMarker, VT_BOOL, L"eos" },
+
+  { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },
+  { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },
+  { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
+  { NCoderPropID::kAlgorithm, VT_UI4, L"a" },
+  { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
+  { NCoderPropID::kNumThreads, VT_UI4, L"mt" }
+};
+
+static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
+{
+  if (varType == srcProp.vt)
+  {
+    destProp = srcProp;
+    return true;
+  }
+  if (varType == VT_UI1)
+  {
+    if (srcProp.vt == VT_UI4)
+    {
+      UInt32 value = srcProp.ulVal;
+      if (value > 0xFF)
+        return false;
+      destProp = (Byte)value;
+      return true;
+    }
+  }
+  else if (varType == VT_BOOL)
+  {
+    bool res;
+    if (SetBoolProperty(res, srcProp) != S_OK)
+      return false;
+    destProp = res;
+    return true;
+  }
+  return false;
+}
+    
+static int FindPropIdFromStringName(const UString &name)
+{
+  for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
+    if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
+      return i;
+  return -1;
+}
+
+static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, 
+    const NWindows::NCOM::CPropVariant &value)
+{
+  for (int j = 0; j < oneMethodInfo.Properties.Size(); j++)
+    if (oneMethodInfo.Properties[j].Id == propID)
+      return;
+  CProp property;
+  property.Id = propID;
+  property.Value = value;
+  oneMethodInfo.Properties.Add(property);
+}
+
+void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
+    #ifdef COMPRESS_MT
+    , UInt32 numThreads
+    #endif
+    )
+{
+  UInt32 level = _level;
+  if (oneMethodInfo.MethodName.IsEmpty())
+    oneMethodInfo.MethodName = kDefaultMethodName;
+  
+  if (IsLZMAMethod(oneMethodInfo.MethodName))
+  {
+    UInt32 dicSize = 
+      (level >= 9 ? kLzmaDicSizeX9 : 
+      (level >= 7 ? kLzmaDicSizeX7 : 
+      (level >= 5 ? kLzmaDicSizeX5 : 
+      (level >= 3 ? kLzmaDicSizeX3 : 
+                    kLzmaDicSizeX1)))); 
+    
+    UInt32 algo = 
+      (level >= 5 ? kLzmaAlgoX5 : 
+                    kLzmaAlgoX1); 
+    
+    UInt32 fastBytes = 
+      (level >= 7 ? kLzmaFastBytesX7 : 
+                    kLzmaFastBytesX1); 
+    
+    const wchar_t *matchFinder = 
+      (level >= 5 ? kLzmaMatchFinderX5 : 
+                    kLzmaMatchFinderX1); 
+    
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
+    #ifdef COMPRESS_MT
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
+    #endif
+  }
+  else if (IsDeflateMethod(oneMethodInfo.MethodName))
+  {
+    UInt32 fastBytes = 
+      (level >= 9 ? kDeflateFastBytesX9 : 
+      (level >= 7 ? kDeflateFastBytesX7 : 
+                    kDeflateFastBytesX1));
+    
+    UInt32 numPasses = 
+      (level >= 9 ? kDeflatePassesX9 :  
+      (level >= 7 ? kDeflatePassesX7 : 
+                    kDeflatePassesX1));
+    
+    UInt32 algo = 
+      (level >= 5 ? kDeflateAlgoX5 : 
+                    kDeflateAlgoX1); 
+    
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
+  }
+  else if (IsBZip2Method(oneMethodInfo.MethodName))
+  {
+    UInt32 numPasses = 
+      (level >= 9 ? kBZip2NumPassesX9 : 
+      (level >= 7 ? kBZip2NumPassesX7 :  
+                    kBZip2NumPassesX1));
+    
+    UInt32 dicSize = 
+      (level >= 5 ? kBZip2DicSizeX5 : 
+      (level >= 3 ? kBZip2DicSizeX3 : 
+                    kBZip2DicSizeX1));
+    
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
+    #ifdef COMPRESS_MT
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
+    #endif
+  }
+  else if (IsPpmdMethod(oneMethodInfo.MethodName))
+  {
+    UInt32 useMemSize = 
+      (level >= 9 ? kPpmdMemSizeX9 : 
+      (level >= 7 ? kPpmdMemSizeX7 : 
+      (level >= 5 ? kPpmdMemSizeX5 : 
+                    kPpmdMemSizeX1)));
+    
+    UInt32 order = 
+      (level >= 9 ? kPpmdOrderX9 : 
+      (level >= 7 ? kPpmdOrderX7 : 
+      (level >= 5 ? kPpmdOrderX5 : 
+                    kPpmdOrderX1)));
+    
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
+    SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
+  }
+}
+
+static void SplitParams(const UString &srcString, UStringVector &subStrings)
+{
+  subStrings.Clear();
+  UString name;
+  int len = srcString.Length();
+  if (len == 0)
+    return;
+  for (int i = 0; i < len; i++)
+  {
+    wchar_t c = srcString[i];
+    if (c == L':')
+    {
+      subStrings.Add(name);
+      name.Empty();
+    }
+    else
+      name += c;
+  }
+  subStrings.Add(name);
+}
+
+static void SplitParam(const UString &param, UString &name, UString &value)
+{
+  int eqPos = param.Find(L'=');
+  if (eqPos >= 0)
+  {
+    name = param.Left(eqPos);
+    value = param.Mid(eqPos + 1);
+    return;
+  }
+  for(int i = 0; i < param.Length(); i++)
+  {
+    wchar_t c = param[i];
+    if (c >= L'0' && c <= L'9')
+    {
+      name = param.Left(i);
+      value = param.Mid(i);
+      return;
+    }
+  }
+  name = param;
+}
+
+HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
+{
+  CProp property;
+  if (
+    name.CompareNoCase(L"D") == 0 || 
+    name.CompareNoCase(L"MEM") == 0)
+  {
+    UInt32 dicSize;
+    RINOK(ParsePropDictionaryValue(value, dicSize));
+    if (name.CompareNoCase(L"D") == 0)
+      property.Id = NCoderPropID::kDictionarySize;
+    else
+      property.Id = NCoderPropID::kUsedMemorySize;
+    property.Value = dicSize;
+    oneMethodInfo.Properties.Add(property);
+  }
+  else
+  {
+    int index = FindPropIdFromStringName(name);
+    if (index < 0)
+      return E_INVALIDARG;
+    
+    const CNameToPropID &nameToPropID = g_NameToPropID[index];
+    property.Id = nameToPropID.PropID;
+    
+    NCOM::CPropVariant propValue;
+    
+    if (nameToPropID.VarType == VT_BSTR)
+      propValue = value;
+    else if (nameToPropID.VarType == VT_BOOL)
+    {
+      bool res;
+      if (!StringToBool(value, res))
+        return E_INVALIDARG;
+      propValue = res;
+    }
+    else
+    {
+      UInt32 number;
+      if (ParseStringToUInt32(value, number) == value.Length())
+        propValue = number;
+      else
+        propValue = value;
+    }
+    
+    if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value))
+      return E_INVALIDARG;
+    
+    oneMethodInfo.Properties.Add(property);
+  }
+  return S_OK;
+}
+
+HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)
+{
+  UStringVector params;
+  SplitParams(srcString, params);
+  if (params.Size() > 0)
+    oneMethodInfo.MethodName = params[0];
+  for (int i = 1; i < params.Size(); i++)
+  {
+    const UString &param = params[i];
+    UString name, value;
+    SplitParam(param, name, value);
+    RINOK(SetParam(oneMethodInfo, name, value));
+  }
+  return S_OK;
+}
+
+HRESULT COutHandler::SetSolidSettings(const UString &s)
+{
+  bool res;
+  if (StringToBool(s, res))
+  {
+    if (res)
+      InitSolid();
+    else
+      _numSolidFiles = 1;
+    return S_OK;
+  }
+  UString s2 = s;
+  s2.MakeUpper();
+  for (int i = 0; i < s2.Length();)
+  {
+    const wchar_t *start = ((const wchar_t *)s2) + i;
+    const wchar_t *end;
+    UInt64 v = ConvertStringToUInt64(start, &end);
+    if (start == end)
+    {
+      if (s2[i++] != 'E')
+        return E_INVALIDARG;
+      _solidExtension = true;
+      continue;
+    }
+    i += (int)(end - start);
+    if (i == s2.Length())
+      return E_INVALIDARG;
+    wchar_t c = s2[i++];
+    switch(c)
+    {
+      case 'F':
+        if (v < 1)
+          v = 1;
+        _numSolidFiles = v;
+        break;
+      case 'B':
+        _numSolidBytes = v;
+        _numSolidBytesDefined = true;
+        break;
+      case 'K':
+        _numSolidBytes = (v << 10);
+        _numSolidBytesDefined = true;
+        break;
+      case 'M':
+        _numSolidBytes = (v << 20);
+        _numSolidBytesDefined = true;
+        break;
+      case 'G':
+        _numSolidBytes = (v << 30);
+        _numSolidBytesDefined = true;
+        break;
+      default:
+        return E_INVALIDARG;
+    }
+  }
+  return S_OK;
+}
+
+HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)
+{
+  switch(value.vt)
+  {
+    case VT_EMPTY:
+      InitSolid();
+      return S_OK;
+    case VT_BSTR:
+      return SetSolidSettings(value.bstrVal);
+    default:
+      return E_INVALIDARG;
+  }
+}
+
+void COutHandler::Init()
+{
+  _removeSfxBlock = false;
+  _compressHeaders = true;
+  _encryptHeaders = false;
+  
+  WriteModified = true;
+  WriteCreated = false;
+  WriteAccessed = false;
+  
+  #ifdef COMPRESS_MT
+  _numThreads = NWindows::NSystem::GetNumberOfProcessors();
+  #endif
+  
+  _level = 5;
+  _autoFilter = true;
+  _volumeMode = false;
+  _crcSize = 4;
+  InitSolid();
+}
+
+void COutHandler::BeforeSetProperty()
+{
+  Init();
+  #ifdef COMPRESS_MT
+  numProcessors = NSystem::GetNumberOfProcessors();
+  #endif
+
+  mainDicSize = 0xFFFFFFFF;
+  mainDicMethodIndex = 0xFFFFFFFF;
+  minNumber = 0;
+  _crcSize = 4;
+}
+
+HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
+{
+  UString name = nameSpec;
+  name.MakeUpper();
+  if (name.IsEmpty())
+    return E_INVALIDARG;
+  
+  if (name[0] == 'X')
+  {
+    name.Delete(0);
+    _level = 9;
+    return ParsePropValue(name, value, _level);
+  }
+  
+  if (name[0] == L'S')
+  {
+    name.Delete(0);
+    if (name.IsEmpty())
+      return SetSolidSettings(value);
+    if (value.vt != VT_EMPTY)
+      return E_INVALIDARG;
+    return SetSolidSettings(name);
+  }
+  
+  if (name == L"CRC")
+  {
+    _crcSize = 4;
+    name.Delete(0, 3);
+    return ParsePropValue(name, value, _crcSize);
+  }
+  
+  UInt32 number;
+  int index = ParseStringToUInt32(name, number);
+  UString realName = name.Mid(index);
+  if (index == 0)
+  {
+    if(name.Left(2).CompareNoCase(L"MT") == 0)
+    {
+      #ifdef COMPRESS_MT
+      RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
+      #endif
+      return S_OK;
+    }
+    if (name.CompareNoCase(L"RSFX") == 0)
+      return SetBoolProperty(_removeSfxBlock, value);
+    if (name.CompareNoCase(L"F") == 0)
+      return SetBoolProperty(_autoFilter, value);
+    if (name.CompareNoCase(L"HC") == 0)
+      return SetBoolProperty(_compressHeaders, value);
+    if (name.CompareNoCase(L"HCF") == 0)
+    {
+      bool compressHeadersFull = true;
+      RINOK(SetBoolProperty(compressHeadersFull, value));
+      if (!compressHeadersFull)
+        return E_INVALIDARG;
+      return S_OK;
+    }
+    if (name.CompareNoCase(L"HE") == 0)
+      return SetBoolProperty(_encryptHeaders, value);
+    if (name.CompareNoCase(L"TM") == 0)
+      return SetBoolProperty(WriteModified, value);
+    if (name.CompareNoCase(L"TC") == 0)
+      return SetBoolProperty(WriteCreated, value);
+    if (name.CompareNoCase(L"TA") == 0)
+      return SetBoolProperty(WriteAccessed, value);
+    if (name.CompareNoCase(L"V") == 0)
+      return SetBoolProperty(_volumeMode, value);
+    number = 0;
+  }
+  if (number > 10000)
+    return E_FAIL;
+  if (number < minNumber)
+    return E_INVALIDARG;
+  number -= minNumber;
+  for(int j = _methods.Size(); j <= (int)number; j++)
+  {
+    COneMethodInfo oneMethodInfo;
+    _methods.Add(oneMethodInfo);
+  }
+  
+  COneMethodInfo &oneMethodInfo = _methods[number];
+  
+  if (realName.Length() == 0)
+  {
+    if (value.vt != VT_BSTR)
+      return E_INVALIDARG;
+    
+    RINOK(SetParams(oneMethodInfo, value.bstrVal));
+  }
+  else
+  {
+    CProp property;
+    if (realName.Left(1).CompareNoCase(L"D") == 0)
+    {
+      UInt32 dicSize;
+      RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize));
+      property.Id = NCoderPropID::kDictionarySize;
+      property.Value = dicSize;
+      oneMethodInfo.Properties.Add(property);
+      if (number <= mainDicMethodIndex)
+        mainDicSize = dicSize;
+    }
+    else if (realName.Left(3).CompareNoCase(L"MEM") == 0)
+    {
+      UInt32 dicSize;
+      RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));
+      property.Id = NCoderPropID::kUsedMemorySize;
+      property.Value = dicSize;
+      oneMethodInfo.Properties.Add(property);
+      if (number <= mainDicMethodIndex)
+        mainDicSize = dicSize;
+    }
+    else
+    {
+      int index = FindPropIdFromStringName(realName);
+      if (index < 0)
+        return E_INVALIDARG;
+      
+      const CNameToPropID &nameToPropID = g_NameToPropID[index];
+      property.Id = nameToPropID.PropID;
+      
+      if (!ConvertProperty(value, nameToPropID.VarType, property.Value))
+        return E_INVALIDARG;
+      
+      oneMethodInfo.Properties.Add(property);
+    }
+  }
+  return S_OK;
+}  
+
+}

Added: trunk/lzma/CPP/7zip/Archive/Common/HandlerOut.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/HandlerOut.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/HandlerOut.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,86 @@
+// HandlerOut.h
+
+#ifndef __HANDLER_OUT_H
+#define __HANDLER_OUT_H
+
+#include "../../Common/MethodProps.h"
+#include "../../Common/CreateCoder.h"
+
+namespace NArchive {
+
+struct COneMethodInfo
+{
+  CObjectVector<CProp> Properties;
+  UString MethodName;
+};
+
+class COutHandler
+{
+public:
+  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);
+  
+  HRESULT SetSolidSettings(const UString &s);
+  HRESULT SetSolidSettings(const PROPVARIANT &value);
+
+  #ifdef COMPRESS_MT
+  UInt32 _numThreads;
+  #endif
+
+  UInt32 _crcSize;
+
+  CObjectVector<COneMethodInfo> _methods;
+  bool _removeSfxBlock;
+  
+  UInt64 _numSolidFiles; 
+  UInt64 _numSolidBytes;
+  bool _numSolidBytesDefined;
+  bool _solidExtension;
+
+  bool _compressHeaders;
+  bool _encryptHeaders;
+
+  bool WriteModified;
+  bool WriteCreated;
+  bool WriteAccessed;
+
+  bool _autoFilter;
+  UInt32 _level;
+
+  bool _volumeMode;
+
+  HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);
+  HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);
+
+  void SetCompressionMethod2(COneMethodInfo &oneMethodInfo
+      #ifdef COMPRESS_MT
+      , UInt32 numThreads
+      #endif
+      );
+
+  void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
+  void InitSolidSize()  { _numSolidBytes = (UInt64)(Int64)(-1); }
+  void InitSolid()
+  {
+    InitSolidFiles();
+    InitSolidSize();
+    _solidExtension = false;
+    _numSolidBytesDefined = false;
+  }
+
+  void Init();
+
+  COutHandler() { Init(); }
+
+  void BeforeSetProperty();
+
+  UInt32 minNumber;
+  UInt32 numProcessors;
+  UInt32 mainDicSize;
+  UInt32 mainDicMethodIndex;
+
+  DECL_EXTERNAL_CODECS_VARS
+};
+
+}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,40 @@
+// InStreamWithCRC.cpp
+
+#include "StdAfx.h"
+
+#include "InStreamWithCRC.h"
+
+STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize;
+  HRESULT result = _stream->Read(data, size, &realProcessedSize);
+  _size += realProcessedSize;
+  if (size > 0 && realProcessedSize == 0)
+    _wasFinished = true;
+  _crc = CrcUpdate(_crc, data, realProcessedSize);
+  if(processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return result;
+}
+
+STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize;
+  HRESULT result = _stream->Read(data, size, &realProcessedSize);
+  if (size > 0 && realProcessedSize == 0)
+    _wasFinished = true;
+  _size += realProcessedSize;
+  _crc = CrcUpdate(_crc, data, realProcessedSize);
+  if(processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return result;
+}
+
+STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+  if (seekOrigin != STREAM_SEEK_SET || offset != 0)
+    return E_FAIL;
+  _size = 0;
+  _crc = CRC_INIT_VAL;
+  return _stream->Seek(offset, seekOrigin, newPosition);
+}

Added: trunk/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/InStreamWithCRC.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,69 @@
+// InStreamWithCRC.h
+
+#ifndef __INSTREAMWITHCRC_H
+#define __INSTREAMWITHCRC_H
+
+#include "../../../Common/MyCom.h"
+#include "../../IStream.h"
+
+extern "C" 
+{ 
+#include "../../../../C/7zCrc.h"
+}
+
+class CSequentialInStreamWithCRC: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+private:
+  CMyComPtr<ISequentialInStream> _stream;
+  UInt64 _size;
+  UInt32 _crc;
+  bool _wasFinished;
+public:
+  void SetStream(ISequentialInStream *stream) { _stream = stream;  }
+  void Init()
+  {
+    _size = 0;
+    _wasFinished = false;
+    _crc = CRC_INIT_VAL;
+  }
+  void ReleaseStream() { _stream.Release(); }
+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
+  UInt64 GetSize() const { return _size; }
+  bool WasFinished() const { return _wasFinished; }
+};
+
+class CInStreamWithCRC: 
+  public IInStream,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP1(IInStream)
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+private:
+  CMyComPtr<IInStream> _stream;
+  UInt64 _size;
+  UInt32 _crc;
+  bool _wasFinished;
+public:
+  void SetStream(IInStream *stream) { _stream = stream;  }
+  void Init()
+  {
+    _size = 0;
+    _wasFinished = false;
+    _crc = CRC_INIT_VAL;
+  }
+  void ReleaseStream() { _stream.Release(); }
+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
+  UInt64 GetSize() const { return _size; }
+  bool WasFinished() const { return _wasFinished; }
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/ItemNameUtils.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,59 @@
+// Archive/Common/ItemNameUtils.cpp
+
+#include "StdAfx.h"
+
+#include "ItemNameUtils.h"
+
+namespace NArchive {
+namespace NItemName {
+
+static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;
+static const wchar_t kDirDelimiter = L'/';
+
+UString MakeLegalName(const UString &name)
+{
+  UString zipName = name;
+  zipName.Replace(kOSDirDelimiter, kDirDelimiter);
+  return zipName;
+}
+
+UString GetOSName(const UString &name)
+{
+  UString newName = name;
+  newName.Replace(kDirDelimiter, kOSDirDelimiter);
+  return newName;
+}
+
+UString GetOSName2(const UString &name)
+{
+  if (name.IsEmpty())
+    return UString();
+  UString newName = GetOSName(name);
+  if (newName[newName.Length() - 1] == kOSDirDelimiter)
+    newName.Delete(newName.Length() - 1);
+  return newName;
+}
+
+bool HasTailSlash(const AString &name, UINT codePage)
+{
+  if (name.IsEmpty())
+    return false;
+  LPCSTR prev = 
+  #ifdef _WIN32
+    CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);
+  #else
+    (LPCSTR)(name) + (name.Length() - 1);
+  #endif
+  return (*prev == '/');
+}
+
+#ifndef _WIN32
+UString WinNameToOSName(const UString &name)
+{
+  UString newName = name;
+  newName.Replace(L'\\', kOSDirDelimiter);
+  return newName;
+}
+#endif
+
+}}

Added: trunk/lzma/CPP/7zip/Archive/Common/ItemNameUtils.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/ItemNameUtils.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/ItemNameUtils.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// Archive/Common/ItemNameUtils.h
+
+#ifndef __ARCHIVE_ITEMNAMEUTILS_H
+#define __ARCHIVE_ITEMNAMEUTILS_H
+
+#include "../../../Common/MyString.h"
+
+namespace NArchive {
+namespace NItemName {
+
+  UString MakeLegalName(const UString &name);
+  UString GetOSName(const UString &name);
+  UString GetOSName2(const UString &name);
+  bool HasTailSlash(const AString &name, UINT codePage);
+
+  #ifdef _WIN32
+  inline UString WinNameToOSName(const UString &name)  { return name; }
+  #else
+  UString WinNameToOSName(const UString &name);
+  #endif
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/Common/MultiStream.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/MultiStream.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/MultiStream.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,201 @@
+// MultiStream.cpp
+
+#include "StdAfx.h"
+
+#include "MultiStream.h"
+
+STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  if(processedSize != NULL)
+    *processedSize = 0;
+  while(_streamIndex < Streams.Size() && size > 0)
+  {
+    CSubStreamInfo &s = Streams[_streamIndex];
+    if (_pos == s.Size)
+    {
+      _streamIndex++;
+      _pos = 0;
+      continue;
+    }
+    RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0));
+    UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos));
+    UInt32 realProcessed;
+    HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed);
+    data = (void *)((Byte *)data + realProcessed);
+    size -= realProcessed;
+    if(processedSize != NULL)
+      *processedSize += realProcessed;
+    _pos += realProcessed;
+    _seekPos += realProcessed;
+    RINOK(result);
+    break;
+  }
+  return S_OK;
+}
+  
+STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, 
+    UInt64 *newPosition)
+{
+  UInt64 newPos;
+  switch(seekOrigin)
+  {
+    case STREAM_SEEK_SET:
+      newPos = offset;
+      break;
+    case STREAM_SEEK_CUR:
+      newPos = _seekPos + offset;
+      break;
+    case STREAM_SEEK_END:
+      newPos = _totalLength + offset;
+      break;
+    default:
+      return STG_E_INVALIDFUNCTION;
+  }
+  _seekPos = 0;
+  for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++)
+  {
+    UInt64 size = Streams[_streamIndex].Size;
+    if (newPos < _seekPos + size)
+    {
+      _pos = newPos - _seekPos;
+      _seekPos += _pos;
+      if (newPosition != 0)
+        *newPosition = newPos;
+      return S_OK;
+    }
+    _seekPos += size;
+  }
+  if (newPos == _seekPos)
+  {
+    if (newPosition != 0)
+      *newPosition = newPos;
+    return S_OK;
+  }
+  return E_FAIL;
+}
+
+
+/*
+class COutVolumeStream: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  int _volIndex;
+  UInt64 _volSize;
+  UInt64 _curPos;
+  CMyComPtr<ISequentialOutStream> _volumeStream;
+  COutArchive _archive;
+  CCRC _crc;
+
+public:
+  MY_UNKNOWN_IMP
+
+  CFileItem _file;
+  CUpdateOptions _options;
+  CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+  void Init(IArchiveUpdateCallback2 *volumeCallback, 
+      const UString &name)  
+  { 
+    _file.Name = name;
+    _file.IsStartPosDefined = true;
+    _file.StartPos = 0;
+    
+    VolumeCallback = volumeCallback;
+    _volIndex = 0;
+    _volSize = 0;
+  }
+  
+  HRESULT Flush();
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+HRESULT COutVolumeStream::Flush()
+{
+  if (_volumeStream)
+  {
+    _file.UnPackSize = _curPos;
+    _file.FileCRC = _crc.GetDigest();
+    RINOK(WriteVolumeHeader(_archive, _file, _options));
+    _archive.Close();
+    _volumeStream.Release();
+    _file.StartPos += _file.UnPackSize;
+  }
+  return S_OK;
+}
+*/
+
+/*
+STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  if(processedSize != NULL)
+    *processedSize = 0;
+  while(size > 0)
+  {
+    if (_streamIndex >= Streams.Size())
+    {
+      CSubStreamInfo subStream;
+      RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
+      RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
+      subStream.Pos = 0;
+      Streams.Add(subStream);
+      continue;
+    }
+    CSubStreamInfo &subStream = Streams[_streamIndex];
+    if (_offsetPos >= subStream.Size)
+    {
+      _offsetPos -= subStream.Size;
+      _streamIndex++;
+      continue;
+    }
+    if (_offsetPos != subStream.Pos)
+    {
+      CMyComPtr<IOutStream> outStream;
+      RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
+      RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
+      subStream.Pos = _offsetPos;
+    }
+
+    UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
+    UInt32 realProcessed;
+    RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
+    data = (void *)((Byte *)data + realProcessed);
+    size -= realProcessed;
+    subStream.Pos += realProcessed;
+    _offsetPos += realProcessed;
+    _absPos += realProcessed;
+    if (_absPos > _length)
+      _length = _absPos;
+    if(processedSize != NULL)
+      *processedSize += realProcessed;
+    if (subStream.Pos == subStream.Size)
+    {
+      _streamIndex++;
+      _offsetPos = 0;
+    }
+    if (realProcessed != curSize && realProcessed == 0)
+      return E_FAIL;
+  }
+  return S_OK;
+}
+
+STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+  if(seekOrigin >= 3)
+    return STG_E_INVALIDFUNCTION;
+  switch(seekOrigin)
+  {
+    case STREAM_SEEK_SET:
+      _absPos = offset;
+      break;
+    case STREAM_SEEK_CUR:
+      _absPos += offset;
+      break;
+    case STREAM_SEEK_END:
+      _absPos = _length + offset;
+      break;
+  }
+  _offsetPos = _absPos;
+  _streamIndex = 0;
+  return S_OK;
+}
+*/

Added: trunk/lzma/CPP/7zip/Archive/Common/MultiStream.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/MultiStream.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/MultiStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,76 @@
+// MultiStream.h
+
+#ifndef __MULTISTREAM_H
+#define __MULTISTREAM_H
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/MyVector.h"
+#include "../../Archive/IArchive.h"
+
+class CMultiStream: 
+  public IInStream,
+  public CMyUnknownImp
+{
+  int _streamIndex;
+  UInt64 _pos;
+  UInt64 _seekPos;
+  UInt64 _totalLength;
+public:
+  struct CSubStreamInfo
+  {
+    CMyComPtr<IInStream> Stream;
+    UInt64 Pos;
+    UInt64 Size;
+  };
+  CObjectVector<CSubStreamInfo> Streams;
+  void Init()
+  {
+    _streamIndex = 0;
+    _pos = 0;
+    _seekPos = 0;
+    _totalLength = 0;
+    for (int i = 0; i < Streams.Size(); i++)
+      _totalLength += Streams[i].Size;
+  }
+
+  MY_UNKNOWN_IMP1(IInStream)
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+/*
+class COutMultiStream: 
+  public IOutStream,
+  public CMyUnknownImp
+{
+  int _streamIndex; // required stream
+  UInt64 _offsetPos; // offset from start of _streamIndex index
+  UInt64 _absPos;
+  UInt64 _length;
+
+  struct CSubStreamInfo
+  {
+    CMyComPtr<ISequentialOutStream> Stream;
+    UInt64 Size;
+    UInt64 Pos;
+ };
+  CObjectVector<CSubStreamInfo> Streams;
+public:
+  CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+  void Init()
+  {
+    _streamIndex = 0;
+    _offsetPos = 0;
+    _absPos = 0;
+    _length = 0;
+  }
+
+  MY_UNKNOWN_IMP1(IOutStream)
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+*/
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// OutStreamWithCRC.cpp
+
+#include "StdAfx.h"
+
+#include "OutStreamWithCRC.h"
+
+STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize;
+  HRESULT result;
+  if(!_stream)
+  {
+    realProcessedSize = size;
+    result = S_OK;
+  }
+  else
+    result = _stream->Write(data, size, &realProcessedSize);
+  if (_calculate)
+    _crc = CrcUpdate(_crc, data, realProcessedSize);
+  _size += realProcessedSize;
+  if(processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return result;
+}

Added: trunk/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/OutStreamWithCRC.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,38 @@
+// OutStreamWithCRC.h
+
+#ifndef __OUTSTREAMWITHCRC_H
+#define __OUTSTREAMWITHCRC_H
+
+#include "../../../Common/MyCom.h"
+#include "../../IStream.h"
+
+extern "C" 
+{ 
+#include "../../../../C/7zCrc.h"
+}
+
+class COutStreamWithCRC: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<ISequentialOutStream> _stream;
+  UInt64 _size;
+  UInt32 _crc;
+  bool _calculate;
+public:
+  MY_UNKNOWN_IMP
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+  void ReleaseStream() { _stream.Release(); }
+  void Init(bool calculate = true)
+  {
+    _size = 0;
+    _calculate = calculate;
+    _crc = CRC_INIT_VAL;
+  }
+  void InitCRC() { _crc = CRC_INIT_VAL; }
+  UInt64 GetSize() const { return _size; }
+  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/Common/ParseProperties.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/ParseProperties.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/ParseProperties.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,174 @@
+// ParseProperties.cpp
+
+#include "StdAfx.h"
+
+#include "ParseProperties.h"
+
+#include "Common/StringToInt.h"
+#include "Common/MyCom.h"
+
+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
+{
+  if (prop.vt == VT_UI4)
+  {
+    if (!name.IsEmpty())
+      return E_INVALIDARG;
+    resValue = prop.ulVal;
+  }
+  else if (prop.vt == VT_EMPTY)
+  {
+    if(!name.IsEmpty())
+    {
+      const wchar_t *start = name;
+      const wchar_t *end;
+      UInt64 v = ConvertStringToUInt64(start, &end);
+      if (end - start != name.Length())
+        return E_INVALIDARG;
+      resValue = (UInt32)v;
+    }
+  }
+  else
+    return E_INVALIDARG;
+  return S_OK;
+}
+
+static const int kLogarithmicSizeLimit = 32;
+static const wchar_t kByteSymbol = L'B';
+static const wchar_t kKiloByteSymbol = L'K';
+static const wchar_t kMegaByteSymbol = L'M';
+
+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)
+{
+  UString srcString = srcStringSpec;
+  srcString.MakeUpper();
+
+  const wchar_t *start = srcString;
+  const wchar_t *end;
+  UInt64 number = ConvertStringToUInt64(start, &end);
+  int numDigits = (int)(end - start);
+  if (numDigits == 0 || srcString.Length() > numDigits + 1)
+    return E_INVALIDARG;
+  if (srcString.Length() == numDigits)
+  {
+    if (number >= kLogarithmicSizeLimit)
+      return E_INVALIDARG;
+    dicSize = (UInt32)1 << (int)number;
+    return S_OK;
+  }
+  switch (srcString[numDigits])
+  {
+    case kByteSymbol:
+      if (number >= ((UInt64)1 << kLogarithmicSizeLimit))
+        return E_INVALIDARG;
+      dicSize = (UInt32)number;
+      break;
+    case kKiloByteSymbol:
+      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))
+        return E_INVALIDARG;
+      dicSize = (UInt32)(number << 10);
+      break;
+    case kMegaByteSymbol:
+      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))
+        return E_INVALIDARG;
+      dicSize = (UInt32)(number << 20);
+      break;
+    default:
+      return E_INVALIDARG;
+  }
+  return S_OK;
+}
+
+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
+{
+  if (name.IsEmpty())
+  {
+    if (prop.vt == VT_UI4)
+    {
+      UInt32 logDicSize = prop.ulVal;
+      if (logDicSize >= 32)
+        return E_INVALIDARG;
+      resValue = (UInt32)1 << logDicSize;
+      return S_OK;
+    }
+    if (prop.vt == VT_BSTR)
+      return ParsePropDictionaryValue(prop.bstrVal, resValue);
+    return E_INVALIDARG;
+  }
+  return ParsePropDictionaryValue(name, resValue);
+}
+
+bool StringToBool(const UString &s, bool &res)
+{
+  if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0)
+  {
+    res = true;
+    return true;
+  }
+  if (s.CompareNoCase(L"OFF") == 0)
+  {
+    res = false;
+    return true;
+  }
+  return false;
+}
+
+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
+{
+  switch(value.vt)
+  {
+    case VT_EMPTY:
+      dest = true;
+      return S_OK;
+    /*
+    case VT_UI4:
+      dest = (value.ulVal != 0);
+      break;
+    */
+    case VT_BSTR:
+      return StringToBool(value.bstrVal, dest) ?  S_OK : E_INVALIDARG;
+  }
+  return E_INVALIDARG;
+}
+
+int ParseStringToUInt32(const UString &srcString, UInt32 &number)
+{
+  const wchar_t *start = srcString;
+  const wchar_t *end;
+  UInt64 number64 = ConvertStringToUInt64(start, &end);
+  if (number64 > 0xFFFFFFFF) 
+  {
+    number = 0;
+    return 0;
+  }
+  number = (UInt32)number64;
+  return (int)(end - start);
+}
+
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
+{
+  if (name.IsEmpty())
+  {
+    switch(prop.vt)
+    {
+      case VT_UI4:
+        numThreads = prop.ulVal;
+        break;
+      default:
+      {
+        bool val; 
+        RINOK(SetBoolProperty(val, prop));
+        numThreads = (val ? defaultNumThreads : 1);
+        break;
+      }
+    }
+  }
+  else
+  {
+    UInt32 number;
+    int index = ParseStringToUInt32(name, number);
+    if (index != name.Length())
+      return E_INVALIDARG;
+    numThreads = number;
+  }
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/Archive/Common/ParseProperties.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/Common/ParseProperties.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/Common/ParseProperties.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,18 @@
+// ParseProperties.h
+
+#ifndef __PARSEPROPERTIES_H
+#define __PARSEPROPERTIES_H
+
+#include "Common/MyString.h"
+#include "Common/Types.h"
+
+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);
+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
+
+bool StringToBool(const UString &s, bool &res);
+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);
+int ParseStringToUInt32(const UString &srcString, UInt32 &number);
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
+
+#endif

Added: trunk/lzma/CPP/7zip/Archive/DllExports2.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Archive/DllExports2.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/DllExports2.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,82 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/MyInitGuid.h"
+#include "../../Common/ComTry.h"
+#include "../../Common/Types.h"
+#include "../../Windows/PropVariant.h"
+#if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)
+extern "C" 
+{ 
+#include "../../../C/Alloc.h"
+}
+#endif
+
+#include "IArchive.h"
+#include "../ICoder.h"
+#include "../IPassword.h"
+
+HINSTANCE g_hInstance;
+#ifndef _UNICODE
+#ifdef _WIN32
+bool g_IsNT = false;
+static bool IsItWindowsNT()
+{
+  OSVERSIONINFO versionInfo;
+  versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+  if (!::GetVersionEx(&versionInfo)) 
+    return false;
+  return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+#endif
+#endif
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
+{
+  if (dwReason == DLL_PROCESS_ATTACH)
+  {
+    g_hInstance = hInstance;
+    #ifndef _UNICODE
+    #ifdef _WIN32
+    g_IsNT = IsItWindowsNT();
+    #endif
+    #endif
+  }
+  return TRUE;
+}
+
+DEFINE_GUID(CLSID_CArchiveHandler, 
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);
+
+static const UInt16 kDecodeId = 0x2790;
+
+DEFINE_GUID(CLSID_CCodec, 
+0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);
+STDAPI CreateArchiver(const GUID *classID, const GUID *iid, void **outObject);
+
+STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)
+{
+  // COM_TRY_BEGIN
+  *outObject = 0;
+  if (*iid == IID_ICompressCoder || *iid == IID_ICompressCoder2 || *iid == IID_ICompressFilter)
+  {
+    return CreateCoder(clsid, iid, outObject);
+  }
+  else
+  {
+    return CreateArchiver(clsid, iid, outObject);
+  }
+  // COM_TRY_END
+}
+
+STDAPI SetLargePageMode()
+{
+  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)
+  SetLargePageSize();
+  #endif
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/Archive/IArchive.h
===================================================================
--- trunk/lzma/CPP/7zip/Archive/IArchive.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Archive/IArchive.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,207 @@
+// IArchive.h
+
+#ifndef __IARCHIVE_H
+#define __IARCHIVE_H
+
+#include "../IStream.h"
+#include "../IProgress.h"
+#include "../PropID.h"
+
+#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x)
+#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
+
+namespace NFileTimeType
+{
+  enum EEnum
+  {
+    kWindows,
+    kUnix,
+    kDOS
+  };
+}
+
+namespace NArchive
+{
+  enum 
+  {
+    kName = 0,
+    kClassID,
+    kExtension,
+    kAddExtension,
+    kUpdate,
+    kKeepName,
+    kStartSignature,
+    kFinishSignature,
+    kAssociate
+  };
+
+  namespace NExtract
+  {
+    namespace NAskMode
+    {
+      enum 
+      {
+        kExtract = 0,
+        kTest,
+        kSkip
+      };
+    }
+    namespace NOperationResult
+    {
+      enum 
+      {
+        kOK = 0,
+        kUnSupportedMethod,
+        kDataError,
+        kCRCError
+      };
+    }
+  }
+  namespace NUpdate
+  {
+    namespace NOperationResult
+    {
+      enum 
+      {
+        kOK = 0,
+        kError
+      };
+    }
+  }
+}
+
+ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
+{
+  STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) PURE;
+  STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) PURE;
+};
+
+
+ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
+{
+  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, 
+      Int32 askExtractMode) PURE;
+  // GetStream OUT: S_OK - OK, S_FALSE - skeep this file
+  STDMETHOD(PrepareOperation)(Int32 askExtractMode) PURE;
+  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) PURE;
+};
+
+
+ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)
+{
+  STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) PURE;
+  STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) PURE;
+};
+
+
+ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)
+{
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;  
+};
+
+
+ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)
+{
+  STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;
+};
+
+
+/*
+IInArchive::Extract:
+  indices must be sorted 
+  numItems = 0xFFFFFFFF means "all files"
+  testMode != 0 means "test files without writing to outStream"
+*/
+
+#define INTERFACE_IInArchive(x) \
+  STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \
+  STDMETHOD(Close)() x; \
+  STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \
+  STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \
+  STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \
+  STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
+  STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
+  STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \
+  STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x;
+
+ARCHIVE_INTERFACE(IInArchive, 0x60)
+{
+  INTERFACE_IInArchive(PURE)
+};
+
+
+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)
+{
+  STDMETHOD(GetUpdateItemInfo)(UInt32 index, 
+      Int32 *newData, // 1 - new data, 0 - old data
+      Int32 *newProperties, // 1 - new properties, 0 - old properties
+      UInt32 *indexInArchive // -1 if there is no in archive, or if doesn't matter
+      ) PURE;
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) PURE;
+  STDMETHOD(SetOperationResult)(Int32 operationResult) PURE;
+};
+
+
+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
+{
+  STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) PURE;
+  STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) PURE;
+};
+
+
+#define INTERFACE_IOutArchive(x) \
+  STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \
+  STDMETHOD(GetFileTimeType)(UInt32 *type) x;
+
+ARCHIVE_INTERFACE(IOutArchive, 0xA0)
+{
+  INTERFACE_IOutArchive(PURE)
+};
+
+
+ARCHIVE_INTERFACE(ISetProperties, 0x03)
+{
+  STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;
+};
+
+
+#define IMP_IInArchive_GetProp(k) \
+  (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
+    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \
+    const STATPROPSTG &srcItem = k[index]; \
+    *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \
+
+#define IMP_IInArchive_GetProp_WITH_NAME(k) \
+  (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
+    { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \
+    const STATPROPSTG &srcItem = k[index]; \
+    *propID = srcItem.propid; *varType = srcItem.vt; \
+    if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \
+
+#define IMP_IInArchive_Props \
+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \
+    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \
+  STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps)
+
+#define IMP_IInArchive_Props_WITH_NAME \
+  STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \
+    { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \
+  STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps)
+
+
+#define IMP_IInArchive_ArcProps \
+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
+    { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \
+  STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps)
+
+#define IMP_IInArchive_ArcProps_NO \
+  STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \
+    { *numProperties = 0; return S_OK; } \
+  STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \
+    { return E_NOTIMPL; } \
+  STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \
+    { value->vt = VT_EMPTY; return S_OK; } 
+
+#endif

Added: trunk/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1453 @@
+# Microsoft Developer Studio Project File - Name="Alone" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Alone - Win32 DebugU
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "Alone.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "Alone.mak" CFG="Alone - Win32 DebugU"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Alone - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Alone - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "Alone - Win32 ReleaseU" (based on "Win32 (x86) Console Application")
+!MESSAGE "Alone - Win32 DebugU" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "Alone - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /Gz /MT /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MDd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseU"
+# PROP BASE Intermediate_Dir "ReleaseU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseU"
+# PROP Intermediate_Dir "ReleaseU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za.exe" /opt:NOWIN98
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7zr.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugU"
+# PROP BASE Intermediate_Dir "DebugU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugU"
+# PROP Intermediate_Dir "DebugU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /Gz /W4 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "COMPRESS_MT" /D "_NO_CRYPTO" /D "BREAK_HANDLER" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za.exe" /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7zr.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "Alone - Win32 Release"
+# Name "Alone - Win32 Debug"
+# Name "Alone - Win32 ReleaseU"
+# Name "Alone - Win32 DebugU"
+# Begin Group "Console"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ArError.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\CompressionMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ConsoleClose.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ConsoleClose.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\ExtractCallbackConsole.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\List.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\List.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\Main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\MainAr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\OpenCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\OpenCallbackConsole.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\PercentPrinter.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\PercentPrinter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\UpdateCallbackConsole.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\UpdateCallbackConsole.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\UserInputUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Console\UserInputUtils.h
+# End Source File
+# End Group
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\AutoPtr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Buffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ComTry.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\DynamicBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ListFileUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\ListFileUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyCom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyException.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyGuidDef.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyInitGuid.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyUnknown.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyWindows.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyWindows.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Random.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Random.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StdOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Device.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Error.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Handle.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\MemoryLock.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\MemoryLock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Thread.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Time.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\CreateCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\CreateCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CrossThreadProgress.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CrossThreadProgress.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FilePathAutoRename.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FilterCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FilterCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InOutTempBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InOutTempBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LimitedStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LimitedStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LockedStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LockedStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LSBFDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LSBFDecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LSBFEncoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LSBFEncoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MethodId.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MethodId.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MethodProps.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MethodProps.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MSBFDecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MSBFEncoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OffsetStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OffsetStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressMt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressMt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\RegisterArc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\RegisterCodec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamBinder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamBinder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamObjects.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamObjects.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\VirtThread.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Group "Branch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\BranchCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\Coder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\x86.cpp
+
+!IF  "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\x86.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\x86_2.cpp
+
+!IF  "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Branch\x86_2.h
+# End Source File
+# End Group
+# Begin Group "Copy"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyRegister.cpp
+# End Source File
+# End Group
+# Begin Group "LZ"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\LZ\LZOutWindow.cpp
+
+!IF  "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O1
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# ADD CPP /O1
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZ\LZOutWindow.h
+# End Source File
+# End Group
+# Begin Group "LZMA"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA\LZMA.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA\LZMADecoder.cpp
+
+!IF  "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA\LZMADecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA\LZMAEncoder.cpp
+
+!IF  "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA\LZMAEncoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA\LZMARegister.cpp
+# End Source File
+# End Group
+# Begin Group "RangeCoder"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\RangeCoder\RangeCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\RangeCoder\RangeCoderBit.cpp
+
+!IF  "$(CFG)" == "Alone - Win32 Release"
+
+# ADD CPP /O1
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 Debug"
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 ReleaseU"
+
+# ADD CPP /O1
+
+!ELSEIF  "$(CFG)" == "Alone - Win32 DebugU"
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\RangeCoder\RangeCoderBit.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\RangeCoder\RangeCoderBitTree.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\RangeCoder\RangeCoderOpt.h
+# End Source File
+# End Group
+# Begin Group "LZMA_Alone"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA_Alone\LzmaBench.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\LZMA_Alone\LzmaBenchCon.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "Archive"
+
+# PROP Default_Filter ""
+# Begin Group "7z"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zCompressionMode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zCompressionMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zDecode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zEncode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zEncode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zExtract.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zFolderInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zFolderInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zFolderOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zFolderOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHandlerOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zOut.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zProperties.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zRegister.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zSpecStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zSpecStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zUpdate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\7z\7zUpdate.h
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CoderMixer2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CoderMixer2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CoderMixer2MT.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\CoderMixer2MT.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\DummyOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\DummyOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\HandlerOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\HandlerOut.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\InStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\InStreamWithCRC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ItemNameUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\MultiStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\MultiStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ParseProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\ParseProperties.h
+# End Source File
+# End Group
+# Begin Group "split"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Archive\Split\SplitHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Split\SplitHandler.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "UI Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveCommandLine.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveCommandLine.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveExtractCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ArchiveOpenCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\DefaultName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\EnumDirItems.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\EnumDirItems.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Extract.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Extract.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractingFilePath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\ExtractingFilePath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\LoadCodecs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\OpenArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Property.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\PropIDUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\PropIDUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\SetProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\SetProperties.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\SortUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\SortUtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\TempFiles.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\TempFiles.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Update.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\Update.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateAction.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateAction.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateCallback.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateCallback.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdatePair.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdatePair.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateProduce.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\UpdateProduce.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\WorkDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\UI\Common\WorkDir.h
+# End Source File
+# End Group
+# Begin Group "7-zip"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\ICoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IMyUnknown.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IPassword.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IProgress.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\PropID.h
+# End Source File
+# End Group
+# Begin Group "C"
+
+# PROP Default_Filter ""
+# Begin Group "C Branch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchARM.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchARM.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchARMThumb.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchARMThumb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchIA64.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchIA64.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchPPC.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchPPC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchSPARC.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchSPARC.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Alloc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Alloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\IStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lz\LzHash.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Types.h
+# End Source File
+# End Group
+# End Target
+# End Project

Added: trunk/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Alone7z/Alone.dsw	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Alone"=.\Alone.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

Added: trunk/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Alone7z/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif

Added: trunk/lzma/CPP/7zip/Bundles/Alone7z/makefile
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Alone7z/makefile	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Alone7z/makefile	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,236 @@
+PROG = 7za.exe
+LIBS = $(LIBS) user32.lib oleaut32.lib Advapi32.lib
+
+CFLAGS = $(CFLAGS) -I ../../../ \
+  -D_NO_CRYPTO \
+  -DWIN_LONG_PATH \
+  -DCOMPRESS_MT \
+  -DCOMPRESS_MF_MT \
+  -D_NO_CRYPTO \
+  -DBREAK_HANDLER \
+  -DBENCH_MT \
+
+
+CONSOLE_OBJS = \
+  $O\ConsoleClose.obj \
+  $O\ExtractCallbackConsole.obj \
+  $O\List.obj \
+  $O\Main.obj \
+  $O\MainAr.obj \
+  $O\OpenCallbackConsole.obj \
+  $O\PercentPrinter.obj \
+  $O\UpdateCallbackConsole.obj \
+  $O\UserInputUtils.obj \
+
+COMMON_OBJS = \
+  $O\CommandLineParser.obj \
+  $O\CRC.obj \
+  $O\IntToString.obj \
+  $O\ListFileUtils.obj \
+  $O\NewHandler.obj \
+  $O\StdInStream.obj \
+  $O\StdOutStream.obj \
+  $O\MyString.obj \
+  $O\StringConvert.obj \
+  $O\StringToInt.obj \
+  $O\UTFConvert.obj \
+  $O\MyVector.obj \
+  $O\Wildcard.obj \
+
+WIN_OBJS = \
+  $O\DLL.obj \
+  $O\Error.obj \
+  $O\FileDir.obj \
+  $O\FileFind.obj \
+  $O\FileIO.obj \
+  $O\FileName.obj \
+  $O\MemoryLock.obj \
+  $O\PropVariant.obj \
+  $O\PropVariantConversions.obj \
+  $O\Synchronization.obj \
+  $O\System.obj \
+
+7ZIP_COMMON_OBJS = \
+  $O\CreateCoder.obj \
+  $O\FilePathAutoRename.obj \
+  $O\FileStreams.obj \
+  $O\InBuffer.obj \
+  $O\InOutTempBuffer.obj \
+  $O\FilterCoder.obj \
+  $O\LimitedStreams.obj \
+  $O\LockedStream.obj \
+  $O\MethodId.obj \
+  $O\MethodProps.obj \
+  $O\OffsetStream.obj \
+  $O\OutBuffer.obj \
+  $O\ProgressUtils.obj \
+  $O\StreamBinder.obj \
+  $O\StreamObjects.obj \
+  $O\StreamUtils.obj \
+  $O\VirtThread.obj \
+
+UI_COMMON_OBJS = \
+  $O\ArchiveCommandLine.obj \
+  $O\ArchiveExtractCallback.obj \
+  $O\ArchiveOpenCallback.obj \
+  $O\DefaultName.obj \
+  $O\EnumDirItems.obj \
+  $O\Extract.obj \
+  $O\ExtractingFilePath.obj \
+  $O\LoadCodecs.obj \
+  $O\OpenArchive.obj \
+  $O\PropIDUtils.obj \
+  $O\SetProperties.obj \
+  $O\SortUtils.obj \
+  $O\TempFiles.obj \
+  $O\Update.obj \
+  $O\UpdateAction.obj \
+  $O\UpdateCallback.obj \
+  $O\UpdatePair.obj \
+  $O\UpdateProduce.obj \
+  $O\WorkDir.obj \
+
+AR_COMMON_OBJS = \
+  $O\CoderMixer2.obj \
+  $O\CoderMixer2MT.obj \
+  $O\CrossThreadProgress.obj \
+  $O\DummyOutStream.obj \
+  $O\HandlerOut.obj \
+  $O\InStreamWithCRC.obj \
+  $O\ItemNameUtils.obj \
+  $O\MultiStream.obj \
+  $O\OutStreamWithCRC.obj \
+  $O\ParseProperties.obj \
+
+
+7Z_OBJS = \
+  $O\7zCompressionMode.obj \
+  $O\7zDecode.obj \
+  $O\7zEncode.obj \
+  $O\7zExtract.obj \
+  $O\7zFolderInStream.obj \
+  $O\7zFolderOutStream.obj \
+  $O\7zHandler.obj \
+  $O\7zHandlerOut.obj \
+  $O\7zHeader.obj \
+  $O\7zIn.obj \
+  $O\7zOut.obj \
+  $O\7zProperties.obj \
+  $O\7zRegister.obj \
+  $O\7zSpecStream.obj \
+  $O\7zUpdate.obj \
+
+
+BRANCH_OPT_OBJS = \
+  $O\BranchCoder.obj \
+  $O\x86.obj \
+  $O\x86_2.obj \
+  $O\ARM.obj \
+  $O\ARMThumb.obj \
+  $O\IA64.obj \
+  $O\PPC.obj \
+  $O\SPARC.obj \
+  $O\BranchRegister.obj \
+  $O\BCJRegister.obj \
+  $O\BCJ2Register.obj \
+
+SWAP_OPT_OBJS = \
+  $O\ByteSwap.obj \
+  $O\ByteSwapRegister.obj \
+
+COPY_OBJS = \
+  $O\CopyCoder.obj \
+  $O\CopyRegister.obj \
+
+LZ_OBJS = \
+  $O\LZOutWindow.obj \
+
+LZMA_OPT_OBJS = \
+  $O\LZMADecoder.obj \
+  $O\LZMAEncoder.obj \
+  $O\LZMARegister.obj \
+
+LZMA_BENCH_OBJS = \
+  $O\LzmaBench.obj \
+  $O\LzmaBenchCon.obj \
+
+C_OBJS = \
+  $O\Alloc.obj \
+  $O\7zCrc.obj \
+  $O\Sort.obj \
+  $O\Threads.obj \
+
+C_LZ_OBJS = \
+  $O\MatchFinder.obj \
+  $O\MatchFinderMt.obj \
+
+C_BRANCH_OBJS = \
+  $O\BranchARM.obj \
+  $O\BranchARMThumb.obj \
+  $O\BranchIA64.obj \
+  $O\BranchPPC.obj \
+  $O\BranchSPARC.obj \
+  $O\BranchX86.obj \
+
+OBJS = \
+  $O\StdAfx.obj \
+  $(CONSOLE_OBJS) \
+  $(COMMON_OBJS) \
+  $(WIN_OBJS) \
+  $(7ZIP_COMMON_OBJS) \
+  $(UI_COMMON_OBJS) \
+  $(AR_COMMON_OBJS) \
+  $(7Z_OBJS) \
+  $(BRANCH_OPT_OBJS) \
+  $(SWAP_OPT_OBJS) \
+  $(COPY_OBJS) \
+  $(LZ_OBJS) \
+  $(LZMA_OPT_OBJS) \
+  $(LZMA_BENCH_OBJS) \
+  $(C_OBJS) \
+  $(C_LZ_OBJS) \
+  $(C_BRANCH_OBJS) \
+  $O\RangeCoderBit.obj \
+  $(CRC_OBJS) \
+  $O\resource.res
+
+
+!include "../../../Build.mak"
+
+$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp
+	$(COMPL)
+
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+	$(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+	$(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+	$(COMPL)
+$(UI_COMMON_OBJS): ../../UI/Common/$(*B).cpp
+	$(COMPL)
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp
+	$(COMPL)
+
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp
+	$(COMPL)
+$(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp
+	$(COMPL_O2)
+$(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp
+	$(COMPL_O2)
+$(COPY_OBJS): ../../Compress/Copy/$(*B).cpp
+	$(COMPL)
+$(LZ_OBJS): ../../Compress/LZ/$(*B).cpp
+	$(COMPL)
+$(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp
+	$(COMPL_O2)
+$(LZMA_BENCH_OBJS): ../../Compress/LZMA_Alone/$(*B).cpp
+	$(COMPL)
+$O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp
+	$(COMPL)
+
+$(C_OBJS): ../../../../C/$(*B).c
+	$(COMPL_O2)
+$(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c
+	$(COMPL_O2)
+$(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c
+	$(COMPL_O2)

Added: trunk/lzma/CPP/7zip/Bundles/Alone7z/resource.rc
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Alone7z/resource.rc	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Alone7z/resource.rc	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_APP("7-Zip Standalone Console", "7za")

Added: trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif

Added: trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/makefile
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/makefile	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/makefile	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,165 @@
+PROG = 7zxr.dll
+DEF_FILE = ../../Archive/Archive2.def
+LIBS = $(LIBS) user32.lib oleaut32.lib
+CFLAGS = $(CFLAGS) -I ../../../ \
+  -DEXTRACT_ONLY \
+  -DCOMPRESS_MT \
+  -D_NO_CRYPTO
+
+COMMON_OBJS = \
+  $O\CRC.obj \
+  $O\IntToString.obj \
+  $O\NewHandler.obj \
+  $O\MyString.obj \
+  $O\StringConvert.obj \
+  $O\StringToInt.obj \
+  $O\MyVector.obj \
+  $O\Wildcard.obj \
+
+WIN_OBJS = \
+  $O\FileDir.obj \
+  $O\FileFind.obj \
+  $O\FileIO.obj \
+  $O\PropVariant.obj \
+  $O\Synchronization.obj \
+  $O\System.obj \
+
+7ZIP_COMMON_OBJS = \
+  $O\CreateCoder.obj \
+  $O\InBuffer.obj \
+  $O\InOutTempBuffer.obj \
+  $O\FilterCoder.obj \
+  $O\LimitedStreams.obj \
+  $O\LockedStream.obj \
+  $O\MethodId.obj \
+  $O\MethodProps.obj \
+  $O\OutBuffer.obj \
+  $O\ProgressUtils.obj \
+  $O\StreamBinder.obj \
+  $O\StreamObjects.obj \
+  $O\StreamUtils.obj \
+  $O\VirtThread.obj \
+
+AR_OBJS = \
+  $O\ArchiveExports.obj \
+  $O\DllExports2.obj \
+
+AR_COMMON_OBJS = \
+  $O\CoderMixer2.obj \
+  $O\CoderMixer2MT.obj \
+  $O\CrossThreadProgress.obj \
+  $O\HandlerOut.obj \
+  $O\ItemNameUtils.obj \
+  $O\OutStreamWithCRC.obj \
+  $O\ParseProperties.obj \
+
+
+7Z_OBJS = \
+  $O\7zCompressionMode.obj \
+  $O\7zDecode.obj \
+  $O\7zExtract.obj \
+  $O\7zFolderOutStream.obj \
+  $O\7zHandler.obj \
+  $O\7zHeader.obj \
+  $O\7zIn.obj \
+  $O\7zProperties.obj \
+  $O\7zRegister.obj \
+
+
+COMPRESS_OBJS = \
+  $O\CodecExports.obj \
+
+SWAP_OPT_OBJS = \
+  $O\ByteSwap.obj \
+  $O\ByteSwapRegister.obj \
+
+BRANCH_OPT_OBJS = \
+  $O\BranchCoder.obj \
+  $O\x86.obj \
+  $O\x86_2.obj \
+  $O\ARM.obj \
+  $O\ARMThumb.obj \
+  $O\IA64.obj \
+  $O\PPC.obj \
+  $O\SPARC.obj \
+  $O\BranchRegister.obj \
+  $O\BCJRegister.obj \
+  $O\BCJ2Register.obj \
+
+COPY_OBJS = \
+  $O\CopyCoder.obj \
+  $O\CopyRegister.obj \
+
+LZ_OBJS = \
+  $O\LZOutWindow.obj \
+
+LZMA_OPT_OBJS = \
+  $O\LZMADecoder.obj \
+  $O\LZMARegister.obj \
+
+C_OBJS = \
+  $O\Alloc.obj \
+  $O\7zCrc.obj \
+  $O\Threads.obj \
+
+C_BRANCH_OBJS = \
+  $O\BranchARM.obj \
+  $O\BranchARMThumb.obj \
+  $O\BranchIA64.obj \
+  $O\BranchPPC.obj \
+  $O\BranchSPARC.obj \
+  $O\BranchX86.obj \
+
+OBJS = \
+  $O\StdAfx.obj \
+  $(CONSOLE_OBJS) \
+  $(COMMON_OBJS) \
+  $(WIN_OBJS) \
+  $(7ZIP_COMMON_OBJS) \
+  $(AR_OBJS) \
+  $(AR_COMMON_OBJS) \
+  $(7Z_OBJS) \
+  $(COMPRESS_OBJS) \
+  $(BRANCH_OPT_OBJS) \
+  $(SWAP_OPT_OBJS) \
+  $(COPY_OBJS) \
+  $(LZ_OBJS) \
+  $(LZMA_OPT_OBJS) \
+  $(C_OBJS) \
+  $(C_BRANCH_OBJS) \
+  $O\resource.res
+
+
+!include "../../../Build.mak"
+
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+	$(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+	$(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+	$(COMPL)
+$(AR_OBJS): ../../Archive/$(*B).cpp
+	$(COMPL)
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp
+	$(COMPL)
+
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp
+	$(COMPL)
+
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp
+	$(COMPL)
+$(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp
+	$(COMPL_O2)
+$(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp
+	$(COMPL_O2)
+$(COPY_OBJS): ../../Compress/Copy/$(*B).cpp
+	$(COMPL)
+$(LZ_OBJS): ../../Compress/LZ/$(*B).cpp
+	$(COMPL)
+$(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp
+	$(COMPL_O2)
+
+$(C_OBJS): ../../../../C/$(*B).c
+	$(COMPL_O2)
+$(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c
+	$(COMPL_O2)

Added: trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Format7zExtractR/resource.rc	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("7z Standalone Extracting Plugin", "7zxr")
+
+101  ICON  "../../Archive/7z/7z.ico"

Added: trunk/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Format7zR/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif

Added: trunk/lzma/CPP/7zip/Bundles/Format7zR/makefile
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Format7zR/makefile	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Format7zR/makefile	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,188 @@
+PROG = 7zra.dll
+DEF_FILE = ../../Archive/Archive2.def
+LIBS = $(LIBS) user32.lib oleaut32.lib
+CFLAGS = $(CFLAGS) -I ../../../ \
+  -DCOMPRESS_MT \
+  -DCOMPRESS_MF_MT \
+  -D_NO_CRYPTO
+
+COMMON_OBJS = \
+  $O\CRC.obj \
+  $O\IntToString.obj \
+  $O\NewHandler.obj \
+  $O\MyString.obj \
+  $O\StringConvert.obj \
+  $O\StringToInt.obj \
+  $O\MyVector.obj \
+  $O\Wildcard.obj \
+
+WIN_OBJS = \
+  $O\FileDir.obj \
+  $O\FileFind.obj \
+  $O\FileIO.obj \
+  $O\PropVariant.obj \
+  $O\Synchronization.obj \
+  $O\System.obj \
+
+7ZIP_COMMON_OBJS = \
+  $O\CreateCoder.obj \
+  $O\InBuffer.obj \
+  $O\InOutTempBuffer.obj \
+  $O\FilterCoder.obj \
+  $O\LimitedStreams.obj \
+  $O\LockedStream.obj \
+  $O\MethodId.obj \
+  $O\MethodProps.obj \
+  $O\OutBuffer.obj \
+  $O\ProgressUtils.obj \
+  $O\StreamBinder.obj \
+  $O\StreamObjects.obj \
+  $O\StreamUtils.obj \
+  $O\VirtThread.obj \
+
+AR_OBJS = \
+  $O\ArchiveExports.obj \
+  $O\DllExports2.obj \
+
+AR_COMMON_OBJS = \
+  $O\CoderMixer2.obj \
+  $O\CoderMixer2MT.obj \
+  $O\CrossThreadProgress.obj \
+  $O\HandlerOut.obj \
+  $O\InStreamWithCRC.obj \
+  $O\ItemNameUtils.obj \
+  $O\OutStreamWithCRC.obj \
+  $O\ParseProperties.obj \
+
+
+7Z_OBJS = \
+  $O\7zCompressionMode.obj \
+  $O\7zDecode.obj \
+  $O\7zEncode.obj \
+  $O\7zExtract.obj \
+  $O\7zFolderInStream.obj \
+  $O\7zFolderOutStream.obj \
+  $O\7zHandler.obj \
+  $O\7zHandlerOut.obj \
+  $O\7zHeader.obj \
+  $O\7zIn.obj \
+  $O\7zOut.obj \
+  $O\7zProperties.obj \
+  $O\7zSpecStream.obj \
+  $O\7zUpdate.obj \
+  $O\7zRegister.obj \
+
+
+COMPRESS_OBJS = \
+  $O\CodecExports.obj \
+
+BRANCH_OPT_OBJS = \
+  $O\BranchCoder.obj \
+  $O\x86.obj \
+  $O\x86_2.obj \
+  $O\ARM.obj \
+  $O\ARMThumb.obj \
+  $O\IA64.obj \
+  $O\PPC.obj \
+  $O\SPARC.obj \
+  $O\BranchRegister.obj \
+  $O\BCJRegister.obj \
+  $O\BCJ2Register.obj \
+
+SWAP_OPT_OBJS = \
+  $O\ByteSwap.obj \
+  $O\ByteSwapRegister.obj \
+
+COPY_OBJS = \
+  $O\CopyCoder.obj \
+  $O\CopyRegister.obj \
+
+LZ_OBJS = \
+  $O\LZOutWindow.obj \
+
+LZMA_OPT_OBJS = \
+  $O\LZMADecoder.obj \
+  $O\LZMAEncoder.obj \
+  $O\LZMARegister.obj \
+
+C_OBJS = \
+  $O\Alloc.obj \
+  $O\7zCrc.obj \
+  $O\Sort.obj \
+  $O\Threads.obj \
+
+C_LZ_OBJS = \
+  $O\MatchFinder.obj \
+  $O\MatchFinderMt.obj \
+
+C_BRANCH_OBJS = \
+  $O\BranchARM.obj \
+  $O\BranchARMThumb.obj \
+  $O\BranchIA64.obj \
+  $O\BranchPPC.obj \
+  $O\BranchSPARC.obj \
+  $O\BranchX86.obj \
+
+OBJS = \
+  $O\StdAfx.obj \
+  $(CONSOLE_OBJS) \
+  $(COMMON_OBJS) \
+  $(WIN_OBJS) \
+  $(7ZIP_COMMON_OBJS) \
+  $(AR_OBJS) \
+  $(AR_COMMON_OBJS) \
+  $(7Z_OBJS) \
+  $(BZIP2_OBJS) \
+  $(BZIP2_OPT_OBJS) \
+  $(COMPRESS_OBJS) \
+  $(BRANCH_OPT_OBJS) \
+  $(SWAP_OPT_OBJS) \
+  $(COPY_OBJS) \
+  $(DEFLATE_OPT_OBJS) \
+  $(LZ_OBJS) \
+  $(LZMA_OPT_OBJS) \
+  $(PPMD_OPT_OBJS) \
+  $(C_OBJS) \
+  $(C_LZ_OBJS) \
+  $(C_BRANCH_OBJS) \
+  $O\RangeCoderBit.obj \
+  $O\resource.res
+
+
+!include "../../../Build.mak"
+
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+	$(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+	$(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+	$(COMPL)
+$(AR_OBJS): ../../Archive/$(*B).cpp
+	$(COMPL)
+$(AR_COMMON_OBJS): ../../Archive/Common/$(*B).cpp
+	$(COMPL)
+
+$(7Z_OBJS): ../../Archive/7z/$(*B).cpp
+	$(COMPL)
+
+$(COMPRESS_OBJS): ../../Compress/$(*B).cpp
+	$(COMPL)
+$(BRANCH_OPT_OBJS): ../../Compress/Branch/$(*B).cpp
+	$(COMPL_O2)
+$(SWAP_OPT_OBJS): ../../Compress/ByteSwap/$(*B).cpp
+	$(COMPL_O2)
+$(COPY_OBJS): ../../Compress/Copy/$(*B).cpp
+	$(COMPL)
+$(LZ_OBJS): ../../Compress/LZ/$(*B).cpp
+	$(COMPL)
+$(LZMA_OPT_OBJS): ../../Compress/LZMA/$(*B).cpp
+	$(COMPL_O2)
+$O\RangeCoderBit.obj: ../../Compress/RangeCoder/$(*B).cpp
+	$(COMPL)
+
+$(C_OBJS): ../../../../C/$(*B).c
+	$(COMPL_O2)
+$(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c
+	$(COMPL_O2)
+$(C_BRANCH_OBJS): ../../../../C/Compress/Branch/$(*B).c
+	$(COMPL_O2)

Added: trunk/lzma/CPP/7zip/Bundles/Format7zR/resource.rc
===================================================================
--- trunk/lzma/CPP/7zip/Bundles/Format7zR/resource.rc	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Bundles/Format7zR/resource.rc	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("7z Standalone Plugin", "7zr")
+
+101  ICON  "../../Archive/7z/7z.ico"

Added: trunk/lzma/CPP/7zip/Common/CreateCoder.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/CreateCoder.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/CreateCoder.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,292 @@
+// CreateCoder.cpp
+
+#include "StdAfx.h"
+
+#include "CreateCoder.h"
+
+#include "../../Windows/PropVariant.h"
+#include "../../Windows/Defs.h"
+#include "FilterCoder.h"
+#include "RegisterCodec.h"
+
+static const unsigned int kNumCodecsMax = 64;
+unsigned int g_NumCodecs = 0;
+const CCodecInfo *g_Codecs[kNumCodecsMax]; 
+void RegisterCodec(const CCodecInfo *codecInfo) 
+{ 
+  if (g_NumCodecs < kNumCodecsMax)
+    g_Codecs[g_NumCodecs++] = codecInfo; 
+}
+
+#ifdef EXTERNAL_CODECS
+static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)
+{
+  NWindows::NCOM::CPropVariant prop;
+  RINOK(codecsInfo->GetProperty(index, propID, &prop));
+  if (prop.vt == VT_EMPTY)
+    res = 1;
+  else if (prop.vt == VT_UI4)
+    res = prop.ulVal;
+  else
+    return E_INVALIDARG;
+  return S_OK;
+}
+
+static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)
+{
+  NWindows::NCOM::CPropVariant prop;
+  RINOK(codecsInfo->GetProperty(index, propID, &prop));
+  if (prop.vt == VT_EMPTY)
+    res = true;
+  else if (prop.vt == VT_BOOL)
+    res = VARIANT_BOOLToBool(prop.boolVal);
+  else
+    return E_INVALIDARG;
+  return S_OK;
+}
+
+HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs)
+{
+  UInt32 num;
+  RINOK(codecsInfo->GetNumberOfMethods(&num));
+  for (UInt32 i = 0; i < num; i++)
+  {
+    CCodecInfoEx info;
+    NWindows::NCOM::CPropVariant prop;
+    RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop));
+    // if (prop.vt != VT_BSTR)
+    // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal);
+    // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize);
+    if (prop.vt != VT_UI8)
+    {
+      continue; // old Interface 
+      // return E_INVALIDARG;
+    }
+    info.Id = prop.uhVal.QuadPart;
+    prop.Clear();
+    
+    RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop));
+    if (prop.vt == VT_BSTR)
+      info.Name = prop.bstrVal;
+    else if (prop.vt != VT_EMPTY)
+      return E_INVALIDARG;;
+    
+    RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams));
+    RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams));
+    RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));
+    RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));
+    
+    externalCodecs.Add(info);
+  }
+  return S_OK;
+}
+
+#endif
+
+bool FindMethod(
+  #ifdef EXTERNAL_CODECS
+  ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,
+  #endif
+  const UString &name,
+  CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)
+{
+  UInt32 i;
+  for (i = 0; i < g_NumCodecs; i++)
+  {
+    const CCodecInfo &codec = *g_Codecs[i]; 
+    if (name.CompareNoCase(codec.Name) == 0)
+    {
+      methodId = codec.Id;
+      numInStreams = codec.NumInStreams;
+      numOutStreams = 1;
+      return true;
+    }
+  }
+  #ifdef EXTERNAL_CODECS
+  if (externalCodecs)
+    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
+    {
+      const CCodecInfoEx &codec = (*externalCodecs)[i]; 
+      if (codec.Name.CompareNoCase(name) == 0)
+      {
+        methodId = codec.Id;
+        numInStreams = codec.NumInStreams;
+        numOutStreams = codec.NumOutStreams;
+        return true;
+      }
+    }
+  #endif
+  return false;
+}
+
+bool FindMethod(
+  #ifdef EXTERNAL_CODECS
+  ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,
+  #endif
+  CMethodId methodId, UString &name)
+{
+  UInt32 i;
+  for (i = 0; i < g_NumCodecs; i++)
+  {
+    const CCodecInfo &codec = *g_Codecs[i]; 
+    if (methodId == codec.Id)
+    {
+      name = codec.Name;
+      return true;
+    }
+  }
+  #ifdef EXTERNAL_CODECS
+  if (externalCodecs)
+    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
+    {
+      const CCodecInfoEx &codec = (*externalCodecs)[i]; 
+      if (methodId == codec.Id)
+      {
+        name = codec.Name;
+        return true;
+      }
+    }
+  #endif
+  return false;
+}
+
+HRESULT CreateCoder(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  CMethodId methodId,
+  CMyComPtr<ICompressFilter> &filter,
+  CMyComPtr<ICompressCoder> &coder,
+  CMyComPtr<ICompressCoder2> &coder2,
+  bool encode, bool onlyCoder)
+{
+  bool created = false;
+  UInt32 i;
+  for (i = 0; i < g_NumCodecs; i++)
+  {
+    const CCodecInfo &codec = *g_Codecs[i]; 
+    if (codec.Id == methodId)
+    {
+      if (encode)
+      {
+        if (codec.CreateEncoder)
+        {
+          void *p = codec.CreateEncoder();
+          if (codec.IsFilter) filter = (ICompressFilter *)p;
+          else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
+          else coder2 = (ICompressCoder2 *)p;
+          created = (p != 0);
+          break;
+        }
+      }
+      else
+        if (codec.CreateDecoder)
+        {
+          void *p = codec.CreateDecoder();
+          if (codec.IsFilter) filter = (ICompressFilter *)p;
+          else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
+          else coder2 = (ICompressCoder2 *)p;
+          created = (p != 0);
+          break;
+        }
+    }
+  }
+
+  #ifdef EXTERNAL_CODECS
+  if (!created && externalCodecs)
+    for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
+    {
+      const CCodecInfoEx &codec = (*externalCodecs)[i]; 
+      if (codec.Id == methodId)
+      {
+        if (encode)
+        {
+          if (codec.EncoderIsAssigned)
+          {
+            if (codec.IsSimpleCodec())
+            {
+              HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder);
+              if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 
+                return result;
+              if (!coder)
+              {
+                RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));
+              }
+            }
+            else
+            {
+              RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));
+            }
+            break;
+          }
+        }
+        else
+          if (codec.DecoderIsAssigned)
+          {
+            if (codec.IsSimpleCodec())
+            {
+              HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder);
+              if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 
+                return result;
+              if (!coder)
+              {
+                RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));
+              }
+            }
+            else
+            {
+              RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));
+            }
+            break;
+          }
+      }
+    }
+  #endif
+
+  if (onlyCoder && filter)
+  {
+    CFilterCoder *coderSpec = new CFilterCoder;
+    coder = coderSpec;
+    coderSpec->Filter = filter;
+  }
+  return S_OK;
+}
+
+HRESULT CreateCoder(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  CMethodId methodId,
+  CMyComPtr<ICompressCoder> &coder, 
+  CMyComPtr<ICompressCoder2> &coder2,
+  bool encode)
+{
+  CMyComPtr<ICompressFilter> filter;
+  return CreateCoder(
+    EXTERNAL_CODECS_LOC_VARS
+    methodId,
+    filter, coder, coder2, encode, true);
+}
+
+HRESULT CreateCoder(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  CMethodId methodId,
+  CMyComPtr<ICompressCoder> &coder, bool encode)
+{
+  CMyComPtr<ICompressFilter> filter;
+  CMyComPtr<ICompressCoder2> coder2;
+  return CreateCoder(
+    EXTERNAL_CODECS_LOC_VARS
+    methodId,
+    coder, coder2, encode);
+}
+
+HRESULT CreateFilter(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  CMethodId methodId,
+  CMyComPtr<ICompressFilter> &filter,
+  bool encode)
+{
+  CMyComPtr<ICompressCoder> coder;
+  CMyComPtr<ICompressCoder2> coder2;
+  return CreateCoder(
+    EXTERNAL_CODECS_LOC_VARS
+    methodId,
+    filter, coder, coder2, encode, false);
+}

Added: trunk/lzma/CPP/7zip/Common/CreateCoder.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/CreateCoder.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/CreateCoder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,98 @@
+// CreateCoder.h
+
+#ifndef __CREATECODER_H
+#define __CREATECODER_H
+
+#include "Common/MyCom.h"
+#include "Common/MyString.h"
+#include "../ICoder.h"
+
+#include "MethodId.h"
+
+#ifdef EXTERNAL_CODECS
+
+struct CCodecInfoEx
+{
+  UString Name;
+  CMethodId Id;
+  UInt32 NumInStreams;
+  UInt32 NumOutStreams;
+  bool EncoderIsAssigned;
+  bool DecoderIsAssigned;
+  bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; }
+  CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}
+};
+
+HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs);
+
+#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,
+#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)
+#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);
+#define IMPL_ISetCompressCodecsInfo2(x) \
+STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \
+  COM_TRY_BEGIN _codecsInfo = compressCodecsInfo;  return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END }
+#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)
+
+#define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs
+
+#define DECL_EXTERNAL_CODECS_VARS CMyComPtr<ICompressCodecsInfo> _codecsInfo; CObjectVector<CCodecInfoEx> _externalCodecs;
+#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,
+
+#define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const CObjectVector<CCodecInfoEx> *externalCodecs
+#define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs
+
+#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,
+#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,
+
+#else
+
+#define PUBLIC_ISetCompressCodecsInfo
+#define QUERY_ENTRY_ISetCompressCodecsInfo
+#define DECL_ISetCompressCodecsInfo
+#define IMPL_ISetCompressCodecsInfo
+#define EXTERNAL_CODECS_VARS2
+#define DECL_EXTERNAL_CODECS_VARS
+#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2
+#define DECL_EXTERNAL_CODECS_LOC_VARS2
+#define EXTERNAL_CODECS_LOC_VARS2
+#define DECL_EXTERNAL_CODECS_LOC_VARS
+#define EXTERNAL_CODECS_LOC_VARS
+
+#endif
+
+bool FindMethod(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams);
+
+bool FindMethod(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  CMethodId methodId, UString &name);
+
+
+HRESULT CreateCoder(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  CMethodId methodId,
+  CMyComPtr<ICompressFilter> &filter,
+  CMyComPtr<ICompressCoder> &coder,
+  CMyComPtr<ICompressCoder2> &coder2,
+  bool encode, bool onlyCoder);
+
+HRESULT CreateCoder(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  CMethodId methodId,
+  CMyComPtr<ICompressCoder> &coder,
+  CMyComPtr<ICompressCoder2> &coder2,
+  bool encode);
+
+HRESULT CreateCoder(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  CMethodId methodId, 
+  CMyComPtr<ICompressCoder> &coder, bool encode);
+
+HRESULT CreateFilter(
+  DECL_EXTERNAL_CODECS_LOC_VARS
+  CMethodId methodId,
+  CMyComPtr<ICompressFilter> &filter,
+  bool encode);
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/FilePathAutoRename.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/FilePathAutoRename.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/FilePathAutoRename.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,57 @@
+// FilePathAutoRename.cpp
+
+#include "StdAfx.h"
+#include "FilePathAutoRename.h"
+
+#include "Common/Defs.h"
+#include "Common/IntToString.h"
+
+#include "Windows/FileName.h"
+#include "Windows/FileFind.h"
+
+using namespace NWindows;
+
+static bool MakeAutoName(const UString &name, 
+    const UString &extension, int value, UString &path)
+{
+  wchar_t number[32];
+  ConvertUInt64ToString(value, number);
+  path = name;
+  path += number;
+  path += extension;
+  return NFile::NFind::DoesFileExist(path);
+}
+
+bool AutoRenamePath(UString &fullProcessedPath)
+{
+  UString path;
+  int dotPos = fullProcessedPath.ReverseFind(L'.');
+
+  int slashPos = fullProcessedPath.ReverseFind(L'/');
+  #ifdef _WIN32
+  int slash1Pos = fullProcessedPath.ReverseFind(L'\\');
+  slashPos = MyMax(slashPos, slash1Pos);
+  #endif
+
+  UString name, extension;
+  if (dotPos > slashPos &&  dotPos > 0)
+  {
+    name = fullProcessedPath.Left(dotPos);
+    extension = fullProcessedPath.Mid(dotPos);
+  }
+  else
+    name = fullProcessedPath;
+  name += L'_';
+  int indexLeft = 1, indexRight = (1 << 30);
+  while (indexLeft != indexRight)
+  {
+    int indexMid = (indexLeft + indexRight) / 2;
+    if (MakeAutoName(name, extension, indexMid, path))
+      indexLeft = indexMid + 1;
+    else
+      indexRight = indexMid;
+  }
+  if (MakeAutoName(name, extension, indexRight, fullProcessedPath))
+    return false;
+  return true;
+}

Added: trunk/lzma/CPP/7zip/Common/FilePathAutoRename.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/FilePathAutoRename.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/FilePathAutoRename.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// Util/FilePathAutoRename.h
+
+#ifndef __FILEPATHAUTORENAME_H
+#define __FILEPATHAUTORENAME_H
+
+#include "Common/MyString.h"
+
+bool AutoRenamePath(UString &fullProcessedPath);
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/FileStreams.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/FileStreams.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/FileStreams.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,261 @@
+// FileStreams.cpp
+
+#include "StdAfx.h"
+
+#ifndef _WIN32
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#endif
+
+#include "FileStreams.h"
+
+static inline HRESULT ConvertBoolToHRESULT(bool result)
+{
+  #ifdef _WIN32
+  if (result)
+    return S_OK;
+  DWORD lastError = ::GetLastError();
+  if (lastError == 0)
+    return E_FAIL;
+  return lastError;
+  #else
+  return result ? S_OK: E_FAIL;
+  #endif
+}
+
+bool CInFileStream::Open(LPCTSTR fileName)
+{
+  return File.Open(fileName);
+}
+
+#ifdef USE_WIN_FILE
+#ifndef _UNICODE
+bool CInFileStream::Open(LPCWSTR fileName)
+{
+  return File.Open(fileName);
+}
+#endif
+#endif
+
+bool CInFileStream::OpenShared(LPCTSTR fileName, bool shareForWrite)
+{
+  return File.OpenShared(fileName, shareForWrite);
+}
+
+#ifdef USE_WIN_FILE
+#ifndef _UNICODE
+bool CInFileStream::OpenShared(LPCWSTR fileName, bool shareForWrite)
+{
+  return File.OpenShared(fileName, shareForWrite);
+}
+#endif
+#endif
+
+STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  #ifdef USE_WIN_FILE
+  
+  UInt32 realProcessedSize;
+  bool result = File.ReadPart(data, size, realProcessedSize);
+  if(processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return ConvertBoolToHRESULT(result);
+  
+  #else
+  
+  if(processedSize != NULL)
+    *processedSize = 0;
+  ssize_t res = File.Read(data, (size_t)size);
+  if (res == -1)
+    return E_FAIL;
+  if(processedSize != NULL)
+    *processedSize = (UInt32)res;
+  return S_OK;
+
+  #endif
+}
+
+#ifndef _WIN32_WCE
+STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  #ifdef _WIN32
+  UInt32 realProcessedSize;
+  BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), 
+      data, size, (DWORD *)&realProcessedSize, NULL);
+  if(processedSize != NULL)
+    *processedSize = realProcessedSize;
+  if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
+    return S_OK;
+  return ConvertBoolToHRESULT(res != FALSE);
+  
+  #else
+
+  if(processedSize != NULL)
+    *processedSize = 0;
+  ssize_t res;
+  do 
+  {
+    res = read(0, data, (size_t)size);
+  } 
+  while (res < 0 && (errno == EINTR));
+  if (res == -1)
+    return E_FAIL;
+  if(processedSize != NULL)
+    *processedSize = (UInt32)res;
+  return S_OK;
+  
+  #endif
+}
+  
+#endif
+
+STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, 
+    UInt64 *newPosition)
+{
+  if(seekOrigin >= 3)
+    return STG_E_INVALIDFUNCTION;
+
+  #ifdef USE_WIN_FILE
+
+  UInt64 realNewPosition;
+  bool result = File.Seek(offset, seekOrigin, realNewPosition);
+  if(newPosition != NULL)
+    *newPosition = realNewPosition;
+  return ConvertBoolToHRESULT(result);
+  
+  #else
+  
+  off_t res = File.Seek(offset, seekOrigin);
+  if (res == -1)
+    return E_FAIL;
+  if(newPosition != NULL)
+    *newPosition = (UInt64)res;
+  return S_OK;
+  
+  #endif
+}
+
+STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
+{
+  return ConvertBoolToHRESULT(File.GetLength(*size));
+}
+
+
+//////////////////////////
+// COutFileStream
+
+HRESULT COutFileStream::Close()
+{
+  return ConvertBoolToHRESULT(File.Close());
+}
+
+STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  #ifdef USE_WIN_FILE
+
+  UInt32 realProcessedSize;
+  bool result = File.WritePart(data, size, realProcessedSize);
+  ProcessedSize += realProcessedSize;
+  if(processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return ConvertBoolToHRESULT(result);
+  
+  #else
+  
+  if(processedSize != NULL)
+    *processedSize = 0;
+  ssize_t res = File.Write(data, (size_t)size);
+  if (res == -1)
+    return E_FAIL;
+  if(processedSize != NULL)
+    *processedSize = (UInt32)res;
+  ProcessedSize += res;
+  return S_OK;
+  
+  #endif
+}
+  
+STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+  if(seekOrigin >= 3)
+    return STG_E_INVALIDFUNCTION;
+  #ifdef USE_WIN_FILE
+
+  UInt64 realNewPosition;
+  bool result = File.Seek(offset, seekOrigin, realNewPosition);
+  if(newPosition != NULL)
+    *newPosition = realNewPosition;
+  return ConvertBoolToHRESULT(result);
+  
+  #else
+  
+  off_t res = File.Seek(offset, seekOrigin);
+  if (res == -1)
+    return E_FAIL;
+  if(newPosition != NULL)
+    *newPosition = (UInt64)res;
+  return S_OK;
+  
+  #endif
+}
+
+STDMETHODIMP COutFileStream::SetSize(Int64 newSize)
+{
+  #ifdef USE_WIN_FILE
+  UInt64 currentPos;
+  if(!File.Seek(0, FILE_CURRENT, currentPos))
+    return E_FAIL;
+  bool result = File.SetLength(newSize);
+  UInt64 currentPos2;
+  result = result && File.Seek(currentPos, currentPos2);
+  return result ? S_OK : E_FAIL;
+  #else
+  return E_FAIL;
+  #endif
+}
+
+#ifndef _WIN32_WCE
+STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  if(processedSize != NULL)
+    *processedSize = 0;
+
+  #ifdef _WIN32
+  UInt32 realProcessedSize;
+  BOOL res = TRUE;
+  if (size > 0)
+  {
+    // Seems that Windows doesn't like big amounts writing to stdout.
+    // So we limit portions by 32KB.
+    UInt32 sizeTemp = (1 << 15); 
+    if (sizeTemp > size)
+      sizeTemp = size;
+    res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), 
+        data, sizeTemp, (DWORD *)&realProcessedSize, NULL);
+    size -= realProcessedSize;
+    data = (const void *)((const Byte *)data + realProcessedSize);
+    if(processedSize != NULL)
+      *processedSize += realProcessedSize;
+  }
+  return ConvertBoolToHRESULT(res != FALSE);
+
+  #else
+  
+  ssize_t res;
+  do 
+  {
+    res = write(1, data, (size_t)size);
+  } 
+  while (res < 0 && (errno == EINTR));
+  if (res == -1)
+    return E_FAIL;
+  if(processedSize != NULL)
+    *processedSize = (UInt32)res;
+  return S_OK;
+  
+  return S_OK;
+  #endif
+}
+  
+#endif

Added: trunk/lzma/CPP/7zip/Common/FileStreams.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/FileStreams.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/FileStreams.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,143 @@
+// FileStreams.h
+
+#ifndef __FILESTREAMS_H
+#define __FILESTREAMS_H
+
+#ifdef _WIN32
+#define USE_WIN_FILE
+#endif
+
+#ifdef USE_WIN_FILE
+#include "../../Windows/FileIO.h"
+#else
+#include "../../Common/C_FileIO.h"
+#endif
+
+#include "../IStream.h"
+#include "../../Common/MyCom.h"
+
+class CInFileStream: 
+  public IInStream,
+  public IStreamGetSize,
+  public CMyUnknownImp
+{
+public:
+  #ifdef USE_WIN_FILE
+  NWindows::NFile::NIO::CInFile File;
+  #else
+  NC::NFile::NIO::CInFile File;
+  #endif
+  CInFileStream() {}
+  virtual ~CInFileStream() {}
+
+  bool Open(LPCTSTR fileName);
+  #ifdef USE_WIN_FILE
+  #ifndef _UNICODE
+  bool Open(LPCWSTR fileName);
+  #endif
+  #endif
+
+  bool OpenShared(LPCTSTR fileName, bool shareForWrite);
+  #ifdef USE_WIN_FILE
+  #ifndef _UNICODE
+  bool OpenShared(LPCWSTR fileName, bool shareForWrite);
+  #endif
+  #endif
+
+  MY_UNKNOWN_IMP2(IInStream, IStreamGetSize)
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+
+  STDMETHOD(GetSize)(UInt64 *size);
+};
+
+#ifndef _WIN32_WCE
+class CStdInFileStream: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+public:
+  // HANDLE File;
+  // CStdInFileStream() File(INVALID_HANDLE_VALUE): {}
+  // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); };
+  MY_UNKNOWN_IMP
+
+  virtual ~CStdInFileStream() {}
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+#endif
+
+class COutFileStream: 
+  public IOutStream,
+  public CMyUnknownImp
+{
+  #ifdef USE_WIN_FILE
+  NWindows::NFile::NIO::COutFile File;
+  #else
+  NC::NFile::NIO::COutFile File;
+  #endif
+public:
+  virtual ~COutFileStream() {}
+  bool Create(LPCTSTR fileName, bool createAlways)
+  {
+    ProcessedSize = 0;
+    return File.Create(fileName, createAlways);
+  }
+  bool Open(LPCTSTR fileName, DWORD creationDisposition)
+  {
+    ProcessedSize = 0;
+    return File.Open(fileName, creationDisposition);
+  }
+  #ifdef USE_WIN_FILE
+  #ifndef _UNICODE
+  bool Create(LPCWSTR fileName, bool createAlways)
+  {
+    ProcessedSize = 0;
+    return File.Create(fileName, createAlways);
+  }
+  bool Open(LPCWSTR fileName, DWORD creationDisposition)
+  {
+    ProcessedSize = 0;
+    return File.Open(fileName, creationDisposition);
+  }
+  #endif
+  #endif
+
+  HRESULT Close();
+  
+  UInt64 ProcessedSize;
+
+  #ifdef USE_WIN_FILE
+  bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime)
+  {
+    return File.SetTime(creationTime, lastAccessTime, lastWriteTime);
+  }
+  bool SetLastWriteTime(const FILETIME *lastWriteTime)
+  {
+    return File.SetLastWriteTime(lastWriteTime);
+  }
+  #endif
+
+
+  MY_UNKNOWN_IMP1(IOutStream)
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+  STDMETHOD(SetSize)(Int64 newSize);
+};
+
+#ifndef _WIN32_WCE
+class CStdOutFileStream: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP
+
+  virtual ~CStdOutFileStream() {}
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+#endif
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/FilterCoder.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/FilterCoder.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/FilterCoder.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,264 @@
+// FilterCoder.cpp
+
+#include "StdAfx.h"
+
+#include "FilterCoder.h"
+extern "C" 
+{ 
+#include "../../../C/Alloc.h"
+}
+#include "../../Common/Defs.h"
+#include "StreamUtils.h"
+
+static const UInt32 kBufferSize = 1 << 17;
+
+CFilterCoder::CFilterCoder()
+{ 
+  _buffer = (Byte *)::MidAlloc(kBufferSize); 
+}
+
+CFilterCoder::~CFilterCoder() 
+{ 
+  ::MidFree(_buffer); 
+}
+
+HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
+{
+  if (_outSizeIsDefined)
+  {
+    UInt64 remSize = _outSize - _nowPos64;
+    if (size > remSize)
+      size = (UInt32)remSize;
+  }
+  UInt32 processedSize = 0;
+  RINOK(WriteStream(outStream, _buffer, size, &processedSize));
+  if (size != processedSize)
+    return E_FAIL;
+  _nowPos64 += processedSize;
+  return S_OK;
+}
+
+
+STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
+      ICompressProgressInfo *progress)
+{
+  RINOK(Init());
+  UInt32 bufferPos = 0;
+  _outSizeIsDefined = (outSize != 0);
+  if (_outSizeIsDefined)
+    _outSize = *outSize;
+
+  while(NeedMore())
+  {
+    UInt32 processedSize;
+    
+    // Change it: It can be optimized using ReadPart
+    RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize));
+    
+    UInt32 endPos = bufferPos + processedSize;
+
+    bufferPos = Filter->Filter(_buffer, endPos);
+    if (bufferPos > endPos)
+    {
+      for (; endPos< bufferPos; endPos++)
+        _buffer[endPos] = 0;
+      bufferPos = Filter->Filter(_buffer, endPos);
+    }
+
+    if (bufferPos == 0)
+    {
+      if (endPos > 0)
+        return WriteWithLimit(outStream, endPos);
+      return S_OK;
+    }
+    RINOK(WriteWithLimit(outStream, bufferPos));
+    if (progress != NULL)
+    {
+      RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
+    }
+    UInt32 i = 0;
+    while(bufferPos < endPos)
+      _buffer[i++] = _buffer[bufferPos++];
+    bufferPos = i;
+  }
+  return S_OK;
+}
+
+// #ifdef _ST_MODE
+STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
+{
+  _bufferPos = 0;
+  _outStream = outStream;
+  return Init();
+}
+
+STDMETHODIMP CFilterCoder::ReleaseOutStream()
+{
+  _outStream.Release();
+  return S_OK;
+};
+
+
+STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 processedSizeTotal = 0;
+  while(size > 0)
+  {
+    UInt32 sizeMax = kBufferSize - _bufferPos;
+    UInt32 sizeTemp = size;
+    if (sizeTemp > sizeMax)
+      sizeTemp = sizeMax;
+    memmove(_buffer + _bufferPos, data, sizeTemp);
+    size -= sizeTemp;
+    processedSizeTotal += sizeTemp;
+    data = (const Byte *)data + sizeTemp;
+    UInt32 endPos = _bufferPos + sizeTemp;
+    _bufferPos = Filter->Filter(_buffer, endPos);
+    if (_bufferPos == 0)
+    {
+      _bufferPos = endPos;
+      break;
+    }
+    if (_bufferPos > endPos)
+    {
+      if (size != 0)
+        return E_FAIL;
+      break;
+    }
+    RINOK(WriteWithLimit(_outStream, _bufferPos));
+    UInt32 i = 0;
+    while(_bufferPos < endPos)
+      _buffer[i++] = _buffer[_bufferPos++];
+    _bufferPos = i;
+  }
+  if (processedSize != NULL)
+    *processedSize = processedSizeTotal;
+  return S_OK;
+}
+
+STDMETHODIMP CFilterCoder::Flush()
+{
+  if (_bufferPos != 0)
+  {
+    UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
+    if (endPos > _bufferPos)
+    {
+      for (; _bufferPos < endPos; _bufferPos++)
+        _buffer[_bufferPos] = 0;
+      if (Filter->Filter(_buffer, endPos) != endPos)
+        return E_FAIL;
+    }
+    UInt32 processedSize;
+    RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize));
+    if (_bufferPos != processedSize)
+      return E_FAIL;
+    _bufferPos = 0;
+  }
+  CMyComPtr<IOutStreamFlush> flush;
+  _outStream.QueryInterface(IID_IOutStreamFlush, &flush);
+  if (flush)
+    return  flush->Flush();
+  return S_OK;
+}
+
+
+STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
+{
+  _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
+  _inStream = inStream;
+  return Init();
+}
+
+STDMETHODIMP CFilterCoder::ReleaseInStream()
+{
+  _inStream.Release();
+  return S_OK;
+};
+
+STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 processedSizeTotal = 0;
+  while(size > 0)
+  {
+    if (_convertedPosBegin != _convertedPosEnd)
+    {
+      UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
+      memmove(data, _buffer + _convertedPosBegin, sizeTemp);
+      _convertedPosBegin += sizeTemp;
+      data = (void *)((Byte *)data + sizeTemp);
+      size -= sizeTemp;
+      processedSizeTotal += sizeTemp;
+      break;
+    }
+    int i;
+    for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
+      _buffer[i] = _buffer[i + _convertedPosEnd];
+    _bufferPos = i;
+    _convertedPosBegin = _convertedPosEnd = 0;
+    UInt32 processedSizeTemp;
+    UInt32 size0 = kBufferSize - _bufferPos;
+    // Optimize it:
+    RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp));
+    _bufferPos = _bufferPos + processedSizeTemp;
+    _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
+    if (_convertedPosEnd == 0)
+    {
+      if (_bufferPos == 0)
+        break;
+      else
+      {
+        _convertedPosEnd = _bufferPos; // check it
+        continue;
+      }
+    }
+    if (_convertedPosEnd > _bufferPos)
+    {
+      for (; _bufferPos < _convertedPosEnd; _bufferPos++)
+        _buffer[_bufferPos] = 0;
+      _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
+    }
+  }
+  if (processedSize != NULL)
+    *processedSize = processedSizeTotal;
+  return S_OK;
+}
+
+// #endif // _ST_MODE
+
+#ifndef _NO_CRYPTO
+STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
+{
+  return _setPassword->CryptoSetPassword(data, size);
+}
+#endif
+
+#ifndef EXTRACT_ONLY
+STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, 
+      const PROPVARIANT *properties, UInt32 numProperties)
+{
+  return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);
+}
+
+STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{
+  return _writeCoderProperties->WriteCoderProperties(outStream);
+}
+
+/*
+STDMETHODIMP CFilterCoder::ResetSalt()
+{
+  return _CryptoResetSalt->ResetSalt();
+}
+*/
+
+STDMETHODIMP CFilterCoder::ResetInitVector()
+{
+  return _CryptoResetInitVector->ResetInitVector();
+}
+#endif
+
+STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
+{
+  return _setDecoderProperties->SetDecoderProperties2(data, size);
+}

Added: trunk/lzma/CPP/7zip/Common/FilterCoder.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/FilterCoder.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/FilterCoder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,143 @@
+// FilterCoder.h
+
+#ifndef __FILTERCODER_H
+#define __FILTERCODER_H
+
+#include "../../Common/MyCom.h"
+#include "../ICoder.h"
+#include "../IPassword.h"
+
+#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \
+{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
+*outObject = (void *)(i *)this; AddRef(); return S_OK; } 
+
+class CFilterCoder:
+  public ICompressCoder,
+  // #ifdef _ST_MODE
+  public ICompressSetInStream,
+  public ISequentialInStream,
+  public ICompressSetOutStream,
+  public ISequentialOutStream,
+  public IOutStreamFlush,
+  // #endif
+
+  #ifndef _NO_CRYPTO
+  public ICryptoSetPassword,
+  #endif
+  #ifndef EXTRACT_ONLY
+  public ICompressSetCoderProperties,
+  public ICompressWriteCoderProperties,
+  // public ICryptoResetSalt,
+  public ICryptoResetInitVector,
+  #endif
+  public ICompressSetDecoderProperties2,
+  public CMyUnknownImp
+{
+protected:
+  Byte *_buffer;
+  // #ifdef _ST_MODE
+  CMyComPtr<ISequentialInStream> _inStream;
+  CMyComPtr<ISequentialOutStream> _outStream;
+  UInt32 _bufferPos;
+  UInt32 _convertedPosBegin;
+  UInt32 _convertedPosEnd;
+  // #endif
+  bool _outSizeIsDefined;
+  UInt64 _outSize;
+  UInt64 _nowPos64;
+
+  HRESULT Init() 
+  { 
+    _nowPos64 = 0;
+    _outSizeIsDefined = false;
+    return Filter->Init(); 
+  }
+
+  CMyComPtr<ICryptoSetPassword> _setPassword;
+  #ifndef EXTRACT_ONLY
+  CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
+  CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
+  // CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
+  CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
+  #endif
+  CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties;
+public:
+  CMyComPtr<ICompressFilter> Filter;
+
+  CFilterCoder();
+  ~CFilterCoder();
+  HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size);
+  bool NeedMore() const  
+    { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); }
+
+public:
+  MY_QUERYINTERFACE_BEGIN
+    MY_QUERYINTERFACE_ENTRY(ICompressCoder)
+    // #ifdef _ST_MODE
+    MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
+    MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
+
+    MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)
+    MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)
+    MY_QUERYINTERFACE_ENTRY(IOutStreamFlush)
+    // #endif
+
+    #ifndef _NO_CRYPTO
+    MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)
+    #endif
+
+    #ifndef EXTRACT_ONLY
+    MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)
+    MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
+    // MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)
+    MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
+    #endif
+
+    MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties)
+  MY_QUERYINTERFACE_END
+  MY_ADDREF_RELEASE
+  STDMETHOD(Code)(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress);
+  // #ifdef _ST_MODE
+  STDMETHOD(ReleaseInStream)();
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \
+  STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
+  STDMETHOD(ReleaseOutStream)();
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Flush)();
+  // #endif
+
+  #ifndef _NO_CRYPTO
+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
+  #endif
+  #ifndef EXTRACT_ONLY
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, 
+      const PROPVARIANT *properties, UInt32 numProperties);
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+  // STDMETHOD(ResetSalt)();
+  STDMETHOD(ResetInitVector)();
+  #endif
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+};
+
+// #ifdef _ST_MODE
+class CInStreamReleaser
+{
+public:
+  CFilterCoder *FilterCoder;
+  CInStreamReleaser(): FilterCoder(0) {}
+  ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
+};
+
+class COutStreamReleaser
+{
+public:
+  CFilterCoder *FilterCoder;
+  COutStreamReleaser(): FilterCoder(0) {}
+  ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
+};
+// #endif
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/InBuffer.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/InBuffer.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/InBuffer.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,83 @@
+// InBuffer.cpp
+
+#include "StdAfx.h"
+
+#include "InBuffer.h"
+
+extern "C"
+{
+  #include "../../../C/Alloc.h"
+}
+
+CInBuffer::CInBuffer(): 
+  _buffer(0), 
+  _bufferLimit(0), 
+  _bufferBase(0), 
+  _stream(0),
+  _bufferSize(0)
+{}
+
+bool CInBuffer::Create(UInt32 bufferSize)
+{
+  const UInt32 kMinBlockSize = 1;
+  if (bufferSize < kMinBlockSize)
+    bufferSize = kMinBlockSize;
+  if (_bufferBase != 0 && _bufferSize == bufferSize)
+    return true;
+  Free();
+  _bufferSize = bufferSize;
+  _bufferBase = (Byte *)::MidAlloc(bufferSize);
+  return (_bufferBase != 0);
+}
+
+void CInBuffer::Free()
+{
+  ::MidFree(_bufferBase);
+  _bufferBase = 0;
+}
+
+void CInBuffer::SetStream(ISequentialInStream *stream)
+{
+  _stream = stream;
+}
+
+void CInBuffer::Init()
+{
+  _processedSize = 0;
+  _buffer = _bufferBase;
+  _bufferLimit = _buffer;
+  _wasFinished = false;
+  #ifdef _NO_EXCEPTIONS
+  ErrorCode = S_OK;
+  #endif
+}
+
+bool CInBuffer::ReadBlock()
+{
+  #ifdef _NO_EXCEPTIONS
+  if (ErrorCode != S_OK)
+    return false;
+  #endif
+  if (_wasFinished)
+    return false;
+  _processedSize += (_buffer - _bufferBase);
+  UInt32 numProcessedBytes;
+  HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes);
+  #ifdef _NO_EXCEPTIONS
+  ErrorCode = result;
+  #else
+  if (result != S_OK)
+    throw CInBufferException(result);
+  #endif
+  _buffer = _bufferBase;
+  _bufferLimit = _buffer + numProcessedBytes;
+  _wasFinished = (numProcessedBytes == 0);
+  return (!_wasFinished);
+}
+
+Byte CInBuffer::ReadBlock2()
+{
+  if(!ReadBlock())
+    return 0xFF;
+  return *_buffer++;
+}

Added: trunk/lzma/CPP/7zip/Common/InBuffer.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/InBuffer.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/InBuffer.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,75 @@
+// InBuffer.h
+
+#ifndef __INBUFFER_H
+#define __INBUFFER_H
+
+#include "../IStream.h"
+#include "../../Common/MyCom.h"
+#include "../../Common/MyException.h"
+
+#ifndef _NO_EXCEPTIONS
+struct CInBufferException: public CSystemException 
+{
+  CInBufferException(HRESULT errorCode): CSystemException(errorCode) {} 
+};
+#endif
+
+class CInBuffer
+{
+  Byte *_buffer;
+  Byte *_bufferLimit;
+  Byte *_bufferBase;
+  CMyComPtr<ISequentialInStream> _stream;
+  UInt64 _processedSize;
+  UInt32 _bufferSize;
+  bool _wasFinished;
+
+  bool ReadBlock();
+  Byte ReadBlock2();
+
+public:
+  #ifdef _NO_EXCEPTIONS
+  HRESULT ErrorCode;
+  #endif
+
+  CInBuffer();
+  ~CInBuffer() { Free(); }
+
+  bool Create(UInt32 bufferSize);
+  void Free();
+  
+  void SetStream(ISequentialInStream *stream);
+  void Init();
+  void ReleaseStream() { _stream.Release(); }
+
+  bool ReadByte(Byte &b)
+  {
+    if(_buffer >= _bufferLimit)
+      if(!ReadBlock())
+        return false;
+    b = *_buffer++;
+    return true;
+  }
+  Byte ReadByte()
+  {
+    if(_buffer >= _bufferLimit)
+      return ReadBlock2();
+    return *_buffer++;
+  }
+  void ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+  {
+    for(processedSize = 0; processedSize < size; processedSize++)
+      if (!ReadByte(((Byte *)data)[processedSize]))
+        return;
+  }
+  bool ReadBytes(void *data, UInt32 size)
+  {
+    UInt32 processedSize;
+    ReadBytes(data, size, processedSize);
+    return (processedSize == size);
+  }
+  UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); }
+  bool WasFinished() const { return _wasFinished; }
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/InOutTempBuffer.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/InOutTempBuffer.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/InOutTempBuffer.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,122 @@
+// InOutTempBuffer.cpp
+
+#include "StdAfx.h"
+
+#include "InOutTempBuffer.h"
+#include "../../Common/Defs.h"
+// #include "Windows/Defs.h"
+
+#include "StreamUtils.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDirectory;
+
+static UInt32 kTmpBufferMemorySize = (1 << 20);
+
+static LPCTSTR kTempFilePrefixString = TEXT("iot");
+
+CInOutTempBuffer::CInOutTempBuffer():
+  _buffer(NULL)
+{
+}
+
+void CInOutTempBuffer::Create()
+{
+  _buffer = new Byte[kTmpBufferMemorySize];
+}
+
+CInOutTempBuffer::~CInOutTempBuffer()
+{
+  delete []_buffer;
+}
+void CInOutTempBuffer::InitWriting()
+{
+  _bufferPosition = 0;
+  _tmpFileCreated = false;
+  _fileSize = 0;
+}
+
+bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size)
+{
+  if (size == 0)
+    return true;
+  if(!_tmpFileCreated)
+  {
+    CSysString tempDirPath;
+    if(!MyGetTempPath(tempDirPath))
+      return false;
+    if (_tempFile.Create(tempDirPath, kTempFilePrefixString, _tmpFileName) == 0)
+      return false;
+    // _outFile.SetOpenCreationDispositionCreateAlways();
+    if(!_outFile.Create(_tmpFileName, true))
+      return false;
+    _tmpFileCreated = true;
+  }
+  UInt32 processedSize;
+  if(!_outFile.Write(data, size, processedSize))
+    return false;
+  _fileSize += processedSize;
+  return (processedSize == size);
+}
+
+bool CInOutTempBuffer::FlushWrite()
+{
+  return _outFile.Close();
+}
+
+bool CInOutTempBuffer::Write(const void *data, UInt32 size)
+{
+  if(_bufferPosition < kTmpBufferMemorySize)
+  {
+    UInt32 curSize = MyMin(kTmpBufferMemorySize - _bufferPosition, size);
+    memmove(_buffer + _bufferPosition, (const Byte *)data, curSize);
+    _bufferPosition += curSize;
+    size -= curSize;
+    data = ((const Byte *)data) + curSize;
+    _fileSize += curSize;
+  }
+  return WriteToFile(data, size);
+}
+
+bool CInOutTempBuffer::InitReading()
+{
+  _currentPositionInBuffer = 0;
+  if(_tmpFileCreated)
+    return _inFile.Open(_tmpFileName);
+  return true;
+}
+
+HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)
+{
+  if (_currentPositionInBuffer < _bufferPosition)
+  {
+    UInt32 sizeToWrite = _bufferPosition - _currentPositionInBuffer;
+    RINOK(WriteStream(stream, _buffer + _currentPositionInBuffer, sizeToWrite, NULL));
+    _currentPositionInBuffer += sizeToWrite;
+  }
+  if (!_tmpFileCreated)
+    return true;
+  for (;;)
+  {
+    UInt32 localProcessedSize;
+    if (!_inFile.ReadPart(_buffer, kTmpBufferMemorySize, localProcessedSize))
+      return E_FAIL;
+    if (localProcessedSize == 0)
+      return S_OK;
+    RINOK(WriteStream(stream, _buffer, localProcessedSize, NULL));
+  }
+}
+
+STDMETHODIMP CSequentialOutTempBufferImp::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (!_buffer->Write(data, size))
+  {
+    if (processedSize != NULL)
+      *processedSize = 0;
+    return E_FAIL;
+  }
+  if (processedSize != NULL)
+    *processedSize = size;
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/Common/InOutTempBuffer.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/InOutTempBuffer.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/InOutTempBuffer.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,55 @@
+// Util/InOutTempBuffer.h
+
+#ifndef __IN_OUT_TEMP_BUFFER_H
+#define __IN_OUT_TEMP_BUFFER_H
+
+#include "../../Windows/FileIO.h"
+#include "../../Windows/FileDir.h"
+#include "../../Common/MyCom.h"
+
+#include "../IStream.h"
+
+class CInOutTempBuffer
+{
+  NWindows::NFile::NDirectory::CTempFile _tempFile;
+  NWindows::NFile::NIO::COutFile _outFile;
+  NWindows::NFile::NIO::CInFile _inFile;
+  Byte *_buffer;
+  UInt32 _bufferPosition;
+  UInt32 _currentPositionInBuffer;
+  CSysString _tmpFileName;
+  bool _tmpFileCreated;
+
+  UInt64 _fileSize;
+
+  bool WriteToFile(const void *data, UInt32 size);
+public:
+  CInOutTempBuffer();
+  ~CInOutTempBuffer();
+  void Create();
+
+  void InitWriting();
+  bool Write(const void *data, UInt32 size);
+  UInt64 GetDataSize() const { return _fileSize; }
+  bool FlushWrite();
+  bool InitReading();
+  HRESULT WriteToStream(ISequentialOutStream *stream);
+};
+
+class CSequentialOutTempBufferImp: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  CInOutTempBuffer *_buffer;
+public:
+  // CSequentialOutStreamImp(): _size(0) {}
+  // UInt32 _size;
+  void Init(CInOutTempBuffer *buffer)  { _buffer = buffer; }
+  // UInt32 GetSize() const { return _size; }
+
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/LimitedStreams.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/LimitedStreams.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/LimitedStreams.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// LimitedStreams.cpp
+
+#include "StdAfx.h"
+
+#include "LimitedStreams.h"
+#include "../../Common/Defs.h"
+
+STDMETHODIMP CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize = 0;
+  UInt32 sizeToRead = (UInt32)MyMin((_size - _pos), (UInt64)size);
+  HRESULT result = S_OK;
+  if (sizeToRead > 0)
+  {
+    result = _stream->Read(data, sizeToRead, &realProcessedSize);
+    _pos += realProcessedSize;
+    if (realProcessedSize == 0)
+      _wasFinished = true;
+  }
+  if(processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return result;
+}
+

Added: trunk/lzma/CPP/7zip/Common/LimitedStreams.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/LimitedStreams.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/LimitedStreams.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,33 @@
+// LimitedStreams.h
+
+#ifndef __LIMITEDSTREAMS_H
+#define __LIMITEDSTREAMS_H
+
+#include "../../Common/MyCom.h"
+#include "../IStream.h"
+
+class CLimitedSequentialInStream: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<ISequentialInStream> _stream;
+  UInt64 _size;
+  UInt64 _pos;
+  bool _wasFinished;
+public:
+  void SetStream(ISequentialInStream *stream) { _stream = stream; }
+  void Init(UInt64 streamSize)  
+  { 
+    _size = streamSize; 
+    _pos = 0; 
+    _wasFinished = false; 
+  }
+ 
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  UInt64 GetSize() const { return _pos; }
+  bool WasFinished() const { return _wasFinished; }
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/LockedStream.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/LockedStream.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/LockedStream.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,23 @@
+// LockedStream.cpp
+
+#include "StdAfx.h"
+
+#include "LockedStream.h"
+
+HRESULT CLockedInStream::Read(UInt64 startPos, void *data, UInt32 size, 
+  UInt32 *processedSize)
+{
+  NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
+  RINOK(_stream->Seek(startPos, STREAM_SEEK_SET, NULL));
+  return _stream->Read(data, size, processedSize);
+}
+
+STDMETHODIMP CLockedSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize = 0;
+  HRESULT result = _lockedInStream->Read(_pos, data, size, &realProcessedSize);
+  _pos += realProcessedSize;
+  if (processedSize != NULL)
+    *processedSize = realProcessedSize;
+  return result;
+}

Added: trunk/lzma/CPP/7zip/Common/LockedStream.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/LockedStream.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/LockedStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,38 @@
+// LockedStream.h
+
+#ifndef __LOCKEDSTREAM_H
+#define __LOCKEDSTREAM_H
+
+#include "../../Windows/Synchronization.h"
+#include "../../Common/MyCom.h"
+#include "../IStream.h"
+
+class CLockedInStream
+{
+  CMyComPtr<IInStream> _stream;
+  NWindows::NSynchronization::CCriticalSection _criticalSection;
+public:
+  void Init(IInStream *stream)
+    { _stream = stream; }
+  HRESULT Read(UInt64 startPos, void *data, UInt32 size, UInt32 *processedSize);
+};
+
+class CLockedSequentialInStreamImp: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+  CLockedInStream *_lockedInStream;
+  UInt64 _pos;
+public:
+  void Init(CLockedInStream *lockedInStream, UInt64 startPos)
+  {
+    _lockedInStream = lockedInStream;
+    _pos = startPos;
+  }
+
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/MethodId.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/MethodId.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/MethodId.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,27 @@
+// MethodId.cpp
+
+#include "StdAfx.h"
+
+#include "MethodId.h"
+#include "../../Common/MyString.h"
+
+static inline wchar_t GetHex(Byte value)
+{
+  return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+UString ConvertMethodIdToString(UInt64 id)
+{
+  wchar_t s[32];
+  int len = 32;
+  s[--len] = 0;
+  do
+  {
+    s[--len] = GetHex((Byte)id & 0xF);
+    id >>= 4;
+    s[--len] = GetHex((Byte)id & 0xF);
+    id >>= 4;
+  }
+  while (id != 0);
+  return s + len;
+}

Added: trunk/lzma/CPP/7zip/Common/MethodId.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/MethodId.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/MethodId.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// MethodId.h
+
+#ifndef __7Z_METHOD_ID_H
+#define __7Z_METHOD_ID_H
+
+#include "../../Common/Types.h"
+
+typedef UInt64 CMethodId;
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/MethodProps.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/MethodProps.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/MethodProps.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,96 @@
+// MethodProps.cpp
+
+#include "StdAfx.h"
+
+#include "MethodProps.h"
+#include "../../Common/MyCom.h"
+
+static UInt64 k_LZMA = 0x030101;
+// static UInt64 k_LZMA2 = 0x030102;
+
+HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder)
+{
+  bool tryReduce = false;
+  UInt32 reducedDictionarySize = 1 << 10;
+  if (inSizeForReduce != 0 && (method.Id == k_LZMA /* || methodFull.MethodID == k_LZMA2 */))
+  {
+    for (;;)
+    {
+      const UInt32 step = (reducedDictionarySize >> 1);
+      if (reducedDictionarySize >= *inSizeForReduce)
+      {
+        tryReduce = true;
+        break;
+      }
+      reducedDictionarySize += step;
+      if (reducedDictionarySize >= *inSizeForReduce)
+      {
+        tryReduce = true;
+        break;
+      }
+      if (reducedDictionarySize >= ((UInt32)3 << 30))
+        break;
+      reducedDictionarySize += step;
+    }
+  }
+
+  {
+    int numProperties = method.Properties.Size();
+    CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
+    coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
+    if (setCoderProperties == NULL)
+    {
+      if (numProperties != 0)
+        return E_INVALIDARG;
+    }
+    else
+    {
+      CRecordVector<PROPID> propIDs;
+      NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProperties];
+      HRESULT res = S_OK;
+      try
+      {
+        for (int i = 0; i < numProperties; i++)
+        {
+          const CProp &prop = method.Properties[i];
+          propIDs.Add(prop.Id);
+          NWindows::NCOM::CPropVariant &value = values[i];
+          value = prop.Value;
+          // if (tryReduce && prop.Id == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal)
+          if (tryReduce)
+            if (prop.Id == NCoderPropID::kDictionarySize)
+              if (value.vt == VT_UI4)
+                if (reducedDictionarySize < value.ulVal)
+            value.ulVal = reducedDictionarySize;
+        }
+        CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
+        coder->QueryInterface(IID_ICompressSetCoderProperties, (void **)&setCoderProperties);
+        res = setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProperties);
+      }
+      catch(...)
+      {
+        delete []values;
+        throw;
+      }
+      delete []values;
+      RINOK(res);
+    }
+  }
+ 
+  /*
+  CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
+  coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+  if (writeCoderProperties != NULL)
+  {
+    CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
+    CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+    outStreamSpec->Init();
+    RINOK(writeCoderProperties->WriteCoderProperties(outStream));
+    size_t size = outStreamSpec->GetSize();
+    filterProps.SetCapacity(size);
+    memmove(filterProps, outStreamSpec->GetBuffer(), size);
+  }
+  */
+  return S_OK;
+}
+

Added: trunk/lzma/CPP/7zip/Common/MethodProps.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/MethodProps.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/MethodProps.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,41 @@
+// MethodProps.h
+
+#ifndef __7Z_METHOD_PROPS_H
+#define __7Z_METHOD_PROPS_H
+
+#include "MethodId.h"
+
+#include "../../Windows/PropVariant.h"
+#include "../../Common/MyVector.h"
+#include "../ICoder.h"
+
+struct CProp
+{
+  PROPID Id;
+  NWindows::NCOM::CPropVariant Value;
+};
+
+struct CMethod
+{
+  CMethodId Id;
+  CObjectVector<CProp> Properties;
+};
+
+struct CMethodsMode
+{
+  CObjectVector<CMethod> Methods;
+  #ifdef COMPRESS_MT
+  UInt32 NumThreads;
+  #endif
+
+  CMethodsMode()
+      #ifdef COMPRESS_MT
+      : NumThreads(1) 
+      #endif
+  {}
+  bool IsEmpty() const { return Methods.IsEmpty() ; }
+};
+
+HRESULT SetMethodProperties(const CMethod &method, const UInt64 *inSizeForReduce, IUnknown *coder);
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/OffsetStream.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/OffsetStream.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/OffsetStream.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,35 @@
+// OffsetStream.cpp
+
+#include "StdAfx.h"
+
+#include "Common/Defs.h"
+#include "OffsetStream.h"
+
+HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)
+{
+  _offset = offset;
+  _stream = stream;
+  return _stream->Seek(offset, STREAM_SEEK_SET, NULL);
+}
+
+STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  return _stream->Write(data, size, processedSize);
+}
+
+STDMETHODIMP COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, 
+    UInt64 *newPosition)
+{
+  UInt64 absoluteNewPosition;
+  if (seekOrigin == STREAM_SEEK_SET)
+    offset += _offset;
+  HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);
+  if (newPosition != NULL)
+    *newPosition = absoluteNewPosition - _offset;
+  return result;
+}
+
+STDMETHODIMP COffsetOutStream::SetSize(Int64 newSize)
+{
+  return _stream->SetSize(_offset + newSize);
+}

Added: trunk/lzma/CPP/7zip/Common/OffsetStream.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/OffsetStream.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/OffsetStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,25 @@
+// OffsetStream.h
+
+#ifndef __OFFSETSTREAM_H
+#define __OFFSETSTREAM_H
+
+#include "Common/MyCom.h"
+#include "../IStream.h"
+
+class COffsetOutStream: 
+  public IOutStream,
+  public CMyUnknownImp
+{
+  UInt64 _offset;
+  CMyComPtr<IOutStream> _stream;
+public:
+  HRESULT Init(IOutStream *stream, UInt64 offset);
+  
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+  STDMETHOD(SetSize)(Int64 newSize);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/OutBuffer.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/OutBuffer.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/OutBuffer.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,119 @@
+// OutByte.cpp
+
+#include "StdAfx.h"
+
+#include "OutBuffer.h"
+
+extern "C"
+{
+  #include "../../../C/Alloc.h"
+}
+
+bool COutBuffer::Create(UInt32 bufferSize)
+{
+  const UInt32 kMinBlockSize = 1;
+  if (bufferSize < kMinBlockSize)
+    bufferSize = kMinBlockSize;
+  if (_buffer != 0 && _bufferSize == bufferSize)
+    return true;
+  Free();
+  _bufferSize = bufferSize;
+  _buffer = (Byte *)::MidAlloc(bufferSize);
+  return (_buffer != 0);
+}
+
+void COutBuffer::Free()
+{
+  ::MidFree(_buffer);
+  _buffer = 0;
+}
+
+void COutBuffer::SetStream(ISequentialOutStream *stream)
+{
+  _stream = stream;
+}
+
+void COutBuffer::Init()
+{
+  _streamPos = 0;
+  _limitPos = _bufferSize;
+  _pos = 0;
+  _processedSize = 0;
+  _overDict = false;
+  #ifdef _NO_EXCEPTIONS
+  ErrorCode = S_OK;
+  #endif
+}
+
+UInt64 COutBuffer::GetProcessedSize() const
+{ 
+  UInt64 res = _processedSize + _pos - _streamPos;
+  if (_streamPos > _pos) 
+    res += _bufferSize;
+  return res;
+}
+
+
+HRESULT COutBuffer::FlushPart()
+{
+  // _streamPos < _bufferSize
+  UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos);
+  HRESULT result = S_OK;
+  #ifdef _NO_EXCEPTIONS
+  result = ErrorCode;
+  #endif
+  if (_buffer2 != 0)
+  {
+    memmove(_buffer2, _buffer + _streamPos, size);
+    _buffer2 += size;
+  }
+
+  if (_stream != 0
+      #ifdef _NO_EXCEPTIONS
+      && (ErrorCode == S_OK)
+      #endif
+     )
+  {
+    UInt32 processedSize = 0;
+    result = _stream->Write(_buffer + _streamPos, size, &processedSize);
+    size = processedSize;
+  }
+  _streamPos += size;
+  if (_streamPos == _bufferSize)
+    _streamPos = 0;
+  if (_pos == _bufferSize)
+  {
+    _overDict = true;
+    _pos = 0;
+  }
+  _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize;
+  _processedSize += size;
+  return result;
+}
+
+HRESULT COutBuffer::Flush()
+{
+  #ifdef _NO_EXCEPTIONS
+  if (ErrorCode != S_OK)
+    return ErrorCode;
+  #endif
+
+  while(_streamPos != _pos)
+  {
+    HRESULT result = FlushPart();
+    if (result != S_OK)
+      return result;
+  }
+  return S_OK;
+}
+
+void COutBuffer::FlushWithCheck()
+{
+  HRESULT result = Flush();
+  #ifdef _NO_EXCEPTIONS
+  ErrorCode = result;
+  #else
+  if (result != S_OK)
+    throw COutBufferException(result);
+  #endif
+}

Added: trunk/lzma/CPP/7zip/Common/OutBuffer.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/OutBuffer.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/OutBuffer.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,64 @@
+// OutBuffer.h
+
+#ifndef __OUTBUFFER_H
+#define __OUTBUFFER_H
+
+#include "../IStream.h"
+#include "../../Common/MyCom.h"
+#include "../../Common/MyException.h"
+
+#ifndef _NO_EXCEPTIONS
+struct COutBufferException: public CSystemException 
+{ 
+  COutBufferException(HRESULT errorCode): CSystemException(errorCode) {} 
+};
+#endif
+
+class COutBuffer
+{
+protected:
+  Byte *_buffer;
+  UInt32 _pos;
+  UInt32 _limitPos;
+  UInt32 _streamPos;
+  UInt32 _bufferSize;
+  CMyComPtr<ISequentialOutStream> _stream;
+  UInt64 _processedSize;
+  Byte  *_buffer2;
+  bool _overDict;
+
+  HRESULT FlushPart();
+public:
+  #ifdef _NO_EXCEPTIONS
+  HRESULT ErrorCode;
+  #endif
+
+  COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {}
+  ~COutBuffer() { Free(); }
+  
+  bool Create(UInt32 bufferSize);
+  void Free();
+
+  void SetMemStream(Byte *buffer) { _buffer2 = buffer; }
+  void SetStream(ISequentialOutStream *stream);
+  void Init();
+  HRESULT Flush();
+  void FlushWithCheck();
+  void ReleaseStream() {  _stream.Release(); }
+
+  void WriteByte(Byte b)
+  {
+    _buffer[_pos++] = b;
+    if(_pos == _limitPos)
+      FlushWithCheck();
+  }
+  void WriteBytes(const void *data, size_t size)
+  {
+    for (size_t i = 0; i < size; i++)
+      WriteByte(((const Byte *)data)[i]);
+  }
+
+  UInt64 GetProcessedSize() const;
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/ProgressUtils.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/ProgressUtils.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/ProgressUtils.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,42 @@
+// ProgressUtils.h
+
+#include "StdAfx.h"
+
+#include "ProgressUtils.h"
+
+CLocalProgress::CLocalProgress()
+{
+  ProgressOffset = InSize = OutSize = 0;
+  SendRatio = SendProgress = true;
+}
+
+void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
+{
+  _ratioProgress.Release();
+  _progress = progress;
+  _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress);
+  _inSizeIsMain = inSizeIsMain;
+}
+
+STDMETHODIMP CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+  UInt64 inSizeNew = InSize, outSizeNew = OutSize;
+  if (inSize)
+    inSizeNew += (*inSize);
+  if (outSize)
+    outSizeNew += (*outSize);
+  if (SendRatio && _ratioProgress)
+  {
+    RINOK(_ratioProgress->SetRatioInfo(&inSizeNew, &outSizeNew));
+  }
+  inSizeNew += ProgressOffset;
+  outSizeNew += ProgressOffset;
+  if (SendProgress)
+    return _progress->SetCompleted(_inSizeIsMain ? &inSizeNew : &outSizeNew);
+  return S_OK;
+}
+
+HRESULT CLocalProgress::SetCur()
+{
+  return SetRatioInfo(NULL, NULL);
+}

Added: trunk/lzma/CPP/7zip/Common/ProgressUtils.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/ProgressUtils.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/ProgressUtils.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,34 @@
+// ProgressUtils.h
+
+#ifndef __PROGRESSUTILS_H
+#define __PROGRESSUTILS_H
+
+#include "../../Common/MyCom.h"
+
+#include "../ICoder.h"
+#include "../IProgress.h"
+
+class CLocalProgress: 
+  public ICompressProgressInfo,
+  public CMyUnknownImp
+{
+  CMyComPtr<IProgress> _progress;
+  CMyComPtr<ICompressProgressInfo> _ratioProgress;
+  bool _inSizeIsMain;
+public:
+  UInt64 ProgressOffset;
+  UInt64 InSize;
+  UInt64 OutSize;
+  bool SendRatio;
+  bool SendProgress;
+
+  CLocalProgress();
+  void Init(IProgress *progress, bool inSizeIsMain);
+  HRESULT SetCur();
+
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/RegisterArc.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/RegisterArc.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/RegisterArc.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,36 @@
+// RegisterArc.h
+
+#ifndef __REGISTERARC_H
+#define __REGISTERARC_H
+
+#include "../Archive/IArchive.h"
+
+typedef IInArchive * (*CreateInArchiveP)();
+typedef IOutArchive * (*CreateOutArchiveP)();
+
+struct CArcInfo
+{
+  const wchar_t *Name;
+  const wchar_t *Ext;
+  const wchar_t *AddExt;
+  Byte ClassId;
+  Byte Signature[16];
+  int SignatureSize;
+  bool KeepName;
+  CreateInArchiveP CreateInArchive;
+  CreateOutArchiveP CreateOutArchive;
+};
+
+void RegisterArc(const CArcInfo *arcInfo);
+
+#define REGISTER_ARC_NAME(x) CRegister ## x 
+
+#define REGISTER_ARC_DEC_SIG(x) struct REGISTER_ARC_NAME(x) { \
+    REGISTER_ARC_NAME(x)() { g_ArcInfo.Signature[0]--; RegisterArc(&g_ArcInfo); }}; \
+    static REGISTER_ARC_NAME(x) g_RegisterArc;
+
+#define REGISTER_ARC(x) struct REGISTER_ARC_NAME(x) { \
+    REGISTER_ARC_NAME(x)() { RegisterArc(&g_ArcInfo); }}; \
+    static REGISTER_ARC_NAME(x) g_RegisterArc;
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/RegisterCodec.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/RegisterCodec.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/RegisterCodec.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,33 @@
+// RegisterCodec.h
+
+#ifndef __REGISTERCODEC_H
+#define __REGISTERCODEC_H
+
+#include "../Common/MethodId.h"
+
+typedef void * (*CreateCodecP)();
+struct CCodecInfo
+{
+  CreateCodecP CreateDecoder;
+  CreateCodecP CreateEncoder;
+  CMethodId Id;
+  const wchar_t *Name;
+  UInt32 NumInStreams;
+  bool IsFilter;
+};
+
+void RegisterCodec(const CCodecInfo *codecInfo);
+
+#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x 
+
+#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \
+    REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \
+    static REGISTER_CODEC_NAME(x) g_RegisterCodec;
+
+#define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x 
+#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \
+    REGISTER_CODECS_NAME(x)() { for (int i = 0; i < sizeof(g_CodecsInfo) / sizeof(g_CodecsInfo[0]); i++) \
+    RegisterCodec(&g_CodecsInfo[i]); }}; \
+    static REGISTER_CODECS_NAME(x) g_RegisterCodecs;
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../Common/MyWindows.h"
+#include "../../Common/NewHandler.h"
+
+#endif 

Added: trunk/lzma/CPP/7zip/Common/StreamBinder.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/StreamBinder.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/StreamBinder.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,150 @@
+// StreamBinder.cpp
+
+#include "StdAfx.h"
+
+#include "StreamBinder.h"
+#include "../../Common/Defs.h"
+#include "../../Common/MyCom.h"
+
+using namespace NWindows;
+using namespace NSynchronization;
+
+class CSequentialInStreamForBinder: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+private:
+  CStreamBinder *m_StreamBinder;
+public:
+  ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); }
+  void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }
+};
+
+STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
+  { return m_StreamBinder->Read(data, size, processedSize); }
+
+class CSequentialOutStreamForBinder: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+
+private:
+  CStreamBinder *m_StreamBinder;
+public:
+  ~CSequentialOutStreamForBinder() {  m_StreamBinder->CloseWrite(); }
+  void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }
+};
+
+STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
+  { return m_StreamBinder->Write(data, size, processedSize); }
+
+
+//////////////////////////
+// CStreamBinder
+// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished.
+
+HRes CStreamBinder::CreateEvents()
+{
+  RINOK(_allBytesAreWritenEvent.Create(true));
+  RINOK(_thereAreBytesToReadEvent.Create());
+  return _readStreamIsClosedEvent.Create();
+}
+
+void CStreamBinder::ReInit()
+{
+  _thereAreBytesToReadEvent.Reset();
+  _readStreamIsClosedEvent.Reset();
+  ProcessedSize = 0;
+}
+
+
+  
+void CStreamBinder::CreateStreams(ISequentialInStream **inStream, 
+      ISequentialOutStream **outStream)
+{
+  CSequentialInStreamForBinder *inStreamSpec = new 
+      CSequentialInStreamForBinder;
+  CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+  inStreamSpec->SetBinder(this);
+  *inStream = inStreamLoc.Detach();
+
+  CSequentialOutStreamForBinder *outStreamSpec = new 
+      CSequentialOutStreamForBinder;
+  CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
+  outStreamSpec->SetBinder(this);
+  *outStream = outStreamLoc.Detach();
+
+  _buffer = NULL;
+  _bufferSize= 0;
+  ProcessedSize = 0;
+}
+
+HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 sizeToRead = size;
+  if (size > 0)
+  {
+    RINOK(_thereAreBytesToReadEvent.Lock());
+    sizeToRead = MyMin(_bufferSize, size);
+    if (_bufferSize > 0)
+    {
+      MoveMemory(data, _buffer, sizeToRead);
+      _buffer = ((const Byte *)_buffer) + sizeToRead;
+      _bufferSize -= sizeToRead;
+      if (_bufferSize == 0)
+      {
+        _thereAreBytesToReadEvent.Reset();
+        _allBytesAreWritenEvent.Set();
+      }
+    }
+  }
+  if (processedSize != NULL)
+    *processedSize = sizeToRead;
+  ProcessedSize += sizeToRead;
+  return S_OK;
+}
+
+void CStreamBinder::CloseRead()
+{
+  _readStreamIsClosedEvent.Set();
+}
+
+HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (size > 0)
+  {
+    _buffer = data;
+    _bufferSize = size;
+    _allBytesAreWritenEvent.Reset();
+    _thereAreBytesToReadEvent.Set();
+
+    HANDLE events[2]; 
+    events[0] = _allBytesAreWritenEvent;
+    events[1] = _readStreamIsClosedEvent; 
+    DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
+    if (waitResult != WAIT_OBJECT_0 + 0)
+    {
+      // ReadingWasClosed = true;
+      return S_FALSE;
+    }
+    // if(!_allBytesAreWritenEvent.Lock())
+    //   return E_FAIL;
+  }
+  if (processedSize != NULL)
+    *processedSize = size;
+  return S_OK;
+}
+
+void CStreamBinder::CloseWrite()
+{
+  // _bufferSize must be = 0
+  _thereAreBytesToReadEvent.Set();
+}

Added: trunk/lzma/CPP/7zip/Common/StreamBinder.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/StreamBinder.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/StreamBinder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,32 @@
+// StreamBinder.h
+
+#ifndef __STREAMBINDER_H
+#define __STREAMBINDER_H
+
+#include "../IStream.h"
+#include "../../Windows/Synchronization.h"
+
+class CStreamBinder
+{
+  NWindows::NSynchronization::CManualResetEvent _allBytesAreWritenEvent;
+  NWindows::NSynchronization::CManualResetEvent _thereAreBytesToReadEvent;
+  NWindows::NSynchronization::CManualResetEvent _readStreamIsClosedEvent;
+  UInt32 _bufferSize;
+  const void *_buffer;
+public:
+  // bool ReadingWasClosed;
+  UInt64 ProcessedSize;
+  CStreamBinder() {}
+  HRes CreateEvents();
+
+  void CreateStreams(ISequentialInStream **inStream, 
+      ISequentialOutStream **outStream);
+  HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
+  void CloseRead();
+
+  HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);
+  void CloseWrite();
+  void ReInit();
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/StreamObjects.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/StreamObjects.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/StreamObjects.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,68 @@
+// StreamObjects.cpp
+
+#include "StdAfx.h"
+
+#include "StreamObjects.h"
+#include "../../Common/Defs.h"
+
+
+STDMETHODIMP CSequentialInStreamImp::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 numBytesToRead = (UInt32)(MyMin(_pos + size, _size) - _pos);
+  memmove(data, _dataPointer + _pos, numBytesToRead);
+  _pos += numBytesToRead;
+  if(processedSize != NULL)
+    *processedSize = numBytesToRead;
+  return S_OK;
+}
+
+
+void CWriteBuffer::Write(const void *data, size_t size)
+{
+  size_t newCapacity = _size + size;
+  _buffer.EnsureCapacity(newCapacity);
+  memmove(_buffer + _size, data, size);
+  _size += size;
+}
+
+STDMETHODIMP CSequentialOutStreamImp::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  _writeBuffer.Write(data, size);
+  if(processedSize != NULL)
+    *processedSize = size;
+  return S_OK; 
+}
+
+STDMETHODIMP CSequentialOutStreamImp2::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 newSize = size;
+  if (_pos + size > _size)
+    newSize = (UInt32)(_size - _pos);
+  memmove(_buffer + _pos, data, newSize);
+  if(processedSize != NULL)
+    *processedSize = newSize;
+  _pos += newSize;
+  if (newSize != size)
+    return E_FAIL;
+  return S_OK; 
+}
+
+STDMETHODIMP CSequentialInStreamSizeCount::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize;
+  HRESULT result = _stream->Read(data, size, &realProcessedSize);
+  _size += realProcessedSize;
+  if (processedSize != 0)
+    *processedSize = realProcessedSize;
+  return result; 
+}
+
+STDMETHODIMP CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 realProcessedSize;
+  HRESULT result = _stream->Write(data, size, &realProcessedSize);
+  _size += realProcessedSize;
+  if (processedSize != 0)
+    *processedSize = realProcessedSize;
+  return result; 
+}

Added: trunk/lzma/CPP/7zip/Common/StreamObjects.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/StreamObjects.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/StreamObjects.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,117 @@
+// StreamObjects.h
+
+#ifndef __STREAMOBJECTS_H
+#define __STREAMOBJECTS_H
+
+#include "../../Common/DynamicBuffer.h"
+#include "../../Common/MyCom.h"
+#include "../IStream.h"
+
+class CSequentialInStreamImp: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+  const Byte *_dataPointer;
+  size_t _size;
+  size_t _pos;
+
+public:
+  void Init(const Byte *dataPointer, size_t size)
+  {
+    _dataPointer = dataPointer;
+    _size = size;
+    _pos = 0;
+  }
+
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+
+class CWriteBuffer
+{
+  CByteDynamicBuffer _buffer;
+  size_t _size;
+public:
+  CWriteBuffer(): _size(0) {}
+  void Init() { _size = 0;  }
+  void Write(const void *data, size_t size);
+  size_t GetSize() const { return _size; }
+  const CByteDynamicBuffer& GetBuffer() const { return _buffer; }
+};
+
+class CSequentialOutStreamImp: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  CWriteBuffer _writeBuffer;
+public:
+  void Init() { _writeBuffer.Init(); }
+  size_t GetSize() const { return _writeBuffer.GetSize(); }
+  const CByteDynamicBuffer& GetBuffer() const { return _writeBuffer.GetBuffer(); }
+
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+class CSequentialOutStreamImp2: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  Byte *_buffer;
+  size_t _size;
+  size_t _pos;
+public:
+
+  void Init(Byte *buffer, size_t size)  
+  { 
+    _buffer = buffer;
+    _pos = 0;
+    _size = size; 
+  }
+
+  size_t GetPos() const { return _pos; }
+
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+class CSequentialInStreamSizeCount: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<ISequentialInStream> _stream;
+  UInt64 _size;
+public:
+  void Init(ISequentialInStream *stream)
+  {
+    _stream = stream;
+    _size = 0;
+  }
+  UInt64 GetSize() const { return _size; }
+
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+class CSequentialOutStreamSizeCount: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  CMyComPtr<ISequentialOutStream> _stream;
+  UInt64 _size;
+public:
+  void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+  void Init() { _size = 0; }
+  UInt64 GetSize() const { return _size; }
+
+  MY_UNKNOWN_IMP
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/StreamUtils.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/StreamUtils.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/StreamUtils.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,44 @@
+// StreamUtils.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/MyCom.h"
+#include "StreamUtils.h"
+
+HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (processedSize != 0)
+    *processedSize = 0;
+  while(size != 0)
+  {
+    UInt32 processedSizeLoc; 
+    HRESULT res = stream->Read(data, size, &processedSizeLoc);
+    if (processedSize != 0)
+      *processedSize += processedSizeLoc;
+    data = (Byte *)((Byte *)data + processedSizeLoc);
+    size -= processedSizeLoc;
+    RINOK(res);
+    if (processedSizeLoc == 0)
+      return S_OK;
+  }
+  return S_OK;
+}
+
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (processedSize != 0)
+    *processedSize = 0;
+  while(size != 0)
+  {
+    UInt32 processedSizeLoc; 
+    HRESULT res = stream->Write(data, size, &processedSizeLoc);
+    if (processedSize != 0)
+      *processedSize += processedSizeLoc;
+    data = (const void *)((const Byte *)data + processedSizeLoc);
+    size -= processedSizeLoc;
+    RINOK(res);
+    if (processedSizeLoc == 0)
+      return E_FAIL;
+  }
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/Common/StreamUtils.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/StreamUtils.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/StreamUtils.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,11 @@
+// StreamUtils.h
+
+#ifndef __STREAMUTILS_H
+#define __STREAMUTILS_H
+
+#include "../IStream.h"
+
+HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize);
+HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize);
+
+#endif

Added: trunk/lzma/CPP/7zip/Common/VirtThread.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Common/VirtThread.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/VirtThread.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,45 @@
+// VirtThread.cpp
+
+#include "StdAfx.h"
+
+#include "VirtThread.h"
+
+static THREAD_FUNC_DECL CoderThread(void *p)
+{
+  for (;;)
+  {
+    CVirtThread *t = (CVirtThread *)p;
+    t->StartEvent.Lock();
+    if (t->ExitEvent)
+      return 0;
+    t->Execute();
+    t->FinishedEvent.Set();
+  }
+}
+
+HRes CVirtThread::Create()
+{
+  RINOK(StartEvent.CreateIfNotCreated());
+  RINOK(FinishedEvent.CreateIfNotCreated());
+  StartEvent.Reset();
+  FinishedEvent.Reset();
+  ExitEvent = false;
+  if (Thread.IsCreated())
+    return S_OK;
+  return Thread.Create(CoderThread, this);
+}
+
+void CVirtThread::Start()
+{
+  ExitEvent = false;
+  StartEvent.Set();
+}
+
+CVirtThread::~CVirtThread()
+{
+  ExitEvent = true;
+  if (StartEvent.IsCreated())
+    StartEvent.Set();
+  Thread.Wait();
+}
+

Added: trunk/lzma/CPP/7zip/Common/VirtThread.h
===================================================================
--- trunk/lzma/CPP/7zip/Common/VirtThread.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Common/VirtThread.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,23 @@
+// VirtThread.h
+
+#ifndef __VIRTTHREAD_H
+#define __VIRTTHREAD_H
+
+#include "../../Windows/Synchronization.h"
+#include "../../Windows/Thread.h"
+
+struct CVirtThread
+{
+  NWindows::NSynchronization::CAutoResetEvent StartEvent;
+  NWindows::NSynchronization::CAutoResetEvent FinishedEvent;
+  NWindows::CThread Thread;
+  bool ExitEvent;
+
+  ~CVirtThread();
+  HRes Create();
+  void Start();
+  void WaitFinish() { FinishedEvent.Lock(); } 
+  virtual void Execute() = 0;
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Branch/ARM.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/ARM.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/ARM.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,19 @@
+// ARM.cpp
+
+#include "StdAfx.h"
+#include "ARM.h"
+
+extern "C" 
+{ 
+#include "../../../../C/Compress/Branch/BranchARM.h"
+}
+
+UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::ARM_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::ARM_Convert(data, size, _bufferPos, 0);
+}

Added: trunk/lzma/CPP/7zip/Compress/Branch/ARM.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/ARM.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/ARM.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// ARM.h
+
+#ifndef __ARM_H
+#define __ARM_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_ARM, 0x05, 1)
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Branch/ARMThumb.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/ARMThumb.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/ARMThumb.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,20 @@
+// ARMThumb.cpp
+
+#include "StdAfx.h"
+
+#include "ARMThumb.h"
+
+extern "C" 
+{ 
+#include "../../../../C/Compress/Branch/BranchARMThumb.h"
+}
+
+UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::ARMThumb_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::ARMThumb_Convert(data, size, _bufferPos, 0);
+}

Added: trunk/lzma/CPP/7zip/Compress/Branch/ARMThumb.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/ARMThumb.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/ARMThumb.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// ARMThumb.h
+
+#ifndef __ARMTHUMB_H
+#define __ARMTHUMB_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_ARMThumb, 0x07, 1)
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Branch/BCJ2Register.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/BCJ2Register.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/BCJ2Register.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,18 @@
+// BranchRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterCodec.h"
+
+#include "x86_2.h"
+static void *CreateCodec() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CDecoder()); }
+#ifndef EXTRACT_ONLY
+static void *CreateCodecOut() { return (void *)(ICompressCoder2 *)(new NCompress::NBcj2::CEncoder());  }
+#else
+#define CreateCodecOut 0
+#endif
+
+static CCodecInfo g_CodecInfo =
+  { CreateCodec, CreateCodecOut, 0x0303011B, L"BCJ2", 4, false };
+
+REGISTER_CODEC(BCJ2)

Added: trunk/lzma/CPP/7zip/Compress/Branch/BCJRegister.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/BCJRegister.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/BCJRegister.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,18 @@
+// BranchRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterCodec.h"
+
+#include "x86.h"
+static void *CreateCodec() { return (void *)(ICompressFilter *)(new CBCJ_x86_Decoder()); }
+#ifndef EXTRACT_ONLY
+static void *CreateCodecOut() { return (void *)(ICompressFilter *)(new CBCJ_x86_Encoder());  }
+#else
+#define CreateCodecOut 0
+#endif
+
+static CCodecInfo g_CodecInfo =
+  { CreateCodec, CreateCodecOut, 0x03030103, L"BCJ", 1, true };
+
+REGISTER_CODEC(BCJ)

Added: trunk/lzma/CPP/7zip/Compress/Branch/BranchCoder.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/BranchCoder.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/BranchCoder.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,18 @@
+// BranchCoder.cpp
+
+#include "StdAfx.h"
+#include "BranchCoder.h"
+
+STDMETHODIMP CBranchConverter::Init()
+{
+  _bufferPos = 0;
+  SubInit();
+  return S_OK;
+}
+
+STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size)
+{
+  UInt32 processedSize = SubFilter(data, size);
+  _bufferPos += processedSize;
+  return processedSize;
+}

Added: trunk/lzma/CPP/7zip/Compress/Branch/BranchCoder.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/BranchCoder.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/BranchCoder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,45 @@
+// BranchCoder.h
+
+#ifndef __BRANCH_CODER_H
+#define __BRANCH_CODER_H
+
+#include "Common/MyCom.h"
+#include "Common/Types.h"
+
+#include "../../ICoder.h"
+
+class CBranchConverter:
+  public ICompressFilter,
+  public CMyUnknownImp
+{
+protected:
+  UInt32 _bufferPos;
+  virtual void SubInit() {}
+  virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0;
+public:
+  MY_UNKNOWN_IMP;
+  STDMETHOD(Init)();
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
+};
+
+#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \
+  { public: UInt32 SubFilter(Byte *data, UInt32 size); }; 
+
+#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \
+  { public: UInt32 SubFilter(Byte *data, UInt32 size); }; 
+
+#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \
+  { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; 
+
+#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \
+  { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; 
+
+#define MyClassA(Name, id, subId)  \
+MyClassEncoderA(Name ## _Encoder) \
+MyClassDecoderA(Name ## _Decoder)
+
+#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT)  \
+MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \
+MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT)
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Branch/BranchRegister.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/BranchRegister.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/BranchRegister.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,34 @@
+// BranchRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterCodec.h"
+
+#include "PPC.h"
+#include "IA64.h"
+#include "ARM.h"
+#include "ARMThumb.h"
+#include "SPARC.h"
+
+#define CREATE_CODEC(x) \
+  static void *CreateCodec ## x() { return (void *)(ICompressFilter *)(new C ## x ## _Decoder); } \
+  static void *CreateCodec ## x ## Out() { return (void *)(ICompressFilter *)(new C ## x ## _Encoder); }
+
+CREATE_CODEC(BC_PPC_B)
+CREATE_CODEC(BC_IA64)
+CREATE_CODEC(BC_ARM)
+CREATE_CODEC(BC_ARMThumb)
+CREATE_CODEC(BC_SPARC)
+
+#define METHOD_ITEM(x, id1, id2, name) { CreateCodec ## x, CreateCodec ## x ## Out, 0x03030000 + (id1 * 256) + id2, name, 1, true  }
+
+static CCodecInfo g_CodecsInfo[] =
+{
+  METHOD_ITEM(BC_PPC_B,   0x02, 0x05, L"BC_PPC_B"),
+  METHOD_ITEM(BC_IA64,    0x04, 1, L"BC_IA64"),
+  METHOD_ITEM(BC_ARM,     0x05, 1, L"BC_ARM"),
+  METHOD_ITEM(BC_ARMThumb,0x07, 1, L"BC_ARMThumb"),
+  METHOD_ITEM(BC_SPARC,   0x08, 0x05, L"BC_SPARC")
+};
+
+REGISTER_CODECS(Branch)

Added: trunk/lzma/CPP/7zip/Compress/Branch/IA64.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/IA64.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/IA64.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,19 @@
+// IA64.cpp
+
+#include "StdAfx.h"
+#include "IA64.h"
+
+extern "C" 
+{ 
+#include "../../../../C/Compress/Branch/BranchIA64.h"
+}
+
+UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::IA64_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::IA64_Convert(data, size, _bufferPos, 0);
+}

Added: trunk/lzma/CPP/7zip/Compress/Branch/IA64.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/IA64.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/IA64.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// IA64.h
+
+#ifndef __IA64_H
+#define __IA64_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_IA64, 0x04, 1)
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Branch/PPC.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/PPC.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/PPC.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,19 @@
+// PPC.cpp
+
+#include "StdAfx.h"
+#include "PPC.h"
+
+extern "C" 
+{ 
+#include "../../../../C/Compress/Branch/BranchPPC.h"
+}
+
+UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::PPC_B_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::PPC_B_Convert(data, size, _bufferPos, 0);
+}

Added: trunk/lzma/CPP/7zip/Compress/Branch/PPC.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/PPC.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/PPC.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// PPC.h
+
+#ifndef __PPC_H
+#define __PPC_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_PPC_B, 0x02, 5)
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Branch/SPARC.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/SPARC.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/SPARC.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,19 @@
+// SPARC.cpp
+
+#include "StdAfx.h"
+#include "SPARC.h"
+
+extern "C" 
+{ 
+#include "../../../../C/Compress/Branch/BranchSPARC.h"
+}
+
+UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::SPARC_Convert(data, size, _bufferPos, 1);
+}
+
+UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+  return ::SPARC_Convert(data, size, _bufferPos, 0);
+}

Added: trunk/lzma/CPP/7zip/Compress/Branch/SPARC.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/SPARC.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/SPARC.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// SPARC.h
+
+#ifndef __SPARC_H
+#define __SPARC_H
+
+#include "BranchCoder.h"
+
+MyClassA(BC_SPARC, 0x08, 5)
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Branch/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Compress/Branch/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Branch/x86.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/x86.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/x86.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,14 @@
+// x86.cpp
+
+#include "StdAfx.h"
+#include "x86.h"
+
+UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size)
+{
+  return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 1);
+}
+
+UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size)
+{
+  return (UInt32)::x86_Convert(data, size, _bufferPos, &_prevMask, 0);
+}

Added: trunk/lzma/CPP/7zip/Compress/Branch/x86.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/x86.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/x86.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,21 @@
+// x86.h
+
+#ifndef __X86_H
+#define __X86_H
+
+#include "BranchCoder.h"
+extern "C" 
+{ 
+#include "../../../../C/Compress/Branch/BranchX86.h"
+}
+
+struct CBranch86
+{
+  UInt32 _prevMask;
+  void x86Init() { x86_Convert_Init(_prevMask); }
+};
+
+MyClassB(BCJ_x86, 0x01, 3, CBranch86 , 
+    virtual void SubInit() { x86Init(); })
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Branch/x86_2.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/x86_2.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/x86_2.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,392 @@
+// x86_2.cpp
+
+#include "StdAfx.h"
+#include "x86_2.h"
+
+extern "C" 
+{ 
+#include "../../../../C/Alloc.h"
+}
+
+namespace NCompress {
+namespace NBcj2 {
+
+inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); }
+inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); }
+inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); }
+
+#ifndef EXTRACT_ONLY
+
+static const int kBufferSize = 1 << 17;
+
+static bool inline Test86MSByte(Byte b)
+{
+  return (b == 0 || b == 0xFF);
+}
+
+bool CEncoder::Create()
+{
+  if (!_mainStream.Create(1 << 16))
+    return false;
+  if (!_callStream.Create(1 << 20))
+    return false;
+  if (!_jumpStream.Create(1 << 20))
+    return false;
+  if (!_rangeEncoder.Create(1 << 20))
+    return false;
+  if (_buffer == 0)
+  {
+    _buffer = (Byte *)MidAlloc(kBufferSize);
+    if (_buffer == 0)
+      return false;
+  }
+  return true;
+}
+
+CEncoder::~CEncoder()
+{
+  ::MidFree(_buffer);
+}
+
+HRESULT CEncoder::Flush()
+{
+  RINOK(_mainStream.Flush());
+  RINOK(_callStream.Flush());
+  RINOK(_jumpStream.Flush());
+  _rangeEncoder.FlushData();
+  return _rangeEncoder.FlushStream();
+}
+
+const UInt32 kDefaultLimit = (1 << 24);
+
+HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 ** /* outSizes */,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  if (numInStreams != 1 || numOutStreams != 4)
+    return E_INVALIDARG;
+
+  if (!Create())
+    return E_OUTOFMEMORY;
+
+  bool sizeIsDefined = false;
+  UInt64 inSize = 0;
+  if (inSizes != NULL)
+    if (inSizes[0] != NULL)
+    {
+      inSize = *inSizes[0];
+      if (inSize <= kDefaultLimit)
+        sizeIsDefined = true;
+    }
+
+  ISequentialInStream *inStream = inStreams[0];
+
+  _mainStream.SetStream(outStreams[0]);
+  _mainStream.Init();
+  _callStream.SetStream(outStreams[1]);
+  _callStream.Init();
+  _jumpStream.SetStream(outStreams[2]);
+  _jumpStream.Init();
+  _rangeEncoder.SetStream(outStreams[3]);
+  _rangeEncoder.Init();
+  for (int i = 0; i < 256 + 2; i++)
+    _statusEncoder[i].Init();
+  CCoderReleaser releaser(this);
+
+  CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
+  {
+    inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
+  }
+
+  UInt32 nowPos = 0;
+  UInt64 nowPos64 = 0;
+  UInt32 bufferPos = 0;
+
+  Byte prevByte = 0;
+
+  UInt64 subStreamIndex = 0;
+  UInt64 subStreamStartPos  = 0;
+  UInt64 subStreamEndPos = 0;
+
+  for (;;)
+  {
+    UInt32 processedSize = 0;
+    for (;;)
+    {
+      UInt32 size = kBufferSize - (bufferPos + processedSize);
+      UInt32 processedSizeLoc;
+      if (size == 0)
+        break;
+      RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc));
+      if (processedSizeLoc == 0)
+        break;
+      processedSize += processedSizeLoc;
+    }
+    UInt32 endPos = bufferPos + processedSize;
+    
+    if (endPos < 5)
+    {
+      // change it 
+      for (bufferPos = 0; bufferPos < endPos; bufferPos++)
+      {
+        Byte b = _buffer[bufferPos];
+        _mainStream.WriteByte(b);
+        UInt32 index;
+        if (b == 0xE8)
+          index = prevByte;
+        else if (b == 0xE9)
+          index = 256;
+        else if (IsJcc(prevByte, b))
+          index = 257;
+        else
+        {
+          prevByte = b;
+          continue;
+        }
+        _statusEncoder[index].Encode(&_rangeEncoder, 0);
+        prevByte = b;
+      }
+      return Flush();
+    }
+
+    bufferPos = 0;
+
+    UInt32 limit = endPos - 5;
+    while(bufferPos <= limit)
+    {
+      Byte b = _buffer[bufferPos];
+      _mainStream.WriteByte(b);
+      if (!IsJ(prevByte, b))
+      {
+        bufferPos++;
+        prevByte = b;
+        continue;
+      }
+      Byte nextByte = _buffer[bufferPos + 4];
+      UInt32 src = 
+        (UInt32(nextByte) << 24) |
+        (UInt32(_buffer[bufferPos + 3]) << 16) |
+        (UInt32(_buffer[bufferPos + 2]) << 8) |
+        (_buffer[bufferPos + 1]);
+      UInt32 dest = (nowPos + bufferPos + 5) + src;
+      // if (Test86MSByte(nextByte))
+      bool convert;
+      if (getSubStreamSize != NULL)
+      {
+        UInt64 currentPos = (nowPos64 + bufferPos);
+        while (subStreamEndPos < currentPos)
+        {
+          UInt64 subStreamSize;
+          HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
+          if (result == S_OK)
+          {
+            subStreamStartPos = subStreamEndPos;
+            subStreamEndPos += subStreamSize;          
+            subStreamIndex++;
+          }
+          else if (result == S_FALSE || result == E_NOTIMPL)
+          {
+            getSubStreamSize.Release();
+            subStreamStartPos = 0;
+            subStreamEndPos = subStreamStartPos - 1;          
+          }
+          else
+            return result;
+        }
+        if (getSubStreamSize == NULL)
+        {
+          if (sizeIsDefined)
+            convert = (dest < inSize);
+          else
+            convert = Test86MSByte(nextByte);
+        }
+        else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)
+          convert = Test86MSByte(nextByte);
+        else
+        {
+          UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
+          convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
+        }
+      }
+      else if (sizeIsDefined)
+        convert = (dest < inSize);
+      else
+        convert = Test86MSByte(nextByte);
+      unsigned index = GetIndex(prevByte, b);
+      if (convert)
+      {
+        _statusEncoder[index].Encode(&_rangeEncoder, 1);
+        bufferPos += 5;
+        COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;
+        for (int i = 24; i >= 0; i -= 8)
+          s.WriteByte((Byte)(dest >> i));
+        prevByte = nextByte;
+      }
+      else
+      {
+        _statusEncoder[index].Encode(&_rangeEncoder, 0);
+        bufferPos++;
+        prevByte = b;
+      }
+    }
+    nowPos += bufferPos;
+    nowPos64 += bufferPos;
+
+    if (progress != NULL)
+    {
+      /*
+      const UInt64 compressedSize = 
+        _mainStream.GetProcessedSize() + 
+        _callStream.GetProcessedSize() +
+        _jumpStream.GetProcessedSize() +
+        _rangeEncoder.GetProcessedSize();
+      */
+      RINOK(progress->SetRatioInfo(&nowPos64, NULL));
+    }
+ 
+    UInt32 i = 0;
+    while(bufferPos < endPos)
+      _buffer[i++] = _buffer[bufferPos++];
+    bufferPos = i;
+  }
+}
+
+STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  try
+  {
+    return CodeReal(inStreams, inSizes, numInStreams,
+      outStreams, outSizes,numOutStreams, progress);
+  }
+  catch(const COutBufferException &e) { return e.ErrorCode; }
+  catch(...) { return S_FALSE; }
+}
+
+#endif
+
+HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams,
+      const UInt64 ** /* inSizes */,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 ** /* outSizes */,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  if (numInStreams != 4 || numOutStreams != 1)
+    return E_INVALIDARG;
+
+  if (!_mainInStream.Create(1 << 16))
+    return E_OUTOFMEMORY;
+  if (!_callStream.Create(1 << 20))
+    return E_OUTOFMEMORY;
+  if (!_jumpStream.Create(1 << 16))
+    return E_OUTOFMEMORY;
+  if (!_rangeDecoder.Create(1 << 20))
+    return E_OUTOFMEMORY;
+  if (!_outStream.Create(1 << 16))
+    return E_OUTOFMEMORY;
+
+  _mainInStream.SetStream(inStreams[0]);
+  _callStream.SetStream(inStreams[1]);
+  _jumpStream.SetStream(inStreams[2]);
+  _rangeDecoder.SetStream(inStreams[3]);
+  _outStream.SetStream(outStreams[0]);
+
+  _mainInStream.Init();
+  _callStream.Init();
+  _jumpStream.Init();
+  _rangeDecoder.Init();
+  _outStream.Init();
+
+  for (int i = 0; i < 256 + 2; i++)
+    _statusDecoder[i].Init();
+
+  CCoderReleaser releaser(this);
+
+  Byte prevByte = 0;
+  UInt32 processedBytes = 0;
+  for (;;)
+  {
+    if (processedBytes >= (1 << 20) && progress != NULL)
+    {
+      /*
+      const UInt64 compressedSize = 
+        _mainInStream.GetProcessedSize() + 
+        _callStream.GetProcessedSize() +
+        _jumpStream.GetProcessedSize() +
+        _rangeDecoder.GetProcessedSize();
+      */
+      const UInt64 nowPos64 = _outStream.GetProcessedSize();
+      RINOK(progress->SetRatioInfo(NULL, &nowPos64));
+      processedBytes = 0;
+    }
+    UInt32 i;
+    Byte b = 0;
+    const UInt32 kBurstSize = (1 << 18);
+    for (i = 0; i < kBurstSize; i++)
+    {
+      if (!_mainInStream.ReadByte(b))
+        return Flush();
+      _outStream.WriteByte(b);
+      if (IsJ(prevByte, b))
+        break;
+      prevByte = b;
+    }
+    processedBytes += i;
+    if (i == kBurstSize)
+      continue;
+    unsigned index = GetIndex(prevByte, b);
+    if (_statusDecoder[index].Decode(&_rangeDecoder) == 1)
+    {
+      UInt32 src = 0;
+      CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;
+      for (int i = 0; i < 4; i++)
+      {
+        Byte b0;
+        if(!s.ReadByte(b0))
+          return S_FALSE;
+        src <<= 8;
+        src |= ((UInt32)b0);
+      }
+      UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;
+      _outStream.WriteByte((Byte)(dest));
+      _outStream.WriteByte((Byte)(dest >> 8));
+      _outStream.WriteByte((Byte)(dest >> 16));
+      _outStream.WriteByte((Byte)(dest >> 24));
+      prevByte = (Byte)(dest >> 24);
+      processedBytes += 4;
+    }
+    else
+      prevByte = b;
+  }
+}
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  try
+  {
+    return CodeReal(inStreams, inSizes, numInStreams,
+        outStreams, outSizes,numOutStreams, progress);
+  }
+  catch(const CInBufferException &e) { return e.ErrorCode; }
+  catch(const COutBufferException &e) { return e.ErrorCode; }
+  catch(...) { return S_FALSE; }
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Compress/Branch/x86_2.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Branch/x86_2.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Branch/x86_2.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,123 @@
+// x86_2.h
+
+#ifndef __BRANCH_X86_2_H
+#define __BRANCH_X86_2_H
+
+#include "../../../Common/MyCom.h"
+#include "../RangeCoder/RangeCoderBit.h"
+#include "../../ICoder.h"
+
+namespace NCompress {
+namespace NBcj2 {
+
+const int kNumMoveBits = 5;
+
+#ifndef EXTRACT_ONLY
+
+class CEncoder:
+  public ICompressCoder2,
+  public CMyUnknownImp
+{
+  Byte *_buffer;
+public:
+  CEncoder(): _buffer(0) {};
+  ~CEncoder();
+  bool Create();
+
+  COutBuffer _mainStream;
+  COutBuffer _callStream;
+  COutBuffer _jumpStream;
+  NCompress::NRangeCoder::CEncoder _rangeEncoder;
+  NCompress::NRangeCoder::CBitEncoder<kNumMoveBits> _statusEncoder[256 + 2];
+
+  HRESULT Flush();
+  void ReleaseStreams()
+  {
+    _mainStream.ReleaseStream();
+    _callStream.ReleaseStream();
+    _jumpStream.ReleaseStream();
+    _rangeEncoder.ReleaseStream();
+  }
+
+  class CCoderReleaser
+  {
+    CEncoder *_coder;
+  public:
+    CCoderReleaser(CEncoder *coder): _coder(coder) {}
+    ~CCoderReleaser() {  _coder->ReleaseStreams(); }
+  };
+
+public: 
+
+  MY_UNKNOWN_IMP
+
+  HRESULT CodeReal(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress);
+  STDMETHOD(Code)(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress);
+}; 
+
+#endif
+
+class CDecoder:
+  public ICompressCoder2,
+  public CMyUnknownImp
+{ 
+public:
+  CInBuffer _mainInStream;
+  CInBuffer _callStream;
+  CInBuffer _jumpStream;
+  NCompress::NRangeCoder::CDecoder _rangeDecoder;
+  NCompress::NRangeCoder::CBitDecoder<kNumMoveBits> _statusDecoder[256 + 2];
+
+  COutBuffer _outStream;
+
+  void ReleaseStreams()
+  {
+    _mainInStream.ReleaseStream();
+    _callStream.ReleaseStream();
+    _jumpStream.ReleaseStream();
+    _rangeDecoder.ReleaseStream();
+    _outStream.ReleaseStream();
+  }
+
+  HRESULT Flush() { return _outStream.Flush(); }
+  class CCoderReleaser
+  {
+    CDecoder *_coder;
+  public:
+    CCoderReleaser(CDecoder *coder): _coder(coder) {}
+    ~CCoderReleaser()  { _coder->ReleaseStreams(); }
+  };
+
+public: 
+  MY_UNKNOWN_IMP
+  HRESULT CodeReal(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress);
+  STDMETHOD(Code)(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress);
+}; 
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,38 @@
+// ByteSwap.cpp
+
+#include "StdAfx.h"
+
+#include "ByteSwap.h"
+
+STDMETHODIMP CByteSwap2::Init() { return S_OK; }
+
+STDMETHODIMP_(UInt32) CByteSwap2::Filter(Byte *data, UInt32 size)
+{
+  const UInt32 kStep = 2;
+  UInt32 i;
+  for (i = 0; i + kStep <= size; i += kStep)
+  {
+    Byte b = data[i];
+    data[i] = data[i + 1];
+    data[i + 1] = b;
+  }
+  return i;
+}
+
+STDMETHODIMP CByteSwap4::Init() { return S_OK; }
+
+STDMETHODIMP_(UInt32) CByteSwap4::Filter(Byte *data, UInt32 size)
+{
+  const UInt32 kStep = 4;
+  UInt32 i;
+  for (i = 0; i + kStep <= size; i += kStep)
+  {
+    Byte b0 = data[i];
+    Byte b1 = data[i + 1];
+    data[i] = data[i + 3];
+    data[i + 1] = data[i + 2];
+    data[i + 2] = b1;
+    data[i + 3] = b0;
+  }
+  return i;
+}

Added: trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwap.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,37 @@
+// ByteSwap.h
+
+#ifndef __BYTESWAP_H
+#define __BYTESWAP_H
+
+#include "../../ICoder.h"
+#include "Common/MyCom.h"
+
+// {23170F69-40C1-278B-0203-020000000000}
+DEFINE_GUID(CLSID_CCompressConvertByteSwap2, 
+0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+// {23170F69-40C1-278B-0203-040000000000}
+DEFINE_GUID(CLSID_CCompressConvertByteSwap4, 
+0x23170F69, 0x40C1, 0x278B, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+class CByteSwap2: 
+  public ICompressFilter,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP
+  STDMETHOD(Init)();
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
+};
+
+class CByteSwap4: 
+  public ICompressFilter,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP
+  STDMETHOD(Init)();
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwapRegister.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwapRegister.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/ByteSwap/ByteSwapRegister.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,17 @@
+// ByteSwapRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterCodec.h"
+
+#include "ByteSwap.h"
+static void *CreateCodec2() { return (void *)(ICompressFilter *)(new CByteSwap2); }
+static void *CreateCodec4() { return (void *)(ICompressFilter *)(new CByteSwap4); }
+
+static CCodecInfo g_CodecsInfo[] =
+{
+  { CreateCodec2, CreateCodec4, 0x020302, L"Swap2", 1, true },
+  { CreateCodec4, CreateCodec4, 0x020304, L"Swap4", 1, true }
+};
+
+REGISTER_CODECS(ByteSwap)

Added: trunk/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/ByteSwap/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/CodecExports.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/CodecExports.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/CodecExports.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,157 @@
+// CodecExports.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/ComTry.h"
+#include "../../Windows/PropVariant.h"
+#include "../Common/RegisterCodec.h"
+#include "../ICoder.h"
+
+extern unsigned int g_NumCodecs;
+extern const CCodecInfo *g_Codecs[]; 
+
+static const UInt16 kDecodeId = 0x2790;
+
+DEFINE_GUID(CLSID_CCodec, 
+0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)
+{
+  if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
+    value->vt = VT_BSTR;
+  return S_OK;
+}
+
+static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
+{
+  return SetPropString((const char *)&guid, sizeof(GUID), value);
+}
+
+static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value)
+{
+  GUID clsId = CLSID_CCodec;
+  for (int i = 0; i < sizeof(id); i++, id >>= 8)
+    clsId.Data4[i] = (Byte)(id & 0xFF);
+  if (encode)
+    clsId.Data3++;
+  return SetPropGUID(clsId, value);
+}
+
+static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index)
+{
+  index = -1;
+  if (clsID->Data1 != CLSID_CCodec.Data1 || 
+      clsID->Data2 != CLSID_CCodec.Data2 ||
+      (clsID->Data3 & ~1) != kDecodeId)
+    return S_OK;
+  encode = (clsID->Data3 != kDecodeId);
+  UInt64 id = 0;
+  for (int j = 0; j < 8; j++)
+    id |= ((UInt64)clsID->Data4[j]) << (8 * j);
+  for (UInt32 i = 0; i < g_NumCodecs; i++)
+  {
+    const CCodecInfo &codec = *g_Codecs[i];
+    if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder)
+      continue;
+    if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
+        codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
+      return E_NOINTERFACE;
+    index = i;
+    return S_OK;
+  }
+  return S_OK;
+}
+
+STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)
+{
+  COM_TRY_BEGIN
+  *outObject = 0;
+  bool isCoder = (*iid == IID_ICompressCoder) != 0;
+  bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
+  bool isFilter = (*iid == IID_ICompressFilter) != 0;
+  const CCodecInfo &codec = *g_Codecs[index];
+  if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
+      codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
+    return E_NOINTERFACE;
+  if (encode)
+  {
+    if (!codec.CreateEncoder)
+      return CLASS_E_CLASSNOTAVAILABLE;
+    *outObject = codec.CreateEncoder();
+  }
+  else
+  {
+    if (!codec.CreateDecoder)
+      return CLASS_E_CLASSNOTAVAILABLE;
+    *outObject = codec.CreateDecoder();
+  }
+  if (isCoder)
+    ((ICompressCoder *)*outObject)->AddRef();
+  else if (isCoder2)
+    ((ICompressCoder2 *)*outObject)->AddRef();
+  else
+    ((ICompressFilter *)*outObject)->AddRef();
+  return S_OK;
+  COM_TRY_END
+}
+
+STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)
+{
+  *outObject = 0;
+  bool isCoder = (*iid == IID_ICompressCoder) != 0;
+  bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
+  bool isFilter = (*iid == IID_ICompressFilter) != 0;
+  if (!isCoder && !isCoder2 && !isFilter)
+    return E_NOINTERFACE;
+  bool encode;
+  int codecIndex;
+  HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);
+  if (res != S_OK)
+    return res;
+  if (codecIndex < 0)
+    return CLASS_E_CLASSNOTAVAILABLE;
+  return CreateCoder2(encode, codecIndex, iid, outObject);
+}
+
+STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
+{
+  ::VariantClear((VARIANTARG *)value);
+  const CCodecInfo &codec = *g_Codecs[codecIndex];
+  switch(propID)
+  {
+    case NMethodPropID::kID:
+    {
+      value->uhVal.QuadPart = (UInt64)codec.Id;
+      value->vt = VT_UI8;
+      break;
+    }
+    case NMethodPropID::kName:
+      if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)
+        value->vt = VT_BSTR;
+      break;
+    case NMethodPropID::kDecoder:
+      if (codec.CreateDecoder)
+        return SetClassID(codec.Id, false, value);
+      break;
+    case NMethodPropID::kEncoder:
+      if (codec.CreateEncoder)
+        return SetClassID(codec.Id, true, value);
+      break;
+    case NMethodPropID::kInStreams:
+    {
+      if (codec.NumInStreams != 1)
+      {
+        value->vt = VT_UI4;
+        value->ulVal = codec.NumInStreams;
+      }
+      break;
+    }
+  }
+  return S_OK;
+}
+
+STDAPI GetNumberOfMethods(UINT32 *numCodecs)
+{
+  *numCodecs = g_NumCodecs;
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/Compress/Copy/CopyCoder.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Copy/CopyCoder.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Copy/CopyCoder.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,62 @@
+// Compress/CopyCoder.cpp
+
+#include "StdAfx.h"
+
+extern "C" 
+{ 
+#include "../../../../C/Alloc.h"
+}
+
+#include "CopyCoder.h"
+#include "../../Common/StreamUtils.h"
+
+namespace NCompress {
+
+static const UInt32 kBufferSize = 1 << 17;
+
+CCopyCoder::~CCopyCoder()
+{
+  ::MidFree(_buffer);
+}
+
+STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
+    ISequentialOutStream *outStream, 
+    const UInt64 * /* inSize */, const UInt64 *outSize,
+    ICompressProgressInfo *progress)
+{
+  if (_buffer == 0)
+  {
+    _buffer = (Byte *)::MidAlloc(kBufferSize);
+    if (_buffer == 0)
+      return E_OUTOFMEMORY;
+  }
+
+  TotalSize = 0;
+  for (;;)
+  {
+    UInt32 realProcessedSize;
+    UInt32 size = kBufferSize;
+    if (outSize != 0)
+      if (size > *outSize - TotalSize)
+        size = (UInt32)(*outSize - TotalSize);
+    RINOK(inStream->Read(_buffer, size, &realProcessedSize));
+    if (realProcessedSize == 0)
+      break;
+    RINOK(WriteStream(outStream, _buffer, realProcessedSize, NULL));
+    TotalSize += realProcessedSize;
+    if (progress != NULL)
+    {
+      RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));
+    }
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)
+{
+  *value = TotalSize;
+  return S_OK;
+}
+
+}
+

Added: trunk/lzma/CPP/7zip/Compress/Copy/CopyCoder.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Copy/CopyCoder.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Copy/CopyCoder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,33 @@
+// Compress/CopyCoder.h
+
+#ifndef __COMPRESS_COPYCODER_H
+#define __COMPRESS_COPYCODER_H
+
+#include "../../ICoder.h"
+#include "../../../Common/MyCom.h"
+
+namespace NCompress {
+
+class CCopyCoder: 
+  public ICompressCoder,
+  public ICompressGetInStreamProcessedSize,
+  public CMyUnknownImp
+{
+  Byte *_buffer;
+public:
+  UInt64 TotalSize;
+  CCopyCoder(): TotalSize(0) , _buffer(0) {};
+  ~CCopyCoder();
+
+  MY_UNKNOWN_IMP1(ICompressGetInStreamProcessedSize)
+
+  STDMETHOD(Code)(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, 
+      const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress);
+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+};
+
+}
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/Copy/CopyRegister.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Copy/CopyRegister.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Copy/CopyRegister.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,13 @@
+// LZMARegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterCodec.h"
+
+#include "CopyCoder.h"
+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::CCopyCoder); }
+
+static CCodecInfo g_CodecInfo =
+{ CreateCodec, CreateCodec, 0x00, L"Copy", 1, false };
+
+REGISTER_CODEC(Copy)

Added: trunk/lzma/CPP/7zip/Compress/Copy/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Copy/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Copy/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Compress/Copy/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/Copy/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/Copy/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif 

Added: trunk/lzma/CPP/7zip/Compress/LZ/LZOutWindow.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZ/LZOutWindow.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZ/LZOutWindow.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,16 @@
+// LZOutWindow.cpp
+
+#include "StdAfx.h"
+
+#include "LZOutWindow.h"
+
+void CLZOutWindow::Init(bool solid)
+{
+  if(!solid)
+    COutBuffer::Init();
+  #ifdef _NO_EXCEPTIONS
+  ErrorCode = S_OK;
+  #endif
+}
+
+

Added: trunk/lzma/CPP/7zip/Compress/LZ/LZOutWindow.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZ/LZOutWindow.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZ/LZOutWindow.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,65 @@
+// LZOutWindow.h
+
+#ifndef __LZ_OUT_WINDOW_H
+#define __LZ_OUT_WINDOW_H
+
+#include "../../IStream.h"
+#include "../../Common/OutBuffer.h"
+
+#ifndef _NO_EXCEPTIONS
+typedef COutBufferException CLZOutWindowException;
+#endif
+
+class CLZOutWindow: public COutBuffer
+{
+public:
+  void Init(bool solid = false);
+  
+  // distance >= 0, len > 0, 
+  bool CopyBlock(UInt32 distance, UInt32 len)
+  {
+    UInt32 pos = _pos - distance - 1;
+    if (distance >= _pos)
+    {
+      if (!_overDict || distance >= _bufferSize)
+        return false;
+      pos += _bufferSize;
+    }
+    if (_limitPos - _pos > len && _bufferSize - pos > len)
+    {
+      const Byte *src = _buffer + pos;
+      Byte *dest = _buffer + _pos;
+      _pos += len;
+      do
+        *dest++ = *src++;
+      while(--len != 0);
+    }
+    else do
+    {
+      if (pos == _bufferSize)
+        pos = 0;
+      _buffer[_pos++] = _buffer[pos++];
+      if (_pos == _limitPos)
+        FlushWithCheck();  
+    }
+    while(--len != 0);
+    return true;
+  }
+  
+  void PutByte(Byte b)
+  {
+    _buffer[_pos++] = b;
+    if (_pos == _limitPos)
+      FlushWithCheck();  
+  }
+  
+  Byte GetByte(UInt32 distance) const
+  {
+    UInt32 pos = _pos - distance - 1;
+    if (pos >= _bufferSize)
+      pos += _bufferSize;
+    return _buffer[pos]; 
+  }
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/LZ/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZ/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZ/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,6 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#endif 

Added: trunk/lzma/CPP/7zip/Compress/LZMA/LZMA.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA/LZMA.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA/LZMA.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,82 @@
+// LZMA.h
+
+#ifndef __LZMA_H
+#define __LZMA_H
+
+namespace NCompress {
+namespace NLZMA {
+
+const UInt32 kNumRepDistances = 4;
+
+const int kNumStates = 12;
+
+const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
+const Byte kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+const Byte kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+class CState
+{
+public:
+  Byte Index;
+  void Init() { Index = 0; }
+  void UpdateChar() { Index = kLiteralNextStates[Index]; }
+  void UpdateMatch() { Index = kMatchNextStates[Index]; }
+  void UpdateRep() { Index = kRepNextStates[Index]; }
+  void UpdateShortRep() { Index = kShortRepNextStates[Index]; }
+  bool IsCharState() const { return Index < 7; }
+};
+
+const int kNumPosSlotBits = 6; 
+const int kDicLogSizeMin = 0; 
+const int kDicLogSizeMax = 32; 
+const int kDistTableSizeMax = kDicLogSizeMax * 2; 
+
+const UInt32 kNumLenToPosStates = 4;
+
+inline UInt32 GetLenToPosState(UInt32 len)
+{
+  len -= 2;
+  if (len < kNumLenToPosStates)
+    return len;
+  return kNumLenToPosStates - 1;
+}
+
+namespace NLength {
+
+const int kNumPosStatesBitsMax = 4;
+const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
+
+const int kNumPosStatesBitsEncodingMax = 4;
+const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
+
+const int kNumLowBits = 3;
+const int kNumMidBits = 3;
+const int kNumHighBits = 8;
+const UInt32 kNumLowSymbols = 1 << kNumLowBits;
+const UInt32 kNumMidSymbols = 1 << kNumMidBits;
+const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits);
+
+}
+
+const UInt32 kMatchMinLen = 2;
+const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1;
+
+const int kNumAlignBits = 4;
+const UInt32 kAlignTableSize = 1 << kNumAlignBits;
+const UInt32 kAlignMask = (kAlignTableSize - 1);
+
+const UInt32 kStartPosModelIndex = 4;
+const UInt32 kEndPosModelIndex = 14;
+const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
+
+const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2);
+
+const int kNumLitPosStatesBitsEncodingMax = 4;
+const int kNumLitContextBitsMax = 8;
+
+const int kNumMoveBits = 5;
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,338 @@
+// LZMADecoder.cpp
+
+#include "StdAfx.h"
+
+#include "LZMADecoder.h"
+#include "../../../Common/Defs.h"
+
+namespace NCompress {
+namespace NLZMA {
+
+const int kLenIdFinished = -1;
+const int kLenIdNeedInit = -2;
+
+void CDecoder::Init()
+{
+  { 
+    for(int i = 0; i < kNumStates; i++)
+    {
+      for (UInt32 j = 0; j <= _posStateMask; j++)
+      {
+        _isMatch[i][j].Init();
+        _isRep0Long[i][j].Init();
+      }
+      _isRep[i].Init();
+      _isRepG0[i].Init();
+      _isRepG1[i].Init();
+      _isRepG2[i].Init();
+    }
+  }
+  { 
+    for (UInt32 i = 0; i < kNumLenToPosStates; i++)
+    _posSlotDecoder[i].Init();
+  }
+  { 
+    for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+      _posDecoders[i].Init();
+  }
+  _posAlignDecoder.Init();
+  _lenDecoder.Init(_posStateMask + 1);
+  _repMatchLenDecoder.Init(_posStateMask + 1);
+  _literalDecoder.Init();
+
+  _state.Init();
+  _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0;
+}
+
+HRESULT CDecoder::CodeSpec(UInt32 curSize)
+{
+  if (_outSizeDefined)
+  {
+    const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize();
+    if (curSize > rem)
+      curSize = (UInt32)rem;
+  }
+
+  if (_remainLen == kLenIdFinished)
+    return S_OK;
+  if (_remainLen == kLenIdNeedInit)
+  {
+    _rangeDecoder.Init();
+    Init();
+    _remainLen = 0;
+  }
+  if (curSize == 0)
+    return S_OK;
+
+  UInt32 rep0 = _reps[0];
+  UInt32 rep1 = _reps[1];
+  UInt32 rep2 = _reps[2];
+  UInt32 rep3 = _reps[3];
+  CState state = _state;
+  Byte previousByte;
+
+  while(_remainLen > 0 && curSize > 0)
+  {
+    previousByte = _outWindowStream.GetByte(rep0);
+    _outWindowStream.PutByte(previousByte);
+    _remainLen--;
+    curSize--;
+  }
+  UInt64 nowPos64 = _outWindowStream.GetProcessedSize();
+  if (nowPos64 == 0)
+    previousByte = 0;
+  else
+    previousByte = _outWindowStream.GetByte(0);
+
+  while(curSize > 0)
+  {
+    {
+      #ifdef _NO_EXCEPTIONS
+      if (_rangeDecoder.Stream.ErrorCode != S_OK)
+        return _rangeDecoder.Stream.ErrorCode;
+      #endif
+      if (_rangeDecoder.Stream.WasFinished())
+        return S_FALSE;
+      UInt32 posState = UInt32(nowPos64) & _posStateMask;
+      if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0)
+      {
+        if(!state.IsCharState())
+          previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, 
+              (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0));
+        else
+          previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, 
+              (UInt32)nowPos64, previousByte);
+        _outWindowStream.PutByte(previousByte);
+        state.UpdateChar();
+        curSize--;
+        nowPos64++;
+      }
+      else             
+      {
+        UInt32 len;
+        if(_isRep[state.Index].Decode(&_rangeDecoder) == 1)
+        {
+          len = 0;
+          if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0)
+          {
+            if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0)
+            {
+              state.UpdateShortRep();
+              len = 1;
+            }
+          }
+          else
+          {
+            UInt32 distance;
+            if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0)
+              distance = rep1;
+            else 
+            {
+              if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0)
+                distance = rep2;
+              else
+              {
+                distance = rep3;
+                rep3 = rep2;
+              }
+              rep2 = rep1;
+            }
+            rep1 = rep0;
+            rep0 = distance;
+          }
+          if (len == 0)
+          {
+            len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen;
+            state.UpdateRep();
+          }
+        }
+        else
+        {
+          rep3 = rep2;
+          rep2 = rep1;
+          rep1 = rep0;
+          len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState);
+          state.UpdateMatch();
+          UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder);
+          if (posSlot >= kStartPosModelIndex)
+          {
+            UInt32 numDirectBits = (posSlot >> 1) - 1;
+            rep0 = ((2 | (posSlot & 1)) << numDirectBits);
+
+            if (posSlot < kEndPosModelIndex)
+              rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + 
+                  rep0 - posSlot - 1, &_rangeDecoder, numDirectBits);
+            else
+            {
+              rep0 += (_rangeDecoder.DecodeDirectBits(
+                  numDirectBits - kNumAlignBits) << kNumAlignBits);
+              rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder);
+              if (rep0 == 0xFFFFFFFF)
+              {
+                _remainLen = kLenIdFinished;
+                return S_OK;
+              }
+            }
+          }
+          else
+            rep0 = posSlot;
+        }
+        UInt32 locLen = len;
+        if (len > curSize)
+          locLen = (UInt32)curSize;
+        if (!_outWindowStream.CopyBlock(rep0, locLen))
+          return S_FALSE;
+        previousByte = _outWindowStream.GetByte(0);
+        curSize -= locLen;
+        nowPos64 += locLen;
+        len -= locLen;
+        if (len != 0)
+        {
+          _remainLen = (Int32)len;
+          break;
+        }
+
+        #ifdef _NO_EXCEPTIONS
+        if (_outWindowStream.ErrorCode != S_OK)
+          return _outWindowStream.ErrorCode;
+        #endif
+      }
+    }
+  }
+  if (_rangeDecoder.Stream.WasFinished())
+    return S_FALSE;
+  _reps[0] = rep0;
+  _reps[1] = rep1;
+  _reps[2] = rep2;
+  _reps[3] = rep3;
+  _state = state;
+
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
+    ISequentialOutStream *outStream, 
+    const UInt64 *, const UInt64 *outSize,
+    ICompressProgressInfo *progress)
+{
+  SetInStream(inStream);
+  _outWindowStream.SetStream(outStream);
+  SetOutStreamSize(outSize);
+  CDecoderFlusher flusher(this);
+
+  for (;;)
+  {
+    UInt32 curSize = 1 << 18;
+    RINOK(CodeSpec(curSize));
+    if (_remainLen == kLenIdFinished)
+      break;
+    if (progress != NULL)
+    {
+      UInt64 inSize = _rangeDecoder.GetProcessedSize();
+      UInt64 nowPos64 = _outWindowStream.GetProcessedSize();
+      RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
+    }
+    if (_outSizeDefined)
+      if (_outWindowStream.GetProcessedSize() >= _outSize)
+        break;
+  } 
+  flusher.NeedFlush = false;
+  return Flush();
+}
+
+
+#ifdef _NO_EXCEPTIONS
+
+#define LZMA_TRY_BEGIN
+#define LZMA_TRY_END
+
+#else
+
+#define LZMA_TRY_BEGIN try { 
+#define LZMA_TRY_END } \
+  catch(const CInBufferException &e)  { return e.ErrorCode; } \
+  catch(const CLZOutWindowException &e)  { return e.ErrorCode; } \
+  catch(...) { return S_FALSE; }
+
+#endif
+
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress)
+{
+  LZMA_TRY_BEGIN
+  return CodeReal(inStream, outStream, inSize, outSize, progress); 
+  LZMA_TRY_END
+}
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
+{
+  if (size < 5)
+    return E_INVALIDARG;
+  int lc = properties[0] % 9;
+  Byte remainder = (Byte)(properties[0] / 9);
+  int lp = remainder % 5;
+  int pb = remainder / 5;
+  if (pb > NLength::kNumPosStatesBitsMax)
+    return E_INVALIDARG;
+  _posStateMask = (1 << pb) - 1;
+  UInt32 dictionarySize = 0;
+  for (int i = 0; i < 4; i++)
+    dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
+  if (!_outWindowStream.Create(dictionarySize))
+    return E_OUTOFMEMORY;
+  if (!_literalDecoder.Create(lp, lc))
+    return E_OUTOFMEMORY;
+  if (!_rangeDecoder.Create(1 << 20))
+    return E_OUTOFMEMORY;
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+  *value = _rangeDecoder.GetProcessedSize();
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
+{
+  _rangeDecoder.SetStream(inStream);
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::ReleaseInStream()
+{
+  _rangeDecoder.ReleaseStream();
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
+{
+  _outSizeDefined = (outSize != NULL);
+  if (_outSizeDefined)
+    _outSize = *outSize;
+  _remainLen = kLenIdNeedInit;
+  _outWindowStream.Init();
+  return S_OK;
+}
+
+#ifndef NO_READ_FROM_CODER
+
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  LZMA_TRY_BEGIN
+  if (processedSize)
+    *processedSize = 0;
+  const UInt64 startPos = _outWindowStream.GetProcessedSize();
+  _outWindowStream.SetMemStream((Byte *)data);
+  RINOK(CodeSpec(size));
+  if (processedSize)
+    *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos);
+  return Flush();
+  LZMA_TRY_END
+}
+
+#endif
+
+}}

Added: trunk/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,255 @@
+// LZMA/Decoder.h
+
+#ifndef __LZMA_DECODER_H
+#define __LZMA_DECODER_H
+
+#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+#include "../LZ/LZOutWindow.h"
+#include "../RangeCoder/RangeCoderBitTree.h"
+
+extern "C"
+{
+  #include "../../../../C/Alloc.h"
+}
+
+#include "LZMA.h"
+
+namespace NCompress {
+namespace NLZMA {
+
+typedef NRangeCoder::CBitDecoder<kNumMoveBits> CMyBitDecoder;
+
+class CLiteralDecoder2
+{
+  CMyBitDecoder _decoders[0x300];
+public:
+  void Init()
+  {
+    for (int i = 0; i < 0x300; i++)
+      _decoders[i].Init();
+  }
+  Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder)
+  {
+    UInt32 symbol = 1;
+    RC_INIT_VAR
+    do
+    {
+      // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
+      RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
+    }
+    while (symbol < 0x100);
+    RC_FLUSH_VAR
+    return (Byte)symbol;
+  }
+  Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte)
+  {
+    UInt32 symbol = 1;
+    RC_INIT_VAR
+    do
+    {
+      UInt32 matchBit = (matchByte >> 7) & 1;
+      matchByte <<= 1;
+      // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder);
+      // symbol = (symbol << 1) | bit;
+      UInt32 bit;
+      RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, 
+          bit = 0, bit = 1)
+      if (matchBit != bit)
+      {
+        while (symbol < 0x100)
+        {
+          // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder);
+          RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol)
+        }
+        break;
+      }
+    }
+    while (symbol < 0x100);
+    RC_FLUSH_VAR
+    return (Byte)symbol;
+  }
+};
+
+class CLiteralDecoder
+{
+  CLiteralDecoder2 *_coders;
+  int _numPrevBits;
+  int _numPosBits;
+  UInt32 _posMask;
+public:
+  CLiteralDecoder(): _coders(0) {}
+  ~CLiteralDecoder()  { Free(); }
+  void Free()
+  { 
+    MyFree(_coders);
+    _coders = 0;
+  }
+  bool Create(int numPosBits, int numPrevBits)
+  {
+    if (_coders == 0 || (numPosBits + numPrevBits) != 
+        (_numPrevBits + _numPosBits) )
+    {
+      Free();
+      UInt32 numStates = 1 << (numPosBits + numPrevBits);
+      _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2));
+    }
+    _numPosBits = numPosBits;
+    _posMask = (1 << numPosBits) - 1;
+    _numPrevBits = numPrevBits;
+    return (_coders != 0);
+  }
+  void Init()
+  {
+    UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
+    for (UInt32 i = 0; i < numStates; i++)
+      _coders[i].Init();
+  }
+  UInt32 GetState(UInt32 pos, Byte prevByte) const
+    { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); }
+  Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte)
+    { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
+  Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte)
+    { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
+};
+
+namespace NLength {
+
+class CDecoder
+{
+  CMyBitDecoder _choice;
+  CMyBitDecoder _choice2;
+  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumLowBits>  _lowCoder[kNumPosStatesMax];
+  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumMidBits>  _midCoder[kNumPosStatesMax];
+  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumHighBits> _highCoder; 
+public:
+  void Init(UInt32 numPosStates)
+  {
+    _choice.Init();
+    _choice2.Init();
+    for (UInt32 posState = 0; posState < numPosStates; posState++)
+    {
+      _lowCoder[posState].Init();
+      _midCoder[posState].Init();
+    }
+    _highCoder.Init();
+  }
+  UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState)
+  {
+    if(_choice.Decode(rangeDecoder) == 0)
+      return _lowCoder[posState].Decode(rangeDecoder);
+    if(_choice2.Decode(rangeDecoder) == 0)
+      return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder);
+    return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder);
+  }
+};
+
+}
+
+class CDecoder: 
+  public ICompressCoder,
+  public ICompressSetDecoderProperties2,
+  public ICompressGetInStreamProcessedSize,
+  #ifndef NO_READ_FROM_CODER
+  public ICompressSetInStream,
+  public ICompressSetOutStreamSize,
+  public ISequentialInStream,
+  #endif
+  public CMyUnknownImp
+{
+  CLZOutWindow _outWindowStream;
+  NRangeCoder::CDecoder _rangeDecoder;
+
+  CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax];
+  CMyBitDecoder _isRep[kNumStates];
+  CMyBitDecoder _isRepG0[kNumStates];
+  CMyBitDecoder _isRepG1[kNumStates];
+  CMyBitDecoder _isRepG2[kNumStates];
+  CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax];
+
+  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumPosSlotBits> _posSlotDecoder[kNumLenToPosStates];
+
+  CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex];
+  NRangeCoder::CBitTreeDecoder<kNumMoveBits, kNumAlignBits> _posAlignDecoder;
+  
+  NLength::CDecoder _lenDecoder;
+  NLength::CDecoder _repMatchLenDecoder;
+
+  CLiteralDecoder _literalDecoder;
+
+  UInt32 _posStateMask;
+
+  ///////////////////
+  // State
+  UInt32 _reps[4];
+  CState _state;
+  Int32 _remainLen; // -1 means end of stream. // -2 means need Init
+  UInt64 _outSize;
+  bool _outSizeDefined;
+
+  void Init();
+  HRESULT CodeSpec(UInt32 size);
+public:
+
+  #ifndef NO_READ_FROM_CODER
+  MY_UNKNOWN_IMP5(
+      ICompressSetDecoderProperties2, 
+      ICompressGetInStreamProcessedSize,
+      ICompressSetInStream, 
+      ICompressSetOutStreamSize, 
+      ISequentialInStream)
+  #else
+  MY_UNKNOWN_IMP2(
+      ICompressSetDecoderProperties2,
+      ICompressGetInStreamProcessedSize)
+  #endif
+
+  void ReleaseStreams()
+  {
+    _outWindowStream.ReleaseStream();
+    ReleaseInStream();
+  }
+
+  class CDecoderFlusher
+  {
+    CDecoder *_decoder;
+  public:
+    bool NeedFlush;
+    CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}
+    ~CDecoderFlusher() 
+    { 
+      if (NeedFlush)
+        _decoder->Flush();
+      _decoder->ReleaseStreams(); 
+    }
+  };
+
+  HRESULT Flush() {  return _outWindowStream.Flush(); }  
+
+  STDMETHOD(CodeReal)(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress);
+  
+  STDMETHOD(Code)(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress);
+
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+
+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
+
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+  STDMETHOD(ReleaseInStream)();
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
+
+  #ifndef NO_READ_FROM_CODER
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+  #endif
+
+  CDecoder(): _outSizeDefined(false) {}
+  virtual ~CDecoder() {}
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1547 @@
+// LZMA/Encoder.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#ifdef _WIN32
+#define USE_ALLOCA
+#endif
+
+#ifdef USE_ALLOCA
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+
+#include "../../../Common/Defs.h"
+#include "../../Common/StreamUtils.h"
+
+#include "LZMAEncoder.h"
+
+// extern "C" { #include "../../../../C/7zCrc.h" }
+
+// #define SHOW_STAT
+
+
+namespace NCompress {
+namespace NLZMA {
+
+// struct CCrcInit { CCrcInit() { InitCrcTable(); } } g_CrcInit;
+
+const int kDefaultDictionaryLogSize = 22;
+const UInt32 kNumFastBytesDefault = 0x20;
+
+#ifndef LZMA_LOG_BSR
+Byte g_FastPos[1 << kNumLogBits];
+
+class CFastPosInit
+{
+public:
+  CFastPosInit() { Init(); }
+  void Init()
+  {
+    const Byte kFastSlots = kNumLogBits * 2;
+    int c = 2;
+    g_FastPos[0] = 0;
+    g_FastPos[1] = 1;
+
+    for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
+    {
+      UInt32 k = (1 << ((slotFast >> 1) - 1));
+      for (UInt32 j = 0; j < k; j++, c++)
+        g_FastPos[c] = slotFast;
+    }
+  }
+} g_FastPosInit;
+#endif
+
+void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol)
+{
+  UInt32 context = 1;
+  int i = 8;
+  do 
+  {
+    i--;
+    UInt32 bit = (symbol >> i) & 1;
+    _encoders[context].Encode(rangeEncoder, bit);
+    context = (context << 1) | bit;
+  }
+  while(i != 0);
+}
+
+void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, 
+    Byte matchByte, Byte symbol)
+{
+  UInt32 context = 1;
+  int i = 8;
+  do 
+  {
+    i--;
+    UInt32 bit = (symbol >> i) & 1;
+    UInt32 matchBit = (matchByte >> i) & 1;
+    _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit);
+    context = (context << 1) | bit;
+    if (matchBit != bit)
+    {
+      while(i != 0)
+      {
+        i--;
+        UInt32 bit = (symbol >> i) & 1;
+        _encoders[context].Encode(rangeEncoder, bit);
+        context = (context << 1) | bit;
+      }
+      break;
+    }
+  }
+  while(i != 0);
+}
+
+UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const
+{
+  UInt32 price = 0;
+  UInt32 context = 1;
+  int i = 8;
+  if (matchMode)
+  {
+    do 
+    {
+      i--;
+      UInt32 matchBit = (matchByte >> i) & 1;
+      UInt32 bit = (symbol >> i) & 1;
+      price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit);
+      context = (context << 1) | bit;
+      if (matchBit != bit)
+        break;
+    }
+    while (i != 0);
+  }
+  while(i != 0)
+  {
+    i--;
+    UInt32 bit = (symbol >> i) & 1;
+    price += _encoders[context].GetPrice(bit);
+    context = (context << 1) | bit;
+  }
+  return price;
+};
+
+
+namespace NLength {
+
+void CEncoder::Init(UInt32 numPosStates)
+{
+  _choice.Init();
+  _choice2.Init();
+  for (UInt32 posState = 0; posState < numPosStates; posState++)
+  {
+    _lowCoder[posState].Init();
+    _midCoder[posState].Init();
+  }
+  _highCoder.Init();
+}
+
+void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
+{
+  if(symbol < kNumLowSymbols)
+  {
+    _choice.Encode(rangeEncoder, 0);
+    _lowCoder[posState].Encode(rangeEncoder, symbol);
+  }
+  else
+  {
+    _choice.Encode(rangeEncoder, 1);
+    if(symbol < kNumLowSymbols + kNumMidSymbols)
+    {
+      _choice2.Encode(rangeEncoder, 0);
+      _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols);
+    }
+    else
+    {
+      _choice2.Encode(rangeEncoder, 1);
+      _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols);
+    }
+  }
+}
+
+void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const
+{
+  UInt32 a0 = _choice.GetPrice0();
+  UInt32 a1 = _choice.GetPrice1();
+  UInt32 b0 = a1 + _choice2.GetPrice0();
+  UInt32 b1 = a1 + _choice2.GetPrice1();
+  UInt32 i = 0;
+  for (i = 0; i < kNumLowSymbols; i++)
+  {
+    if (i >= numSymbols)
+      return;
+    prices[i] = a0 + _lowCoder[posState].GetPrice(i);
+  }
+  for (; i < kNumLowSymbols + kNumMidSymbols; i++)
+  {
+    if (i >= numSymbols)
+      return;
+    prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols);
+  }
+  for (; i < numSymbols; i++)
+    prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols);
+}
+
+}
+
+CEncoder::CEncoder():
+  _numFastBytes(kNumFastBytesDefault),
+  _distTableSize(kDefaultDictionaryLogSize * 2),
+  _posStateBits(2),
+  _posStateMask(4 - 1),
+  _numLiteralPosStateBits(0),
+  _numLiteralContextBits(3),
+  _dictionarySize(1 << kDefaultDictionaryLogSize),
+  _matchFinderCycles(0),
+  #ifdef COMPRESS_MF_MT
+  _multiThread(false),
+  #endif
+  _writeEndMark(false)
+{
+  MatchFinder_Construct(&_matchFinderBase);
+  // _maxMode = false;
+  _fastMode = false;
+  #ifdef COMPRESS_MF_MT
+  MatchFinderMt_Construct(&_matchFinderMt);
+  _matchFinderMt.MatchFinder = &_matchFinderBase;
+  #endif
+}
+
+
+static void *SzAlloc(size_t size) { return BigAlloc(size); }
+static void SzFree(void *address) { BigFree(address); }
+ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+CEncoder::~CEncoder()
+{
+  #ifdef COMPRESS_MF_MT
+  MatchFinderMt_Destruct(&_matchFinderMt, &g_Alloc);
+  #endif
+  MatchFinder_Free(&_matchFinderBase, &g_Alloc);
+}
+
+static const UInt32 kBigHashDicLimit = (UInt32)1 << 24;
+
+HRESULT CEncoder::Create()
+{
+  if (!_rangeEncoder.Create(1 << 20))
+    return E_OUTOFMEMORY;
+  bool btMode = (_matchFinderBase.btMode != 0);
+  #ifdef COMPRESS_MF_MT
+  _mtMode = (_multiThread && !_fastMode && btMode);
+  #endif
+  
+  if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits))
+    return E_OUTOFMEMORY;
+
+  _matchFinderBase.bigHash = (_dictionarySize > kBigHashDicLimit);
+
+  UInt32 numCycles = 16 + (_numFastBytes >> 1);
+  if (!btMode)
+    numCycles >>= 1;
+  if (_matchFinderCycles != 0)
+    numCycles = _matchFinderCycles;
+  _matchFinderBase.cutValue = numCycles;
+  #ifdef COMPRESS_MF_MT
+  if (_mtMode)
+  {
+    RINOK(MatchFinderMt_Create(&_matchFinderMt, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc));
+    _matchFinderObj = &_matchFinderMt;
+    MatchFinderMt_CreateVTable(&_matchFinderMt, &_matchFinder);
+  }
+  else
+  #endif
+  {
+    if (!MatchFinder_Create(&_matchFinderBase, _dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen, &g_Alloc))
+      return E_OUTOFMEMORY;
+    _matchFinderObj = &_matchFinderBase;
+    MatchFinder_CreateVTable(&_matchFinderBase, &_matchFinder);
+  }
+  return S_OK;
+}
+
+inline wchar_t GetUpperChar(wchar_t c)
+{
+  if (c >= 'a' && c <= 'z')
+    c -= 0x20;
+  return c;
+}
+
+static int ParseMatchFinder(const wchar_t *s, int *btMode, UInt32 *numHashBytes /* , int *skipModeBits */)
+{
+  wchar_t c = GetUpperChar(*s++);
+  if (c == L'H')
+  {
+    if (GetUpperChar(*s++) != L'C')
+      return 0;
+    int numHashBytesLoc = (int)(*s++ - L'0');
+    if (numHashBytesLoc < 4 || numHashBytesLoc > 4)
+      return 0;
+    if (*s++ != 0)
+      return 0;
+    *btMode = 0;
+    *numHashBytes = numHashBytesLoc;
+    return 1;
+  }
+  if (c != L'B')
+    return 0;
+
+  if (GetUpperChar(*s++) != L'T')
+    return 0;
+  int numHashBytesLoc = (int)(*s++ - L'0');
+  if (numHashBytesLoc < 2 || numHashBytesLoc > 4)
+    return 0;
+  c = GetUpperChar(*s++);
+  /*
+  int skipModeBitsLoc = 0;
+  if (c == L'D')
+  {
+    skipModeBitsLoc = 2;
+    c = GetUpperChar(*s++);
+  }
+  */
+  if (c != L'\0')
+    return 0;
+  *btMode = 1;
+  *numHashBytes = numHashBytesLoc;
+  // *skipModeBits = skipModeBitsLoc;
+  return 1;
+}
+
+STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, 
+    const PROPVARIANT *properties, UInt32 numProperties)
+{
+  for (UInt32 i = 0; i < numProperties; i++)
+  {
+    const PROPVARIANT &prop = properties[i];
+    switch(propIDs[i])
+    {
+      case NCoderPropID::kNumFastBytes:
+      {
+        if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        UInt32 numFastBytes = prop.ulVal;
+        if(numFastBytes < 5 || numFastBytes > kMatchMaxLen)
+          return E_INVALIDARG;
+        _numFastBytes = numFastBytes;
+        break;
+      }
+      case NCoderPropID::kMatchFinderCycles:
+      {
+        if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        _matchFinderCycles = prop.ulVal;
+        break;
+      }
+      case NCoderPropID::kAlgorithm:
+      {
+        if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        UInt32 maximize = prop.ulVal;
+        _fastMode = (maximize == 0); 
+        // _maxMode = (maximize >= 2);
+        break;
+      }
+      case NCoderPropID::kMatchFinder:
+      {
+        if (prop.vt != VT_BSTR)
+          return E_INVALIDARG;
+        if (!ParseMatchFinder(prop.bstrVal, &_matchFinderBase.btMode, &_matchFinderBase.numHashBytes /* , &_matchFinderBase.skipModeBits */))
+          return E_INVALIDARG;
+        break;
+      }
+      case NCoderPropID::kMultiThread:
+      {
+        if (prop.vt != VT_BOOL)
+          return E_INVALIDARG;
+        #ifdef COMPRESS_MF_MT
+        Bool newMultiThread = (prop.boolVal == VARIANT_TRUE);
+        if (newMultiThread != _multiThread)
+        {
+          ReleaseMatchFinder();
+          _multiThread = newMultiThread;
+        }
+        #endif
+        break;
+      }
+      case NCoderPropID::kNumThreads:
+      {
+        if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        #ifdef COMPRESS_MF_MT
+        Bool newMultiThread = (prop.ulVal > 1) ? True : False;
+        if (newMultiThread != _multiThread)
+        {
+          ReleaseMatchFinder();
+          _multiThread = newMultiThread;
+        }
+        #endif
+        break;
+      }
+      case NCoderPropID::kDictionarySize:
+      {
+        const int kDicLogSizeMaxCompress = 30; // must be <= ((kNumLogBits - 1) * 2) + 7 = 31;
+        if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        UInt32 dictionarySize = prop.ulVal;
+        if (dictionarySize < UInt32(1 << kDicLogSizeMin) ||
+            dictionarySize > UInt32(1 << kDicLogSizeMaxCompress))
+          return E_INVALIDARG;
+        _dictionarySize = dictionarySize;
+        UInt32 dicLogSize;
+        for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
+          if (dictionarySize <= (UInt32(1) << dicLogSize))
+            break;
+        _distTableSize = dicLogSize * 2;
+        break;
+      }
+      case NCoderPropID::kPosStateBits:
+      {
+        if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        UInt32 value = prop.ulVal;
+        if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax)
+          return E_INVALIDARG;
+        _posStateBits = value;
+        _posStateMask = (1 << _posStateBits) - 1;
+        break;
+      }
+      case NCoderPropID::kLitPosBits:
+      {
+        if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        UInt32 value = prop.ulVal;
+        if (value > (UInt32)kNumLitPosStatesBitsEncodingMax)
+          return E_INVALIDARG;
+        _numLiteralPosStateBits = value;
+        break;
+      }
+      case NCoderPropID::kLitContextBits:
+      {
+        if (prop.vt != VT_UI4)
+          return E_INVALIDARG;
+        UInt32 value = prop.ulVal;
+        if (value > (UInt32)kNumLitContextBitsMax)
+          return E_INVALIDARG;
+        _numLiteralContextBits = value;
+        break;
+      }
+      case NCoderPropID::kEndMarker:
+      {
+        if (prop.vt != VT_BOOL)
+          return E_INVALIDARG;
+        SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE);
+        break;
+      }
+      default:
+        return E_INVALIDARG;
+    }
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{ 
+  const UInt32 kPropSize = 5;
+  Byte properties[kPropSize];
+  properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
+  for (int i = 0; i < 4; i++)
+    properties[1 + i] = Byte(_dictionarySize >> (8 * i));
+  return WriteStream(outStream, properties, kPropSize, NULL);
+}
+
+STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream)
+{
+  _rangeEncoder.SetStream(outStream);
+  return S_OK;
+}
+
+STDMETHODIMP CEncoder::ReleaseOutStream()
+{
+  _rangeEncoder.ReleaseStream();
+  return S_OK;
+}
+
+HRESULT CEncoder::Init()
+{
+  CBaseState::Init();
+
+  _rangeEncoder.Init();
+
+  for(int i = 0; i < kNumStates; i++)
+  {
+    for (UInt32 j = 0; j <= _posStateMask; j++)
+    {
+      _isMatch[i][j].Init();
+      _isRep0Long[i][j].Init();
+    }
+    _isRep[i].Init();
+    _isRepG0[i].Init();
+    _isRepG1[i].Init();
+    _isRepG2[i].Init();
+  }
+
+  _literalEncoder.Init();
+
+  {
+    for(UInt32 i = 0; i < kNumLenToPosStates; i++)
+      _posSlotEncoder[i].Init();
+  }
+  {
+    for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+      _posEncoders[i].Init();
+  }
+
+  _lenEncoder.Init(1 << _posStateBits);
+  _repMatchLenEncoder.Init(1 << _posStateBits);
+
+  _posAlignEncoder.Init();
+
+  _longestMatchWasFound = false;
+  _optimumEndIndex = 0;
+  _optimumCurrentIndex = 0;
+  _additionalOffset = 0;
+
+  return S_OK;
+}
+
+#ifdef SHOW_STAT
+static int ttt = 0;
+#endif
+
+void CEncoder::MovePos(UInt32 num)
+{
+  #ifdef SHOW_STAT
+  ttt += num;
+  printf("\n MovePos %d", num);
+  #endif
+  if (num != 0)
+  {
+    _additionalOffset += num;
+    _matchFinder.Skip(_matchFinderObj, num);
+  }
+}
+
+UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)
+{
+  _optimumEndIndex = cur;
+  UInt32 posMem = _optimum[cur].PosPrev;
+  UInt32 backMem = _optimum[cur].BackPrev;
+  do
+  {
+    if (_optimum[cur].Prev1IsChar)
+    {
+      _optimum[posMem].MakeAsChar();
+      _optimum[posMem].PosPrev = posMem - 1;
+      if (_optimum[cur].Prev2)
+      {
+        _optimum[posMem - 1].Prev1IsChar = false;
+        _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
+        _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
+      }
+    }
+    UInt32 posPrev = posMem;
+    UInt32 backCur = backMem;
+
+    backMem = _optimum[posPrev].BackPrev;
+    posMem = _optimum[posPrev].PosPrev;
+
+    _optimum[posPrev].BackPrev = backCur;
+    _optimum[posPrev].PosPrev = cur;
+    cur = posPrev;
+  }
+  while(cur != 0);
+  backRes = _optimum[0].BackPrev;
+  _optimumCurrentIndex  = _optimum[0].PosPrev;
+  return _optimumCurrentIndex; 
+}
+
+/*
+Out:
+  (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal
+*/
+
+UInt32 CEncoder::GetOptimum(UInt32 position, UInt32 &backRes)
+{
+  if(_optimumEndIndex != _optimumCurrentIndex)
+  {
+    const COptimal &optimum = _optimum[_optimumCurrentIndex];
+    UInt32 lenRes = optimum.PosPrev - _optimumCurrentIndex;
+    backRes = optimum.BackPrev;
+    _optimumCurrentIndex = optimum.PosPrev;
+    return lenRes;
+  }
+  _optimumCurrentIndex = _optimumEndIndex = 0;
+  
+  UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
+
+  UInt32 lenMain, numDistancePairs;
+  if (!_longestMatchWasFound)
+  {
+    lenMain = ReadMatchDistances(numDistancePairs);
+  }
+  else
+  {
+    lenMain = _longestMatchLength;
+    numDistancePairs = _numDistancePairs;
+    _longestMatchWasFound = false;
+  }
+
+  const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
+  if (numAvailableBytes < 2)
+  {
+    backRes = (UInt32)(-1);
+    return 1;
+  }
+  if (numAvailableBytes > kMatchMaxLen)
+    numAvailableBytes = kMatchMaxLen;
+
+  UInt32 reps[kNumRepDistances];
+  UInt32 repLens[kNumRepDistances];
+  UInt32 repMaxIndex = 0;
+  UInt32 i;
+  for(i = 0; i < kNumRepDistances; i++)
+  {
+    reps[i] = _repDistances[i];
+    const Byte *data2 = data - (reps[i] + 1);
+    if (data[0] != data2[0] || data[1] != data2[1])
+    {
+      repLens[i] = 0;
+      continue;
+    }
+    UInt32 lenTest;
+    for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
+    repLens[i] = lenTest;
+    if (lenTest > repLens[repMaxIndex])
+      repMaxIndex = i;
+  }
+  if(repLens[repMaxIndex] >= _numFastBytes)
+  {
+    backRes = repMaxIndex;
+    UInt32 lenRes = repLens[repMaxIndex];
+    MovePos(lenRes - 1);
+    return lenRes;
+  }
+
+  UInt32 *matchDistances = _matchDistances;
+  if(lenMain >= _numFastBytes)
+  {
+    backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; 
+    MovePos(lenMain - 1);
+    return lenMain;
+  }
+  Byte currentByte = *data;
+  Byte matchByte = *(data - (reps[0] + 1));
+
+  if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
+  {
+    backRes = (UInt32)-1;
+    return 1;
+  }
+
+  _optimum[0].State = _state;
+
+  UInt32 posState = (position & _posStateMask);
+
+  _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + 
+      _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte);
+  _optimum[1].MakeAsChar();
+
+  UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1();
+  UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
+
+  if(matchByte == currentByte)
+  {
+    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
+    if(shortRepPrice < _optimum[1].Price)
+    {
+      _optimum[1].Price = shortRepPrice;
+      _optimum[1].MakeAsShortRep();
+    }
+  }
+  UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
+
+  if(lenEnd < 2)
+  {
+    backRes = _optimum[1].BackPrev;
+    return 1;
+  }
+
+  _optimum[1].PosPrev = 0;
+  for (i = 0; i < kNumRepDistances; i++)
+    _optimum[0].Backs[i] = reps[i];
+
+  UInt32 len = lenEnd;
+  do
+    _optimum[len--].Price = kIfinityPrice;
+  while (len >= 2);
+
+  for(i = 0; i < kNumRepDistances; i++)
+  {
+    UInt32 repLen = repLens[i];
+    if (repLen < 2)
+      continue;
+    UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
+    do
+    {
+      UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
+      COptimal &optimum = _optimum[repLen];
+      if (curAndLenPrice < optimum.Price) 
+      {
+        optimum.Price = curAndLenPrice;
+        optimum.PosPrev = 0;
+        optimum.BackPrev = i;
+        optimum.Prev1IsChar = false;
+      }
+    }
+    while(--repLen >= 2);
+  }
+
+  UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
+
+  len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+  if (len <= lenMain)
+  {
+    UInt32 offs = 0;
+    while (len > matchDistances[offs])
+      offs += 2;
+    for(; ; len++)
+    {
+      UInt32 distance = matchDistances[offs + 1];
+      UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
+      COptimal &optimum = _optimum[len];
+      if (curAndLenPrice < optimum.Price) 
+      {
+        optimum.Price = curAndLenPrice;
+        optimum.PosPrev = 0;
+        optimum.BackPrev = distance + kNumRepDistances;
+        optimum.Prev1IsChar = false;
+      }
+      if (len == matchDistances[offs])
+      {
+        offs += 2;
+        if (offs == numDistancePairs)
+          break;
+      }
+    }
+  }
+
+  UInt32 cur = 0;
+
+  for (;;)
+  {
+    cur++;
+    if(cur == lenEnd)
+    {
+      return Backward(backRes, cur);
+    }
+    UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
+    UInt32 newLen, numDistancePairs;
+    newLen = ReadMatchDistances(numDistancePairs);
+    if(newLen >= _numFastBytes)
+    {
+      _numDistancePairs = numDistancePairs;
+      _longestMatchLength = newLen;
+      _longestMatchWasFound = true;
+      return Backward(backRes, cur);
+    }
+    position++;
+    COptimal &curOptimum = _optimum[cur];
+    UInt32 posPrev = curOptimum.PosPrev;
+    CState state;
+    if (curOptimum.Prev1IsChar)
+    {
+      posPrev--;
+      if (curOptimum.Prev2)
+      {
+        state = _optimum[curOptimum.PosPrev2].State;
+        if (curOptimum.BackPrev2 < kNumRepDistances)
+          state.UpdateRep();
+        else
+          state.UpdateMatch();
+      }
+      else
+        state = _optimum[posPrev].State;
+      state.UpdateChar();
+    }
+    else
+      state = _optimum[posPrev].State;
+    if (posPrev == cur - 1)
+    {
+      if (curOptimum.IsShortRep())
+        state.UpdateShortRep();
+      else
+        state.UpdateChar();
+    }
+    else
+    {
+      UInt32 pos;
+      if (curOptimum.Prev1IsChar && curOptimum.Prev2)
+      {
+        posPrev = curOptimum.PosPrev2;
+        pos = curOptimum.BackPrev2;
+        state.UpdateRep();
+      }
+      else
+      {
+        pos = curOptimum.BackPrev;
+        if (pos < kNumRepDistances)
+          state.UpdateRep();
+        else
+          state.UpdateMatch();
+      }
+      const COptimal &prevOptimum = _optimum[posPrev];
+      if (pos < kNumRepDistances)
+      {
+        reps[0] = prevOptimum.Backs[pos];
+        UInt32 i;
+        for(i = 1; i <= pos; i++)
+          reps[i] = prevOptimum.Backs[i - 1];
+        for(; i < kNumRepDistances; i++)
+          reps[i] = prevOptimum.Backs[i];
+      }
+      else
+      {
+        reps[0] = (pos - kNumRepDistances);
+        for(UInt32 i = 1; i < kNumRepDistances; i++)
+          reps[i] = prevOptimum.Backs[i - 1];
+      }
+    }
+    curOptimum.State = state;
+    for(UInt32 i = 0; i < kNumRepDistances; i++)
+      curOptimum.Backs[i] = reps[i];
+    UInt32 curPrice = curOptimum.Price; 
+    const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
+    const Byte currentByte = *data;
+    const Byte matchByte = *(data - (reps[0] + 1));
+
+    UInt32 posState = (position & _posStateMask);
+
+    UInt32 curAnd1Price = curPrice +
+        _isMatch[state.Index][posState].GetPrice0() +
+        _literalEncoder.GetSubCoder(position, *(data - 1))->GetPrice(!state.IsCharState(), matchByte, currentByte);
+
+    COptimal &nextOptimum = _optimum[cur + 1];
+
+    bool nextIsChar = false;
+    if (curAnd1Price < nextOptimum.Price) 
+    {
+      nextOptimum.Price = curAnd1Price;
+      nextOptimum.PosPrev = cur;
+      nextOptimum.MakeAsChar();
+      nextIsChar = true;
+    }
+
+    UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1();
+    UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
+    
+    if(matchByte == currentByte &&
+        !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
+    {
+      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
+      if(shortRepPrice <= nextOptimum.Price)
+      {
+        nextOptimum.Price = shortRepPrice;
+        nextOptimum.PosPrev = cur;
+        nextOptimum.MakeAsShortRep();
+        nextIsChar = true;
+      }
+    }
+    /*
+    if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
+      continue;
+    */
+
+    numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull);
+    UInt32 numAvailableBytes = numAvailableBytesFull;
+
+    if (numAvailableBytes < 2)
+      continue;
+    if (numAvailableBytes > _numFastBytes)
+      numAvailableBytes = _numFastBytes;
+    if (!nextIsChar && matchByte != currentByte) // speed optimization
+    {
+      // try Literal + rep0
+      const Byte *data2 = data - (reps[0] + 1);
+      UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1);
+      UInt32 temp;
+      for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
+      UInt32 lenTest2 = temp - 1;
+      if (lenTest2 >= 2)
+      {
+        CState state2 = state;
+        state2.UpdateChar();
+        UInt32 posStateNext = (position + 1) & _posStateMask;
+        UInt32 nextRepMatchPrice = curAnd1Price + 
+            _isMatch[state2.Index][posStateNext].GetPrice1() +
+            _isRep[state2.Index].GetPrice1();
+        // for (; lenTest2 >= 2; lenTest2--)
+        {
+          UInt32 offset = cur + 1 + lenTest2;
+          while(lenEnd < offset)
+            _optimum[++lenEnd].Price = kIfinityPrice;
+          UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
+              0, lenTest2, state2, posStateNext);
+          COptimal &optimum = _optimum[offset];
+          if (curAndLenPrice < optimum.Price) 
+          {
+            optimum.Price = curAndLenPrice;
+            optimum.PosPrev = cur + 1;
+            optimum.BackPrev = 0;
+            optimum.Prev1IsChar = true;
+            optimum.Prev2 = false;
+          }
+        }
+      }
+    }
+    
+    UInt32 startLen = 2; // speed optimization 
+    for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++)
+    {
+      // UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
+      const Byte *data2 = data - (reps[repIndex] + 1);
+      if (data[0] != data2[0] || data[1] != data2[1])
+        continue;
+      UInt32 lenTest;
+      for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
+      while(lenEnd < cur + lenTest)
+        _optimum[++lenEnd].Price = kIfinityPrice;
+      UInt32 lenTestTemp = lenTest;
+      UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState);
+      do
+      {
+        UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState);
+        COptimal &optimum = _optimum[cur + lenTest];
+        if (curAndLenPrice < optimum.Price) 
+        {
+          optimum.Price = curAndLenPrice;
+          optimum.PosPrev = cur;
+          optimum.BackPrev = repIndex;
+          optimum.Prev1IsChar = false;
+        }
+      }
+      while(--lenTest >= 2);
+      lenTest = lenTestTemp;
+      
+      if (repIndex == 0)
+        startLen = lenTest + 1;
+        
+      // if (_maxMode)
+        {
+          UInt32 lenTest2 = lenTest + 1;
+          UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+          lenTest2 -= lenTest + 1;
+          if (lenTest2 >= 2)
+          {
+            CState state2 = state;
+            state2.UpdateRep();
+            UInt32 posStateNext = (position + lenTest) & _posStateMask;
+            UInt32 curAndLenCharPrice = 
+                price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + 
+                _isMatch[state2.Index][posStateNext].GetPrice0() +
+                _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice(
+                true, data2[lenTest], data[lenTest]);
+            state2.UpdateChar();
+            posStateNext = (position + lenTest + 1) & _posStateMask;
+            UInt32 nextRepMatchPrice = curAndLenCharPrice + 
+                _isMatch[state2.Index][posStateNext].GetPrice1() +
+                _isRep[state2.Index].GetPrice1();
+            
+            // for(; lenTest2 >= 2; lenTest2--)
+            {
+              UInt32 offset = cur + lenTest + 1 + lenTest2;
+              while(lenEnd < offset)
+                _optimum[++lenEnd].Price = kIfinityPrice;
+              UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
+                  0, lenTest2, state2, posStateNext);
+              COptimal &optimum = _optimum[offset];
+              if (curAndLenPrice < optimum.Price) 
+              {
+                optimum.Price = curAndLenPrice;
+                optimum.PosPrev = cur + lenTest + 1;
+                optimum.BackPrev = 0;
+                optimum.Prev1IsChar = true;
+                optimum.Prev2 = true;
+                optimum.PosPrev2 = cur;
+                optimum.BackPrev2 = repIndex;
+              }
+            }
+          }
+        }
+      }
+    
+    //    for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)
+    if (newLen > numAvailableBytes)
+    {
+      newLen = numAvailableBytes;
+      for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2);
+      matchDistances[numDistancePairs] = newLen;
+      numDistancePairs += 2;
+    }
+    if (newLen >= startLen)
+    {
+      UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
+      while(lenEnd < cur + newLen)
+        _optimum[++lenEnd].Price = kIfinityPrice;
+
+      UInt32 offs = 0;
+      while(startLen > matchDistances[offs])
+        offs += 2;
+      UInt32 curBack = matchDistances[offs + 1];
+      UInt32 posSlot = GetPosSlot2(curBack);
+      for(UInt32 lenTest = /*2*/ startLen; ; lenTest++)
+      {
+        UInt32 curAndLenPrice = normalMatchPrice;
+        UInt32 lenToPosState = GetLenToPosState(lenTest);
+        if (curBack < kNumFullDistances)
+          curAndLenPrice += _distancesPrices[lenToPosState][curBack];
+        else
+          curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask];
+  
+        curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState);
+        
+        COptimal &optimum = _optimum[cur + lenTest];
+        if (curAndLenPrice < optimum.Price) 
+        {
+          optimum.Price = curAndLenPrice;
+          optimum.PosPrev = cur;
+          optimum.BackPrev = curBack + kNumRepDistances;
+          optimum.Prev1IsChar = false;
+        }
+
+        if (/*_maxMode && */lenTest == matchDistances[offs])
+        {
+          // Try Match + Literal + Rep0
+          const Byte *data2 = data - (curBack + 1);
+          UInt32 lenTest2 = lenTest + 1;
+          UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+          lenTest2 -= lenTest + 1;
+          if (lenTest2 >= 2)
+          {
+            CState state2 = state;
+            state2.UpdateMatch();
+            UInt32 posStateNext = (position + lenTest) & _posStateMask;
+            UInt32 curAndLenCharPrice = curAndLenPrice + 
+                _isMatch[state2.Index][posStateNext].GetPrice0() +
+                _literalEncoder.GetSubCoder(position + lenTest, data[lenTest - 1])->GetPrice( 
+                true, data2[lenTest], data[lenTest]);
+            state2.UpdateChar();
+            posStateNext = (posStateNext + 1) & _posStateMask;
+            UInt32 nextRepMatchPrice = curAndLenCharPrice + 
+                _isMatch[state2.Index][posStateNext].GetPrice1() +
+                _isRep[state2.Index].GetPrice1();
+            
+            // for(; lenTest2 >= 2; lenTest2--)
+            {
+              UInt32 offset = cur + lenTest + 1 + lenTest2;
+              while(lenEnd < offset)
+                _optimum[++lenEnd].Price = kIfinityPrice;
+              UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+              COptimal &optimum = _optimum[offset];
+              if (curAndLenPrice < optimum.Price) 
+              {
+                optimum.Price = curAndLenPrice;
+                optimum.PosPrev = cur + lenTest + 1;
+                optimum.BackPrev = 0;
+                optimum.Prev1IsChar = true;
+                optimum.Prev2 = true;
+                optimum.PosPrev2 = cur;
+                optimum.BackPrev2 = curBack + kNumRepDistances;
+              }
+            }
+          }
+          offs += 2;
+          if (offs == numDistancePairs)
+            break;
+          curBack = matchDistances[offs + 1];
+          if (curBack >= kNumFullDistances)
+            posSlot = GetPosSlot2(curBack);
+        }
+      }
+    }
+  }
+}
+
+static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist)
+{
+  return ((bigDist >> 7) > smallDist);
+}
+
+UInt32 CEncoder::ReadMatchDistances(UInt32 &numDistancePairs)
+{
+  UInt32 lenRes = 0;
+  numDistancePairs = _matchFinder.GetMatches(_matchFinderObj, _matchDistances);
+  #ifdef SHOW_STAT
+  printf("\n i = %d numPairs = %d    ", ttt, numDistancePairs / 2);
+  if (ttt >= 61994)
+    ttt = ttt;
+
+  ttt++;
+  for (UInt32 i = 0; i < numDistancePairs; i += 2)
+    printf("%2d %6d   | ", _matchDistances[i], _matchDistances[i + 1]);
+  #endif
+  if (numDistancePairs > 0)
+  {
+    lenRes = _matchDistances[numDistancePairs - 2];
+    if (lenRes == _numFastBytes)
+    {
+      UInt32 numAvail = _matchFinder.GetNumAvailableBytes(_matchFinderObj) + 1;
+      const Byte *pby = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
+      UInt32 distance = _matchDistances[numDistancePairs - 1] + 1;
+      if (numAvail > kMatchMaxLen)
+        numAvail = kMatchMaxLen;
+
+      const Byte *pby2 = pby - distance;
+      for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
+    }
+  }
+  _additionalOffset++;
+  return lenRes;
+}
+
+UInt32 CEncoder::GetOptimumFast(UInt32 &backRes)
+{
+  UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
+  UInt32 lenMain, numDistancePairs;
+  if (!_longestMatchWasFound)
+  {
+    lenMain = ReadMatchDistances(numDistancePairs);
+  }
+  else
+  {
+    lenMain = _longestMatchLength;
+    numDistancePairs = _numDistancePairs;
+    _longestMatchWasFound = false;
+  }
+
+  const Byte *data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
+  if (numAvailableBytes > kMatchMaxLen)
+    numAvailableBytes = kMatchMaxLen;
+  if (numAvailableBytes < 2)
+  {
+    backRes = (UInt32)(-1);
+    return 1;
+  }
+
+  UInt32 repLens[kNumRepDistances];
+  UInt32 repMaxIndex = 0;
+
+  for(UInt32 i = 0; i < kNumRepDistances; i++)
+  {
+    const Byte *data2 = data - (_repDistances[i] + 1);
+    if (data[0] != data2[0] || data[1] != data2[1])
+    {
+      repLens[i] = 0;
+      continue;
+    }
+    UInt32 len;
+    for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
+    if(len >= _numFastBytes)
+    {
+      backRes = i;
+      MovePos(len - 1);
+      return len;
+    }
+    repLens[i] = len;
+    if (len > repLens[repMaxIndex])
+      repMaxIndex = i;
+  }
+  UInt32 *matchDistances = _matchDistances;
+  if(lenMain >= _numFastBytes)
+  {
+    backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; 
+    MovePos(lenMain - 1);
+    return lenMain;
+  }
+
+  UInt32 backMain = 0; // for GCC
+  if (lenMain >= 2)
+  {
+    backMain = matchDistances[numDistancePairs - 1];
+    while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1)
+    {
+      if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))
+        break;
+      numDistancePairs -= 2;
+      lenMain = matchDistances[numDistancePairs - 2];
+      backMain = matchDistances[numDistancePairs - 1];
+    }
+    if (lenMain == 2 && backMain >= 0x80)
+      lenMain = 1;
+  }
+
+  if (repLens[repMaxIndex] >= 2)
+  {
+    if (repLens[repMaxIndex] + 1 >= lenMain || 
+        repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) ||
+        repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)))
+    {
+      backRes = repMaxIndex;
+      UInt32 lenRes = repLens[repMaxIndex];
+      MovePos(lenRes - 1);
+      return lenRes;
+    }
+  }
+  
+  if (lenMain >= 2 && numAvailableBytes > 2)
+  {
+    numAvailableBytes = _matchFinder.GetNumAvailableBytes(_matchFinderObj);
+    _longestMatchLength = ReadMatchDistances(_numDistancePairs);
+    if (_longestMatchLength >= 2)
+    {
+      UInt32 newDistance = matchDistances[_numDistancePairs - 1];
+      if (_longestMatchLength >= lenMain && newDistance < backMain || 
+          _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) ||
+          _longestMatchLength > lenMain + 1 ||
+          _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain))
+      {
+        _longestMatchWasFound = true;
+        backRes = UInt32(-1);
+        return 1;
+      }
+    }
+    data = _matchFinder.GetPointerToCurrentPos(_matchFinderObj) - 1;
+    for(UInt32 i = 0; i < kNumRepDistances; i++)
+    {
+      const Byte *data2 = data - (_repDistances[i] + 1);
+      if (data[1] != data2[1] || data[2] != data2[2])
+      {
+        repLens[i] = 0;
+        continue;
+      }
+      UInt32 len;
+      for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
+      if (len + 1 >= lenMain)
+      {
+        _longestMatchWasFound = true;
+        backRes = UInt32(-1);
+        return 1;
+      }
+    }
+    backRes = backMain + kNumRepDistances; 
+    MovePos(lenMain - 2);
+    return lenMain;
+  }
+  backRes = UInt32(-1);
+  return 1;
+}
+
+HRESULT CEncoder::Flush(UInt32 nowPos)
+{
+  // ReleaseMFStream();
+  if (_matchFinderBase.result != SZ_OK)
+    return _matchFinderBase.result;
+  WriteEndMarker(nowPos & _posStateMask);
+  _rangeEncoder.FlushData();
+  return _rangeEncoder.FlushStream();
+}
+
+void CEncoder::WriteEndMarker(UInt32 posState)
+{
+  // This function for writing End Mark for stream version of LZMA. 
+  // In current version this feature is not used.
+  if (!_writeEndMark)
+    return;
+
+  _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
+  _isRep[_state.Index].Encode(&_rangeEncoder, 0);
+  _state.UpdateMatch();
+  UInt32 len = kMatchMinLen; // kMatchMaxLen;
+  _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
+  UInt32 posSlot = (1 << kNumPosSlotBits)  - 1;
+  UInt32 lenToPosState = GetLenToPosState(len);
+  _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
+  UInt32 footerBits = 30;
+  UInt32 posReduced = (UInt32(1) << footerBits) - 1;
+  _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+  _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
+}
+
+HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, 
+      const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress)
+{
+  // _needReleaseMFStream = false;
+  #ifdef COMPRESS_MF_MT
+  #ifdef USE_ALLOCA
+  alloca(0x300);
+  #endif
+  #endif
+  CCoderReleaser coderReleaser(this);
+  RINOK(SetStreams(inStream, outStream, inSize, outSize));
+  for (;;)
+  {
+    UInt64 processedInSize;
+    UInt64 processedOutSize;
+    Int32 finished;
+    RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished));
+    if (finished != 0)
+      break;
+    if (progress != 0)
+    {
+      RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize));
+    }
+  }
+  return S_OK;
+}
+
+HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, 
+      const UInt64 * /* inSize */, const UInt64 * /* outSize */)
+{
+  _inStream = inStream;
+  _finished = false;
+  RINOK(Create());
+  RINOK(SetOutStream(outStream));
+  RINOK(Init());
+  
+  if (!_fastMode)
+  {
+    FillDistancesPrices();
+    FillAlignPrices();
+  }
+
+  _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
+  _lenEncoder.UpdateTables(1 << _posStateBits);
+  _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
+  _repMatchLenEncoder.UpdateTables(1 << _posStateBits);
+
+  nowPos64 = 0;
+  return S_OK;
+}
+
+static HRes MyRead(void *object, void *data, UInt32 size, UInt32 *processedSize)
+{
+  return (HRes)((CSeqInStream *)object)->RealStream->Read(data, size, processedSize);
+}
+
+HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
+{
+  if (_inStream != 0)
+  {
+    _seqInStream.RealStream = _inStream;
+    _seqInStream.SeqInStream.Read = MyRead;
+    _matchFinderBase.stream = &_seqInStream.SeqInStream;
+    _matchFinder.Init(_matchFinderObj);
+    _needReleaseMFStream = true;
+    _inStream = 0;
+  }
+
+
+  *finished = 1;
+  if (_finished)
+    return _matchFinderBase.result;
+  _finished = true;
+
+  if (nowPos64 == 0)
+  {
+    if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0)
+      return Flush((UInt32)nowPos64);
+    UInt32 len, numDistancePairs;
+    len = ReadMatchDistances(numDistancePairs);
+    UInt32 posState = UInt32(nowPos64) & _posStateMask;
+    _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
+    _state.UpdateChar();
+    Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset);
+    _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte);
+    _previousByte = curByte;
+    _additionalOffset--;
+    nowPos64++;
+  }
+
+  UInt32 nowPos32 = (UInt32)nowPos64;
+  UInt32 progressPosValuePrev = nowPos32;
+
+  if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0)
+    return Flush(nowPos32);
+
+  for (;;)
+  {
+    #ifdef _NO_EXCEPTIONS
+    if (_rangeEncoder.Stream.ErrorCode != S_OK)
+      return _rangeEncoder.Stream.ErrorCode;
+    #endif
+    UInt32 pos, len;
+
+    if (_fastMode)
+      len = GetOptimumFast(pos);
+    else
+      len = GetOptimum(nowPos32, pos);
+
+    UInt32 posState = nowPos32 & _posStateMask;
+    if(len == 1 && pos == 0xFFFFFFFF)
+    {
+      _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
+      Byte curByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _additionalOffset);
+      CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte);
+      if(_state.IsCharState())
+        subCoder->Encode(&_rangeEncoder, curByte);
+      else
+      {
+        Byte matchByte = _matchFinder.GetIndexByte(_matchFinderObj, 0 - _repDistances[0] - 1 - _additionalOffset);
+        subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);
+      }
+      _state.UpdateChar();
+      _previousByte = curByte;
+    }
+    else
+    {
+      _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
+      if(pos < kNumRepDistances)
+      {
+        _isRep[_state.Index].Encode(&_rangeEncoder, 1);
+        if(pos == 0)
+        {
+          _isRepG0[_state.Index].Encode(&_rangeEncoder, 0);
+          _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1));
+        }
+        else
+        {
+          UInt32 distance = _repDistances[pos];
+          _isRepG0[_state.Index].Encode(&_rangeEncoder, 1);
+          if (pos == 1)
+            _isRepG1[_state.Index].Encode(&_rangeEncoder, 0);
+          else
+          {
+            _isRepG1[_state.Index].Encode(&_rangeEncoder, 1);
+            _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);
+            if (pos == 3)
+              _repDistances[3] = _repDistances[2];
+            _repDistances[2] = _repDistances[1];
+          }
+          _repDistances[1] = _repDistances[0];
+          _repDistances[0] = distance;
+        }
+        if (len == 1)
+          _state.UpdateShortRep();
+        else
+        {
+          _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
+          _state.UpdateRep();
+        }
+      }
+      else
+      {
+        _isRep[_state.Index].Encode(&_rangeEncoder, 0);
+        _state.UpdateMatch();
+        _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
+        pos -= kNumRepDistances;
+        UInt32 posSlot = GetPosSlot(pos);
+        _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot);
+        
+        if (posSlot >= kStartPosModelIndex)
+        {
+          UInt32 footerBits = ((posSlot >> 1) - 1);
+          UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+          UInt32 posReduced = pos - base;
+
+          if (posSlot < kEndPosModelIndex)
+            NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, 
+                &_rangeEncoder, footerBits, posReduced);
+          else
+          {
+            _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+            _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
+            _alignPriceCount++;
+          }
+        }
+        _repDistances[3] = _repDistances[2];
+        _repDistances[2] = _repDistances[1];
+        _repDistances[1] = _repDistances[0];
+        _repDistances[0] = pos;
+        _matchPriceCount++;
+      }
+      _previousByte = _matchFinder.GetIndexByte(_matchFinderObj, len - 1 - _additionalOffset);
+    }
+    _additionalOffset -= len;
+    nowPos32 += len;
+    if (_additionalOffset == 0)
+    {
+      if (!_fastMode)
+      {
+        if (_matchPriceCount >= (1 << 7))
+          FillDistancesPrices();
+        if (_alignPriceCount >= kAlignTableSize)
+          FillAlignPrices();
+      }
+      if (_matchFinder.GetNumAvailableBytes(_matchFinderObj) == 0)
+        return Flush(nowPos32);
+      if (nowPos32 - progressPosValuePrev >= (1 << 14))
+      {
+        nowPos64 += nowPos32 - progressPosValuePrev;
+        *inSize = nowPos64;
+        *outSize = _rangeEncoder.GetProcessedSize();
+        _finished = false;
+        *finished = 0;
+        return _matchFinderBase.result;
+      }
+    }
+  }
+}
+
+STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
+    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+    ICompressProgressInfo *progress)
+{
+  #ifndef _NO_EXCEPTIONS
+  try 
+  { 
+  #endif
+    return CodeReal(inStream, outStream, inSize, outSize, progress); 
+  #ifndef _NO_EXCEPTIONS
+  }
+  catch(const COutBufferException &e) { return e.ErrorCode; }
+  catch(...) { return E_FAIL; }
+  #endif
+}
+  
+void CEncoder::FillDistancesPrices()
+{
+  UInt32 tempPrices[kNumFullDistances];
+  for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++)
+  { 
+    UInt32 posSlot = GetPosSlot(i);
+    UInt32 footerBits = ((posSlot >> 1) - 1);
+    UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+    tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + 
+      base - posSlot - 1, footerBits, i - base);
+  }
+
+  for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
+  {
+    UInt32 posSlot;
+    NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> &encoder = _posSlotEncoder[lenToPosState];
+    UInt32 *posSlotPrices = _posSlotPrices[lenToPosState];
+    for (posSlot = 0; posSlot < _distTableSize; posSlot++)
+      posSlotPrices[posSlot] = encoder.GetPrice(posSlot);
+    for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
+      posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);
+
+    UInt32 *distancesPrices = _distancesPrices[lenToPosState];
+    UInt32 i;
+    for (i = 0; i < kStartPosModelIndex; i++)
+      distancesPrices[i] = posSlotPrices[i];
+    for (; i < kNumFullDistances; i++)
+      distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i];
+  }
+  _matchPriceCount = 0;
+}
+
+void CEncoder::FillAlignPrices()
+{
+  for (UInt32 i = 0; i < kAlignTableSize; i++)
+    _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
+  _alignPriceCount = 0;
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA/LZMAEncoder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,465 @@
+// LZMA/Encoder.h
+
+#ifndef __LZMA_ENCODER_H
+#define __LZMA_ENCODER_H
+
+#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+
+extern "C"
+{
+  #include "../../../../C/Alloc.h"
+  #include "../../../../C/Compress/Lz/MatchFinder.h"
+  #ifdef COMPRESS_MF_MT
+  #include "../../../../C/Compress/Lz/MatchFinderMt.h"
+  #endif
+}
+
+#include "../RangeCoder/RangeCoderBitTree.h"
+
+#include "LZMA.h"
+
+namespace NCompress {
+namespace NLZMA {
+
+typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder;
+
+class CBaseState
+{
+protected:
+  CState _state;
+  Byte _previousByte;
+  UInt32 _repDistances[kNumRepDistances];
+  void Init()
+  {
+    _state.Init();
+    _previousByte = 0;
+    for(UInt32 i = 0 ; i < kNumRepDistances; i++)
+      _repDistances[i] = 0;
+  }
+};
+
+struct COptimal
+{
+  CState State;
+
+  bool Prev1IsChar;
+  bool Prev2;
+
+  UInt32 PosPrev2;
+  UInt32 BackPrev2;     
+
+  UInt32 Price;    
+  UInt32 PosPrev;         // posNext;
+  UInt32 BackPrev;     
+  UInt32 Backs[kNumRepDistances];
+  void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; }
+  void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
+  bool IsShortRep() { return (BackPrev == 0); }
+};
+
+
+// #define LZMA_LOG_BRANCH
+
+#if _MSC_VER >= 1400
+// Must give gain in core 2. but slower ~2% on k8.
+// #define LZMA_LOG_BSR
+#endif
+
+#ifndef LZMA_LOG_BSR
+static const int kNumLogBits = 13; // don't change it !
+extern Byte g_FastPos[];
+#endif
+inline UInt32 GetPosSlot(UInt32 pos)
+{
+  #ifdef LZMA_LOG_BSR
+  if (pos < 2)
+    return pos;
+  unsigned long index;
+  _BitScanReverse(&index, pos);
+  return (index + index) + ((pos >> (index - 1)) & 1);
+  #else
+  if (pos < (1 << kNumLogBits))
+    return g_FastPos[pos];
+  if (pos < (1 << (kNumLogBits * 2 - 1)))
+    return g_FastPos[pos >> (kNumLogBits - 1)] + (kNumLogBits - 1) * 2;
+  return g_FastPos[pos >> (kNumLogBits - 1) * 2] + (kNumLogBits - 1) * 4;
+  #endif
+}
+
+inline UInt32 GetPosSlot2(UInt32 pos)
+{
+  #ifdef LZMA_LOG_BSR
+  unsigned long index;
+  _BitScanReverse(&index, pos);
+  return (index + index) + ((pos >> (index - 1)) & 1);
+  #else
+  #ifdef LZMA_LOG_BRANCH
+  if (pos < (1 << (kNumLogBits + 6)))
+    return g_FastPos[pos >> 6] + 12;
+  if (pos < (1 << (kNumLogBits * 2 + 5)))
+    return g_FastPos[pos >> (kNumLogBits + 5)] + (kNumLogBits + 5) * 2;
+  return g_FastPos[pos >> (kNumLogBits * 2 + 4)] + (kNumLogBits * 2 + 4) * 2;
+  #else
+  // it's faster with VC6-32bit.
+  UInt32 s = 6 + ((kNumLogBits - 1) & (UInt32)((Int32)(((1 << (kNumLogBits + 6)) - 1) -  pos) >> 31));
+  return g_FastPos[pos >> s] + (s * 2);
+  #endif
+  #endif
+}
+
+const UInt32 kIfinityPrice = 0xFFFFFFF;
+
+const UInt32 kNumOpts = 1 << 12;
+
+
+class CLiteralEncoder2
+{
+  CMyBitEncoder _encoders[0x300];
+public:
+  void Init()
+  {
+    for (int i = 0; i < 0x300; i++)
+      _encoders[i].Init();
+  }
+  void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol);
+  void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol);
+  UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const;
+};
+
+class CLiteralEncoder
+{
+  CLiteralEncoder2 *_coders;
+  int _numPrevBits;
+  int _numPosBits;
+  UInt32 _posMask;
+public:
+  CLiteralEncoder(): _coders(0) {}
+  ~CLiteralEncoder()  { Free(); }
+  void Free()
+  { 
+    MyFree(_coders);
+    _coders = 0;
+  }
+  bool Create(int numPosBits, int numPrevBits)
+  {
+    if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits))
+    {
+      Free();
+      UInt32 numStates = 1 << (numPosBits + numPrevBits);
+      _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2));
+    }
+    _numPosBits = numPosBits;
+    _posMask = (1 << numPosBits) - 1;
+    _numPrevBits = numPrevBits;
+    return (_coders != 0);
+  }
+  void Init()
+  {
+    UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
+    for (UInt32 i = 0; i < numStates; i++)
+      _coders[i].Init();
+  }
+  CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte)
+    { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; }
+};
+
+namespace NLength {
+
+class CEncoder
+{
+  CMyBitEncoder _choice;
+  CMyBitEncoder _choice2;
+  NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax];
+  NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];
+  NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder;
+public:
+  void Init(UInt32 numPosStates);
+  void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState);
+  void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const;
+};
+
+const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;
+
+class CPriceTableEncoder: public CEncoder
+{
+  UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal];
+  UInt32 _tableSize;
+  UInt32 _counters[kNumPosStatesEncodingMax];
+public:
+  void SetTableSize(UInt32 tableSize) { _tableSize = tableSize;  }
+  UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; }
+  void UpdateTable(UInt32 posState)
+  {
+    SetPrices(posState, _tableSize, _prices[posState]);
+    _counters[posState] = _tableSize;
+  }
+  void UpdateTables(UInt32 numPosStates)
+  {
+    for (UInt32 posState = 0; posState < numPosStates; posState++)
+      UpdateTable(posState);
+  }
+  void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice)
+  {
+    CEncoder::Encode(rangeEncoder, symbol, posState);
+    if (updatePrice)
+      if (--_counters[posState] == 0)
+        UpdateTable(posState);
+  }
+};
+
+}
+
+typedef struct _CSeqInStream
+{
+  ISeqInStream SeqInStream;
+  CMyComPtr<ISequentialInStream> RealStream;
+} CSeqInStream;
+
+
+class CEncoder : 
+  public ICompressCoder,
+  public ICompressSetOutStream,
+  public ICompressSetCoderProperties,
+  public ICompressWriteCoderProperties,
+  public CBaseState,
+  public CMyUnknownImp
+{
+  NRangeCoder::CEncoder _rangeEncoder;
+
+  IMatchFinder _matchFinder;
+  void *_matchFinderObj;
+  
+  #ifdef COMPRESS_MF_MT
+  Bool _multiThread;
+  Bool _mtMode;
+  CMatchFinderMt _matchFinderMt;
+  #endif
+
+  CMatchFinder _matchFinderBase;
+  #ifdef COMPRESS_MF_MT
+  Byte _pad1[kMtCacheLineDummy];
+  #endif
+
+  COptimal _optimum[kNumOpts];
+
+  CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax];
+  CMyBitEncoder _isRep[kNumStates];
+  CMyBitEncoder _isRepG0[kNumStates];
+  CMyBitEncoder _isRepG1[kNumStates];
+  CMyBitEncoder _isRepG2[kNumStates];
+  CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax];
+
+  NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates];
+
+  CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex];
+  NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder;
+  
+  NLength::CPriceTableEncoder _lenEncoder;
+  NLength::CPriceTableEncoder _repMatchLenEncoder;
+
+  CLiteralEncoder _literalEncoder;
+
+  UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1];
+
+  bool _fastMode;
+  // bool _maxMode;
+  UInt32 _numFastBytes;
+  UInt32 _longestMatchLength;    
+  UInt32 _numDistancePairs;
+
+  UInt32 _additionalOffset;
+
+  UInt32 _optimumEndIndex;
+  UInt32 _optimumCurrentIndex;
+
+  bool _longestMatchWasFound;
+
+  UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
+  
+  UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances];
+
+  UInt32 _alignPrices[kAlignTableSize];
+  UInt32 _alignPriceCount;
+
+  UInt32 _distTableSize;
+
+  UInt32 _posStateBits;
+  UInt32 _posStateMask;
+  UInt32 _numLiteralPosStateBits;
+  UInt32 _numLiteralContextBits;
+
+  UInt32 _dictionarySize;
+
+  UInt32 _matchPriceCount;
+  UInt64 nowPos64;
+  bool _finished;
+  ISequentialInStream *_inStream;
+
+  CSeqInStream _seqInStream;
+
+  UInt32 _matchFinderCycles;
+  // int _numSkip
+
+  bool _writeEndMark;
+
+  bool _needReleaseMFStream;
+
+  void ReleaseMatchFinder()
+  {
+    _matchFinder.Init = 0;
+    _seqInStream.RealStream.Release();
+  }
+
+  void ReleaseMFStream()
+  {
+    if (_matchFinderObj && _needReleaseMFStream)
+    {
+      #ifdef COMPRESS_MF_MT
+      if (_mtMode)
+        MatchFinderMt_ReleaseStream(&_matchFinderMt);
+      #endif
+      _needReleaseMFStream = false;
+    }
+    _seqInStream.RealStream.Release();
+  }
+  
+  UInt32 ReadMatchDistances(UInt32 &numDistancePairs);
+
+  void MovePos(UInt32 num);
+  UInt32 GetRepLen1Price(CState state, UInt32 posState) const
+  {
+    return _isRepG0[state.Index].GetPrice0() +
+        _isRep0Long[state.Index][posState].GetPrice0();
+  }
+  
+  UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const
+  {
+    UInt32 price;
+    if(repIndex == 0)
+    {
+      price = _isRepG0[state.Index].GetPrice0();
+      price += _isRep0Long[state.Index][posState].GetPrice1();
+    }
+    else
+    {
+      price = _isRepG0[state.Index].GetPrice1();
+      if (repIndex == 1)
+        price += _isRepG1[state.Index].GetPrice0();
+      else
+      {
+        price += _isRepG1[state.Index].GetPrice1();
+        price += _isRepG2[state.Index].GetPrice(repIndex - 2);
+      }
+    }
+    return price;
+  }
+  UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const
+  {
+    return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) +
+        GetPureRepPrice(repIndex, state, posState);
+  }
+  /*
+  UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const
+  {
+    if (pos >= kNumFullDistances)
+      return kIfinityPrice;
+    return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState);
+  }
+  UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const
+  {
+    UInt32 price;
+    UInt32 lenToPosState = GetLenToPosState(len);
+    if (pos < kNumFullDistances)
+      price = _distancesPrices[lenToPosState][pos];
+    else
+      price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + 
+          _alignPrices[pos & kAlignMask];
+    return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
+  }
+  */
+  UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const
+  {
+    UInt32 price;
+    UInt32 lenToPosState = GetLenToPosState(len);
+    if (pos < kNumFullDistances)
+      price = _distancesPrices[lenToPosState][pos];
+    else
+      price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + 
+          _alignPrices[pos & kAlignMask];
+    return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
+  }
+
+  UInt32 Backward(UInt32 &backRes, UInt32 cur);
+  UInt32 GetOptimum(UInt32 position, UInt32 &backRes);
+  UInt32 GetOptimumFast(UInt32 &backRes);
+
+  void FillDistancesPrices();
+  void FillAlignPrices();
+    
+  void ReleaseStreams()
+  {
+    ReleaseMFStream();
+    ReleaseOutStream();
+  }
+
+  HRESULT Flush(UInt32 nowPos);
+  class CCoderReleaser
+  {
+    CEncoder *_coder;
+  public:
+    CCoderReleaser(CEncoder *coder): _coder(coder) {}
+    ~CCoderReleaser() { _coder->ReleaseStreams(); }
+  };
+  friend class CCoderReleaser;
+
+  void WriteEndMarker(UInt32 posState);
+
+public:
+  CEncoder();
+  void SetWriteEndMarkerMode(bool writeEndMarker)
+    { _writeEndMark= writeEndMarker; }
+
+  HRESULT Create();
+
+  MY_UNKNOWN_IMP3(
+      ICompressSetOutStream,
+      ICompressSetCoderProperties,
+      ICompressWriteCoderProperties
+      )
+    
+  HRESULT Init();
+  
+  // ICompressCoder interface
+  HRESULT SetStreams(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream,
+      const UInt64 *inSize, const UInt64 *outSize);
+  HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished);
+
+  HRESULT CodeReal(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, 
+      const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress);
+
+  // ICompressCoder interface
+  STDMETHOD(Code)(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, 
+      const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress);
+
+  // ICompressSetCoderProperties2
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, 
+      const PROPVARIANT *properties, UInt32 numProperties);
+  
+  // ICompressWriteCoderProperties
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+
+  STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
+  STDMETHOD(ReleaseOutStream)();
+
+  virtual ~CEncoder();
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/LZMA/LZMARegister.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA/LZMARegister.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA/LZMARegister.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,19 @@
+// LZMARegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterCodec.h"
+
+#include "LZMADecoder.h"
+static void *CreateCodec() { return (void *)(ICompressCoder *)(new NCompress::NLZMA::CDecoder); }
+#ifndef EXTRACT_ONLY
+#include "LZMAEncoder.h"
+static void *CreateCodecOut() { return (void *)(ICompressCoder *)(new NCompress::NLZMA::CEncoder);  }
+#else
+#define CreateCodecOut 0
+#endif
+
+static CCodecInfo g_CodecInfo =
+  { CreateCodec, CreateCodecOut, 0x030101, L"LZMA", 1, false };
+
+REGISTER_CODEC(LZMA)

Added: trunk/lzma/CPP/7zip/Compress/LZMA/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Compress/LZMA/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,504 @@
+# Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=AloneLZMA - Win32 DebugU
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "AloneLZMA.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application")
+!MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "AloneLZMA - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /FAcs /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "AloneLZMA - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "AloneLZMA - Win32 ReleaseU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ReleaseU"
+# PROP BASE Intermediate_Dir "ReleaseU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseU"
+# PROP Intermediate_Dir "ReleaseU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "AloneLZMA - Win32 DebugU"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "DebugU"
+# PROP BASE Intermediate_Dir "DebugU"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugU"
+# PROP Intermediate_Dir "DebugU"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /D "COMPRESS_MF_MT" /D "BENCH_MT" /Yu"StdAfx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "AloneLZMA - Win32 Release"
+# Name "AloneLZMA - Win32 Debug"
+# Name "AloneLZMA - Win32 ReleaseU"
+# Name "AloneLZMA - Win32 DebugU"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Group "LZMA"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\LZMA\LZMA.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZMA\LZMADecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZMA\LZMADecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZMA\LZMAEncoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZMA\LZMAEncoder.h
+# End Source File
+# End Group
+# Begin Group "RangeCoder"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoderBit.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoderBit.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoderBitTree.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\RangeCoder\RangeCoderOpt.h
+# End Source File
+# End Group
+# Begin Group "LZ"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\LZ\LZOutWindow.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\LZ\LZOutWindow.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Synchronization.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\System.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Thread.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CommandLineParser.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Defs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyCom.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyWindows.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringToInt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Types.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Group "C"
+
+# PROP Default_Filter ""
+# Begin Group "C-Lz"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lz\MatchFinder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lz\MatchFinderMt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Threads.h
+# End Source File
+# End Group
+# Begin Group "LZMA_C"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lzma\LzmaDecode.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lzma\LzmaDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Lzma\LzmaTypes.h
+# End Source File
+# End Group
+# Begin Group "Branch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchTypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Compress\Branch\BranchX86.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\7zCrc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Alloc.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Alloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\..\C\Types.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\ICoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaAlone.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaBench.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaBench.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaBenchCon.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaBenchCon.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaRam.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaRam.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaRamDecode.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzmaRamDecode.h
+# End Source File
+# End Target
+# End Project

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/AloneLZMA.dsw	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,554 @@
+// LzmaAlone.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/MyInitGuid.h"
+
+#include <stdio.h>
+
+#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
+#include <fcntl.h>
+#include <io.h>
+#define MY_SET_BINARY_MODE(file) _setmode(_fileno(file), O_BINARY)
+#else
+#define MY_SET_BINARY_MODE(file)
+#endif
+
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../LZMA/LZMADecoder.h"
+#include "../LZMA/LZMAEncoder.h"
+
+#include "LzmaBenchCon.h"
+#include "LzmaRam.h"
+
+#ifdef COMPRESS_MF_MT
+#include "../../../Windows/System.h"
+#endif
+
+#include "../../MyVersion.h"
+
+extern "C"
+{
+#include "LzmaRamDecode.h"
+}
+
+using namespace NCommandLineParser;
+
+#ifdef _WIN32
+bool g_IsNT = false;
+static inline bool IsItWindowsNT()
+{
+  OSVERSIONINFO versionInfo;
+  versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+  if (!::GetVersionEx(&versionInfo)) 
+    return false;
+  return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+#endif
+
+static const char *kCantAllocate = "Can not allocate memory";
+static const char *kReadError = "Read error";
+static const char *kWriteError = "Write error";
+
+namespace NKey {
+enum Enum
+{
+  kHelp1 = 0,
+  kHelp2,
+  kMode,
+  kDictionary,
+  kFastBytes,
+  kMatchFinderCycles,
+  kLitContext,
+  kLitPos,
+  kPosBits,
+  kMatchFinder,
+  kMultiThread,
+  kEOS,
+  kStdIn,
+  kStdOut,
+  kFilter86
+};
+}
+
+static const CSwitchForm kSwitchForms[] = 
+{
+  { L"?",  NSwitchType::kSimple, false },
+  { L"H",  NSwitchType::kSimple, false },
+  { L"A", NSwitchType::kUnLimitedPostString, false, 1 },
+  { L"D", NSwitchType::kUnLimitedPostString, false, 1 },
+  { L"FB", NSwitchType::kUnLimitedPostString, false, 1 },
+  { L"MC", NSwitchType::kUnLimitedPostString, false, 1 },
+  { L"LC", NSwitchType::kUnLimitedPostString, false, 1 },
+  { L"LP", NSwitchType::kUnLimitedPostString, false, 1 },
+  { L"PB", NSwitchType::kUnLimitedPostString, false, 1 },
+  { L"MF", NSwitchType::kUnLimitedPostString, false, 1 },
+  { L"MT", NSwitchType::kUnLimitedPostString, false, 0 },
+  { L"EOS", NSwitchType::kSimple, false },
+  { L"SI",  NSwitchType::kSimple, false },
+  { L"SO",  NSwitchType::kSimple, false },
+  { L"F86",  NSwitchType::kPostChar, false, 0, 0, L"+" }
+};
+
+static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]);
+
+static void PrintHelp()
+{
+  fprintf(stderr, "\nUsage:  LZMA <e|d> inputFile outputFile [<switches>...]\n"
+             "  e: encode file\n"
+             "  d: decode file\n"
+             "  b: Benchmark\n"
+    "<Switches>\n"
+    "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n"
+    "  -d{N}:  set dictionary - [0,30], default: 23 (8MB)\n"
+    "  -fb{N}: set number of fast bytes - [5, 273], default: 128\n"
+    "  -mc{N}: set number of cycles for match finder\n"
+    "  -lc{N}: set number of literal context bits - [0, 8], default: 3\n"
+    "  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n"
+    "  -pb{N}: set number of pos bits - [0, 4], default: 2\n"
+    "  -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n"
+    "  -mt{N}: set number of CPU threads\n"
+    "  -eos:   write End Of Stream marker\n"
+    "  -si:    read data from stdin\n"
+    "  -so:    write data to stdout\n"
+    );
+}
+
+static void PrintHelpAndExit(const char *s)
+{
+  fprintf(stderr, "\nError: %s\n\n", s);
+  PrintHelp();
+  throw -1;
+}
+
+static void IncorrectCommand()
+{
+  PrintHelpAndExit("Incorrect command");
+}
+
+static void WriteArgumentsToStringList(int numArguments, const char *arguments[], 
+    UStringVector &strings)
+{
+  for(int i = 1; i < numArguments; i++)
+    strings.Add(MultiByteToUnicodeString(arguments[i]));
+}
+
+static bool GetNumber(const wchar_t *s, UInt32 &value)
+{
+  value = 0;
+  if (MyStringLen(s) == 0)
+    return false;
+  const wchar_t *end;
+  UInt64 res = ConvertStringToUInt64(s, &end);
+  if (*end != L'\0')
+    return false;
+  if (res > 0xFFFFFFFF)
+    return false;
+  value = UInt32(res);
+  return true;
+}
+
+int main2(int n, const char *args[])
+{
+  #ifdef _WIN32
+  g_IsNT = IsItWindowsNT();
+  #endif
+
+  fprintf(stderr, "\nLZMA " MY_VERSION_COPYRIGHT_DATE "\n");
+
+  if (n == 1)
+  {
+    PrintHelp();
+    return 0;
+  }
+
+  bool unsupportedTypes = (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4);
+  if (unsupportedTypes)
+  {
+    fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile");
+    return 1;
+  }   
+
+  UStringVector commandStrings;
+  WriteArgumentsToStringList(n, args, commandStrings);
+  CParser parser(kNumSwitches);
+  try
+  {
+    parser.ParseStrings(kSwitchForms, commandStrings);
+  }
+  catch(...) 
+  {
+    IncorrectCommand();
+  }
+
+  if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
+  {
+    PrintHelp();
+    return 0;
+  }
+  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
+
+  int paramIndex = 0;
+  if (paramIndex >= nonSwitchStrings.Size())
+    IncorrectCommand();
+  const UString &command = nonSwitchStrings[paramIndex++]; 
+
+  bool dictionaryIsDefined = false;
+  UInt32 dictionary = (UInt32)-1;
+  if(parser[NKey::kDictionary].ThereIs)
+  {
+    UInt32 dicLog;
+    if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog))
+      IncorrectCommand();
+    dictionary = 1 << dicLog;
+    dictionaryIsDefined = true;
+  }
+  UString mf = L"BT4";
+  if (parser[NKey::kMatchFinder].ThereIs)
+    mf = parser[NKey::kMatchFinder].PostStrings[0];
+
+  UInt32 numThreads = (UInt32)-1;
+
+  #ifdef COMPRESS_MF_MT
+  if (parser[NKey::kMultiThread].ThereIs)
+  {
+    UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
+    const UString &s = parser[NKey::kMultiThread].PostStrings[0];
+    if (s.IsEmpty())
+      numThreads = numCPUs;
+    else
+      if (!GetNumber(s, numThreads))
+        IncorrectCommand();
+  }
+  #endif
+
+  if (command.CompareNoCase(L"b") == 0)
+  {
+    const UInt32 kNumDefaultItereations = 1;
+    UInt32 numIterations = kNumDefaultItereations;
+    {
+      if (paramIndex < nonSwitchStrings.Size())
+        if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations))
+          numIterations = kNumDefaultItereations;
+    }
+    return LzmaBenchCon(stderr, numIterations, numThreads, dictionary);
+  }
+
+  if (numThreads == (UInt32)-1)
+    numThreads = 1;
+
+  bool encodeMode = false;
+  if (command.CompareNoCase(L"e") == 0)
+    encodeMode = true;
+  else if (command.CompareNoCase(L"d") == 0)
+    encodeMode = false;
+  else
+    IncorrectCommand();
+
+  bool stdInMode = parser[NKey::kStdIn].ThereIs;
+  bool stdOutMode = parser[NKey::kStdOut].ThereIs;
+
+  CMyComPtr<ISequentialInStream> inStream;
+  CInFileStream *inStreamSpec = 0;
+  if (stdInMode)
+  {
+    inStream = new CStdInFileStream;
+    MY_SET_BINARY_MODE(stdin);
+  }
+  else
+  {
+    if (paramIndex >= nonSwitchStrings.Size())
+      IncorrectCommand();
+    const UString &inputName = nonSwitchStrings[paramIndex++]; 
+    inStreamSpec = new CInFileStream;
+    inStream = inStreamSpec;
+    if (!inStreamSpec->Open(GetSystemString(inputName)))
+    {
+      fprintf(stderr, "\nError: can not open input file %s\n", 
+          (const char *)GetOemString(inputName));
+      return 1;
+    }
+  }
+
+  CMyComPtr<ISequentialOutStream> outStream;
+  COutFileStream *outStreamSpec = NULL;
+  if (stdOutMode)
+  {
+    outStream = new CStdOutFileStream;
+    MY_SET_BINARY_MODE(stdout);
+  }
+  else
+  {
+    if (paramIndex >= nonSwitchStrings.Size())
+      IncorrectCommand();
+    const UString &outputName = nonSwitchStrings[paramIndex++]; 
+    outStreamSpec = new COutFileStream;
+    outStream = outStreamSpec;
+    if (!outStreamSpec->Create(GetSystemString(outputName), true))
+    {
+      fprintf(stderr, "\nError: can not open output file %s\n", 
+        (const char *)GetOemString(outputName));
+      return 1;
+    }
+  }
+
+  if (parser[NKey::kFilter86].ThereIs)
+  {
+    // -f86 switch is for x86 filtered mode: BCJ + LZMA.
+    if (parser[NKey::kEOS].ThereIs || stdInMode)
+      throw "Can not use stdin in this mode";
+    UInt64 fileSize;
+    inStreamSpec->File.GetLength(fileSize);
+    if (fileSize > 0xF0000000)
+      throw "File is too big";
+    UInt32 inSize = (UInt32)fileSize;
+    Byte *inBuffer = 0;
+    if (inSize != 0)
+    {
+      inBuffer = (Byte *)MyAlloc((size_t)inSize); 
+      if (inBuffer == 0)
+        throw kCantAllocate;
+    }
+    
+    UInt32 processedSize;
+    if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK)
+      throw "Can not read";
+    if ((UInt32)inSize != processedSize)
+      throw "Read size error";
+
+    Byte *outBuffer = 0;
+    size_t outSizeProcessed;
+    if (encodeMode)
+    {
+      // we allocate 105% of original size for output buffer
+      size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16);
+      if (outSize != 0)
+      {
+        outBuffer = (Byte *)MyAlloc((size_t)outSize); 
+        if (outBuffer == 0)
+          throw kCantAllocate;
+      }
+      if (!dictionaryIsDefined)
+        dictionary = 1 << 23;
+      int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, 
+          dictionary, parser[NKey::kFilter86].PostCharIndex == 0 ? SZ_FILTER_YES : SZ_FILTER_AUTO);
+      if (res != 0)
+      {
+        fprintf(stderr, "\nEncoder error = %d\n", (int)res);
+        return 1;
+      }
+    }
+    else
+    {
+      size_t outSize;
+      if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0)
+        throw "data error";
+      if (outSize != 0)
+      {
+        outBuffer = (Byte *)MyAlloc(outSize); 
+        if (outBuffer == 0)
+          throw kCantAllocate;
+      }
+      int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free);
+      if (res != 0)
+        throw "LzmaDecoder error";
+    }
+    if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK)
+      throw kWriteError;
+    MyFree(outBuffer);
+    MyFree(inBuffer);
+    return 0;
+  }
+
+
+  UInt64 fileSize;
+  if (encodeMode)
+  {
+    NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
+    CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+    if (!dictionaryIsDefined)
+      dictionary = 1 << 23;
+
+    UInt32 posStateBits = 2;
+    UInt32 litContextBits = 3; // for normal files
+    // UInt32 litContextBits = 0; // for 32-bit data
+    UInt32 litPosBits = 0;
+    // UInt32 litPosBits = 2; // for 32-bit data
+    UInt32 algorithm = 1;
+    UInt32 numFastBytes = 128;
+    UInt32 matchFinderCycles = 16 + numFastBytes / 2;
+    bool matchFinderCyclesDefined = false;
+
+    bool eos = parser[NKey::kEOS].ThereIs || stdInMode;
+ 
+    if(parser[NKey::kMode].ThereIs)
+      if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm))
+        IncorrectCommand();
+
+    if(parser[NKey::kFastBytes].ThereIs)
+      if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes))
+        IncorrectCommand();
+    matchFinderCyclesDefined = parser[NKey::kMatchFinderCycles].ThereIs;
+    if (matchFinderCyclesDefined)
+      if (!GetNumber(parser[NKey::kMatchFinderCycles].PostStrings[0], matchFinderCycles))
+        IncorrectCommand();
+    if(parser[NKey::kLitContext].ThereIs)
+      if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits))
+        IncorrectCommand();
+    if(parser[NKey::kLitPos].ThereIs)
+      if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits))
+        IncorrectCommand();
+    if(parser[NKey::kPosBits].ThereIs)
+      if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits))
+        IncorrectCommand();
+
+    PROPID propIDs[] = 
+    {
+      NCoderPropID::kDictionarySize,
+      NCoderPropID::kPosStateBits,
+      NCoderPropID::kLitContextBits,
+      NCoderPropID::kLitPosBits,
+      NCoderPropID::kAlgorithm,
+      NCoderPropID::kNumFastBytes,
+      NCoderPropID::kMatchFinder,
+      NCoderPropID::kEndMarker,
+      NCoderPropID::kNumThreads,
+      NCoderPropID::kMatchFinderCycles,
+    };
+    const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]);
+
+    PROPVARIANT properties[kNumPropsMax];
+    for (int p = 0; p < 6; p++)
+      properties[p].vt = VT_UI4;
+
+    properties[0].ulVal = (UInt32)dictionary;
+    properties[1].ulVal = (UInt32)posStateBits;
+    properties[2].ulVal = (UInt32)litContextBits;
+    properties[3].ulVal = (UInt32)litPosBits;
+    properties[4].ulVal = (UInt32)algorithm;
+    properties[5].ulVal = (UInt32)numFastBytes;
+
+    properties[6].vt = VT_BSTR;
+    properties[6].bstrVal = (BSTR)(const wchar_t *)mf;
+
+    properties[7].vt = VT_BOOL;
+    properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE;
+
+    properties[8].vt = VT_UI4;
+    properties[8].ulVal = (UInt32)numThreads;
+
+    // it must be last in property list
+    properties[9].vt = VT_UI4;
+    properties[9].ulVal = (UInt32)matchFinderCycles;
+
+    int numProps = kNumPropsMax;
+    if (!matchFinderCyclesDefined)
+      numProps--;
+
+    if (encoderSpec->SetCoderProperties(propIDs, properties, numProps) != S_OK)
+      IncorrectCommand();
+    encoderSpec->WriteCoderProperties(outStream);
+
+    if (eos || stdInMode)
+      fileSize = (UInt64)(Int64)-1;
+    else
+      inStreamSpec->File.GetLength(fileSize);
+
+    for (int i = 0; i < 8; i++)
+    {
+      Byte b = Byte(fileSize >> (8 * i));
+      if (outStream->Write(&b, 1, 0) != S_OK)
+      {
+        fprintf(stderr, kWriteError);
+        return 1;
+      }
+    }
+    HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
+    if (result == E_OUTOFMEMORY)
+    {
+      fprintf(stderr, "\nError: Can not allocate memory\n");
+      return 1;
+    }   
+    else if (result != S_OK)
+    {
+      fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result);
+      return 1;
+    }   
+  }
+  else
+  {
+    NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder;
+    CMyComPtr<ICompressCoder> decoder = decoderSpec;
+    const UInt32 kPropertiesSize = 5;
+    Byte properties[kPropertiesSize];
+    UInt32 processedSize;
+    if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK)
+    {
+      fprintf(stderr, kReadError);
+      return 1;
+    }
+    if (processedSize != kPropertiesSize)
+    {
+      fprintf(stderr, kReadError);
+      return 1;
+    }
+    if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK)
+    {
+      fprintf(stderr, "SetDecoderProperties error");
+      return 1;
+    }
+    fileSize = 0;
+    for (int i = 0; i < 8; i++)
+    {
+      Byte b;
+      if (inStream->Read(&b, 1, &processedSize) != S_OK)
+      {
+        fprintf(stderr, kReadError);
+        return 1;
+      }
+      if (processedSize != 1)
+      {
+        fprintf(stderr, kReadError);
+        return 1;
+      }
+      fileSize |= ((UInt64)b) << (8 * i);
+    }
+    if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK)
+    {
+      fprintf(stderr, "Decoder error");
+      return 1;
+    }   
+  }
+  if (outStreamSpec != NULL)
+  {
+    if (outStreamSpec->Close() != S_OK)
+    {
+      fprintf(stderr, "File closing error");
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int main(int n, const char *args[])
+{
+  try { return main2(n, args); }
+  catch(const char *s) 
+  { 
+    fprintf(stderr, "\nError: %s\n", s);
+    return 1; 
+  }
+  catch(...) 
+  { 
+    fprintf(stderr, "\nError\n");
+    return 1; 
+  }
+}

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1024 @@
+// LzmaBench.cpp
+
+#include "StdAfx.h"
+
+#include "LzmaBench.h"
+
+#ifndef _WIN32
+#define USE_POSIX_TIME
+#define USE_POSIX_TIME2
+#endif
+
+#ifdef USE_POSIX_TIME
+#include <time.h>
+#ifdef USE_POSIX_TIME2
+#include <sys/time.h>
+#endif
+#endif
+
+#ifdef _WIN32
+#define USE_ALLOCA
+#endif
+
+#ifdef USE_ALLOCA
+#ifdef _WIN32
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+
+extern "C" 
+{ 
+#include "../../../../C/Alloc.h"
+#include "../../../../C/7zCrc.h"
+}
+#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+
+#ifdef BENCH_MT
+#include "../../../Windows/Thread.h"
+#include "../../../Windows/Synchronization.h"
+#endif
+
+#ifdef EXTERNAL_LZMA
+#include "../../../Windows/PropVariant.h"
+#else
+#include "../LZMA/LZMADecoder.h"
+#include "../LZMA/LZMAEncoder.h"
+#endif
+
+static const UInt32 kUncompressMinBlockSize = 1 << 26;
+static const UInt32 kAdditionalSize = (1 << 16);
+static const UInt32 kCompressedAdditionalSize = (1 << 10);
+static const UInt32 kMaxLzmaPropSize = 5;
+
+class CBaseRandomGenerator
+{
+  UInt32 A1;
+  UInt32 A2;
+public:
+  CBaseRandomGenerator() { Init(); }
+  void Init() { A1 = 362436069; A2 = 521288629;}
+  UInt32 GetRnd() 
+  {
+    return 
+      ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) +
+      ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );
+  }
+};
+
+class CBenchBuffer
+{
+public:
+  size_t BufferSize;
+  Byte *Buffer;
+  CBenchBuffer(): Buffer(0) {} 
+  virtual ~CBenchBuffer() { Free(); }
+  void Free() 
+  { 
+    ::MidFree(Buffer);
+    Buffer = 0;
+  }
+  bool Alloc(size_t bufferSize) 
+  {
+    if (Buffer != 0 && BufferSize == bufferSize)
+      return true;
+    Free();
+    Buffer = (Byte *)::MidAlloc(bufferSize);
+    BufferSize = bufferSize;
+    return (Buffer != 0);
+  }
+};
+
+class CBenchRandomGenerator: public CBenchBuffer
+{
+  CBaseRandomGenerator *RG;
+public:
+  void Set(CBaseRandomGenerator *rg) { RG = rg; }
+  UInt32 GetVal(UInt32 &res, int numBits) 
+  {
+    UInt32 val = res & (((UInt32)1 << numBits) - 1);
+    res >>= numBits;
+    return val;
+  }
+  UInt32 GetLen(UInt32 &res) 
+  { 
+    UInt32 len = GetVal(res, 2);
+    return GetVal(res, 1 + len);
+  }
+  void Generate()
+  {
+    UInt32 pos = 0;
+    UInt32 rep0 = 1;
+    while (pos < BufferSize)
+    {
+      UInt32 res = RG->GetRnd();
+      res >>= 1;
+      if (GetVal(res, 1) == 0 || pos < 1024)
+        Buffer[pos++] = (Byte)(res & 0xFF);
+      else
+      {
+        UInt32 len;
+        len = 1 + GetLen(res);
+        if (GetVal(res, 3) != 0)
+        {
+          len += GetLen(res);
+          do
+          {
+            UInt32 ppp = GetVal(res, 5) + 6;
+            res = RG->GetRnd();
+            if (ppp > 30)
+              continue;
+            rep0 = /* (1 << ppp) +*/  GetVal(res, ppp);
+            res = RG->GetRnd();
+          }
+          while (rep0 >= pos);
+          rep0++;
+        }
+
+        for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++)
+          Buffer[pos] = Buffer[pos - rep0];
+      }
+    }
+  }
+};
+
+
+class CBenchmarkInStream: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+  const Byte *Data;
+  size_t Pos;
+  size_t Size;
+public:
+  MY_UNKNOWN_IMP
+  void Init(const Byte *data, size_t size)
+  {
+    Data = data;
+    Size = size;
+    Pos = 0;
+  }
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  size_t remain = Size - Pos;
+  UInt32 kMaxBlockSize = (1 << 20);
+  if (size > kMaxBlockSize)
+    size = kMaxBlockSize;
+  if (size > remain)
+    size = (UInt32)remain;
+  for (UInt32 i = 0; i < size; i++)
+    ((Byte *)data)[i] = Data[Pos + i];
+  Pos += size;
+  if(processedSize != NULL)
+    *processedSize = size;
+  return S_OK;
+}
+  
+class CBenchmarkOutStream: 
+  public ISequentialOutStream,
+  public CBenchBuffer,
+  public CMyUnknownImp
+{
+  // bool _overflow;
+public:
+  UInt32 Pos;
+  // CBenchmarkOutStream(): _overflow(false) {} 
+  void Init() 
+  {
+    // _overflow = false;
+    Pos = 0;
+  }
+  MY_UNKNOWN_IMP
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  size_t curSize = BufferSize - Pos;
+  if (curSize > size)
+    curSize = size;
+  memcpy(Buffer + Pos, data, curSize);
+  Pos += (UInt32)curSize;
+  if(processedSize != NULL)
+    *processedSize = (UInt32)curSize;
+  if (curSize != size)
+  {
+    // _overflow = true;
+    return E_FAIL;
+  }
+  return S_OK;
+}
+  
+class CCrcOutStream: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+public:
+  UInt32 Crc;
+  MY_UNKNOWN_IMP
+  void Init() { Crc = CRC_INIT_VAL; }
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  Crc = CrcUpdate(Crc, data, size);
+  if (processedSize != NULL)
+    *processedSize = size;
+  return S_OK;
+}
+  
+static UInt64 GetTimeCount()
+{
+  #ifdef USE_POSIX_TIME
+  #ifdef USE_POSIX_TIME2
+  timeval v;
+  if (gettimeofday(&v, 0) == 0)
+    return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec;
+  return (UInt64)time(NULL) * 1000000;
+  #else
+  return time(NULL);
+  #endif
+  #else
+  /*
+  LARGE_INTEGER value;
+  if (::QueryPerformanceCounter(&value))
+    return value.QuadPart;
+  */
+  return GetTickCount();
+  #endif 
+}
+
+static UInt64 GetFreq()
+{
+  #ifdef USE_POSIX_TIME
+  #ifdef USE_POSIX_TIME2
+  return 1000000;
+  #else
+  return 1;
+  #endif 
+  #else
+  /*
+  LARGE_INTEGER value;
+  if (::QueryPerformanceFrequency(&value))
+    return value.QuadPart;
+  */
+  return 1000;
+  #endif 
+}
+
+#ifndef USE_POSIX_TIME
+static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }
+#endif
+static UInt64 GetUserTime()
+{
+  #ifdef USE_POSIX_TIME
+  return clock();
+  #else
+  FILETIME creationTime, exitTime, kernelTime, userTime;
+  if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0)
+    return GetTime64(userTime) + GetTime64(kernelTime);
+  return (UInt64)GetTickCount() * 10000;
+  #endif 
+}
+
+static UInt64 GetUserFreq()
+{
+  #ifdef USE_POSIX_TIME
+  return CLOCKS_PER_SEC;
+  #else
+  return 10000000;
+  #endif 
+}
+
+class CBenchProgressStatus
+{
+  #ifdef BENCH_MT
+  NWindows::NSynchronization::CCriticalSection CS;  
+  #endif
+public:
+  HRESULT Res;
+  bool EncodeMode;
+  void SetResult(HRESULT res) 
+  {
+    #ifdef BENCH_MT
+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);
+    #endif
+    Res = res;
+  }
+  HRESULT GetResult()
+  {
+    #ifdef BENCH_MT
+    NWindows::NSynchronization::CCriticalSectionLock lock(CS);
+    #endif
+    return Res;
+  }
+};
+
+class CBenchProgressInfo:
+  public ICompressProgressInfo,
+  public CMyUnknownImp
+{
+public:
+  CBenchProgressStatus *Status;
+  CBenchInfo BenchInfo;
+  HRESULT Res;
+  IBenchCallback *callback;
+  CBenchProgressInfo(): callback(0) {}
+  MY_UNKNOWN_IMP
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+void SetStartTime(CBenchInfo &bi)
+{
+  bi.GlobalFreq = GetFreq();
+  bi.UserFreq = GetUserFreq();
+  bi.GlobalTime = ::GetTimeCount();
+  bi.UserTime = ::GetUserTime();
+}
+
+void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest)
+{
+  dest.GlobalFreq = GetFreq();
+  dest.UserFreq = GetUserFreq();
+  dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime;
+  dest.UserTime = ::GetUserTime() - biStart.UserTime;
+}
+
+STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+  HRESULT res = Status->GetResult();
+  if (res != S_OK)
+    return res;
+  if (!callback)
+    return res;
+  CBenchInfo info = BenchInfo;
+  SetFinishTime(BenchInfo, info);
+  if (Status->EncodeMode)
+  {
+    info.UnpackSize = *inSize;
+    info.PackSize = *outSize;
+    res = callback->SetEncodeResult(info, false);
+  }
+  else
+  {
+    info.PackSize = BenchInfo.PackSize + *inSize;
+    info.UnpackSize = BenchInfo.UnpackSize + *outSize;
+    res = callback->SetDecodeResult(info, false);
+  }
+  if (res != S_OK)
+    Status->SetResult(res);
+  return res;
+}
+
+static const int kSubBits = 8;
+
+static UInt32 GetLogSize(UInt32 size)
+{
+  for (int i = kSubBits; i < 32; i++)
+    for (UInt32 j = 0; j < (1 << kSubBits); j++)
+      if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
+        return (i << kSubBits) + j;
+  return (32 << kSubBits);
+}
+
+static void NormalizeVals(UInt64 &v1, UInt64 &v2)
+{
+  while (v1 > 1000000)
+  {
+    v1 >>= 1;
+    v2 >>= 1;
+  }
+}
+
+UInt64 GetUsage(const CBenchInfo &info)
+{
+  UInt64 userTime = info.UserTime;
+  UInt64 userFreq = info.UserFreq;
+  UInt64 globalTime = info.GlobalTime;
+  UInt64 globalFreq = info.GlobalFreq;
+  NormalizeVals(userTime, userFreq);
+  NormalizeVals(globalFreq, globalTime);
+  if (userFreq == 0)
+    userFreq = 1;
+  if (globalTime == 0)
+    globalTime = 1;
+  return userTime * globalFreq * 1000000 / userFreq / globalTime;
+}
+
+UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating)
+{
+  UInt64 userTime = info.UserTime;
+  UInt64 userFreq = info.UserFreq;
+  UInt64 globalTime = info.GlobalTime;
+  UInt64 globalFreq = info.GlobalFreq;
+  NormalizeVals(userFreq, userTime);
+  NormalizeVals(globalTime, globalFreq);
+  if (globalFreq == 0)
+    globalFreq = 1;
+  if (userTime == 0)
+    userTime = 1;
+  return userFreq * globalTime / globalFreq *  rating / userTime;
+}
+
+static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
+{
+  UInt64 elTime = elapsedTime;
+  NormalizeVals(freq, elTime);
+  if (elTime == 0)
+    elTime = 1;
+  return value * freq / elTime;
+}
+
+UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size)
+{
+  UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits);
+  // UInt64 numCommandsForOne = 1000 + ((t * t * 7) >> (2 * kSubBits)); // AMD K8
+  UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); // Intel Core2
+
+  UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
+  return MyMultDiv64(numCommands, elapsedTime, freq);
+}
+
+UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations)
+{
+  // UInt64 numCommands = (inSize * 216 + outSize * 14) * numIterations; // AMD K8
+  UInt64 numCommands = (inSize * 220 + outSize * 8) * numIterations; // Intel Core2
+  return MyMultDiv64(numCommands, elapsedTime, freq);
+}
+
+#ifdef EXTERNAL_LZMA
+typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, 
+    const GUID *interfaceID, void **outObject);
+#endif
+
+struct CEncoderInfo;
+
+struct CEncoderInfo
+{
+  #ifdef BENCH_MT
+  NWindows::CThread thread[2];
+  #endif
+  CMyComPtr<ICompressCoder> encoder;
+  CBenchProgressInfo *progressInfoSpec[2];
+  CMyComPtr<ICompressProgressInfo> progressInfo[2];
+  UInt32 NumIterations;
+  #ifdef USE_ALLOCA
+  size_t AllocaSize;
+  #endif
+
+  struct CDecoderInfo
+  {
+    CEncoderInfo *Encoder;
+    UInt32 DecoderIndex;
+    #ifdef USE_ALLOCA
+    size_t AllocaSize;
+    #endif
+    bool CallbackMode;
+  };
+  CDecoderInfo decodersInfo[2];
+
+  CMyComPtr<ICompressCoder> decoders[2];
+  HRESULT Results[2];
+  CBenchmarkOutStream *outStreamSpec;
+  CMyComPtr<ISequentialOutStream> outStream;
+  IBenchCallback *callback;
+  UInt32 crc;
+  UInt32 kBufferSize;
+  UInt32 compressedSize;
+  CBenchRandomGenerator rg;
+  CBenchmarkOutStream *propStreamSpec;
+  CMyComPtr<ISequentialOutStream> propStream;
+  HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg);
+  HRESULT Encode();
+  HRESULT Decode(UInt32 decoderIndex);
+
+  CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {}
+
+  #ifdef BENCH_MT
+  static THREAD_FUNC_DECL EncodeThreadFunction(void *param)
+  {
+    CEncoderInfo *encoder = (CEncoderInfo *)param;
+    #ifdef USE_ALLOCA
+    alloca(encoder->AllocaSize);
+    #endif
+    HRESULT res = encoder->Encode();
+    encoder->Results[0] = res;
+    if (res != S_OK)
+      encoder->progressInfoSpec[0]->Status->SetResult(res);
+
+    return 0;
+  }
+  static THREAD_FUNC_DECL DecodeThreadFunction(void *param)
+  {
+    CDecoderInfo *decoder = (CDecoderInfo *)param;
+    #ifdef USE_ALLOCA
+    alloca(decoder->AllocaSize);
+    #endif
+    CEncoderInfo *encoder = decoder->Encoder;
+    encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex);
+    return 0;
+  }
+
+  HRESULT CreateEncoderThread()
+  {
+    return thread[0].Create(EncodeThreadFunction, this);
+  }
+
+  HRESULT CreateDecoderThread(int index, bool callbackMode
+      #ifdef USE_ALLOCA
+      , size_t allocaSize
+      #endif
+      )
+  {
+    CDecoderInfo &decoder = decodersInfo[index];
+    decoder.DecoderIndex = index;
+    decoder.Encoder = this;
+    #ifdef USE_ALLOCA
+    decoder.AllocaSize = allocaSize;
+    #endif
+    decoder.CallbackMode = callbackMode;
+    return thread[index].Create(DecodeThreadFunction, &decoder);
+  }
+  #endif
+};
+
+HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc)
+{
+  rg.Set(rgLoc);
+  kBufferSize = dictionarySize + kAdditionalSize;
+  UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
+  if (!rg.Alloc(kBufferSize))
+    return E_OUTOFMEMORY;
+  rg.Generate();
+  crc = CrcCalc(rg.Buffer, rg.BufferSize);
+
+  outStreamSpec = new CBenchmarkOutStream;
+  if (!outStreamSpec->Alloc(kCompressedBufferSize))
+    return E_OUTOFMEMORY;
+
+  outStream = outStreamSpec;
+
+  propStreamSpec = 0;
+  if (!propStream)
+  {
+    propStreamSpec = new CBenchmarkOutStream;
+    propStream = propStreamSpec;
+  }
+  if (!propStreamSpec->Alloc(kMaxLzmaPropSize))
+    return E_OUTOFMEMORY;
+  propStreamSpec->Init();
+  
+  PROPID propIDs[] = 
+  { 
+    NCoderPropID::kDictionarySize, 
+    NCoderPropID::kMultiThread
+  };
+  const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
+  PROPVARIANT properties[kNumProps];
+  properties[0].vt = VT_UI4;
+  properties[0].ulVal = (UInt32)dictionarySize;
+
+  properties[1].vt = VT_BOOL;
+  properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE;
+
+  {
+    CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
+    RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));
+    if (!setCoderProperties)
+      return E_FAIL;
+    RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps));
+
+    CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
+    encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties);
+    if (writeCoderProperties)
+    {
+      RINOK(writeCoderProperties->WriteCoderProperties(propStream));
+    }
+  }
+  return S_OK;
+}
+
+HRESULT CEncoderInfo::Encode()
+{
+  CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
+  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+  inStreamSpec->Init(rg.Buffer, rg.BufferSize);
+  outStreamSpec->Init();
+
+  RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));
+  compressedSize = outStreamSpec->Pos;
+  encoder.Release();
+  return S_OK;
+}
+
+HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)
+{
+  CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
+  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+  CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex];
+
+  CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
+  decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties);
+  if (!compressSetDecoderProperties)
+    return E_FAIL;
+
+  CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;
+  CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;
+    
+  CBenchProgressInfo *pi = progressInfoSpec[decoderIndex];
+  pi->BenchInfo.UnpackSize = 0;
+  pi->BenchInfo.PackSize = 0;
+
+  for (UInt32 j = 0; j < NumIterations; j++)
+  {
+    inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
+    crcOutStreamSpec->Init();
+    
+    RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));
+    UInt64 outSize = kBufferSize;
+    RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));
+    if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)
+      return S_FALSE;
+    pi->BenchInfo.UnpackSize += kBufferSize;
+    pi->BenchInfo.PackSize += compressedSize;
+  }
+  decoder.Release();
+  return S_OK;
+}
+
+static const UInt32 kNumThreadsMax = (1 << 16);
+
+struct CBenchEncoders
+{
+  CEncoderInfo *encoders;
+  CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; }
+  ~CBenchEncoders() { delete []encoders; }
+};
+
+HRESULT LzmaBench(
+  #ifdef EXTERNAL_LZMA
+  CCodecs *codecs,
+  #endif
+  UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback)
+{
+  UInt32 numEncoderThreads = 
+    #ifdef BENCH_MT
+    (numThreads > 1 ? numThreads / 2 : 1);
+    #else
+    1;
+    #endif
+  UInt32 numSubDecoderThreads = 
+    #ifdef BENCH_MT
+    (numThreads > 1 ? 2 : 1);
+    #else
+    1;
+    #endif
+  if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax)
+  {
+    return E_INVALIDARG;
+  }
+
+  CBenchEncoders encodersSpec(numEncoderThreads);
+  CEncoderInfo *encoders = encodersSpec.encoders;
+
+  #ifdef EXTERNAL_LZMA
+  UString name = L"LZMA";
+  #endif
+
+  UInt32 i;
+  for (i = 0; i < numEncoderThreads; i++)
+  {
+    CEncoderInfo &encoder = encoders[i];
+    encoder.callback = (i == 0) ? callback : 0;
+
+    #ifdef EXTERNAL_LZMA
+    RINOK(codecs->CreateCoder(name, true, encoder.encoder));
+    #else
+    encoder.encoder = new NCompress::NLZMA::CEncoder;
+    #endif
+    for (UInt32 j = 0; j < numSubDecoderThreads; j++)
+    {
+      #ifdef EXTERNAL_LZMA
+      RINOK(codecs->CreateCoder(name, false, encoder.decoders[j]));
+      #else
+      encoder.decoders[j] = new NCompress::NLZMA::CDecoder;
+      #endif
+    }
+  }
+
+  CBaseRandomGenerator rg;
+  rg.Init();
+  for (i = 0; i < numEncoderThreads; i++)
+  {
+    RINOK(encoders[i].Init(dictionarySize, numThreads, &rg));
+  }
+
+  CBenchProgressStatus status;
+  status.Res = S_OK;
+  status.EncodeMode = true;
+
+  for (i = 0; i < numEncoderThreads; i++)
+  {
+    CEncoderInfo &encoder = encoders[i];
+    for (int j = 0; j < 2; j++)
+    {
+      encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo;
+      encoder.progressInfoSpec[j]->Status = &status;
+    }
+    if (i == 0)
+    {
+      encoder.progressInfoSpec[0]->callback = callback;
+      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads;
+      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);
+    }
+
+    #ifdef BENCH_MT
+    if (numEncoderThreads > 1)
+    {
+      #ifdef USE_ALLOCA
+      encoder.AllocaSize = (i * 16 * 21) & 0x7FF;
+      #endif
+      RINOK(encoder.CreateEncoderThread())
+    }
+    else
+    #endif
+    {
+      RINOK(encoder.Encode());
+    }
+  }
+  #ifdef BENCH_MT
+  if (numEncoderThreads > 1)
+    for (i = 0; i < numEncoderThreads; i++)
+      encoders[i].thread[0].Wait();
+  #endif
+
+  RINOK(status.Res);
+
+  CBenchInfo info;
+
+  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);
+  info.UnpackSize = 0;
+  info.PackSize = 0;
+  info.NumIterations = 1; // progressInfoSpec->NumIterations;
+  for (i = 0; i < numEncoderThreads; i++)
+  {
+    CEncoderInfo &encoder = encoders[i];
+    info.UnpackSize += encoder.kBufferSize;
+    info.PackSize += encoder.compressedSize;
+  }
+  RINOK(callback->SetEncodeResult(info, true));
+
+
+  status.Res = S_OK;
+  status.EncodeMode = false;
+
+  UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads;
+  for (i = 0; i < numEncoderThreads; i++)
+  {
+    CEncoderInfo &encoder = encoders[i];
+    encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize;
+
+    if (i == 0)
+    {
+      encoder.progressInfoSpec[0]->callback = callback;
+      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads;
+      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);
+    }
+
+    #ifdef BENCH_MT
+    if (numDecoderThreads > 1)
+    {
+      for (UInt32 j = 0; j < numSubDecoderThreads; j++)
+      {
+        size_t allocaSize = ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF;
+        HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0)
+            #ifdef USE_ALLOCA
+            , allocaSize
+            #endif
+            );
+        RINOK(res);
+      }
+    }
+    else
+    #endif
+    {
+      RINOK(encoder.Decode(0));
+    }
+  }
+  #ifdef BENCH_MT
+  HRESULT res = S_OK;
+  if (numDecoderThreads > 1)
+    for (i = 0; i < numEncoderThreads; i++)
+      for (UInt32 j = 0; j < numSubDecoderThreads; j++)
+      {
+        CEncoderInfo &encoder = encoders[i];
+        encoder.thread[j].Wait();
+        if (encoder.Results[j] != S_OK)
+          res = encoder.Results[j];
+      }
+  RINOK(res);
+  #endif
+  RINOK(status.Res);
+  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);
+  info.UnpackSize = 0;
+  info.PackSize = 0;
+  info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations;
+  for (i = 0; i < numEncoderThreads; i++)
+  {
+    CEncoderInfo &encoder = encoders[i];
+    info.UnpackSize += encoder.kBufferSize;
+    info.PackSize += encoder.compressedSize;
+  }
+  RINOK(callback->SetDecodeResult(info, false));
+  RINOK(callback->SetDecodeResult(info, true));
+  return S_OK;
+}
+
+
+inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary)
+{ 
+  UInt32 hs = dictionary - 1;
+  hs |= (hs >> 1);
+  hs |= (hs >> 2);
+  hs |= (hs >> 4);
+  hs |= (hs >> 8);
+  hs >>= 1;
+  hs |= 0xFFFF;
+  if (hs > (1 << 24))
+    hs >>= 1;
+  hs++;
+  return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 + 
+      (1 << 20) + (multiThread ? (6 << 20) : 0);
+}
+
+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary)
+{
+  const UInt32 kBufferSize = dictionary;
+  const UInt32 kCompressedBufferSize = (kBufferSize / 2);
+  UInt32 numSubThreads = (numThreads > 1) ? 2 : 1;
+  UInt32 numBigThreads = numThreads / numSubThreads;
+  return (kBufferSize + kCompressedBufferSize +
+    GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads;
+}
+
+static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase)
+{
+  for (UInt32 i = 0; i < numCycles; i++)
+    if (CrcCalc(data, size) != crcBase)
+      return false;
+  return true;
+}
+
+#ifdef BENCH_MT
+struct CCrcInfo
+{
+  NWindows::CThread Thread;
+  const Byte *Data;
+  UInt32 Size;
+  UInt32 NumCycles;
+  UInt32 Crc;
+  bool Res;
+  void Wait()
+  {
+    Thread.Wait();
+    Thread.Close();
+  }
+};
+
+static THREAD_FUNC_DECL CrcThreadFunction(void *param)
+{
+  CCrcInfo *p = (CCrcInfo *)param;
+  p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc);
+  return 0;
+}
+
+struct CCrcThreads
+{
+  UInt32 NumThreads;
+  CCrcInfo *Items;
+  CCrcThreads(): Items(0), NumThreads(0) {}
+  void WaitAll()
+  {
+    for (UInt32 i = 0; i < NumThreads; i++)
+      Items[i].Wait();
+    NumThreads = 0;
+  }
+  ~CCrcThreads() 
+  { 
+    WaitAll();
+    delete []Items; 
+  }
+};
+#endif
+
+static UInt32 CrcCalc1(const Byte *buf, UInt32 size)
+{
+  UInt32 crc = CRC_INIT_VAL;;
+  for (UInt32 i = 0; i < size; i++)
+    crc = CRC_UPDATE_BYTE(crc, buf[i]);
+  return CRC_GET_DIGEST(crc);
+}
+
+static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
+{
+  for (UInt32 i = 0; i < size; i++)
+    buf[i] = (Byte)RG.GetRnd();
+}
+
+static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
+{
+  RandGen(buf, size, RG);
+  return CrcCalc1(buf, size);
+}
+
+bool CrcInternalTest()
+{
+  CBenchBuffer buffer;
+  const UInt32 kBufferSize0 = (1 << 8);
+  const UInt32 kBufferSize1 = (1 << 10);
+  const UInt32 kCheckSize = (1 << 5);
+  if (!buffer.Alloc(kBufferSize0 + kBufferSize1))
+    return false;
+  Byte *buf = buffer.Buffer;
+  UInt32 i;
+  for (i = 0; i < kBufferSize0; i++)
+    buf[i] = (Byte)i;
+  UInt32 crc1 = CrcCalc1(buf, kBufferSize0);
+  if (crc1 != 0x29058C73)
+    return false;
+  CBaseRandomGenerator RG;
+  RandGen(buf + kBufferSize0, kBufferSize1, RG);
+  for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++)
+    for (UInt32 j = 0; j < kCheckSize; j++)
+      if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j))
+        return false;
+  return true;
+}
+
+HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed)
+{
+  if (numThreads == 0)
+    numThreads = 1;
+
+  CBenchBuffer buffer;
+  size_t totalSize = (size_t)bufferSize * numThreads;
+  if (totalSize / numThreads != bufferSize)
+    return E_OUTOFMEMORY;
+  if (!buffer.Alloc(totalSize))
+    return E_OUTOFMEMORY;
+
+  Byte *buf = buffer.Buffer;
+  CBaseRandomGenerator RG;
+  UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1;
+
+  UInt64 timeVal;
+  #ifdef BENCH_MT
+  CCrcThreads threads;
+  if (numThreads > 1)
+  {
+    threads.Items = new CCrcInfo[numThreads];
+    UInt32 i;
+    for (i = 0; i < numThreads; i++)
+    {
+      CCrcInfo &info = threads.Items[i];
+      Byte *data = buf + (size_t)bufferSize * i;
+      info.Data = data;
+      info.NumCycles = numCycles;
+      info.Size = bufferSize;
+      info.Crc = RandGenCrc(data, bufferSize, RG);
+    }
+    timeVal = GetTimeCount();
+    for (i = 0; i < numThreads; i++)
+    {
+      CCrcInfo &info = threads.Items[i];
+      RINOK(info.Thread.Create(CrcThreadFunction, &info));
+      threads.NumThreads++;
+    }
+    threads.WaitAll();
+    for (i = 0; i < numThreads; i++)
+      if (!threads.Items[i].Res)
+        return S_FALSE;
+  }
+  else
+  #endif
+  {
+    UInt32 crc = RandGenCrc(buf, bufferSize, RG);
+    timeVal = GetTimeCount();
+    if (!CrcBig(buf, bufferSize, numCycles, crc))
+      return S_FALSE;
+  }
+  timeVal = GetTimeCount() - timeVal;
+  if (timeVal == 0)
+    timeVal = 1;
+
+  UInt64 size = (UInt64)numCycles * totalSize;
+  speed = MyMultDiv64(size, timeVal, GetFreq());
+  return S_OK;
+}
+

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBench.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,48 @@
+// LzmaBench.h
+
+#ifndef __LZMABENCH_H
+#define __LZMABENCH_H
+
+#include <stdio.h>
+#include "../../../Common/Types.h"
+#ifdef EXTERNAL_LZMA
+#include "../../UI/Common/LoadCodecs.h"
+#endif
+
+struct CBenchInfo
+{
+  UInt64 GlobalTime;
+  UInt64 GlobalFreq; 
+  UInt64 UserTime; 
+  UInt64 UserFreq;
+  UInt64 UnpackSize;
+  UInt64 PackSize;
+  UInt32 NumIterations;
+  CBenchInfo(): NumIterations(0) {}
+};
+
+struct IBenchCallback
+{
+  virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0;
+  virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0;
+};
+
+UInt64 GetUsage(const CBenchInfo &benchOnfo);
+UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating);
+UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size);
+UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations);
+
+HRESULT LzmaBench(
+  #ifdef EXTERNAL_LZMA
+  CCodecs *codecs,
+  #endif
+  UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback);
+
+const int kBenchMinDicLogSize = 18;
+
+UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary);
+
+bool CrcInternalTest();
+HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed);
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,311 @@
+// LzmaBenchCon.cpp
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+
+#include "LzmaBench.h"
+#include "LzmaBenchCon.h"
+#include "../../../Common/IntToString.h"
+
+#if defined(BENCH_MT) || defined(_WIN32)
+#include "../../../Windows/System.h"
+#endif
+
+#ifdef BREAK_HANDLER
+#include "../../UI/Console/ConsoleClose.h"
+#endif
+#include "../../../Common/MyCom.h"
+
+struct CTotalBenchRes
+{
+  UInt64 NumIterations;
+  UInt64 Rating;
+  UInt64 Usage;
+  UInt64 RPU;
+  void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }
+  void Normalize() 
+  { 
+    if (NumIterations == 0) 
+      return;
+    Rating /= NumIterations; 
+    Usage /= NumIterations; 
+    RPU /= NumIterations; 
+    NumIterations = 1;
+  }
+  void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2) 
+  { 
+    Rating = (r1.Rating + r2.Rating) / 2; 
+    Usage = (r1.Usage + r2.Usage) / 2;
+    RPU = (r1.RPU + r2.RPU) / 2;
+    NumIterations = (r1.NumIterations + r2.NumIterations) / 2;
+  }
+};
+
+struct CBenchCallback: public IBenchCallback
+{
+  CTotalBenchRes EncodeRes;
+  CTotalBenchRes DecodeRes;
+  FILE *f;
+  void Init() { EncodeRes.Init(); DecodeRes.Init(); }
+  void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); }
+  UInt32 dictionarySize;
+  HRESULT SetEncodeResult(const CBenchInfo &info, bool final);
+  HRESULT SetDecodeResult(const CBenchInfo &info, bool final);
+};
+
+static void NormalizeVals(UInt64 &v1, UInt64 &v2)
+{
+  while (v1 > 1000000)
+  {
+    v1 >>= 1;
+    v2 >>= 1;
+  }
+}
+
+static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
+{
+  UInt64 elTime = elapsedTime;
+  NormalizeVals(freq, elTime);
+  if (elTime == 0)
+    elTime = 1;
+  return value * freq / elTime;
+}
+
+static void PrintNumber(FILE *f, UInt64 value, int size)
+{
+  char s[32];
+  ConvertUInt64ToString(value, s);
+  fprintf(f, " ");
+  for (int len = (int)strlen(s); len < size; len++)
+    fprintf(f, " ");
+  fprintf(f, "%s", s);
+}
+
+static void PrintRating(FILE *f, UInt64 rating)
+{
+  PrintNumber(f, rating / 1000000, 6);
+}
+
+static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating)
+{
+  PrintNumber(f, (usage + 5000) / 10000, 5);
+  PrintRating(f, rpu);
+  PrintRating(f, rating);
+}
+
+
+static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res)
+{
+  UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq);
+  PrintNumber(f, speed / 1024, 7);
+  UInt64 usage = GetUsage(info);
+  UInt64 rpu = GetRatingPerUsage(info, rating);
+  PrintResults(f, usage, rpu, rating);
+  res.NumIterations++;
+  res.RPU += rpu;
+  res.Rating += rating;
+  res.Usage += usage;
+}
+
+static void PrintTotals(FILE *f, const CTotalBenchRes &res)
+{
+  fprintf(f, "       ");
+  PrintResults(f, res.Usage, res.RPU, res.Rating);
+}
+
+
+HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)
+{
+  #ifdef BREAK_HANDLER
+  if (NConsoleClose::TestBreakSignal())
+    return E_ABORT;
+  #endif
+
+  if (final)
+  {
+    UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize);
+    PrintResults(f, info, rating, EncodeRes);
+  }
+  return S_OK;
+}
+
+static const char *kSep = "  | ";
+
+
+HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)
+{
+  #ifdef BREAK_HANDLER
+  if (NConsoleClose::TestBreakSignal())
+    return E_ABORT;
+  #endif
+  if (final)
+  {
+    UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations);
+    fprintf(f, kSep);
+    CBenchInfo info2 = info;
+    info2.UnpackSize *= info2.NumIterations;
+    info2.PackSize *= info2.NumIterations;
+    info2.NumIterations = 1;
+    PrintResults(f, info2, rating, DecodeRes);
+  }
+  return S_OK;
+}
+
+static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)
+{
+  fprintf(f, "\nRAM %s ", sizeString);
+  PrintNumber(f, (size >> 20), 5);
+  fprintf(f, " MB,  # %s %3d", threadsString, (unsigned int)numThreads);
+}
+
+HRESULT LzmaBenchCon(
+  #ifdef EXTERNAL_LZMA
+  CCodecs *codecs,
+  #endif
+  FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)
+{
+  if (!CrcInternalTest())
+    return S_FALSE;
+  #ifdef BENCH_MT
+  UInt64 ramSize = NWindows::NSystem::GetRamSize();  // 
+  UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
+  PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);
+  if (numThreads == (UInt32)-1)
+    numThreads = numCPUs;
+  if (numThreads > 1)
+    numThreads &= ~1;
+  if (dictionary == (UInt32)-1)
+  {
+    int dicSizeLog;
+    for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
+      if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)
+        break;
+    dictionary = (1 << dicSizeLog);
+  }
+  #else
+  if (dictionary == (UInt32)-1)
+    dictionary = (1 << 22);
+  numThreads = 1;
+  #endif
+
+  PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads:   ", numThreads);
+
+  CBenchCallback callback;
+  callback.Init();
+  callback.f = f;
+  
+  fprintf(f, "\n\nDict        Compressing          |        Decompressing\n   ");
+  int j;
+  for (j = 0; j < 2; j++)
+  {
+    fprintf(f, "   Speed Usage    R/U Rating");
+    if (j == 0)
+      fprintf(f, kSep);
+  }
+  fprintf(f, "\n   ");
+  for (j = 0; j < 2; j++)
+  {
+    fprintf(f, "    KB/s     %%   MIPS   MIPS");
+    if (j == 0)
+      fprintf(f, kSep);
+  }
+  fprintf(f, "\n\n");
+  for (UInt32 i = 0; i < numIterations; i++)
+  {
+    const int kStartDicLog = 22;
+    int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;
+    while (((UInt32)1 << pow) > dictionary)
+      pow--;
+    for (; ((UInt32)1 << pow) <= dictionary; pow++)
+    {
+      fprintf(f, "%2d:", pow);
+      callback.dictionarySize = (UInt32)1 << pow;
+      HRESULT res = LzmaBench(
+        #ifdef EXTERNAL_LZMA
+        codecs,
+        #endif
+        numThreads, callback.dictionarySize, &callback);
+      fprintf(f, "\n");
+      RINOK(res);
+    }
+  }
+  callback.Normalize();
+  fprintf(f, "----------------------------------------------------------------\nAvr:");
+  PrintTotals(f, callback.EncodeRes);
+  fprintf(f, "     ");
+  PrintTotals(f, callback.DecodeRes);
+  fprintf(f, "\nTot:");
+  CTotalBenchRes midRes;
+  midRes.SetMid(callback.EncodeRes, callback.DecodeRes);
+  PrintTotals(f, midRes);
+  fprintf(f, "\n");
+  return S_OK;
+}
+
+struct CTempValues
+{
+  UInt64 *Values;
+  CTempValues(UInt32 num) { Values = new UInt64[num]; }
+  ~CTempValues() { delete []Values; }
+};
+
+HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)
+{
+  if (!CrcInternalTest())
+    return S_FALSE;
+
+  #ifdef BENCH_MT
+  UInt64 ramSize = NWindows::NSystem::GetRamSize();
+  UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
+  PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);
+  if (numThreads == (UInt32)-1)
+    numThreads = numCPUs;
+  #else
+  numThreads = 1;
+  #endif
+  if (dictionary == (UInt32)-1)
+    dictionary = (1 << 24);
+
+  CTempValues speedTotals(numThreads);
+  fprintf(f, "\n\nSize");
+  for (UInt32 ti = 0; ti < numThreads; ti++)
+  {
+    fprintf(f, " %5d", ti + 1);
+    speedTotals.Values[ti] = 0;
+  }
+  fprintf(f, "\n\n");
+
+  UInt64 numSteps = 0;
+  for (UInt32 i = 0; i < numIterations; i++)
+  {
+    for (int pow = 10; pow < 32; pow++)
+    {
+      UInt32 bufSize = (UInt32)1 << pow;
+      if (bufSize > dictionary)
+        break;
+      fprintf(f, "%2d: ", pow);
+      UInt64 speed;
+      for (UInt32 ti = 0; ti < numThreads; ti++)
+      {
+        #ifdef BREAK_HANDLER
+        if (NConsoleClose::TestBreakSignal())
+          return E_ABORT;
+        #endif
+        RINOK(CrcBench(ti + 1, bufSize, speed));
+        PrintNumber(f, (speed >> 20), 5);
+        speedTotals.Values[ti] += speed;
+      }
+      fprintf(f, "\n");
+      numSteps++;
+    }
+  }
+  if (numSteps != 0)
+  {
+    fprintf(f, "\nAvg:");
+    for (UInt32 ti = 0; ti < numThreads; ti++)
+      PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5);
+    fprintf(f, "\n");
+  }
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaBenchCon.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,20 @@
+// LzmaBenchCon.h
+
+#ifndef __LZMABENCHCON_H
+#define __LZMABENCHCON_H
+
+#include <stdio.h>
+#include "../../../Common/Types.h"
+#ifdef EXTERNAL_LZMA
+#include "../../UI/Common/LoadCodecs.h"
+#endif
+HRESULT LzmaBenchCon(
+  #ifdef EXTERNAL_LZMA
+  CCodecs *codecs,
+  #endif
+  FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);
+
+HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);
+
+#endif
+

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,226 @@
+// LzmaRam.cpp
+
+#include "StdAfx.h"
+#include "../../../Common/Types.h"
+#include "../LZMA/LZMADecoder.h"
+#include "../LZMA/LZMAEncoder.h"
+#include "LzmaRam.h"
+
+extern "C"
+{
+  #include "../../../../C/Compress/Branch/BranchX86.h"
+}
+
+class CInStreamRam: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+  const Byte *Data;
+  size_t Size;
+  size_t Pos;
+public:
+  MY_UNKNOWN_IMP
+  void Init(const Byte *data, size_t size)
+  {
+    Data = data;
+    Size = size;
+    Pos = 0;
+  }
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (size > (Size - Pos))
+    size = (UInt32)(Size - Pos);
+  for (UInt32 i = 0; i < size; i++)
+    ((Byte *)data)[i] = Data[Pos + i];
+  Pos += size;
+  if(processedSize != NULL)
+    *processedSize = size;
+  return S_OK;
+}
+  
+class COutStreamRam: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  size_t Size;
+public:
+  Byte *Data;
+  size_t Pos;
+  bool Overflow;
+  void Init(Byte *data, size_t size)
+  {
+    Data = data;
+    Size = size;
+    Pos = 0;
+    Overflow = false;
+  }
+  void SetPos(size_t pos)
+  {
+    Overflow = false;
+    Pos = pos;
+  }
+  MY_UNKNOWN_IMP
+  HRESULT WriteByte(Byte b)
+  {
+    if (Pos >= Size)
+    {
+      Overflow = true;
+      return E_FAIL;
+    }
+    Data[Pos++] = b;
+    return S_OK;
+  }
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 i;
+  for (i = 0; i < size && Pos < Size; i++)
+    Data[Pos++] = ((const Byte *)data)[i];
+  if(processedSize != NULL)
+    *processedSize = i;
+  if (i != size)
+  {
+    Overflow = true;
+    return E_FAIL;
+  }
+  return S_OK;
+}
+  
+#define SZ_RAM_E_FAIL (1)
+#define SZ_RAM_E_OUTOFMEMORY (2)
+#define SZE_OUT_OVERFLOW (3)
+
+int LzmaRamEncode(
+    const Byte *inBuffer, size_t inSize, 
+    Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, 
+    UInt32 dictionarySize, ESzFilterMode filterMode)
+{
+  #ifndef _NO_EXCEPTIONS
+  try { 
+  #endif
+
+  *outSizeProcessed = 0;
+  const size_t kIdSize = 1;
+  const size_t kLzmaPropsSize = 5;
+  const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8;
+  if (outSize < kMinDestSize)
+    return SZE_OUT_OVERFLOW;
+  NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
+  CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+  PROPID propIDs[] = 
+  { 
+    NCoderPropID::kAlgorithm,
+    NCoderPropID::kDictionarySize,  
+    NCoderPropID::kNumFastBytes,
+  };
+  const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
+  PROPVARIANT properties[kNumProps];
+  properties[0].vt = VT_UI4;
+  properties[1].vt = VT_UI4;
+  properties[2].vt = VT_UI4;
+  properties[0].ulVal = (UInt32)2;
+  properties[1].ulVal = (UInt32)dictionarySize;
+  properties[2].ulVal = (UInt32)64;
+
+  if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
+    return 1;
+  
+  COutStreamRam *outStreamSpec = new COutStreamRam;
+  if (outStreamSpec == 0)
+    return SZ_RAM_E_OUTOFMEMORY;
+  CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+  CInStreamRam *inStreamSpec = new CInStreamRam;
+  if (inStreamSpec == 0)
+    return SZ_RAM_E_OUTOFMEMORY;
+  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+
+  outStreamSpec->Init(outBuffer, outSize);
+  if (outStreamSpec->WriteByte(0) != S_OK)
+    return SZE_OUT_OVERFLOW;
+
+  if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
+    return SZE_OUT_OVERFLOW;
+  if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize)
+    return 1;
+  
+  int i;
+  for (i = 0; i < 8; i++)
+  {
+    UInt64 t = (UInt64)(inSize);
+    if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK)
+      return SZE_OUT_OVERFLOW;
+  }
+
+  Byte *filteredStream = 0;
+
+  bool useFilter = (filterMode != SZ_FILTER_NO);
+  if (useFilter)
+  {
+    if (inSize != 0)
+    {
+      filteredStream = (Byte *)MyAlloc(inSize);
+      if (filteredStream == 0)
+        return SZ_RAM_E_OUTOFMEMORY;
+      memmove(filteredStream, inBuffer, inSize);
+    }
+    UInt32 x86State;
+    x86_Convert_Init(x86State);
+    x86_Convert(filteredStream, (SizeT)inSize, 0, &x86State, 1);
+  }
+  
+  size_t minSize = 0;
+  int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
+  bool bestIsFiltered = false;
+  int mainResult = 0;
+  size_t startPos = outStreamSpec->Pos;
+  for (i = 0; i < numPasses; i++)
+  {
+    if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered)
+      break;
+    outStreamSpec->SetPos(startPos);
+    bool curModeIsFiltered = false;
+    if (useFilter && i == 0)
+      curModeIsFiltered = true;
+    if (numPasses > 1 && i == numPasses - 1)
+      curModeIsFiltered = true;
+
+    inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize);
+    
+    HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0);
+    
+    mainResult = 0;
+    if (lzmaResult == E_OUTOFMEMORY)
+    {
+      mainResult = SZ_RAM_E_OUTOFMEMORY;
+      break;
+    } 
+    if (i == 0 || outStreamSpec->Pos <= minSize)
+    {
+      minSize = outStreamSpec->Pos;
+      bestIsFiltered = curModeIsFiltered;
+    }
+    if (outStreamSpec->Overflow)
+      mainResult = SZE_OUT_OVERFLOW;
+    else if (lzmaResult != S_OK)
+    {
+      mainResult = SZ_RAM_E_FAIL;
+      break;
+    } 
+  }
+  *outSizeProcessed = outStreamSpec->Pos;
+  if (bestIsFiltered)
+    outBuffer[0] = 1;
+  if (useFilter)
+    MyFree(filteredStream);
+  return mainResult;
+  
+  #ifndef _NO_EXCEPTIONS
+  } catch(...) { return SZ_RAM_E_OUTOFMEMORY; }
+  #endif
+}

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,46 @@
+// LzmaRam.h
+
+#ifndef __LzmaRam_h
+#define __LzmaRam_h
+
+#include <stdlib.h>
+#include "../../../Common/Types.h"
+
+/*
+LzmaRamEncode: BCJ + LZMA RAM->RAM compressing.
+It uses .lzma format, but it writes one additional byte to .lzma file:
+  0: - no filter
+  1: - x86(BCJ) filter.
+
+To provide best compression ratio dictionarySize mustbe >= inSize
+
+LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions.
+RAM Requirements:
+  RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize 
+    FilterBlockSize = 0, if useFilter == false
+    FilterBlockSize = inSize, if useFilter == true
+
+  Return code:
+    0 - OK
+    1 - Unspecified Error
+    2 - Memory allocating error
+    3 - Output buffer OVERFLOW
+
+If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes:
+  2 passes when FILTER_NO provides better compression.
+  3 passes when FILTER_YES provides better compression.
+*/
+
+enum ESzFilterMode 
+{
+  SZ_FILTER_NO,
+  SZ_FILTER_YES,
+  SZ_FILTER_AUTO
+};
+
+int LzmaRamEncode(
+    const Byte *inBuffer, size_t inSize, 
+    Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, 
+    UInt32 dictionarySize, ESzFilterMode filterMode);
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.c
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.c	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.c	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,78 @@
+/* LzmaRamDecode.c */
+
+#include "LzmaRamDecode.h"
+#ifdef _SZ_ONE_DIRECTORY
+#include "LzmaDecode.h"
+#include "BranchX86.h"
+#else
+#include "../../../../C/Compress/Lzma/LzmaDecode.h"
+#include "../../../../C/Compress/Branch/BranchX86.h"
+#endif
+
+#define LZMA_PROPS_SIZE 14
+#define LZMA_SIZE_OFFSET 6
+
+int LzmaRamGetUncompressedSize(
+    const unsigned char *inBuffer, 
+    size_t inSize, 
+    size_t *outSize)
+{
+  unsigned int i;
+  if (inSize < LZMA_PROPS_SIZE)
+    return 1;
+  *outSize = 0;
+  for(i = 0; i < sizeof(size_t); i++)
+    *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i);
+  for(; i < 8; i++)
+    if (inBuffer[LZMA_SIZE_OFFSET + i] != 0)
+      return 1;
+  return 0;
+}
+
+#define SZE_DATA_ERROR (1)
+#define SZE_OUTOFMEMORY (2)
+
+int LzmaRamDecompress(
+    const unsigned char *inBuffer, 
+    size_t inSize,
+    unsigned char *outBuffer,
+    size_t outSize,
+    size_t *outSizeProcessed,
+    void * (*allocFunc)(size_t size), 
+    void (*freeFunc)(void *))
+{
+  CLzmaDecoderState state;  /* it's about 24 bytes structure, if int is 32-bit */
+  int result;
+  SizeT outSizeProcessedLoc;
+  SizeT inProcessed;
+  int useFilter;
+  
+  if (inSize < LZMA_PROPS_SIZE)
+    return 1;
+  useFilter = inBuffer[0];
+
+  *outSizeProcessed = 0;
+  if (useFilter > 1)
+    return 1;
+
+  if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+    return 1;
+  state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+  if (state.Probs == 0)
+    return SZE_OUTOFMEMORY;
+  
+  result = LzmaDecode(&state,
+    inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed,
+    outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
+  freeFunc(state.Probs);
+  if (result != LZMA_RESULT_OK)
+    return 1;
+  *outSizeProcessed = (size_t)outSizeProcessedLoc;
+  if (useFilter == 1)
+  {
+    UInt32 x86State;
+    x86_Convert_Init(x86State);
+    x86_Convert(outBuffer, (SizeT)outSizeProcessedLoc, 0, &x86State, 0);
+  }
+  return 0;
+}

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRamDecode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,55 @@
+/* LzmaRamDecode.h */
+
+#ifndef __LzmaRamDecode_h
+#define __LzmaRamDecode_h
+
+#include <stdlib.h>
+
+/*
+LzmaRamGetUncompressedSize:
+  In: 
+    inBuffer - input data
+    inSize   - input data size
+  Out: 
+    outSize  - uncompressed size
+  Return code:
+    0 - OK
+    1 - Error in headers
+*/
+
+int LzmaRamGetUncompressedSize(
+    const unsigned char *inBuffer, 
+    size_t inSize,
+    size_t *outSize);
+
+
+/*
+LzmaRamDecompress:
+  In: 
+    inBuffer  - input data
+    inSize    - input data size
+    outBuffer - output data
+    outSize   - output size
+    allocFunc - alloc function (can be malloc)
+    freeFunc  - free function (can be free)
+  Out: 
+    outSizeProcessed - processed size
+  Return code:
+    0 - OK
+    1 - Error in headers / data stream
+    2 - Memory allocating error
+
+Memory requirements depend from properties of LZMA stream.
+With default lzma settings it's about 16 KB.
+*/
+
+int LzmaRamDecompress(
+    const unsigned char *inBuffer, 
+    size_t inSize,
+    unsigned char *outBuffer,
+    size_t outSize,
+    size_t *outSizeProcessed,
+    void * (*allocFunc)(size_t size), 
+    void (*freeFunc)(void *));
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/makefile
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/makefile	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/makefile	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,136 @@
+PROG = lzma.exe
+CFLAGS = $(CFLAGS) \
+  -DCOMPRESS_MF_MT \
+  -DBENCH_MT \
+
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+!IFDEF CPU
+LIBS = $(LIBS) bufferoverflowU.lib 
+CFLAGS = $(CFLAGS) -GS- -Zc:forScope -W4 -Wp64 -DUNICODE -D_UNICODE
+!ENDIF
+
+!IFNDEF O
+!IFDEF CPU
+O=$(CPU)
+!ELSE
+O=O
+!ENDIF
+!ENDIF
+
+!IFDEF MY_STATIC_LINK
+!IFNDEF MY_SINGLE_THREAD
+CFLAGS = $(CFLAGS) -MT
+!ENDIF
+!ELSE
+CFLAGS = $(CFLAGS) -MD
+!ENDIF
+
+CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/
+CFLAGS_O1 = $(CFLAGS) -O1
+CFLAGS_O2 = $(CFLAGS) -O2
+
+LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98
+
+PROGPATH = $O\$(PROG)
+
+COMPL_O1   = $(CPP) $(CFLAGS_O1) $**
+COMPL_O2   = $(CPP) $(CFLAGS_O2) $**
+COMPL      = $(CPP) $(CFLAGS_O1) $**
+
+
+LZMA_OBJS = \
+  $O\LzmaAlone.obj \
+  $O\LzmaBench.obj \
+  $O\LzmaBenchCon.obj \
+  $O\LzmaRam.obj \
+
+LZMA_OPT_OBJS = \
+  $O\LZMADecoder.obj \
+  $O\LZMAEncoder.obj \
+
+COMMON_OBJS = \
+  $O\CommandLineParser.obj \
+  $O\CRC.obj \
+  $O\IntToString.obj \
+  $O\MyString.obj \
+  $O\StringConvert.obj \
+  $O\StringToInt.obj \
+  $O\MyVector.obj
+
+WIN_OBJS = \
+  $O\System.obj
+
+7ZIP_COMMON_OBJS = \
+  $O\InBuffer.obj \
+  $O\OutBuffer.obj \
+  $O\StreamUtils.obj \
+
+LZ_OBJS = \
+  $O\LZOutWindow.obj \
+
+C_OBJS = \
+  $O\Alloc.obj \
+  $O\7zCrc.obj \
+  $O\Threads.obj \
+
+C_LZ_OBJS = \
+  $O\MatchFinder.obj \
+  $O\MatchFinderMt.obj \
+
+OBJS = \
+  $(LZMA_OBJS) \
+  $(LZMA_OPT_OBJS) \
+  $(COMMON_OBJS) \
+  $(WIN_OBJS) \
+  $(7ZIP_COMMON_OBJS) \
+  $(LZ_OBJS) \
+  $(C_OBJS) \
+  $(C_LZ_OBJS) \
+  $O\LzmaRamDecode.obj \
+  $O\LzmaDecode.obj \
+  $O\FileStreams.obj \
+  $O\FileIO.obj \
+  $O\RangeCoderBit.obj \
+  $O\BranchX86.obj \
+
+all: $(PROGPATH) 
+
+clean:
+	-del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch 
+
+$O:
+	if not exist "$O" mkdir "$O"
+
+$(PROGPATH): $O $(OBJS)
+	link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
+
+
+$(LZMA_OBJS): $(*B).cpp
+	$(COMPL)
+$(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp
+	$(COMPL_O2)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+	$(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+	$(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+	$(COMPL)
+$(LZ_OBJS): ../LZ/$(*B).cpp
+	$(COMPL)
+$O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp
+	$(COMPL)
+$O\LzmaRamDecode.obj: LzmaRamDecode.c
+	$(COMPL_O1)
+$O\LzmaDecode.obj: ../../../../C/Compress/Lzma/LzmaDecode.c
+	$(COMPL_O2)
+$O\BranchX86.obj: ../../../../C/Compress/Branch/BranchX86.c
+	$(COMPL_O2)
+$O\FileStreams.obj: ../../Common/FileStreams.cpp
+	$(COMPL)
+$O\FileIO.obj: ../../../Windows/FileIO.cpp
+	$(COMPL)
+$(C_OBJS): ../../../../C/$(*B).c
+	$(COMPL_O2)
+$(C_LZ_OBJS): ../../../../C/Compress/Lz/$(*B).c
+	$(COMPL_O2)

Added: trunk/lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc
===================================================================
--- trunk/lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/LZMA_Alone/makefile.gcc	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,139 @@
+PROG = lzma
+CXX = g++ -O2 -Wall
+CXX_C = gcc -O2 -Wall
+LIB = -lm
+RM = rm -f
+CFLAGS = -c
+
+ifdef SystemDrive
+IS_MINGW = 1
+endif
+
+ifdef IS_MINGW
+FILE_IO =FileIO
+FILE_IO_2 =Windows/$(FILE_IO)
+LIB2 = -luuid 
+else
+FILE_IO =C_FileIO
+FILE_IO_2 =Common/$(FILE_IO)
+endif
+
+OBJS = \
+  LzmaAlone.o \
+  LzmaBench.o \
+  LzmaBenchCon.o \
+  LzmaRam.o \
+  LZMADecoder.o \
+  LZMAEncoder.o \
+  LZOutWindow.o \
+  RangeCoderBit.o \
+  InBuffer.o \
+  OutBuffer.o \
+  FileStreams.o \
+  StreamUtils.o \
+  $(FILE_IO).o \
+  CommandLineParser.o \
+  CRC.o \
+  IntToString.o \
+  MyString.o \
+  StringConvert.o \
+  StringToInt.o \
+  MyVector.o \
+  7zCrc.o \
+  Alloc.o \
+  BranchX86.o \
+  MatchFinder.o \
+  LzmaDecode.o \
+  LzmaRamDecode.o \
+
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+	$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2)
+
+LzmaAlone.o: LzmaAlone.cpp
+	$(CXX) $(CFLAGS) LzmaAlone.cpp
+
+LzmaBench.o: LzmaBench.cpp
+	$(CXX) $(CFLAGS) LzmaBench.cpp
+
+LzmaBenchCon.o: LzmaBenchCon.cpp
+	$(CXX) $(CFLAGS) LzmaBenchCon.cpp
+
+LzmaRam.o: LzmaRam.cpp
+	$(CXX) $(CFLAGS) LzmaRam.cpp
+
+LZMADecoder.o: ../LZMA/LZMADecoder.cpp
+	$(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp
+
+LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp
+	$(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp
+
+LZOutWindow.o: ../LZ/LZOutWindow.cpp
+	$(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp
+
+RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp
+	$(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp
+
+InBuffer.o: ../../Common/InBuffer.cpp
+	$(CXX) $(CFLAGS) ../../Common/InBuffer.cpp
+
+OutBuffer.o: ../../Common/OutBuffer.cpp
+	$(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp
+
+FileStreams.o: ../../Common/FileStreams.cpp
+	$(CXX) $(CFLAGS) ../../Common/FileStreams.cpp
+
+StreamUtils.o: ../../Common/StreamUtils.cpp
+	$(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp
+
+$(FILE_IO).o: ../../../$(FILE_IO_2).cpp
+	$(CXX) $(CFLAGS) ../../../$(FILE_IO_2).cpp
+
+
+CommandLineParser.o: ../../../Common/CommandLineParser.cpp
+	$(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp
+
+CRC.o: ../../../Common/CRC.cpp
+	$(CXX) $(CFLAGS) ../../../Common/CRC.cpp
+
+MyWindows.o: ../../../Common/MyWindows.cpp
+	$(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp
+
+IntToString.o: ../../../Common/IntToString.cpp
+	$(CXX) $(CFLAGS) ../../../Common/IntToString.cpp
+
+MyString.o: ../../../Common/MyString.cpp
+	$(CXX) $(CFLAGS) ../../../Common/MyString.cpp
+
+StringConvert.o: ../../../Common/StringConvert.cpp
+	$(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp
+
+StringToInt.o: ../../../Common/StringToInt.cpp
+	$(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp
+
+MyVector.o: ../../../Common/MyVector.cpp
+	$(CXX) $(CFLAGS) ../../../Common/MyVector.cpp
+
+7zCrc.o: ../../../../C/7zCrc.c
+	$(CXX_C) $(CFLAGS) ../../../../C/7zCrc.c
+
+Alloc.o: ../../../../C/Alloc.c
+	$(CXX_C) $(CFLAGS) ../../../../C/Alloc.c
+
+BranchX86.o: ../../../../C/Compress/Branch/BranchX86.c
+	$(CXX_C) $(CFLAGS) ../../../../C/Compress/Branch/BranchX86.c
+
+MatchFinder.o: ../../../../C/Compress/Lz/MatchFinder.c
+	$(CXX_C) $(CFLAGS) ../../../../C/Compress/Lz/MatchFinder.c
+
+LzmaDecode.o: ../../../../C/Compress/Lzma/LzmaDecode.c
+	$(CXX_C) $(CFLAGS) ../../../../C/Compress/Lzma/LzmaDecode.c
+
+LzmaRamDecode.o: LzmaRamDecode.c
+	$(CXX_C) $(CFLAGS) LzmaRamDecode.c
+
+clean:
+	-$(RM) $(PROG) $(OBJS)
+

Added: trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoder.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoder.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,205 @@
+// Compress/RangeCoder/RangeCoder.h
+
+#ifndef __COMPRESS_RANGECODER_H
+#define __COMPRESS_RANGECODER_H
+
+#include "../../Common/InBuffer.h"
+#include "../../Common/OutBuffer.h"
+
+namespace NCompress {
+namespace NRangeCoder {
+
+const int kNumTopBits = 24;
+const UInt32 kTopValue = (1 << kNumTopBits);
+
+class CEncoder
+{
+  UInt32 _cacheSize;
+  Byte _cache;
+public:
+  UInt64 Low;
+  UInt32 Range;
+  COutBuffer Stream;
+  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
+
+  void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }
+  void Init()
+  {
+    Stream.Init();
+    Low = 0;
+    Range = 0xFFFFFFFF;
+    _cacheSize = 1;
+    _cache = 0;
+  }
+
+  void FlushData()
+  {
+    // Low += 1; 
+    for(int i = 0; i < 5; i++)
+      ShiftLow();
+  }
+
+  HRESULT FlushStream() { return Stream.Flush();  }
+
+  void ReleaseStream() { Stream.ReleaseStream(); }
+
+  void Encode(UInt32 start, UInt32 size, UInt32 total)
+  {
+    Low += start * (Range /= total);
+    Range *= size;
+    while (Range < kTopValue)
+    {
+      Range <<= 8;
+      ShiftLow();
+    }
+  }
+
+  void ShiftLow()
+  {
+    if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) 
+    {
+      Byte temp = _cache;
+      do
+      {
+        Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));
+        temp = 0xFF;
+      }
+      while(--_cacheSize != 0);
+      _cache = (Byte)((UInt32)Low >> 24);                      
+    } 
+    _cacheSize++;                               
+    Low = (UInt32)Low << 8;                           
+  }
+  
+  void EncodeDirectBits(UInt32 value, int numTotalBits)
+  {
+    for (int i = numTotalBits - 1; i >= 0; i--)
+    {
+      Range >>= 1;
+      if (((value >> i) & 1) == 1)
+        Low += Range;
+      if (Range < kTopValue)
+      {
+        Range <<= 8;
+        ShiftLow();
+      }
+    }
+  }
+
+  void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)
+  {
+    UInt32 newBound = (Range >> numTotalBits) * size0;
+    if (symbol == 0)
+      Range = newBound;
+    else
+    {
+      Low += newBound;
+      Range -= newBound;
+    }
+    while (Range < kTopValue)
+    {
+      Range <<= 8;
+      ShiftLow();
+    }
+  }
+
+  UInt64 GetProcessedSize() {  return Stream.GetProcessedSize() + _cacheSize + 4; }
+};
+
+class CDecoder
+{
+public:
+  CInBuffer Stream;
+  UInt32 Range;
+  UInt32 Code;
+  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
+
+  void Normalize()
+  {
+    while (Range < kTopValue)
+    {
+      Code = (Code << 8) | Stream.ReadByte();
+      Range <<= 8;
+    }
+  }
+  
+  void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
+  void Init()
+  {
+    Stream.Init();
+    Code = 0;
+    Range = 0xFFFFFFFF;
+    for(int i = 0; i < 5; i++)
+      Code = (Code << 8) | Stream.ReadByte();
+  }
+
+  void ReleaseStream() { Stream.ReleaseStream(); }
+
+  UInt32 GetThreshold(UInt32 total)
+  {
+    return (Code) / ( Range /= total);
+  }
+
+  void Decode(UInt32 start, UInt32 size)
+  {
+    Code -= start * Range;
+    Range *= size;
+    Normalize();
+  }
+
+  UInt32 DecodeDirectBits(int numTotalBits)
+  {
+    UInt32 range = Range;
+    UInt32 code = Code;        
+    UInt32 result = 0;
+    for (int i = numTotalBits; i != 0; i--)
+    {
+      range >>= 1;
+      /*
+      result <<= 1;
+      if (code >= range)
+      {
+        code -= range;
+        result |= 1;
+      }
+      */
+      UInt32 t = (code - range) >> 31;
+      code -= range & (t - 1);
+      result = (result << 1) | (1 - t);
+
+      if (range < kTopValue)
+      {
+        code = (code << 8) | Stream.ReadByte();
+        range <<= 8; 
+      }
+    }
+    Range = range;
+    Code = code;
+    return result;
+  }
+
+  UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
+  {
+    UInt32 newBound = (Range >> numTotalBits) * size0;
+    UInt32 symbol;
+    if (Code < newBound)
+    {
+      symbol = 0;
+      Range = newBound;
+    }
+    else
+    {
+      symbol = 1;
+      Code -= newBound;
+      Range -= newBound;
+    }
+    Normalize();
+    return symbol;
+  }
+
+  UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.cpp
===================================================================
--- trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,80 @@
+// Compress/RangeCoder/RangeCoderBit.cpp
+
+#include "StdAfx.h"
+
+#include "RangeCoderBit.h"
+
+namespace NCompress {
+namespace NRangeCoder {
+
+UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
+static CPriceTables g_PriceTables;
+
+CPriceTables::CPriceTables() { Init(); }
+
+void CPriceTables::Init()
+{
+  const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
+  for(int i = kNumBits - 1; i >= 0; i--)
+  {
+    UInt32 start = 1 << (kNumBits - i - 1);
+    UInt32 end = 1 << (kNumBits - i);
+    for (UInt32 j = start; j < end; j++)
+      ProbPrices[j] = (i << kNumBitPriceShiftBits) + 
+          (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
+  }
+
+  /*
+  // simplest: bad solution
+  for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)
+    ProbPrices[i] = kBitPrice;
+  */
+  
+  /*
+  const double kDummyMultMid = (1.0 / kBitPrice) / 2;
+  const double kDummyMultMid = 0;
+  // float solution
+  double ln2 = log(double(2));
+  double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits));
+  for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)
+    ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice);
+  */
+  
+  /*
+  // experimental, slow, solution:
+  for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)
+  {
+    const int kCyclesBits = 5;
+    const UInt32 kCycles = (1 << kCyclesBits);
+
+    UInt32 range = UInt32(-1);
+    UInt32 bitCount = 0;
+    for (UInt32 j = 0; j < kCycles; j++)
+    {
+      range >>= (kNumBitModelTotalBits - kNumMoveReducingBits);
+      range *= i;
+      while(range < (1 << 31))
+      {
+        range <<= 1;
+        bitCount++;
+      }
+    }
+    bitCount <<= kNumBitPriceShiftBits;
+    range -= (1 << 31);
+    for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--)
+    {
+      range <<= 1;
+      if (range > (1 << 31))
+      {
+        bitCount += (1 << k);
+        range -= (1 << 31);
+      }
+    }
+    ProbPrices[i] = (bitCount 
+      // + (1 << (kCyclesBits - 1))
+      ) >> kCyclesBits;
+  }
+  */
+}
+
+}}

Added: trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBit.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,120 @@
+// Compress/RangeCoder/RangeCoderBit.h
+
+#ifndef __COMPRESS_RANGECODER_BIT_H
+#define __COMPRESS_RANGECODER_BIT_H
+
+#include "RangeCoder.h"
+
+namespace NCompress {
+namespace NRangeCoder {
+
+const int kNumBitModelTotalBits  = 11;
+const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);
+
+const int kNumMoveReducingBits = 2;
+
+const int kNumBitPriceShiftBits = 6;
+const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;
+
+class CPriceTables
+{
+public:
+  static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
+  static void Init();
+  CPriceTables();
+};
+
+template <int numMoveBits>
+class CBitModel
+{
+public:
+  UInt32 Prob;
+  void UpdateModel(UInt32 symbol)
+  {
+    /*
+    Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;
+    Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);
+    */
+    if (symbol == 0)
+      Prob += (kBitModelTotal - Prob) >> numMoveBits;
+    else
+      Prob -= (Prob) >> numMoveBits;
+  }
+public:
+  void Init() { Prob = kBitModelTotal / 2; }
+};
+
+template <int numMoveBits>
+class CBitEncoder: public CBitModel<numMoveBits>
+{
+public:
+  void Encode(CEncoder *encoder, UInt32 symbol)
+  {
+    /*
+    encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);
+    this->UpdateModel(symbol);
+    */
+    UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;
+    if (symbol == 0)
+    {
+      encoder->Range = newBound;
+      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
+    }
+    else
+    {
+      encoder->Low += newBound;
+      encoder->Range -= newBound;
+      this->Prob -= (this->Prob) >> numMoveBits;
+    }
+    if (encoder->Range < kTopValue)
+    {
+      encoder->Range <<= 8;
+      encoder->ShiftLow();
+    }
+  }
+  UInt32 GetPrice(UInt32 symbol) const
+  {
+    return CPriceTables::ProbPrices[
+      (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
+  }
+  UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; }
+  UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; }
+};
+
+
+template <int numMoveBits>
+class CBitDecoder: public CBitModel<numMoveBits>
+{
+public:
+  UInt32 Decode(CDecoder *decoder)
+  {
+    UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;
+    if (decoder->Code < newBound)
+    {
+      decoder->Range = newBound;
+      this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
+      if (decoder->Range < kTopValue)
+      {
+        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
+        decoder->Range <<= 8;
+      }
+      return 0;
+    }
+    else
+    {
+      decoder->Range -= newBound;
+      decoder->Code -= newBound;
+      this->Prob -= (this->Prob) >> numMoveBits;
+      if (decoder->Range < kTopValue)
+      {
+        decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
+        decoder->Range <<= 8;
+      }
+      return 1;
+    }
+  }
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBitTree.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBitTree.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderBitTree.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,161 @@
+// Compress/RangeCoder/RangeCoderBitTree.h
+
+#ifndef __COMPRESS_RANGECODER_BIT_TREE_H
+#define __COMPRESS_RANGECODER_BIT_TREE_H
+
+#include "RangeCoderBit.h"
+#include "RangeCoderOpt.h"
+
+namespace NCompress {
+namespace NRangeCoder {
+
+template <int numMoveBits, int NumBitLevels>
+class CBitTreeEncoder
+{
+  CBitEncoder<numMoveBits> Models[1 << NumBitLevels];
+public:
+  void Init()
+  {
+    for(UInt32 i = 1; i < (1 << NumBitLevels); i++)
+      Models[i].Init();
+  }
+  void Encode(CEncoder *rangeEncoder, UInt32 symbol)
+  {
+    UInt32 modelIndex = 1;
+    for (int bitIndex = NumBitLevels; bitIndex != 0 ;)
+    {
+      bitIndex--;
+      UInt32 bit = (symbol >> bitIndex) & 1;
+      Models[modelIndex].Encode(rangeEncoder, bit);
+      modelIndex = (modelIndex << 1) | bit;
+    }
+  };
+  void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol)
+  {
+    UInt32 modelIndex = 1;
+    for (int i = 0; i < NumBitLevels; i++)
+    {
+      UInt32 bit = symbol & 1;
+      Models[modelIndex].Encode(rangeEncoder, bit);
+      modelIndex = (modelIndex << 1) | bit;
+      symbol >>= 1;
+    }
+  }
+  UInt32 GetPrice(UInt32 symbol) const
+  {
+    symbol |= (1 << NumBitLevels);
+    UInt32 price = 0;
+    while (symbol != 1)
+    {
+      price += Models[symbol >> 1].GetPrice(symbol & 1);
+      symbol >>= 1;
+    }
+    return price;
+  }
+  UInt32 ReverseGetPrice(UInt32 symbol) const
+  {
+    UInt32 price = 0;
+    UInt32 modelIndex = 1;
+    for (int i = NumBitLevels; i != 0; i--)
+    {
+      UInt32 bit = symbol & 1;
+      symbol >>= 1;
+      price += Models[modelIndex].GetPrice(bit);
+      modelIndex = (modelIndex << 1) | bit;
+    }
+    return price;
+  }
+};
+
+template <int numMoveBits, int NumBitLevels>
+class CBitTreeDecoder
+{
+  CBitDecoder<numMoveBits> Models[1 << NumBitLevels];
+public:
+  void Init()
+  {
+    for(UInt32 i = 1; i < (1 << NumBitLevels); i++)
+      Models[i].Init();
+  }
+  UInt32 Decode(CDecoder *rangeDecoder)
+  {
+    UInt32 modelIndex = 1;
+    RC_INIT_VAR
+    for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--)
+    {
+      // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder);
+      RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex)
+    }
+    RC_FLUSH_VAR
+    return modelIndex - (1 << NumBitLevels);
+  };
+  UInt32 ReverseDecode(CDecoder *rangeDecoder)
+  {
+    UInt32 modelIndex = 1;
+    UInt32 symbol = 0;
+    RC_INIT_VAR
+    for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+    {
+      // UInt32 bit = Models[modelIndex].Decode(rangeDecoder);
+      // modelIndex <<= 1;
+      // modelIndex += bit;
+      // symbol |= (bit << bitIndex);
+      RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex))
+    }
+    RC_FLUSH_VAR
+    return symbol;
+  }
+};
+
+template <int numMoveBits>
+void ReverseBitTreeEncode(CBitEncoder<numMoveBits> *Models, 
+    CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol)
+{
+  UInt32 modelIndex = 1;
+  for (int i = 0; i < NumBitLevels; i++)
+  {
+    UInt32 bit = symbol & 1;
+    Models[modelIndex].Encode(rangeEncoder, bit);
+    modelIndex = (modelIndex << 1) | bit;
+    symbol >>= 1;
+  }
+}
+
+template <int numMoveBits>
+UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models, 
+    UInt32 NumBitLevels, UInt32 symbol)
+{
+  UInt32 price = 0;
+  UInt32 modelIndex = 1;
+  for (int i = NumBitLevels; i != 0; i--)
+  {
+    UInt32 bit = symbol & 1;
+    symbol >>= 1;
+    price += Models[modelIndex].GetPrice(bit);
+    modelIndex = (modelIndex << 1) | bit;
+  }
+  return price;
+}
+
+template <int numMoveBits>
+UInt32 ReverseBitTreeDecode(CBitDecoder<numMoveBits> *Models, 
+    CDecoder *rangeDecoder, int NumBitLevels)
+{
+  UInt32 modelIndex = 1;
+  UInt32 symbol = 0;
+  RC_INIT_VAR
+  for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+  {
+    // UInt32 bit = Models[modelIndex].Decode(rangeDecoder);
+    // modelIndex <<= 1;
+    // modelIndex += bit;
+    // symbol |= (bit << bitIndex);
+    RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex))
+  }
+  RC_FLUSH_VAR
+  return symbol;
+}
+
+}}
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderOpt.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderOpt.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/RangeCoder/RangeCoderOpt.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,31 @@
+// Compress/RangeCoder/RangeCoderOpt.h
+
+#ifndef __COMPRESS_RANGECODER_OPT_H
+#define __COMPRESS_RANGECODER_OPT_H
+
+#define RC_INIT_VAR \
+  UInt32 range = rangeDecoder->Range; \
+  UInt32 code = rangeDecoder->Code;        
+
+#define RC_FLUSH_VAR \
+  rangeDecoder->Range = range; \
+  rangeDecoder->Code = code;
+
+#define RC_NORMALIZE \
+  if (range < NCompress::NRangeCoder::kTopValue) \
+    { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; }
+
+#define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \
+  { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \
+  if (code < bound) \
+  { A0; range = bound; \
+    prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \
+    mi <<= 1; } \
+  else \
+  { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \
+    mi = (mi + mi) + 1; }} \
+  RC_NORMALIZE
+
+#define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;)
+
+#endif

Added: trunk/lzma/CPP/7zip/Compress/RangeCoder/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/Compress/RangeCoder/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/Compress/RangeCoder/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,6 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#endif

Added: trunk/lzma/CPP/7zip/ICoder.h
===================================================================
--- trunk/lzma/CPP/7zip/ICoder.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/ICoder.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,185 @@
+// ICoder.h
+
+#ifndef __ICODER_H
+#define __ICODER_H
+
+#include "IStream.h"
+
+#define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x)
+
+CODER_INTERFACE(ICompressProgressInfo, 0x04)
+{
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;
+};
+
+CODER_INTERFACE(ICompressCoder, 0x05)
+{
+  STDMETHOD(Code)(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, 
+      const UInt64 *inSize, 
+      const UInt64 *outSize,
+      ICompressProgressInfo *progress) PURE;
+};
+
+CODER_INTERFACE(ICompressCoder2, 0x18)
+{
+  STDMETHOD(Code)(ISequentialInStream **inStreams,
+      const UInt64 **inSizes, 
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams, 
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress) PURE;
+};
+
+namespace NCoderPropID
+{
+  enum EEnum
+  {
+    kDictionarySize = 0x400,
+    kUsedMemorySize,
+    kOrder,
+    kPosStateBits = 0x440,
+    kLitContextBits,
+    kLitPosBits,
+    kNumFastBytes = 0x450,
+    kMatchFinder,
+    kMatchFinderCycles,
+    kNumPasses = 0x460, 
+    kAlgorithm = 0x470,
+    kMultiThread = 0x480,
+    kNumThreads,
+    kEndMarker = 0x490
+  };
+}
+
+CODER_INTERFACE(ICompressSetCoderProperties, 0x20)
+{
+  STDMETHOD(SetCoderProperties)(const PROPID *propIDs, 
+      const PROPVARIANT *properties, UInt32 numProperties) PURE;
+};
+
+/*
+CODER_INTERFACE(ICompressSetCoderProperties, 0x21)
+{
+  STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE;
+};
+*/
+
+CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)
+{
+  STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;
+};
+
+CODER_INTERFACE(ICompressWriteCoderProperties, 0x23)
+{
+  STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE;
+};
+
+CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24)
+{
+  STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE;
+};
+
+CODER_INTERFACE(ICompressSetCoderMt, 0x25)
+{
+  STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE;
+};
+
+CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)
+{
+  STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;
+};
+
+CODER_INTERFACE(ICompressSetInStream, 0x31)
+{
+  STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE;
+  STDMETHOD(ReleaseInStream)() PURE;
+};
+
+CODER_INTERFACE(ICompressSetOutStream, 0x32)
+{
+  STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE;
+  STDMETHOD(ReleaseOutStream)() PURE;
+};
+
+CODER_INTERFACE(ICompressSetInStreamSize, 0x33)
+{
+  STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;
+};
+
+CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)
+{
+  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;
+};
+
+CODER_INTERFACE(ICompressFilter, 0x40)
+{
+  STDMETHOD(Init)() PURE;
+  STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE;
+  // Filter return outSize (UInt32)
+  // if (outSize <= size): Filter have converted outSize bytes
+  // if (outSize > size): Filter have not converted anything.
+  //      and it needs at least outSize bytes to convert one block 
+  //      (it's for crypto block algorithms).
+};
+
+CODER_INTERFACE(ICompressCodecsInfo, 0x60)
+{
+  STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE;
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
+  STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE;
+  STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE;
+};
+CODER_INTERFACE(ISetCompressCodecsInfo, 0x61)
+{
+  STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE;
+};
+
+CODER_INTERFACE(ICryptoProperties, 0x80)
+{
+  STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE;
+  STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE;
+};
+
+/*
+CODER_INTERFACE(ICryptoResetSalt, 0x88)
+{
+  STDMETHOD(ResetSalt)() PURE;
+};
+*/
+
+CODER_INTERFACE(ICryptoResetInitVector, 0x8C)
+{
+  STDMETHOD(ResetInitVector)() PURE;
+};
+
+CODER_INTERFACE(ICryptoSetPassword, 0x90)
+{
+  STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE;
+};
+
+CODER_INTERFACE(ICryptoSetCRC, 0xA0)
+{
+  STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;
+};
+
+//////////////////////
+// It's for DLL file
+namespace NMethodPropID
+{
+  enum EEnum
+  {
+    kID,
+    kName,
+    kDecoder,
+    kEncoder,
+    kInStreams,
+    kOutStreams,
+    kDescription,
+    kDecoderIsAssigned,
+    kEncoderIsAssigned
+  };
+}
+
+#endif

Added: trunk/lzma/CPP/7zip/IDecl.h
===================================================================
--- trunk/lzma/CPP/7zip/IDecl.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/IDecl.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,15 @@
+// IDecl.h
+
+#ifndef __IDECL_H
+#define __IDECL_H
+
+#include "../Common/MyUnknown.h"
+
+#define DECL_INTERFACE_SUB(i, base, groupId, subId) \
+DEFINE_GUID(IID_ ## i, \
+0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \
+struct i: public base
+
+#define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId)
+
+#endif

Added: trunk/lzma/CPP/7zip/IPassword.h
===================================================================
--- trunk/lzma/CPP/7zip/IPassword.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/IPassword.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// IPassword.h
+
+#ifndef __IPASSWORD_H
+#define __IPASSWORD_H
+
+#include "../Common/MyUnknown.h"
+#include "../Common/Types.h"
+
+#include "IDecl.h"
+
+#define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x)
+
+PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10)
+{
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE;
+};
+
+PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11)
+{
+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE;
+};
+
+#endif
+

Added: trunk/lzma/CPP/7zip/IProgress.h
===================================================================
--- trunk/lzma/CPP/7zip/IProgress.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/IProgress.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,30 @@
+// Interface/IProgress.h
+
+#ifndef __IPROGRESS_H
+#define __IPROGRESS_H
+
+#include "../Common/MyUnknown.h"
+#include "../Common/Types.h"
+
+#include "IDecl.h"
+
+DECL_INTERFACE(IProgress, 0, 5)
+{
+  STDMETHOD(SetTotal)(UInt64 total) PURE;
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE;
+};
+
+/*
+// {23170F69-40C1-278A-0000-000000050002}
+DEFINE_GUID(IID_IProgress2, 
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02);
+MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002")
+IProgress2: public IUnknown
+{
+public:
+  STDMETHOD(SetTotal)(const UInt64 *total) PURE;
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE;
+};
+*/
+
+#endif

Added: trunk/lzma/CPP/7zip/IStream.h
===================================================================
--- trunk/lzma/CPP/7zip/IStream.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/IStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,58 @@
+// IStream.h
+
+#ifndef __ISTREAM_H
+#define __ISTREAM_H
+
+#include "../Common/MyUnknown.h"
+#include "../Common/Types.h"
+
+#include "IDecl.h"
+
+#define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x)
+#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x)
+
+STREAM_INTERFACE(ISequentialInStream, 0x01)
+{
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
+  /*
+  Out: if size != 0, return_value = S_OK and (*processedSize == 0),
+    then there are no more bytes in stream.
+  if (size > 0) && there are bytes in stream, 
+  this function must read at least 1 byte.
+  This function is allowed to read less than number of remaining bytes in stream.
+  You must call Read function in loop, if you need exact amount of data
+  */
+};
+
+STREAM_INTERFACE(ISequentialOutStream, 0x02)
+{
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;
+  /*
+  if (size > 0) this function must write at least 1 byte.
+  This function is allowed to write less than "size".
+  You must call Write function in loop, if you need to write exact amount of data
+  */
+};
+
+STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)
+{
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
+};
+
+STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04)
+{
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
+  STDMETHOD(SetSize)(Int64 newSize) PURE;
+};
+
+STREAM_INTERFACE(IStreamGetSize, 0x06)
+{
+  STDMETHOD(GetSize)(UInt64 *size) PURE;
+};
+
+STREAM_INTERFACE(IOutStreamFlush, 0x07)
+{
+  STDMETHOD(Flush)() PURE;
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/MyVersion.h
===================================================================
--- trunk/lzma/CPP/7zip/MyVersion.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/MyVersion.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,8 @@
+#define MY_VER_MAJOR 4
+#define MY_VER_MINOR 57
+#define MY_VER_BUILD 0
+#define MY_VERSION "4.57"
+#define MY_7ZIP_VERSION "7-Zip 4.57"
+#define MY_DATE "2007-12-06"
+#define MY_COPYRIGHT "Copyright (c) 1999-2007 Igor Pavlov"
+#define MY_VERSION_COPYRIGHT_DATE MY_VERSION "  " MY_COPYRIGHT "  " MY_DATE

Added: trunk/lzma/CPP/7zip/MyVersionInfo.rc
===================================================================
--- trunk/lzma/CPP/7zip/MyVersionInfo.rc	                        (rev 0)
+++ trunk/lzma/CPP/7zip/MyVersionInfo.rc	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,45 @@
+#include <WinVer.h>
+#include "MyVersion.h"
+
+#define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0
+
+#ifdef DEBUG
+#define DBG_FL VS_FF_DEBUG
+#else
+#define DBG_FL 0
+#endif
+
+#define MY_VERSION_INFO(fileType, descr, intName, origName)  \
+LANGUAGE 9, 1 \
+1 VERSIONINFO \
+  FILEVERSION MY_VER \
+  PRODUCTVERSION MY_VER \
+  FILEFLAGSMASK VS_FFI_FILEFLAGSMASK \
+  FILEFLAGS DBG_FL \
+  FILEOS VOS_NT_WINDOWS32 \
+  FILETYPE fileType \
+  FILESUBTYPE 0x0L \
+BEGIN \
+    BLOCK "StringFileInfo" \
+    BEGIN  \
+        BLOCK "040904b0" \
+        BEGIN \
+            VALUE "CompanyName", "Igor Pavlov" \
+            VALUE "FileDescription", descr \
+            VALUE "FileVersion", MY_VERSION  \
+            VALUE "InternalName", intName \
+            VALUE "LegalCopyright", MY_COPYRIGHT \
+            VALUE "OriginalFilename", origName \
+            VALUE "ProductName", "7-Zip" \
+            VALUE "ProductVersion", MY_VERSION \
+        END \
+    END \
+    BLOCK "VarFileInfo" \
+    BEGIN \
+        VALUE "Translation", 0x409, 1200 \
+    END \
+END
+
+#define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(VFT_APP, descr, intName, intName ".exe")
+
+#define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(VFT_DLL, descr, intName, intName ".dll")

Added: trunk/lzma/CPP/7zip/PropID.h
===================================================================
--- trunk/lzma/CPP/7zip/PropID.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/PropID.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,60 @@
+// Interface/PropID.h
+
+#ifndef __INTERFACE_PROPID_H
+#define __INTERFACE_PROPID_H
+
+enum
+{
+  kpidNoProperty = 0,
+  
+  kpidHandlerItemIndex = 2,
+  kpidPath,
+  kpidName,
+  kpidExtension,
+  kpidIsFolder,
+  kpidSize,
+  kpidPackedSize,
+  kpidAttributes,
+  kpidCreationTime,
+  kpidLastAccessTime,
+  kpidLastWriteTime,
+  kpidSolid, 
+  kpidCommented, 
+  kpidEncrypted, 
+  kpidSplitBefore, 
+  kpidSplitAfter, 
+  kpidDictionarySize, 
+  kpidCRC, 
+  kpidType,
+  kpidIsAnti,
+  kpidMethod,
+  kpidHostOS,
+  kpidFileSystem,
+  kpidUser,
+  kpidGroup,
+  kpidBlock,
+  kpidComment,
+  kpidPosition,
+  kpidPrefix,
+  kpidNumSubFolders,
+  kpidNumSubFiles,
+  kpidUnpackVer,
+  kpidVolume,
+  kpidIsVolume,
+  kpidOffset,
+  kpidLinks,
+  kpidNumBlocks,
+  kpidNumVolumes,
+
+  kpidTotalSize = 0x1100,
+  kpidFreeSpace, 
+  kpidClusterSize,
+  kpidVolumeName,
+
+  kpidLocalName = 0x1200,
+  kpidProvider,
+
+  kpidUserDefined = 0x10000
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Client7z/Client7z.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Client7z/Client7z.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Client7z/Client7z.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,880 @@
+// Client7z.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantConversions.h"
+#include "Windows/DLL.h"
+#include "Windows/FileDir.h"
+#include "Windows/FileName.h"
+#include "Windows/FileFind.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Archive/IArchive.h"
+#include "../../IPassword.h"
+#include "../../MyVersion.h"
+
+
+// {23170F69-40C1-278A-1000-000110070000}
+DEFINE_GUID(CLSID_CFormat7z, 
+  0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);
+
+using namespace NWindows;
+
+#define kDllName "7z.dll"
+
+static const char *kCopyrightString = MY_7ZIP_VERSION
+" ("  kDllName " client) "  
+MY_COPYRIGHT " " MY_DATE;
+
+static const char *kHelpString = 
+"Usage: Client7z.exe [a | l | x ] archive.7z [fileName ...]\n"
+"Examples:\n"
+"  Client7z.exe a archive.7z f1.txt f2.txt  : compress two files to archive.7z\n"
+"  Client7z.exe l archive.7z   : List contents of archive.7z\n"
+"  Client7z.exe x archive.7z   : eXtract files from archive.7z\n";
+
+
+typedef UINT32 (WINAPI * CreateObjectFunc)(
+    const GUID *clsID, 
+    const GUID *interfaceID, 
+    void **outObject);
+
+#ifdef _WIN32
+#ifndef _UNICODE
+bool g_IsNT = false;
+static inline bool IsItWindowsNT()
+{
+  OSVERSIONINFO versionInfo;
+  versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+  if (!::GetVersionEx(&versionInfo)) 
+    return false;
+  return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+#endif
+#endif
+
+void PrintString(const UString &s)
+{
+  printf("%s", (LPCSTR)GetOemString(s));
+}
+
+void PrintString(const AString &s)
+{
+  printf("%s", (LPCSTR)s);
+}
+
+void PrintNewLine()
+{
+  PrintString("\n");
+}
+
+void PrintStringLn(const AString &s)
+{
+  PrintString(s);
+  PrintNewLine();
+}
+
+void PrintError(const AString &s)
+{
+  PrintNewLine();
+  PrintString(s);
+  PrintNewLine();
+}
+
+static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
+{
+  NCOM::CPropVariant prop;
+  RINOK(archive->GetProperty(index, propID, &prop));
+  if(prop.vt == VT_BOOL)
+    result = VARIANT_BOOLToBool(prop.boolVal);
+  else if (prop.vt == VT_EMPTY)
+    result = false;
+  else
+    return E_FAIL;
+  return S_OK;
+}
+
+static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
+{
+  return IsArchiveItemProp(archive, index, kpidIsFolder, result);
+}
+
+
+static const wchar_t *kEmptyFileAlias = L"[Content]";
+
+
+//////////////////////////////////////////////////////////////
+// Archive Open callback class
+
+
+class CArchiveOpenCallback: 
+  public IArchiveOpenCallback,
+  public ICryptoGetTextPassword,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+
+  STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
+  STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
+
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+
+  bool PasswordIsDefined;
+  UString Password;
+
+  CArchiveOpenCallback() : PasswordIsDefined(false) {}
+};
+
+STDMETHODIMP CArchiveOpenCallback::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
+{
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveOpenCallback::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */)
+{
+  return S_OK;
+}
+  
+STDMETHODIMP CArchiveOpenCallback::CryptoGetTextPassword(BSTR *password)
+{
+  if (!PasswordIsDefined)
+  {
+    // You can ask real password here from user
+    // Password = GetPassword(OutStream); 
+    // PasswordIsDefined = true;
+    PrintError("Password is not defined");
+    return E_ABORT;
+  }
+  CMyComBSTR tempName(Password);
+  *password = tempName.Detach();
+  return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////
+// Archive Extracting callback class
+
+static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";
+
+static const char *kTestingString    =  "Testing     ";
+static const char *kExtractingString =  "Extracting  ";
+static const char *kSkippingString   =  "Skipping    ";
+
+static const char *kUnsupportedMethod = "Unsupported Method";
+static const char *kCRCFailed = "CRC Failed";
+static const char *kDataError = "Data Error";
+static const char *kUnknownError = "Unknown Error";
+
+class CArchiveExtractCallback: 
+  public IArchiveExtractCallback,
+  public ICryptoGetTextPassword,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
+
+  // IProgress
+  STDMETHOD(SetTotal)(UInt64 size);
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+  // IArchiveExtractCallback
+  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);
+  STDMETHOD(PrepareOperation)(Int32 askExtractMode);
+  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);
+
+  // ICryptoGetTextPassword
+  STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);
+
+private:
+  CMyComPtr<IInArchive> _archiveHandler;
+  UString _directoryPath;  // Output directory
+  UString _filePath;       // name inside arcvhive
+  UString _diskFilePath;   // full path to file on disk
+  bool _extractMode;
+  struct CProcessedFileInfo
+  {
+    FILETIME UTCLastWriteTime;
+    UInt32 Attributes;
+    bool IsDirectory;
+    bool AttributesAreDefined;
+    bool UTCLastWriteTimeIsDefined;
+  } _processedFileInfo;
+
+  COutFileStream *_outFileStreamSpec;
+  CMyComPtr<ISequentialOutStream> _outFileStream;
+
+public:
+  void Init(IInArchive *archiveHandler, const UString &directoryPath);
+
+  UInt64 NumErrors;
+  bool PasswordIsDefined;
+  UString Password;
+
+  CArchiveExtractCallback() : PasswordIsDefined(false) {}
+};
+
+void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath)
+{
+  NumErrors = 0;
+  _archiveHandler = archiveHandler;
+  _directoryPath = directoryPath;
+  NFile::NName::NormalizeDirPathPrefix(_directoryPath);
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */)
+{
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */)
+{
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, 
+    ISequentialOutStream **outStream, Int32 askExtractMode)
+{
+  *outStream = 0;
+  _outFileStream.Release();
+
+  {
+    // Get Name
+    NCOM::CPropVariant propVariant;
+    RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariant));
+    
+    UString fullPath;
+    if(propVariant.vt == VT_EMPTY)
+      fullPath = kEmptyFileAlias;
+    else 
+    {
+      if(propVariant.vt != VT_BSTR)
+        return E_FAIL;
+      fullPath = propVariant.bstrVal;
+    }
+    _filePath = fullPath;
+  }
+
+  if (askExtractMode != NArchive::NExtract::NAskMode::kExtract)
+    return S_OK;
+
+  {
+    // Get Attributes
+    NCOM::CPropVariant propVariant;
+    RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &propVariant));
+    if (propVariant.vt == VT_EMPTY)
+    {
+      _processedFileInfo.Attributes = 0;
+      _processedFileInfo.AttributesAreDefined = false;
+    }
+    else
+    {
+      if (propVariant.vt != VT_UI4)
+        throw "incorrect item";
+      _processedFileInfo.Attributes = propVariant.ulVal;
+      _processedFileInfo.AttributesAreDefined = true;
+    }
+  }
+
+  RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory));
+
+  {
+    // Get Modified Time
+    NCOM::CPropVariant propVariant;
+    RINOK(_archiveHandler->GetProperty(index, kpidLastWriteTime, &propVariant));
+    _processedFileInfo.UTCLastWriteTimeIsDefined = false;
+    switch(propVariant.vt)
+    {
+      case VT_EMPTY:
+        // _processedFileInfo.UTCLastWriteTime = _utcLastWriteTimeDefault;
+        break;
+      case VT_FILETIME:
+        _processedFileInfo.UTCLastWriteTime = propVariant.filetime;
+        _processedFileInfo.UTCLastWriteTimeIsDefined = true;
+        break;
+      default:
+        return E_FAIL;
+    }
+
+  }
+  {
+    // Get Size
+    NCOM::CPropVariant propVariant;
+    RINOK(_archiveHandler->GetProperty(index, kpidSize, &propVariant));
+    bool newFileSizeDefined = (propVariant.vt != VT_EMPTY);
+    UInt64 newFileSize;
+    if (newFileSizeDefined)
+      newFileSize = ConvertPropVariantToUInt64(propVariant);
+  }
+
+  
+  {
+    // Create folders for file
+    int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);
+    if (slashPos >= 0)
+      NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos));
+  }
+
+  UString fullProcessedPath = _directoryPath + _filePath;
+  _diskFilePath = fullProcessedPath;
+
+  if (_processedFileInfo.IsDirectory)
+  {
+    NFile::NDirectory::CreateComplexDirectory(fullProcessedPath);
+  }
+  else
+  {
+    NFile::NFind::CFileInfoW fileInfo;
+    if(NFile::NFind::FindFile(fullProcessedPath, fileInfo))
+    {
+      if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
+      {
+        PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath);
+        return E_ABORT;
+      }
+    }
+    
+    _outFileStreamSpec = new COutFileStream;
+    CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
+    if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS))
+    {
+      PrintString((UString)L"can not open output file " + fullProcessedPath);
+      return E_ABORT;
+    }
+    _outFileStream = outStreamLoc;
+    *outStream = outStreamLoc.Detach();
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
+{
+  _extractMode = false;
+  switch (askExtractMode)
+  {
+    case NArchive::NExtract::NAskMode::kExtract:
+      _extractMode = true;
+  };
+  switch (askExtractMode)
+  {
+    case NArchive::NExtract::NAskMode::kExtract:
+      PrintString(kExtractingString);
+      break;
+    case NArchive::NExtract::NAskMode::kTest:
+      PrintString(kTestingString);
+      break;
+    case NArchive::NExtract::NAskMode::kSkip:
+      PrintString(kSkippingString);
+      break;
+  };
+  PrintString(_filePath);
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
+{
+  switch(operationResult)
+  {
+    case NArchive::NExtract::NOperationResult::kOK:
+      break;
+    default:
+    {
+      NumErrors++;
+      PrintString("     ");
+      switch(operationResult)
+      {
+        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
+          PrintString(kUnsupportedMethod);
+          break;
+        case NArchive::NExtract::NOperationResult::kCRCError:
+          PrintString(kCRCFailed);
+          break;
+        case NArchive::NExtract::NOperationResult::kDataError:
+          PrintString(kDataError);
+          break;
+        default:
+          PrintString(kUnknownError);
+      }
+    }
+  }
+
+  if (_outFileStream != NULL)
+  {
+    if (_processedFileInfo.UTCLastWriteTimeIsDefined)
+      _outFileStreamSpec->SetLastWriteTime(&_processedFileInfo.UTCLastWriteTime);
+    RINOK(_outFileStreamSpec->Close());
+  }
+  _outFileStream.Release();
+  if (_extractMode && _processedFileInfo.AttributesAreDefined)
+    NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes);
+  PrintNewLine();
+  return S_OK;
+}
+
+
+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
+{
+  if (!PasswordIsDefined)
+  {
+    // You can ask real password here from user
+    // Password = GetPassword(OutStream); 
+    // PasswordIsDefined = true;
+    PrintError("Password is not defined");
+    return E_ABORT;
+  }
+  CMyComBSTR tempName(Password);
+  *password = tempName.Detach();
+  return S_OK;
+}
+
+
+
+//////////////////////////////////////////////////////////////
+// Archive Creating callback class
+
+struct CDirItem
+{ 
+  UInt32 Attributes;
+  FILETIME CreationTime;
+  FILETIME LastAccessTime;
+  FILETIME LastWriteTime;
+  UInt64 Size;
+  UString Name;
+  UString FullPath;
+  bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
+};
+
+class CArchiveUpdateCallback: 
+  public IArchiveUpdateCallback2,
+  public ICryptoGetTextPassword2,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2)
+
+  // IProgress
+  STDMETHOD(SetTotal)(UInt64 size);
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+  // IUpdateCallback2
+  STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);  
+  STDMETHOD(GetUpdateItemInfo)(UInt32 index, 
+      Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
+  STDMETHOD(SetOperationResult)(Int32 operationResult);
+  STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);
+  STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);
+
+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
+
+public:
+  CRecordVector<UInt64> VolumesSizes;
+  UString VolName;
+  UString VolExt;
+
+  UString DirPrefix;
+  const CObjectVector<CDirItem> *DirItems;
+
+  bool PasswordIsDefined;
+  UString Password;
+  bool AskPassword;
+
+  bool m_NeedBeClosed;
+
+  UStringVector FailedFiles;
+  CRecordVector<HRESULT> FailedCodes;
+
+  CArchiveUpdateCallback(): PasswordIsDefined(false), AskPassword(false), DirItems(0) {};
+
+  ~CArchiveUpdateCallback() { Finilize(); }
+  HRESULT Finilize();
+
+  void Init(const CObjectVector<CDirItem> *dirItems)
+  {
+    DirItems = dirItems;
+    m_NeedBeClosed = false;
+    FailedFiles.Clear();
+    FailedCodes.Clear();
+  }
+};
+
+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 /* size */)
+{
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 * /* completeValue */)
+{
+  return S_OK;
+}
+
+
+STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG ** /* enumerator */)
+{
+  return E_NOTIMPL;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 /* index */, 
+      Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
+{
+  if(newData != NULL)
+    *newData = BoolToInt(true);
+  if(newProperties != NULL)
+    *newProperties = BoolToInt(true);
+  if(indexInArchive != NULL)
+    *indexInArchive = UInt32(-1);
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  NWindows::NCOM::CPropVariant propVariant;
+  
+  if (propID == kpidIsAnti)
+  {
+    propVariant = false;
+    propVariant.Detach(value);
+    return S_OK;
+  }
+
+  {
+    const CDirItem &dirItem = (*DirItems)[index];
+    switch(propID)
+    {
+      case kpidPath:
+        propVariant = dirItem.Name;
+        break;
+      case kpidIsFolder:
+        propVariant = dirItem.IsDirectory();
+        break;
+      case kpidSize:
+        propVariant = dirItem.Size;
+        break;
+      case kpidAttributes:
+        propVariant = dirItem.Attributes;
+        break;
+      case kpidLastAccessTime:
+        propVariant = dirItem.LastAccessTime;
+        break;
+      case kpidCreationTime:
+        propVariant = dirItem.CreationTime;
+        break;
+      case kpidLastWriteTime:
+        propVariant = dirItem.LastWriteTime;
+        break;
+    }
+  }
+  propVariant.Detach(value);
+  return S_OK;
+}
+
+HRESULT CArchiveUpdateCallback::Finilize()
+{
+  if (m_NeedBeClosed)
+  {
+    PrintNewLine();
+    m_NeedBeClosed = false;
+  }
+  return S_OK;
+}
+
+static void GetStream2(const wchar_t *name)
+{
+  PrintString("Compressing  ");
+  if (name[0] == 0)
+    name = kEmptyFileAlias;
+  PrintString(name);
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
+{
+  RINOK(Finilize());
+
+  const CDirItem &dirItem = (*DirItems)[index];
+  GetStream2(dirItem.Name);
+ 
+  if(dirItem.IsDirectory())
+    return S_OK;
+
+  {
+    CInFileStream *inStreamSpec = new CInFileStream;
+    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+    UString path = DirPrefix + dirItem.FullPath;
+    if(!inStreamSpec->Open(path))
+    {
+      DWORD sysError = ::GetLastError();
+      FailedCodes.Add(sysError);
+      FailedFiles.Add(path);
+      // if (systemError == ERROR_SHARING_VIOLATION)
+      {
+        PrintNewLine();
+        PrintError("WARNING: can't open file");
+        // PrintString(NError::MyFormatMessageW(systemError));
+        return S_FALSE;
+      }
+      // return sysError;
+    }
+    *inStream = inStreamLoc.Detach();
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 /* operationResult */)
+{
+  m_NeedBeClosed = true;
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
+{
+  if (VolumesSizes.Size() == 0)
+    return S_FALSE;
+  if (index >= (UInt32)VolumesSizes.Size())
+    index = VolumesSizes.Size() - 1;
+  *size = VolumesSizes[index];
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
+{
+  wchar_t temp[32];
+  ConvertUInt64ToString(index + 1, temp);
+  UString res = temp;
+  while (res.Length() < 2)
+    res = UString(L'0') + res;
+  UString fileName = VolName;
+  fileName += L'.';
+  fileName += res;
+  fileName += VolExt;
+  COutFileStream *streamSpec = new COutFileStream;
+  CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
+  if(!streamSpec->Create(fileName, false))
+    return ::GetLastError();
+  *volumeStream = streamLoc.Detach();
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
+{
+  if (!PasswordIsDefined) 
+  {
+    if (AskPassword)
+    {
+      // You can ask real password here from user
+      // Password = GetPassword(OutStream); 
+      // PasswordIsDefined = true;
+      PrintError("Password is not defined");
+      return E_ABORT;
+    }
+  }
+  *passwordIsDefined = BoolToInt(PasswordIsDefined);
+  CMyComBSTR tempName(Password);
+  *password = tempName.Detach();
+  return S_OK;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// Main function
+
+int 
+#ifdef _MSC_VER
+__cdecl 
+#endif
+main(int argc, char* argv[])
+{
+  #ifdef _WIN32
+  #ifndef _UNICODE
+  g_IsNT = IsItWindowsNT();
+  #endif
+  #endif
+
+  PrintStringLn(kCopyrightString);
+
+  if (argc < 3)
+  {
+    PrintStringLn(kHelpString);
+    return 1;
+  }
+  NWindows::NDLL::CLibrary library;
+  if (!library.Load(TEXT(kDllName)))
+  {
+    PrintError("Can not load library");
+    return 1;
+  }
+  CreateObjectFunc createObjectFunc = (CreateObjectFunc)library.GetProcAddress("CreateObject");
+  if (createObjectFunc == 0)
+  {
+    PrintError("Can not get CreateObject");
+    return 1;
+  }
+
+  AString command = argv[1];
+  UString archiveName = GetUnicodeString(argv[2], CP_OEMCP);
+  if (command.CompareNoCase("a") == 0)
+  {
+    // create archive command
+    if (argc < 4)
+    {
+      PrintStringLn(kHelpString);
+      return 1;
+    }
+    CObjectVector<CDirItem> dirItems;
+    int i;
+    for (i = 3; i < argc; i++)
+    {
+      CDirItem item;
+      UString name = GetUnicodeString(argv[i], CP_OEMCP);
+      
+      NFile::NFind::CFileInfoW fileInfo;
+      if (!NFile::NFind::FindFile(name, fileInfo))
+      {
+        PrintString(UString(L"Can't find file") + name);
+        return 1;
+      }
+
+      item.Attributes = fileInfo.Attributes;
+      item.Size = fileInfo.Size;
+      item.CreationTime = fileInfo.CreationTime;
+      item.LastAccessTime = fileInfo.LastAccessTime;
+      item.LastWriteTime = fileInfo.LastWriteTime;
+      item.Name = name;
+      item.FullPath = name;
+      dirItems.Add(item);
+    }
+    COutFileStream *outFileStreamSpec = new COutFileStream;
+    CMyComPtr<IOutStream> outFileStream = outFileStreamSpec;
+    if (!outFileStreamSpec->Create(archiveName, false))
+    {
+      PrintError("can't create archive file");
+      return 1;
+    }
+
+    CMyComPtr<IOutArchive> outArchive;
+    if (createObjectFunc(&CLSID_CFormat7z, &IID_IOutArchive, (void **)&outArchive) != S_OK)
+    {
+      PrintError("Can not get class object");
+      return 1;
+    }
+
+    CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+    CMyComPtr<IArchiveUpdateCallback2> updateCallback(updateCallbackSpec);
+    updateCallbackSpec->Init(&dirItems);
+    // updateCallbackSpec->PasswordIsDefined = true;
+    // updateCallbackSpec->Password = L"1";
+
+    HRESULT result = outArchive->UpdateItems(outFileStream, dirItems.Size(), updateCallback);
+    updateCallbackSpec->Finilize();
+    if (result != S_OK)
+    {
+      PrintError("Update Error");
+      return 1;
+    }
+    for (i = 0; i < updateCallbackSpec->FailedFiles.Size(); i++)
+    {
+      PrintNewLine();
+      PrintString((UString)L"Error for file: " + updateCallbackSpec->FailedFiles[i]);
+    }
+    if (updateCallbackSpec->FailedFiles.Size() != 0)
+      return 1;
+  }
+  else
+  {
+    if (argc != 3)
+    {
+      PrintStringLn(kHelpString);
+      return 1;
+    }
+
+    bool listCommand;
+    if (command.CompareNoCase("l") == 0)
+      listCommand = true;
+    else if (command.CompareNoCase("x") == 0)
+      listCommand = false;
+    else
+    {
+      PrintError("incorrect command");
+      return 1;
+    }
+  
+    CMyComPtr<IInArchive> archive;
+    if (createObjectFunc(&CLSID_CFormat7z, &IID_IInArchive, (void **)&archive) != S_OK)
+    {
+      PrintError("Can not get class object");
+      return 1;
+    }
+    
+    CInFileStream *fileSpec = new CInFileStream;
+    CMyComPtr<IInStream> file = fileSpec;
+    
+    if (!fileSpec->Open(archiveName))
+    {
+      PrintError("Can not open archive file");
+      return 1;
+    }
+
+    {
+      CArchiveOpenCallback *openCallbackSpec = new CArchiveOpenCallback;
+      CMyComPtr<IArchiveOpenCallback> openCallback(openCallbackSpec);
+      openCallbackSpec->PasswordIsDefined = false;
+      // openCallbackSpec->PasswordIsDefined = true;
+      // openCallbackSpec->Password = L"1";
+      
+      if (archive->Open(file, 0, openCallback) != S_OK)
+      {
+        PrintError("Can not open archive");
+        return 1;
+      }
+    }
+    
+    if (listCommand)
+    {
+      // List command
+      UInt32 numItems = 0;
+      archive->GetNumberOfItems(&numItems);  
+      for (UInt32 i = 0; i < numItems; i++)
+      {
+        {
+          // Get uncompressed size of file
+          NWindows::NCOM::CPropVariant propVariant;
+          archive->GetProperty(i, kpidSize, &propVariant);
+          UString s = ConvertPropVariantToString(propVariant);
+          PrintString(s);
+          PrintString("  ");
+        }
+        {
+          // Get name of file
+          NWindows::NCOM::CPropVariant propVariant;
+          archive->GetProperty(i, kpidPath, &propVariant);
+          UString s = ConvertPropVariantToString(propVariant);
+          PrintString(s);
+        }
+        PrintString("\n");
+      }
+    }
+    else
+    {
+      // Extract command
+      CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+      CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
+      extractCallbackSpec->Init(archive, L""); // second parameter is output folder path
+      extractCallbackSpec->PasswordIsDefined = false;
+      // extractCallbackSpec->PasswordIsDefined = true;
+      // extractCallbackSpec->Password = L"1";
+      HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback);
+      if (result != S_OK)
+      {
+        PrintError("Extract Error");
+        return 1;
+      }
+    }
+  }
+  return 0;
+}

Added: trunk/lzma/CPP/7zip/UI/Client7z/Client7z.dsp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Client7z/Client7z.dsp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Client7z/Client7z.dsp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,226 @@
+# Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=Client7z - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "Client7z.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "Client7z - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "Client7z - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "Client7z - Win32 Release"
+# Name "Client7z - Win32 Debug"
+# Begin Group "Spec"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\DLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileFind.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariantConversions.h
+# End Source File
+# End Group
+# Begin Group "Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\IntToString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyString.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\MyVector.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\Wildcard.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\FileStreams.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\Client7z.cpp
+# End Source File
+# End Target
+# End Project

Added: trunk/lzma/CPP/7zip/UI/Client7z/Client7z.dsw
===================================================================
--- trunk/lzma/CPP/7zip/UI/Client7z/Client7z.dsw	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Client7z/Client7z.dsw	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Client7z"=.\Client7z.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

Added: trunk/lzma/CPP/7zip/UI/Client7z/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Client7z/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Client7z/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/UI/Client7z/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Client7z/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Client7z/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include <windows.h>
+#include <stdio.h>
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Client7z/makefile
===================================================================
--- trunk/lzma/CPP/7zip/UI/Client7z/makefile	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Client7z/makefile	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,45 @@
+PROG = 7z.exe
+LIBS = $(LIBS) user32.lib oleaut32.lib advapi32.lib
+CFLAGS = $(CFLAGS) -I ../../../
+
+CONSOLE_OBJS = \
+  $O\Client7z.obj \
+
+COMMON_OBJS = \
+  $O\IntToString.obj \
+  $O\NewHandler.obj \
+  $O\MyString.obj \
+  $O\StringConvert.obj \
+  $O\StringToInt.obj \
+  $O\MyVector.obj \
+  $O\Wildcard.obj \
+
+WIN_OBJS = \
+  $O\DLL.obj \
+  $O\FileDir.obj \
+  $O\FileFind.obj \
+  $O\FileIO.obj \
+  $O\FileName.obj \
+  $O\PropVariant.obj \
+  $O\PropVariantConversions.obj \
+
+7ZIP_COMMON_OBJS = \
+  $O\FileStreams.obj \
+
+OBJS = \
+  $O\StdAfx.obj \
+  $(CONSOLE_OBJS) \
+  $(COMMON_OBJS) \
+  $(WIN_OBJS) \
+  $(7ZIP_COMMON_OBJS) \
+
+!include "../../../Build.mak"
+
+$(CONSOLE_OBJS): $(*B).cpp
+	$(COMPL)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+	$(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+	$(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+	$(COMPL)

Added: trunk/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1003 @@
+// ArchiveCommandLine.cpp
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#include <io.h>
+#endif
+#include <stdio.h>
+
+#include "Common/ListFileUtils.h"
+#include "Common/StringConvert.h"
+#include "Common/StringToInt.h"
+
+#include "Windows/FileName.h"
+#include "Windows/FileDir.h"
+#ifdef _WIN32
+#include "Windows/FileMapping.h"
+#include "Windows/Synchronization.h"
+#endif
+
+#include "ArchiveCommandLine.h"
+#include "UpdateAction.h"
+#include "Update.h"
+#include "SortUtils.h"
+#include "EnumDirItems.h"
+
+extern bool g_CaseSensitive;
+
+#if _MSC_VER >= 1400
+#define MY_isatty_fileno(x) _isatty(_fileno(x))
+#else
+#define MY_isatty_fileno(x) isatty(fileno(x))
+#endif
+
+#define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); 
+
+using namespace NCommandLineParser;
+using namespace NWindows;
+using namespace NFile;
+
+namespace NKey {
+enum Enum
+{
+  kHelp1 = 0,
+  kHelp2,
+  kHelp3,
+  kDisableHeaders,
+  kDisablePercents,
+  kArchiveType,
+  kYes,
+  kPassword,
+  kProperty,
+  kOutputDir,
+  kWorkingDir,
+  kInclude,
+  kExclude,
+  kArInclude,
+  kArExclude,
+  kNoArName,
+  kUpdate,
+  kVolume,
+  kRecursed,
+  kSfx,
+  kStdIn,
+  kStdOut,
+  kOverwrite,
+  kEmail,
+  kShowDialog,
+  kLargePages,
+  kCharSet,
+  kTechMode,
+  kShareForWrite,
+  kCaseSensitive
+};
+
+}
+
+
+static const wchar_t kRecursedIDChar = 'R';
+static const wchar_t *kRecursedPostCharSet = L"0-";
+
+namespace NRecursedPostCharIndex {
+  enum EEnum 
+  {
+    kWildCardRecursionOnly = 0, 
+    kNoRecursion = 1
+  };
+}
+
+static const char kImmediateNameID = '!';
+static const char kMapNameID = '#';
+static const char kFileListID = '@';
+
+static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
+static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be
+
+static const wchar_t *kOverwritePostCharSet = L"asut";
+
+NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
+{
+  NExtract::NOverwriteMode::kWithoutPrompt,
+  NExtract::NOverwriteMode::kSkipExisting,
+  NExtract::NOverwriteMode::kAutoRename,
+  NExtract::NOverwriteMode::kAutoRenameExisting
+};
+
+static const CSwitchForm kSwitchForms[] = 
+  {
+    { L"?",  NSwitchType::kSimple, false },
+    { L"H",  NSwitchType::kSimple, false },
+    { L"-HELP",  NSwitchType::kSimple, false },
+    { L"BA", NSwitchType::kSimple, false },
+    { L"BD", NSwitchType::kSimple, false },
+    { L"T",  NSwitchType::kUnLimitedPostString, false, 1 },
+    { L"Y",  NSwitchType::kSimple, false },
+    { L"P",  NSwitchType::kUnLimitedPostString, false, 0 },
+    { L"M",  NSwitchType::kUnLimitedPostString, true, 1 },
+    { L"O",  NSwitchType::kUnLimitedPostString, false, 1 },
+    { L"W",  NSwitchType::kUnLimitedPostString, false, 0 },
+    { L"I",  NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
+    { L"X",  NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
+    { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
+    { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
+    { L"AN", NSwitchType::kSimple, false },
+    { L"U",  NSwitchType::kUnLimitedPostString, true, 1},
+    { L"V",  NSwitchType::kUnLimitedPostString, true, 1},
+    { L"R",  NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet },
+    { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 },
+    { L"SI", NSwitchType::kUnLimitedPostString, false, 0 },
+    { L"SO", NSwitchType::kSimple, false, 0 },
+    { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet},
+    { L"SEML", NSwitchType::kUnLimitedPostString, false, 0},
+    { L"AD",  NSwitchType::kSimple, false },
+    { L"SLP", NSwitchType::kUnLimitedPostString, false, 0},
+    { L"SCS", NSwitchType::kUnLimitedPostString, false, 0},
+    { L"SLT", NSwitchType::kSimple, false },
+    { L"SSW", NSwitchType::kSimple, false },
+    { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" }
+  };
+
+static const CCommandForm g_CommandForms[] = 
+{
+  { L"A", false },
+  { L"U", false },
+  { L"D", false },
+  { L"T", false },
+  { L"E", false },
+  { L"X", false },
+  { L"L", false },
+  { L"B", false },
+  { L"I", false }
+};
+
+static const int kNumCommandForms = sizeof(g_CommandForms) /  sizeof(g_CommandForms[0]);
+
+static const wchar_t *kUniversalWildcard = L"*";
+static const int kMinNonSwitchWords = 1;
+static const int kCommandIndex = 0;
+
+// ---------------------------
+// exception messages
+
+static const char *kUserErrorMessage  = "Incorrect command line";
+static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch.";
+static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile";
+static const char *kIncorrectWildCardInCommandLine  = "Incorrect wildcard in command line";
+static const char *kTerminalOutError = "I won't write compressed data to a terminal";
+static const char *kSameTerminalError = "I won't write data and program's messages to same terminal";
+
+static void ThrowException(const char *errorMessage)
+{
+  throw CArchiveCommandLineException(errorMessage);
+};
+
+static void ThrowUserErrorException()
+{
+  ThrowException(kUserErrorMessage);
+};
+
+// ---------------------------
+
+bool CArchiveCommand::IsFromExtractGroup() const
+{
+  switch(CommandType)
+  {
+    case NCommandType::kTest:
+    case NCommandType::kExtract:
+    case NCommandType::kFullExtract:
+      return true;
+    default:
+      return false;
+  }
+}
+
+NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const
+{
+  switch(CommandType)
+  {
+    case NCommandType::kTest:
+    case NCommandType::kFullExtract:
+      return NExtract::NPathMode::kFullPathnames;
+    default:
+      return NExtract::NPathMode::kNoPathnames;
+  }
+}
+
+bool CArchiveCommand::IsFromUpdateGroup() const
+{
+  return (CommandType == NCommandType::kAdd || 
+    CommandType == NCommandType::kUpdate ||
+    CommandType == NCommandType::kDelete);
+}
+
+static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)
+{
+  switch (index)
+  {
+    case NRecursedPostCharIndex::kWildCardRecursionOnly: 
+      return NRecursedType::kWildCardOnlyRecursed;
+    case NRecursedPostCharIndex::kNoRecursion: 
+      return NRecursedType::kNonRecursed;
+    default:
+      return NRecursedType::kRecursed;
+  }
+}
+
+static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)
+{
+  UString commandStringUpper = commandString;
+  commandStringUpper.MakeUpper();
+  UString postString;
+  int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper, 
+      postString) ;
+  if (commandIndex < 0)
+    return false;
+  command.CommandType = (NCommandType::EEnum)commandIndex;
+  return true;
+}
+
+// ------------------------------------------------------------------
+// filenames functions
+
+static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, 
+    const UString &name, bool include, NRecursedType::EEnum type)
+{
+  bool isWildCard = DoesNameContainWildCard(name);
+  bool recursed = false;
+
+  switch (type)
+  {
+    case NRecursedType::kWildCardOnlyRecursed:
+      recursed = isWildCard;
+      break;
+    case NRecursedType::kRecursed:
+      recursed = true;
+      break;
+    case NRecursedType::kNonRecursed:
+      recursed = false;
+      break;
+  }
+  wildcardCensor.AddItem(include, name, recursed);
+  return true;
+}
+
+static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, 
+    LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage)
+{
+  UStringVector names;
+  if (!ReadNamesFromListFile(fileName, names, codePage))
+    throw kIncorrectListFile;
+  for (int i = 0; i < names.Size(); i++)
+    if (!AddNameToCensor(wildcardCensor, names[i], include, type))
+      throw kIncorrectWildCardInListFile;
+}
+
+static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, 
+    const UString &name, bool include, NRecursedType::EEnum recursedType)
+{
+  if (!AddNameToCensor(wildcardCensor, name, include, recursedType))
+    throw kIncorrectWildCardInCommandLine;
+}
+
+static void AddToCensorFromNonSwitchesStrings(
+    int startIndex,
+    NWildcard::CCensor &wildcardCensor, 
+    const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, 
+    bool thereAreSwitchIncludes, UINT codePage)
+{
+  if(nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) 
+    AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type);
+  for(int i = startIndex; i < nonSwitchStrings.Size(); i++)
+  {
+    const UString &s = nonSwitchStrings[i];
+    if (s[0] == kFileListID)
+      AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage);
+    else
+      AddCommandLineWildCardToCensr(wildcardCensor, s, true, type);
+  }
+}
+
+#ifdef _WIN32
+static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, 
+    const UString &switchParam, bool include, 
+    NRecursedType::EEnum commonRecursedType)
+{
+  int splitPos = switchParam.Find(L':');
+  if (splitPos < 0)
+    ThrowUserErrorException();
+  UString mappingName = switchParam.Left(splitPos);
+  
+  UString switchParam2 = switchParam.Mid(splitPos + 1);
+  splitPos = switchParam2.Find(L':');
+  if (splitPos < 0)
+    ThrowUserErrorException();
+  
+  UString mappingSize = switchParam2.Left(splitPos);
+  UString eventName = switchParam2.Mid(splitPos + 1);
+  
+  UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL);
+  UInt32 dataSize = (UInt32)dataSize64;
+  {
+    CFileMapping fileMapping;
+    if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName)))
+      ThrowException("Can not open mapping");
+    LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize);
+    if (data == NULL)
+      ThrowException("MapViewOfFile error");
+    try
+    {
+      const wchar_t *curData = (const wchar_t *)data;
+      if (*curData != 0)
+        ThrowException("Incorrect mapping data");
+      UInt32 numChars = dataSize / sizeof(wchar_t);
+      UString name;
+      for (UInt32 i = 1; i < numChars; i++)
+      {
+        wchar_t c = curData[i];
+        if (c == L'\0')
+        {
+          AddCommandLineWildCardToCensr(wildcardCensor, 
+              name, include, commonRecursedType);
+          name.Empty();
+        }
+        else
+          name += c;
+      }
+      if (!name.IsEmpty())
+        ThrowException("data error");
+    }
+    catch(...)
+    {
+      UnmapViewOfFile(data);
+      throw;
+    }
+    UnmapViewOfFile(data);
+  }
+  
+  {
+    NSynchronization::CManualResetEvent event;
+    if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK)
+      event.Set();
+  }
+}
+#endif
+
+static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, 
+    const UStringVector &strings, bool include, 
+    NRecursedType::EEnum commonRecursedType, UINT codePage)
+{
+  for(int i = 0; i < strings.Size(); i++)
+  {
+    const UString &name = strings[i];
+    NRecursedType::EEnum recursedType;
+    int pos = 0;
+    if (name.Length() < kSomeCludePostStringMinSize)
+      ThrowUserErrorException();
+    if (::MyCharUpper(name[pos]) == kRecursedIDChar)
+    {
+      pos++;
+      int index = UString(kRecursedPostCharSet).Find(name[pos]);
+      recursedType = GetRecursedTypeFromIndex(index);
+      if (index >= 0)
+        pos++;
+    }
+    else
+      recursedType = commonRecursedType;
+    if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize)
+      ThrowUserErrorException();
+    UString tail = name.Mid(pos + 1);
+    if (name[pos] == kImmediateNameID)
+      AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType);
+    else if (name[pos] == kFileListID)
+      AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage);
+    #ifdef _WIN32
+    else if (name[pos] == kMapNameID)
+      ParseMapWithPaths(wildcardCensor, tail, include, recursedType);
+    #endif
+    else
+      ThrowUserErrorException();
+  }
+}
+
+#ifdef _WIN32
+
+// This code converts all short file names to long file names.
+
+static void ConvertToLongName(const UString &prefix, UString &name)
+{
+  if (name.IsEmpty() || DoesNameContainWildCard(name))
+    return;
+  NFind::CFileInfoW fileInfo;
+  if (NFind::FindFile(prefix + name, fileInfo))
+    name = fileInfo.Name;
+}
+
+static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)
+{
+  for (int i = 0; i < items.Size(); i++)
+  {
+    NWildcard::CItem &item = items[i];
+    if (item.Recursive || item.PathParts.Size() != 1)
+      continue;
+    ConvertToLongName(prefix, item.PathParts.Front());
+  }
+}
+
+static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node)
+{
+  ConvertToLongNames(prefix, node.IncludeItems);
+  ConvertToLongNames(prefix, node.ExcludeItems);
+  int i;
+  for (i = 0; i < node.SubNodes.Size(); i++)
+    ConvertToLongName(prefix, node.SubNodes[i].Name);
+  // mix folders with same name
+  for (i = 0; i < node.SubNodes.Size(); i++)
+  {
+    NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];
+    for (int j = i + 1; j < node.SubNodes.Size();)
+    {
+      const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];
+      if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0)
+      {
+        nextNode1.IncludeItems += nextNode2.IncludeItems;
+        nextNode1.ExcludeItems += nextNode2.ExcludeItems;
+        node.SubNodes.Delete(j);
+      }
+      else
+        j++;
+    }
+  }
+  for (i = 0; i < node.SubNodes.Size(); i++)
+  {
+    NWildcard::CCensorNode &nextNode = node.SubNodes[i];
+    ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); 
+  }
+}
+
+static void ConvertToLongNames(NWildcard::CCensor &censor)
+{
+  for (int i = 0; i < censor.Pairs.Size(); i++)
+  {
+    NWildcard::CPair &pair = censor.Pairs[i];
+    ConvertToLongNames(pair.Prefix, pair.Head);
+  }
+}
+
+#endif
+
+static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)
+{
+  switch(i)
+  {
+    case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore;
+    case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy;
+    case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress;
+    case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti;
+  }
+  throw 98111603;
+}
+
+const UString kUpdatePairStateIDSet = L"PQRXYZW";
+const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};
+
+const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti
+
+const wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; 
+const wchar_t kUpdateNewArchivePostCharID = '!'; 
+
+
+static bool ParseUpdateCommandString2(const UString &command, 
+    NUpdateArchive::CActionSet &actionSet, UString &postString)
+{
+  for(int i = 0; i < command.Length();)
+  {
+    wchar_t c = MyCharUpper(command[i]);
+    int statePos = kUpdatePairStateIDSet.Find(c);
+    if (statePos < 0)
+    {
+      postString = command.Mid(i);
+      return true;
+    }
+    i++;
+    if (i >= command.Length())
+      return false;
+    int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i]));
+    if (actionPos < 0)
+      return false;
+    actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos);
+    if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)
+      return false;
+    i++;
+  }
+  postString.Empty();
+  return true;
+}
+
+static void ParseUpdateCommandString(CUpdateOptions &options, 
+    const UStringVector &updatePostStrings, 
+    const NUpdateArchive::CActionSet &defaultActionSet)
+{
+  for(int i = 0; i < updatePostStrings.Size(); i++)
+  {
+    const UString &updateString = updatePostStrings[i];
+    if(updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0)
+    {
+      if(options.UpdateArchiveItself)
+      {
+        options.UpdateArchiveItself = false;
+        options.Commands.Delete(0);
+      }
+    }
+    else
+    {
+      NUpdateArchive::CActionSet actionSet = defaultActionSet;
+
+      UString postString;
+      if (!ParseUpdateCommandString2(updateString, actionSet, postString))
+        ThrowUserErrorException();
+      if(postString.IsEmpty())
+      {
+        if(options.UpdateArchiveItself)
+          options.Commands[0].ActionSet = actionSet;
+      }
+      else
+      {
+        if(MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID)
+          ThrowUserErrorException();
+        CUpdateArchiveCommand uc;
+        UString archivePath = postString.Mid(1);
+        if (archivePath.IsEmpty())
+          ThrowUserErrorException();
+        uc.UserArchivePath = archivePath;
+        uc.ActionSet = actionSet;
+        options.Commands.Add(uc);
+      }
+    }
+  }
+}
+
+static const char kByteSymbol = 'B';
+static const char kKiloSymbol = 'K';
+static const char kMegaSymbol = 'M';
+static const char kGigaSymbol = 'G';
+
+static bool ParseComplexSize(const UString &src, UInt64 &result)
+{
+  UString s = src;
+  s.MakeUpper();
+
+  const wchar_t *start = s;
+  const wchar_t *end;
+  UInt64 number = ConvertStringToUInt64(start, &end);
+  int numDigits = (int)(end - start);
+  if (numDigits == 0 || s.Length() > numDigits + 1)
+    return false;
+  if (s.Length() == numDigits)
+  {
+    result = number;
+    return true;
+  }
+  int numBits;
+  switch (s[numDigits])
+  {
+    case kByteSymbol:
+      result = number;
+      return true;
+    case kKiloSymbol:
+      numBits = 10;
+      break;
+    case kMegaSymbol:
+      numBits = 20;
+      break;
+    case kGigaSymbol:
+      numBits = 30;
+      break;
+    default:
+      return false;
+  }
+  if (number >= ((UInt64)1 << (64 - numBits)))
+    return false;
+  result = number << numBits;
+  return true;
+}
+
+static void SetAddCommandOptions(
+    NCommandType::EEnum commandType, 
+    const CParser &parser, 
+    CUpdateOptions &options)
+{
+  NUpdateArchive::CActionSet defaultActionSet;
+  switch(commandType)
+  {
+    case NCommandType::kAdd: 
+      defaultActionSet = NUpdateArchive::kAddActionSet;
+      break;
+    case NCommandType::kDelete: 
+      defaultActionSet = NUpdateArchive::kDeleteActionSet;
+      break;
+    default: 
+      defaultActionSet = NUpdateArchive::kUpdateActionSet;
+  }
+  
+  options.UpdateArchiveItself = true;
+  
+  options.Commands.Clear();
+  CUpdateArchiveCommand updateMainCommand;
+  updateMainCommand.ActionSet = defaultActionSet;
+  options.Commands.Add(updateMainCommand);
+  if(parser[NKey::kUpdate].ThereIs)
+    ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings, 
+        defaultActionSet);
+  if(parser[NKey::kWorkingDir].ThereIs)
+  {
+    const UString &postString = parser[NKey::kWorkingDir].PostStrings[0];
+    if (postString.IsEmpty())
+      NDirectory::MyGetTempPath(options.WorkingDir);
+    else
+      options.WorkingDir = postString;
+  }
+  options.SfxMode = parser[NKey::kSfx].ThereIs;
+  if (options.SfxMode)
+    options.SfxModule = parser[NKey::kSfx].PostStrings[0];
+
+  if (parser[NKey::kVolume].ThereIs)
+  {
+    const UStringVector &sv = parser[NKey::kVolume].PostStrings;
+    for (int i = 0; i < sv.Size(); i++)
+    {
+      UInt64 size;
+      if (!ParseComplexSize(sv[i], size))
+        ThrowException("Incorrect volume size");
+      options.VolumesSizes.Add(size);
+    }
+  }
+}
+
+static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &properties)
+{
+  if (parser[NKey::kProperty].ThereIs)
+  {
+    // options.MethodMode.Properties.Clear();
+    for(int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
+    {
+      CProperty property;
+      const UString &postString = parser[NKey::kProperty].PostStrings[i];
+      int index = postString.Find(L'=');
+      if (index < 0)
+        property.Name = postString;
+      else
+      {
+        property.Name = postString.Left(index);
+        property.Value = postString.Mid(index + 1);
+      }
+      properties.Add(property);
+    }
+  }
+}
+
+CArchiveCommandLineParser::CArchiveCommandLineParser(): 
+  parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {}
+
+void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings,
+    CArchiveCommandLineOptions &options)
+{
+  try
+  {
+    parser.ParseStrings(kSwitchForms, commandStrings);
+  }
+  catch(...) 
+  {
+    ThrowUserErrorException();
+  }
+
+  options.IsInTerminal = MY_IS_TERMINAL(stdin);
+  options.IsStdOutTerminal = MY_IS_TERMINAL(stdout);
+  options.IsStdErrTerminal = MY_IS_TERMINAL(stderr);
+  options.StdOutMode = parser[NKey::kStdOut].ThereIs;
+  options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
+  options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs  || parser[NKey::kHelp3].ThereIs;
+
+  #ifdef _WIN32
+  options.LargePages = false;
+  if (parser[NKey::kLargePages].ThereIs)
+  {
+    const UString &postString = parser[NKey::kLargePages].PostStrings.Front();
+    if (postString.IsEmpty())
+      options.LargePages = true;
+  }
+  #endif
+}
+
+struct CCodePagePair
+{
+  const wchar_t *Name;
+  UINT CodePage;
+};
+
+static CCodePagePair g_CodePagePairs[] = 
+{
+  { L"UTF-8", CP_UTF8 },
+  { L"WIN",   CP_ACP },
+  { L"DOS",   CP_OEMCP }
+};
+
+static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]);
+
+static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v)
+{
+  const wchar_t *end;
+  UInt64 number = ConvertStringToUInt64(s, &end);
+  if (*end != 0)
+    return false;
+  if (number > (UInt32)0xFFFFFFFF)
+    return false;
+  v = (UInt32)number;
+  return true;
+}
+
+void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
+{
+  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
+  int numNonSwitchStrings = nonSwitchStrings.Size();
+  if(numNonSwitchStrings < kMinNonSwitchWords)  
+    ThrowUserErrorException();
+
+  if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
+    ThrowUserErrorException();
+
+  options.TechMode = parser[NKey::kTechMode].ThereIs;
+
+  if (parser[NKey::kCaseSensitive].ThereIs)
+    g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0);
+
+  NRecursedType::EEnum recursedType;
+  if (parser[NKey::kRecursed].ThereIs)
+    recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);
+  else
+    recursedType = NRecursedType::kNonRecursed;
+
+  UINT codePage = CP_UTF8;
+  if (parser[NKey::kCharSet].ThereIs)
+  {
+    UString name = parser[NKey::kCharSet].PostStrings.Front();
+    name.MakeUpper();
+    int i;
+    for (i = 0; i < kNumCodePages; i++)
+    {
+      const CCodePagePair &pair = g_CodePagePairs[i];
+      if (name.Compare(pair.Name) == 0)
+      {
+        codePage = pair.CodePage;
+        break;
+      }
+    }
+    if (i >= kNumCodePages)
+      ThrowUserErrorException();
+  }
+
+  bool thereAreSwitchIncludes = false;
+  if (parser[NKey::kInclude].ThereIs)
+  {
+    thereAreSwitchIncludes = true;
+    AddSwitchWildCardsToCensor(options.WildcardCensor, 
+        parser[NKey::kInclude].PostStrings, true, recursedType, codePage);
+  }
+  if (parser[NKey::kExclude].ThereIs)
+    AddSwitchWildCardsToCensor(options.WildcardCensor, 
+        parser[NKey::kExclude].PostStrings, false, recursedType, codePage);
+ 
+  int curCommandIndex = kCommandIndex + 1;
+  bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && 
+      options.Command.CommandType != NCommandType::kBenchmark && 
+      options.Command.CommandType != NCommandType::kInfo;
+  if (thereIsArchiveName)
+  {
+    if(curCommandIndex >= numNonSwitchStrings)  
+      ThrowUserErrorException();
+    options.ArchiveName = nonSwitchStrings[curCommandIndex++];
+  }
+
+  AddToCensorFromNonSwitchesStrings(
+      curCommandIndex, options.WildcardCensor, 
+      nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);
+
+  options.YesToAll = parser[NKey::kYes].ThereIs;
+
+  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
+
+  options.PasswordEnabled = parser[NKey::kPassword].ThereIs;
+
+  if(options.PasswordEnabled)
+    options.Password = parser[NKey::kPassword].PostStrings[0];
+
+  options.StdInMode = parser[NKey::kStdIn].ThereIs;
+  options.ShowDialog = parser[NKey::kShowDialog].ThereIs;
+
+  if(isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
+  {
+    if (options.StdInMode)
+      ThrowException("Reading archives from stdin is not implemented");
+    if (!options.WildcardCensor.AllAreRelative())
+      ThrowException("Cannot use absolute pathnames for this command");
+
+    NWildcard::CCensor archiveWildcardCensor;
+
+    if (parser[NKey::kArInclude].ThereIs)
+    {
+      AddSwitchWildCardsToCensor(archiveWildcardCensor, 
+        parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);
+    }
+    if (parser[NKey::kArExclude].ThereIs)
+      AddSwitchWildCardsToCensor(archiveWildcardCensor, 
+      parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);
+
+    if (thereIsArchiveName)
+      AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);
+
+    #ifdef _WIN32
+    ConvertToLongNames(archiveWildcardCensor);
+    #endif
+
+    archiveWildcardCensor.ExtendExclude();
+
+    CObjectVector<CDirItem> dirItems;
+    {
+      UStringVector errorPaths;
+      CRecordVector<DWORD> errorCodes;
+      HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes);
+      if (res != S_OK || errorPaths.Size() > 0)
+        throw "cannot find archive";
+    }
+    UStringVector archivePaths;
+    int i;
+    for (i = 0; i < dirItems.Size(); i++)
+    {
+      const CDirItem &dirItem = dirItems[i];
+      if (!dirItem.IsDirectory())
+        archivePaths.Add(dirItem.FullPath);
+    }
+
+    if (archivePaths.Size() == 0)
+      throw "there is no such archive";
+
+    UStringVector archivePathsFull;
+
+    for (i = 0; i < archivePaths.Size(); i++)
+    {
+      UString fullPath;
+      NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath);
+      archivePathsFull.Add(fullPath);
+    }
+    CIntVector indices;
+    SortFileNames(archivePathsFull, indices);
+    options.ArchivePathsSorted.Reserve(indices.Size());
+    options.ArchivePathsFullSorted.Reserve(indices.Size());
+    for (i = 0; i < indices.Size(); i++)
+    {
+      options.ArchivePathsSorted.Add(archivePaths[indices[i]]);
+      options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]);
+    }
+
+    if (isExtractGroupCommand)
+    {
+      SetMethodOptions(parser, options.ExtractProperties); 
+      if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)
+        throw kSameTerminalError;
+      if(parser[NKey::kOutputDir].ThereIs)
+      {
+        options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];
+        NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
+      }
+
+      options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
+      if(parser[NKey::kOverwrite].ThereIs)
+        options.OverwriteMode = 
+            k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
+      else if (options.YesToAll)
+        options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
+    }
+  }
+  else if(options.Command.IsFromUpdateGroup())
+  {
+    CUpdateOptions &updateOptions = options.UpdateOptions;
+
+    if(parser[NKey::kArchiveType].ThereIs)
+      options.ArcType = parser[NKey::kArchiveType].PostStrings[0];
+
+    SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); 
+    
+    SetMethodOptions(parser, updateOptions.MethodMode.Properties); 
+
+    if (parser[NKey::kShareForWrite].ThereIs)
+      updateOptions.OpenShareForWrite = true;
+
+    options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;
+
+    if (options.EnablePercents)
+    {
+      if ((options.StdOutMode && !options.IsStdErrTerminal) || 
+         (!options.StdOutMode && !options.IsStdOutTerminal))  
+        options.EnablePercents = false;
+    }
+
+    updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
+    if (updateOptions.EMailMode)
+    {
+      updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
+      if (updateOptions.EMailAddress.Length() > 0)
+        if (updateOptions.EMailAddress[0] == L'.')
+        {
+          updateOptions.EMailRemoveAfter = true;
+          updateOptions.EMailAddress.Delete(0);
+        }
+    }
+
+    updateOptions.StdOutMode = options.StdOutMode;
+    updateOptions.StdInMode = options.StdInMode;
+
+    if (updateOptions.StdOutMode && updateOptions.EMailMode)
+      throw "stdout mode and email mode cannot be combined";
+    if (updateOptions.StdOutMode && options.IsStdOutTerminal)
+      throw kTerminalOutError;
+    if(updateOptions.StdInMode)
+      updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();
+
+    #ifdef _WIN32
+    ConvertToLongNames(options.WildcardCensor);
+    #endif
+  }
+  else if(options.Command.CommandType == NCommandType::kBenchmark)
+  {
+    options.NumThreads = (UInt32)-1;
+    options.DictionarySize = (UInt32)-1;
+    options.NumIterations = 1;
+    if (curCommandIndex < numNonSwitchStrings)  
+    {
+      if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations))
+        ThrowUserErrorException();
+    }
+    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
+    {
+      UString postString = parser[NKey::kProperty].PostStrings[i];
+      postString.MakeUpper();
+      if (postString.Length() < 2)
+        ThrowUserErrorException();
+      if (postString[0] == 'D')
+      {
+        int pos = 1;
+        if (postString[pos] == '=')
+          pos++;
+        UInt32 logSize;
+        if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize))
+          ThrowUserErrorException();
+        if (logSize > 31)
+          ThrowUserErrorException();
+        options.DictionarySize = 1 << logSize;
+      }
+      else if (postString[0] == 'M' && postString[1] == 'T' )
+      {
+        int pos = 2;
+        if (postString[pos] == '=')
+          pos++;
+        if (postString[pos] != 0)
+          if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads))
+            ThrowUserErrorException();
+      }
+      else if (postString[0] == 'M' && postString[1] == '=' )
+      {
+        int pos = 2;
+        if (postString[pos] != 0)
+          options.Method = postString.Mid(2);
+      }
+      else
+        ThrowUserErrorException();
+    }
+  }
+  else if(options.Command.CommandType == NCommandType::kInfo)
+  {
+  }
+  else 
+    ThrowUserErrorException();
+  options.WildcardCensor.ExtendExclude();
+}

Added: trunk/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ArchiveCommandLine.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,104 @@
+// ArchiveCommandLine.h
+
+#ifndef __ARCHIVECOMMANDLINE_H
+#define __ARCHIVECOMMANDLINE_H
+
+#include "Common/Wildcard.h"
+#include "Common/CommandLineParser.h"
+
+#include "Extract.h"
+#include "Update.h"
+
+struct CArchiveCommandLineException: public AString
+{
+  CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {}
+};
+
+namespace NCommandType { enum EEnum
+{
+  kAdd = 0,
+  kUpdate,
+  kDelete,
+  kTest,
+  kExtract,
+  kFullExtract,
+  kList,
+  kBenchmark,
+  kInfo
+};}
+
+namespace NRecursedType { enum EEnum
+{
+  kRecursed,
+  kWildCardOnlyRecursed,
+  kNonRecursed
+};}
+
+struct CArchiveCommand
+{
+  NCommandType::EEnum CommandType;
+  bool IsFromExtractGroup() const;
+  bool IsFromUpdateGroup() const;
+  bool IsTestMode() const { return CommandType == NCommandType::kTest; }
+  NExtract::NPathMode::EEnum GetPathMode() const;
+};
+
+struct CArchiveCommandLineOptions
+{
+  bool HelpMode;
+
+  #ifdef _WIN32
+  bool LargePages;
+  #endif
+
+  bool IsInTerminal;
+  bool IsStdOutTerminal;
+  bool IsStdErrTerminal;
+  bool StdInMode;
+  bool StdOutMode;
+  bool EnableHeaders;
+
+  bool YesToAll;
+  bool ShowDialog;
+  // NWildcard::CCensor ArchiveWildcardCensor;
+  NWildcard::CCensor WildcardCensor;
+
+  CArchiveCommand Command; 
+  UString ArchiveName;
+
+  bool PasswordEnabled;
+  UString Password;
+
+  bool TechMode;
+  // Extract
+  bool AppendName;
+  UString OutputDir;
+  NExtract::NOverwriteMode::EEnum OverwriteMode;
+  UStringVector ArchivePathsSorted;
+  UStringVector ArchivePathsFullSorted;
+  CObjectVector<CProperty> ExtractProperties;
+
+  CUpdateOptions UpdateOptions;
+  UString ArcType;
+  bool EnablePercents;
+
+  // Benchmark 
+  UInt32 NumIterations;
+  UInt32 NumThreads;
+  UInt32 DictionarySize;
+  UString Method;
+
+
+  CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {};
+};
+
+class CArchiveCommandLineParser
+{
+  NCommandLineParser::CParser parser;
+public:
+  CArchiveCommandLineParser();
+  void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options);
+  void Parse2(CArchiveCommandLineOptions &options);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,479 @@
+// ArchiveExtractCallback.cpp
+
+#include "StdAfx.h"
+
+#include "ArchiveExtractCallback.h"
+
+#include "Common/Wildcard.h"
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/FileFind.h"
+#include "Windows/Time.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+
+#include "Windows/PropVariantConversions.h"
+
+#include "../../Common/FilePathAutoRename.h"
+
+#include "../Common/ExtractingFilePath.h"
+#include "OpenArchive.h"
+
+using namespace NWindows;
+
+static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name";
+static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file ";
+static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";
+
+
+void CArchiveExtractCallback::Init(
+    IInArchive *archiveHandler,
+    IFolderArchiveExtractCallback *extractCallback2,
+    bool stdOutMode,
+    const UString &directoryPath, 
+    const UStringVector &removePathParts,
+    const UString &itemDefaultName,
+    const FILETIME &utcLastWriteTimeDefault,
+    UInt32 attributesDefault,
+    UInt64 packSize)
+{
+  _stdOutMode = stdOutMode;
+  _numErrors = 0;
+  _unpTotal = 1;
+  _packTotal = packSize;
+
+  _extractCallback2 = extractCallback2;
+  _compressProgress.Release();
+  _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
+
+  LocalProgressSpec->Init(extractCallback2, true);
+  LocalProgressSpec->SendProgress = false;
+
+  _itemDefaultName = itemDefaultName;
+  _utcLastWriteTimeDefault = utcLastWriteTimeDefault;
+  _attributesDefault = attributesDefault;
+  _removePathParts = removePathParts;
+  _archiveHandler = archiveHandler;
+  _directoryPath = directoryPath;
+  NFile::NName::NormalizeDirPathPrefix(_directoryPath);
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)
+{
+  COM_TRY_BEGIN
+  _unpTotal = size;
+  if (!_multiArchives && _extractCallback2)
+    return _extractCallback2->SetTotal(size);
+  return S_OK;
+  COM_TRY_END
+}
+
+static void NormalizeVals(UInt64 &v1, UInt64 &v2)
+{
+  const UInt64 kMax = (UInt64)1 << 31;
+  while (v1 > kMax)
+  {
+    v1 >>= 1;
+    v2 >>= 1;
+  }
+}
+
+static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal)
+{
+  NormalizeVals(packTotal, unpTotal);
+  NormalizeVals(unpCur, unpTotal);
+  if (unpTotal == 0)
+    unpTotal = 1;
+  return unpCur * packTotal / unpTotal;
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
+{
+  COM_TRY_BEGIN
+  if (!_extractCallback2)
+    return S_OK;
+
+  if (_multiArchives)
+  {
+    if (completeValue != NULL)
+    {
+      UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal);
+      return _extractCallback2->SetCompleted(&packCur);
+    }
+  }
+  return _extractCallback2->SetCompleted(completeValue);
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+  COM_TRY_BEGIN
+  return _localProgress->SetRatioInfo(inSize, outSize);
+  COM_TRY_END
+}
+
+void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath)
+{
+  fullPath = _directoryPath;
+  for(int i = 0; i < dirPathParts.Size(); i++)
+  {
+    if (i > 0)
+      fullPath += wchar_t(NFile::NName::kDirDelimiter);
+    fullPath += dirPathParts[i];
+    NFile::NDirectory::MyCreateDirectory(fullPath);
+  }
+}
+
+static UString MakePathNameFromParts(const UStringVector &parts)
+{
+  UString result;
+  for(int i = 0; i < parts.Size(); i++)
+  {
+    if(i != 0)
+      result += wchar_t(NFile::NName::kDirDelimiter);
+    result += parts[i];
+  }
+  return result;
+}
+
+
+HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
+{
+  filetimeIsDefined = false;
+  NCOM::CPropVariant prop;
+  RINOK(_archiveHandler->GetProperty(index, propID, &prop));
+  if (prop.vt == VT_FILETIME)
+  {
+    filetime = prop.filetime;
+    filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0);
+  }
+  else if (prop.vt != VT_EMPTY)
+    return E_FAIL;
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
+{
+  COM_TRY_BEGIN
+  *outStream = 0;
+  _outFileStream.Release();
+
+  _encrypted = false;
+  _isSplit = false;
+  _curSize = 0;
+
+  UString fullPath;
+
+  RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath));
+  RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory));
+
+  _filePath = fullPath;
+
+  {
+    NCOM::CPropVariant prop;
+    RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop));
+    if (prop.vt != VT_EMPTY)
+    {
+      if (prop.vt != VT_UI8)
+        return E_FAIL;
+      _position = prop.uhVal.QuadPart;
+      _isSplit = true;
+    }
+  }
+    
+  RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted));
+
+  bool newFileSizeDefined;
+  UInt64 newFileSize;
+  {
+    NCOM::CPropVariant prop;
+    RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));
+    newFileSizeDefined = (prop.vt != VT_EMPTY);
+    if (newFileSizeDefined)
+    {
+      newFileSize = ConvertPropVariantToUInt64(prop);
+      _curSize = newFileSize;
+    }
+  }
+
+  if(askExtractMode == NArchive::NExtract::NAskMode::kExtract)
+  {
+    if (_stdOutMode)
+    {
+      CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream;
+      *outStream = outStreamLoc.Detach();
+      return S_OK;
+    }
+
+    {
+      NCOM::CPropVariant prop;
+      RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &prop));
+      if (prop.vt == VT_EMPTY)
+      {
+        _processedFileInfo.Attributes = _attributesDefault;
+        _processedFileInfo.AttributesAreDefined = false;
+      }
+      else
+      {
+        if (prop.vt != VT_UI4)
+          return E_FAIL;
+        _processedFileInfo.Attributes = prop.ulVal;
+        _processedFileInfo.AttributesAreDefined = true;
+      }
+    }
+
+    RINOK(GetTime(index, kpidCreationTime, _processedFileInfo.CreationTime,
+        _processedFileInfo.IsCreationTimeDefined));
+    RINOK(GetTime(index, kpidLastWriteTime, _processedFileInfo.LastWriteTime, 
+        _processedFileInfo.IsLastWriteTimeDefined));
+    RINOK(GetTime(index, kpidLastAccessTime, _processedFileInfo.LastAccessTime,
+        _processedFileInfo.IsLastAccessTimeDefined));
+
+    bool isAnti = false;
+    RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti));
+
+    UStringVector pathParts; 
+    SplitPathToParts(fullPath, pathParts);
+    
+    if(pathParts.IsEmpty())
+      return E_FAIL;
+    int numRemovePathParts = 0;
+    switch(_pathMode)
+    {
+      case NExtract::NPathMode::kFullPathnames:
+        break;
+      case NExtract::NPathMode::kCurrentPathnames:
+      {
+        numRemovePathParts = _removePathParts.Size();
+        if (pathParts.Size() <= numRemovePathParts)
+          return E_FAIL;
+        for (int i = 0; i < numRemovePathParts; i++)
+          if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0)
+            return E_FAIL;
+        break;
+      }
+      case NExtract::NPathMode::kNoPathnames:
+      {
+        numRemovePathParts = pathParts.Size() - 1;
+        break;
+      }
+    }
+    pathParts.Delete(0, numRemovePathParts);
+    MakeCorrectPath(pathParts);
+    UString processedPath = MakePathNameFromParts(pathParts);
+    if (!isAnti)
+    {
+      if (!_processedFileInfo.IsDirectory)
+      {
+        if (!pathParts.IsEmpty())
+          pathParts.DeleteBack();
+      }
+    
+      if (!pathParts.IsEmpty())
+      {
+        UString fullPathNew;
+        CreateComplexDirectory(pathParts, fullPathNew);
+        if (_processedFileInfo.IsDirectory)
+          NFile::NDirectory::SetDirTime(fullPathNew, 
+            (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL, 
+            (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL, 
+            (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault);
+      }
+    }
+
+
+    UString fullProcessedPath = _directoryPath + processedPath;
+
+    if(_processedFileInfo.IsDirectory)
+    {
+      _diskFilePath = fullProcessedPath;
+      if (isAnti)
+        NFile::NDirectory::MyRemoveDirectory(_diskFilePath);
+      return S_OK;
+    }
+
+    if (!_isSplit)
+    {
+    NFile::NFind::CFileInfoW fileInfo;
+    if(NFile::NFind::FindFile(fullProcessedPath, fileInfo))
+    {
+      switch(_overwriteMode)
+      {
+        case NExtract::NOverwriteMode::kSkipExisting:
+          return S_OK;
+        case NExtract::NOverwriteMode::kAskBefore:
+        {
+          Int32 overwiteResult;
+          RINOK(_extractCallback2->AskOverwrite(
+              fullProcessedPath, &fileInfo.LastWriteTime, &fileInfo.Size, fullPath, 
+              _processedFileInfo.IsLastWriteTimeDefined ? &_processedFileInfo.LastWriteTime : NULL, 
+              newFileSizeDefined ? &newFileSize : NULL, 
+              &overwiteResult))
+
+          switch(overwiteResult)
+          {
+            case NOverwriteAnswer::kCancel:
+              return E_ABORT;
+            case NOverwriteAnswer::kNo:
+              return S_OK;
+            case NOverwriteAnswer::kNoToAll:
+              _overwriteMode = NExtract::NOverwriteMode::kSkipExisting;
+              return S_OK;
+            case NOverwriteAnswer::kYesToAll:
+              _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
+              break;
+            case NOverwriteAnswer::kYes:
+              break;
+            case NOverwriteAnswer::kAutoRename:
+              _overwriteMode = NExtract::NOverwriteMode::kAutoRename;
+              break;
+            default:
+              return E_FAIL;
+          }
+        }
+      }
+      if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename)
+      {
+        if (!AutoRenamePath(fullProcessedPath))
+        {
+          UString message = UString(kCantAutoRename) + fullProcessedPath;
+          RINOK(_extractCallback2->MessageError(message));
+          return E_FAIL;
+        }
+      }
+      else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting)
+      {
+        UString existPath = fullProcessedPath;
+        if (!AutoRenamePath(existPath))
+        {
+          UString message = kCantAutoRename + fullProcessedPath;
+          RINOK(_extractCallback2->MessageError(message));
+          return E_FAIL;
+        }
+        if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath))
+        {
+          UString message = UString(kCantRenameFile) + fullProcessedPath;
+          RINOK(_extractCallback2->MessageError(message));
+          return E_FAIL;
+        }
+      }
+      else
+        if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
+        {
+          UString message = UString(kCantDeleteOutputFile) +  fullProcessedPath;
+          RINOK(_extractCallback2->MessageError(message));
+          return S_OK;
+          // return E_FAIL;
+        }
+    }
+    }
+    if (!isAnti)
+    {
+      _outFileStreamSpec = new COutFileStream;
+      CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
+      if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))
+      {
+        // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
+        {
+          UString message = L"can not open output file " + fullProcessedPath;
+          RINOK(_extractCallback2->MessageError(message));
+          return S_OK;
+        }
+      }
+      if (_isSplit)
+      {
+        RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
+      }
+      _outFileStream = outStreamLoc;
+      *outStream = outStreamLoc.Detach();
+    }
+    _diskFilePath = fullProcessedPath;
+  }
+  else
+  {
+    *outStream = NULL;
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
+{
+  COM_TRY_BEGIN
+  _extractMode = false;
+  switch (askExtractMode)
+  {
+    case NArchive::NExtract::NAskMode::kExtract:
+      _extractMode = true;
+  };
+  return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDirectory, 
+      askExtractMode, _isSplit ? &_position: 0);
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
+{
+  COM_TRY_BEGIN
+  switch(operationResult)
+  {
+    case NArchive::NExtract::NOperationResult::kOK:
+    case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
+    case NArchive::NExtract::NOperationResult::kCRCError:
+    case NArchive::NExtract::NOperationResult::kDataError:
+      break;
+    default:
+      _outFileStream.Release();
+      return E_FAIL;
+  }
+  if (_outFileStream != NULL)
+  {
+    _outFileStreamSpec->SetTime(
+        (WriteCreated && _processedFileInfo.IsCreationTimeDefined) ? &_processedFileInfo.CreationTime : NULL, 
+        (WriteAccessed && _processedFileInfo.IsLastAccessTimeDefined) ? &_processedFileInfo.LastAccessTime : NULL, 
+        (WriteModified && _processedFileInfo.IsLastWriteTimeDefined) ? &_processedFileInfo.LastWriteTime : &_utcLastWriteTimeDefault);
+    _curSize = _outFileStreamSpec->ProcessedSize;
+    RINOK(_outFileStreamSpec->Close());
+    _outFileStream.Release();
+  }
+  UnpackSize += _curSize;
+  if (_processedFileInfo.IsDirectory)
+    NumFolders++;
+  else
+    NumFiles++;
+
+  if (_extractMode && _processedFileInfo.AttributesAreDefined)
+    NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes);
+  RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));
+  return S_OK;
+  COM_TRY_END
+}
+
+/*
+STDMETHODIMP CArchiveExtractCallback::GetInStream(
+    const wchar_t *name, ISequentialInStream **inStream)
+{
+  COM_TRY_BEGIN
+  CInFileStream *inFile = new CInFileStream;
+  CMyComPtr<ISequentialInStream> inStreamTemp = inFile;
+  if (!inFile->Open(_srcDirectoryPrefix + name))
+    return ::GetLastError();
+  *inStream = inStreamTemp.Detach();
+  return S_OK;
+  COM_TRY_END
+}
+*/
+
+STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
+{
+  COM_TRY_BEGIN
+  if (!_cryptoGetTextPassword)
+  {
+    RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword, 
+        &_cryptoGetTextPassword));
+  }
+  return _cryptoGetTextPassword->CryptoGetTextPassword(password);
+  COM_TRY_END
+}
+

Added: trunk/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ArchiveExtractCallback.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,139 @@
+// ArchiveExtractCallback.h
+
+#ifndef __ARCHIVEEXTRACTCALLBACK_H
+#define __ARCHIVEEXTRACTCALLBACK_H
+
+#include "../../Archive/IArchive.h"
+#include "IFileExtractCallback.h"
+
+#include "Common/MyString.h"
+#include "Common/MyCom.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../IPassword.h"
+
+#include "ExtractMode.h"
+
+class CArchiveExtractCallback: 
+  public IArchiveExtractCallback,
+  // public IArchiveVolumeExtractCallback,
+  public ICryptoGetTextPassword,
+  public ICompressProgressInfo,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo)
+  // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)
+
+  // IProgress
+  STDMETHOD(SetTotal)(UInt64 size);
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+
+  // IExtractCallBack
+  STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);
+  STDMETHOD(PrepareOperation)(Int32 askExtractMode);
+  STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);
+
+  // IArchiveVolumeExtractCallback
+  // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream);
+
+  // ICryptoGetTextPassword
+  STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);
+
+private:
+  CMyComPtr<IInArchive> _archiveHandler;
+  CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
+  CMyComPtr<ICompressProgressInfo> _compressProgress;
+  CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
+  UString _directoryPath;
+  NExtract::NPathMode::EEnum _pathMode;
+  NExtract::NOverwriteMode::EEnum _overwriteMode;
+
+  UString _filePath;
+  UInt64 _position;
+  bool _isSplit;
+
+  UString _diskFilePath;
+
+  bool _extractMode;
+
+  bool WriteModified;
+  bool WriteCreated;
+  bool WriteAccessed;
+
+  bool _encrypted;
+
+  struct CProcessedFileInfo
+  {
+    FILETIME CreationTime;
+    FILETIME LastWriteTime;
+    FILETIME LastAccessTime;
+    UInt32 Attributes;
+  
+    bool IsCreationTimeDefined;
+    bool IsLastWriteTimeDefined;
+    bool IsLastAccessTimeDefined;
+
+    bool IsDirectory;
+    bool AttributesAreDefined;
+  } _processedFileInfo;
+
+  UInt64 _curSize;
+  COutFileStream *_outFileStreamSpec;
+  CMyComPtr<ISequentialOutStream> _outFileStream;
+  UStringVector _removePathParts;
+
+  UString _itemDefaultName;
+  FILETIME _utcLastWriteTimeDefault;
+  UInt32 _attributesDefault;
+  bool _stdOutMode;
+
+  void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath);
+  HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
+public:
+  CArchiveExtractCallback():
+      WriteModified(true),
+      WriteCreated(false),
+      WriteAccessed(false),
+      _multiArchives(false)
+  {
+    LocalProgressSpec = new CLocalProgress();
+    _localProgress = LocalProgressSpec;
+  }
+
+  CLocalProgress *LocalProgressSpec;
+  CMyComPtr<ICompressProgressInfo> _localProgress;
+  UInt64 _packTotal;
+  UInt64 _unpTotal;
+
+  bool _multiArchives;
+  UInt64 NumFolders;
+  UInt64 NumFiles;
+  UInt64 UnpackSize;
+  
+  void InitForMulti(bool multiArchives, 
+      NExtract::NPathMode::EEnum pathMode,
+      NExtract::NOverwriteMode::EEnum overwriteMode) 
+  { 
+    _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; 
+    _pathMode = pathMode;
+    _overwriteMode = overwriteMode;
+  }
+
+  void Init(
+      IInArchive *archiveHandler, 
+      IFolderArchiveExtractCallback *extractCallback2,
+      bool stdOutMode,
+      const UString &directoryPath,
+      const UStringVector &removePathParts,
+      const UString &itemDefaultName,
+      const FILETIME &utcLastWriteTimeDefault, 
+      UInt32 attributesDefault,
+      UInt64 packSize);
+
+  UInt64 _numErrors;
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/ArchiveName.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ArchiveName.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ArchiveName.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,46 @@
+// ArchiveName.cpp
+
+#include "StdAfx.h"
+
+#include "Windows/FileFind.h"
+#include "Windows/FileDir.h"
+
+using namespace NWindows;
+
+UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)
+{
+  UString resultName = L"Archive";
+  if (fromPrev)
+  {
+    UString dirPrefix;
+    if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix))
+    {
+      if (dirPrefix.Length() > 0)
+        if (dirPrefix[dirPrefix.Length() - 1] == '\\')
+        {
+          dirPrefix.Delete(dirPrefix.Length() - 1);
+          NFile::NFind::CFileInfoW fileInfo;
+          if (NFile::NFind::FindFile(dirPrefix, fileInfo))
+            resultName = fileInfo.Name;
+        }
+    }
+  }
+  else
+  {
+    NFile::NFind::CFileInfoW fileInfo;
+    if (!NFile::NFind::FindFile(srcName, fileInfo))
+      return resultName;
+    resultName = fileInfo.Name;
+    if (!fileInfo.IsDirectory() && !keepName)
+    {
+      int dotPos = resultName.ReverseFind('.');
+      if (dotPos > 0)
+      {
+        UString archiveName2 = resultName.Left(dotPos);
+        if (archiveName2.ReverseFind('.') < 0)
+          resultName = archiveName2;
+      }
+    }
+  }
+  return resultName;
+}

Added: trunk/lzma/CPP/7zip/UI/Common/ArchiveName.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ArchiveName.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ArchiveName.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// ArchiveName.h
+
+#ifndef __ARCHIVENAME_H
+#define __ARCHIVENAME_H
+
+#include "Common/MyString.h"
+
+UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,137 @@
+// ArchiveOpenCallback.cpp
+
+#include "StdAfx.h"
+
+#include "ArchiveOpenCallback.h"
+
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Common/FileStreams.h"
+
+using namespace NWindows;
+
+STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
+{
+  COM_TRY_BEGIN
+  if (!Callback)
+    return S_OK;
+  return Callback->SetTotal(files, bytes);
+  COM_TRY_END
+}
+
+STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
+{
+  COM_TRY_BEGIN
+  if (!Callback)
+    return S_OK;
+  return Callback->SetTotal(files, bytes);
+  COM_TRY_END
+}
+  
+STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  NCOM::CPropVariant propVariant;
+  if (_subArchiveMode)
+  {
+    switch(propID)
+    {
+      case kpidName:
+        propVariant = _subArchiveName;
+        break;
+    }
+    propVariant.Detach(value);
+    return S_OK;
+  }
+  switch(propID)
+  {
+    case kpidName:
+      propVariant = _fileInfo.Name;
+      break;
+    case kpidIsFolder:
+      propVariant = _fileInfo.IsDirectory();
+      break;
+    case kpidSize:
+      propVariant = _fileInfo.Size;
+      break;
+    case kpidAttributes:
+      propVariant = (UInt32)_fileInfo.Attributes;
+      break;
+    case kpidLastAccessTime:
+      propVariant = _fileInfo.LastAccessTime;
+      break;
+    case kpidCreationTime:
+      propVariant = _fileInfo.CreationTime;
+      break;
+    case kpidLastWriteTime:
+      propVariant = _fileInfo.LastWriteTime;
+      break;
+    }
+  propVariant.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+int COpenCallbackImp::FindName(const UString &name)
+{
+  for (int i = 0; i < FileNames.Size(); i++)
+    if (name.CompareNoCase(FileNames[i]) == 0)
+      return i;
+  return -1;
+}
+
+struct CInFileStreamVol: public CInFileStream
+{
+  UString Name;
+  COpenCallbackImp *OpenCallbackImp;
+  CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
+  ~CInFileStreamVol()
+  {
+    int index = OpenCallbackImp->FindName(Name);
+    if (index >= 0)
+      OpenCallbackImp->FileNames.Delete(index);
+  }
+};
+
+STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)
+{
+  COM_TRY_BEGIN
+  if (_subArchiveMode)
+    return S_FALSE;
+  if (Callback)
+  {
+    RINOK(Callback->CheckBreak());
+  }
+  *inStream = NULL;
+  UString fullPath = _folderPrefix + name;
+  if (!NFile::NFind::FindFile(fullPath, _fileInfo))
+    return S_FALSE;
+  if (_fileInfo.IsDirectory())
+    return S_FALSE;
+  CInFileStreamVol *inFile = new CInFileStreamVol;
+  CMyComPtr<IInStream> inStreamTemp = inFile;
+  if (!inFile->Open(fullPath))
+    return ::GetLastError();
+  *inStream = inStreamTemp.Detach();
+  inFile->Name = name;
+  inFile->OpenCallbackImp = this;
+  inFile->OpenCallbackRef = this;
+  FileNames.Add(name);
+  TotalSize += _fileInfo.Size;
+  return S_OK;
+  COM_TRY_END
+}
+
+#ifndef _NO_CRYPTO
+STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
+{
+  COM_TRY_BEGIN
+  if (!Callback)
+    return E_NOTIMPL;
+  return Callback->CryptoGetTextPassword(password);
+  COM_TRY_END
+}
+#endif
+  

Added: trunk/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ArchiveOpenCallback.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,93 @@
+// ArchiveOpenCallback.h
+
+#ifndef __ARCHIVE_OPEN_CALLBACK_H
+#define __ARCHIVE_OPEN_CALLBACK_H
+
+#include "Common/MyString.h"
+#include "Common/MyCom.h"
+#include "Windows/FileFind.h"
+
+#ifndef _NO_CRYPTO
+#include "../../IPassword.h"
+#endif  
+#include "../../Archive/IArchive.h"
+
+struct IOpenCallbackUI
+{
+  virtual HRESULT CheckBreak() = 0;
+  virtual HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes) = 0;
+  virtual HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes) = 0;
+  #ifndef _NO_CRYPTO
+  virtual HRESULT CryptoGetTextPassword(BSTR *password) = 0;
+  virtual HRESULT GetPasswordIfAny(UString &password) = 0;
+  virtual bool WasPasswordAsked() = 0;
+  virtual void ClearPasswordWasAskedFlag() = 0;
+  #endif  
+};
+
+class COpenCallbackImp: 
+  public IArchiveOpenCallback,
+  public IArchiveOpenVolumeCallback,
+  public IArchiveOpenSetSubArchiveName,
+  #ifndef _NO_CRYPTO
+  public ICryptoGetTextPassword,
+  #endif  
+  public CMyUnknownImp
+{
+public:
+  #ifndef _NO_CRYPTO
+  MY_UNKNOWN_IMP3(
+      IArchiveOpenVolumeCallback, 
+      ICryptoGetTextPassword,
+      IArchiveOpenSetSubArchiveName
+      )
+  #else
+  MY_UNKNOWN_IMP2(
+      IArchiveOpenVolumeCallback, 
+      IArchiveOpenSetSubArchiveName
+      )
+  #endif
+
+  STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
+  STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
+
+  // IArchiveOpenVolumeCallback
+  STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
+  STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
+
+  #ifndef _NO_CRYPTO
+  // ICryptoGetTextPassword
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+  #endif
+
+  STDMETHOD(SetSubArchiveName(const wchar_t *name))
+  {
+    _subArchiveMode = true;
+    _subArchiveName = name;
+    return  S_OK;
+  }
+
+private:
+  UString _folderPrefix;
+  NWindows::NFile::NFind::CFileInfoW _fileInfo;
+  bool _subArchiveMode;
+  UString _subArchiveName;
+public:
+  UStringVector FileNames;
+  IOpenCallbackUI *Callback;
+  UInt64 TotalSize;
+
+  COpenCallbackImp(): Callback(NULL) {}
+  void Init(const UString &folderPrefix,  const UString &fileName)
+  {
+    _folderPrefix = folderPrefix;
+    if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo))
+      throw 1;
+    FileNames.Clear();
+    _subArchiveMode = false;
+    TotalSize = 0;
+  }
+  int FindName(const UString &name);
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/DefaultName.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/DefaultName.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/DefaultName.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,26 @@
+// DefaultName.cpp
+
+#include "StdAfx.h"
+
+#include "DefaultName.h"
+
+static const wchar_t *kEmptyFileAlias = L"[Content]";
+
+UString GetDefaultName2(const UString &fileName, 
+    const UString &extension, const UString &addSubExtension)
+{
+  int extLength = extension.Length();
+  int fileNameLength = fileName.Length();
+  if (fileNameLength > extLength + 1)
+  {
+    int dotPos = fileNameLength - (extLength + 1);
+    if (fileName[dotPos] == '.')
+      if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0)
+        return fileName.Left(dotPos) + addSubExtension;
+  }
+  int dotPos = fileName.ReverseFind(L'.');
+  if (dotPos > 0)
+    return fileName.Left(dotPos) + addSubExtension;
+  return kEmptyFileAlias;
+}
+

Added: trunk/lzma/CPP/7zip/UI/Common/DefaultName.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/DefaultName.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/DefaultName.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,11 @@
+// DefaultName.h
+
+#ifndef __DEFAULTNAME_H
+#define __DEFAULTNAME_H
+
+#include "Common/MyString.h"
+
+UString GetDefaultName2(const UString &fileName, 
+    const UString &extension, const UString &addSubExtension);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/DirItem.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/DirItem.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/DirItem.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,34 @@
+// DirItem.h
+
+#ifndef __DIR_ITEM_H
+#define __DIR_ITEM_H
+
+#include "Common/MyString.h"
+#include "Common/Types.h"
+
+struct CDirItem
+{ 
+  UInt32 Attributes;
+  FILETIME CreationTime;
+  FILETIME LastAccessTime;
+  FILETIME LastWriteTime;
+  UInt64 Size;
+  UString Name;
+  UString FullPath;
+  bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
+};
+
+struct CArchiveItem
+{ 
+  bool IsDirectory;
+  // DWORD Attributes;
+  // NWindows::NCOM::CPropVariant LastWriteTime;
+  FILETIME LastWriteTime;
+  bool SizeIsDefined;
+  UInt64 Size;
+  UString Name;
+  bool Censored;
+  int IndexInServer;
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/EnumDirItems.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/EnumDirItems.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/EnumDirItems.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,281 @@
+// EnumDirItems.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/Wildcard.h"
+#include "Common/MyCom.h"
+
+#include "EnumDirItems.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NName;
+
+void AddDirFileInfo(
+    const UString &prefix,        // prefix for logical path
+    const UString &fullPathName,  // path on disk: can be relative to some basePrefix
+    const NFind::CFileInfoW &fileInfo, 
+    CObjectVector<CDirItem> &dirItems)
+{
+  CDirItem item;
+  item.Attributes = fileInfo.Attributes;
+  item.Size = fileInfo.Size;
+  item.CreationTime = fileInfo.CreationTime;
+  item.LastAccessTime = fileInfo.LastAccessTime;
+  item.LastWriteTime = fileInfo.LastWriteTime;
+  item.Name = prefix + fileInfo.Name;
+  item.FullPath = fullPathName;
+  dirItems.Add(item);
+}
+
+static void EnumerateDirectory(
+    const UString &baseFolderPrefix,  // base (disk) prefix for scanning  
+    const UString &directory,         // additional disk prefix starting from baseFolderPrefix
+    const UString &prefix,            // logical prefix
+    CObjectVector<CDirItem> &dirItems,
+    UStringVector &errorPaths,
+    CRecordVector<DWORD> &errorCodes)
+{
+  NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard));
+  for (;;)
+  { 
+    NFind::CFileInfoW fileInfo;
+    bool found;
+    if (!enumerator.Next(fileInfo, found))
+    {
+      errorCodes.Add(::GetLastError());
+      errorPaths.Add(baseFolderPrefix + directory);
+      return;
+    }
+    if (!found)
+      break;
+    AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems);
+    if (fileInfo.IsDirectory())
+    {
+      EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter), 
+          prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes);
+    }
+  }
+}
+
+void EnumerateDirItems(
+    const UString &baseFolderPrefix,   // base (disk) prefix for scanning  
+    const UStringVector &fileNames,    // names relative to baseFolderPrefix
+    const UString &archiveNamePrefix, 
+    CObjectVector<CDirItem> &dirItems,
+    UStringVector &errorPaths,
+    CRecordVector<DWORD> &errorCodes)
+{
+  for(int i = 0; i < fileNames.Size(); i++)
+  {
+    const UString &fileName = fileNames[i];
+    NFind::CFileInfoW fileInfo;
+    if (!NFind::FindFile(baseFolderPrefix + fileName, fileInfo))
+    {
+      errorCodes.Add(::GetLastError());
+      errorPaths.Add(baseFolderPrefix + fileName);
+      continue;
+    }
+    AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems);
+    if (fileInfo.IsDirectory())
+    {
+      EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter), 
+          archiveNamePrefix + fileInfo.Name +  wchar_t(kDirDelimiter), 
+          dirItems, errorPaths, errorCodes);
+    }
+  }
+}
+
+static HRESULT EnumerateDirItems(
+    const NWildcard::CCensorNode &curNode, 
+    const UString &diskPrefix,        // full disk path prefix 
+    const UString &archivePrefix,     // prefix from root
+    const UStringVector &addArchivePrefix,  // prefix from curNode
+    CObjectVector<CDirItem> &dirItems, 
+    bool enterToSubFolders,
+    IEnumDirItemCallback *callback,
+    UStringVector &errorPaths,
+    CRecordVector<DWORD> &errorCodes)
+{
+  if (!enterToSubFolders)
+    if (curNode.NeedCheckSubDirs())
+      enterToSubFolders = true;
+  if (callback)
+    RINOK(callback->CheckBreak());
+
+  // try direct_names case at first
+  if (addArchivePrefix.IsEmpty() && !enterToSubFolders)
+  {
+    // check that all names are direct
+    int i;
+    for (i = 0; i < curNode.IncludeItems.Size(); i++)
+    {
+      const NWildcard::CItem &item = curNode.IncludeItems[i];
+      if (item.Recursive || item.PathParts.Size() != 1)
+        break;
+      const UString &name = item.PathParts.Front();
+      if (name.IsEmpty() || DoesNameContainWildCard(name))
+        break;
+    }
+    if (i == curNode.IncludeItems.Size())
+    {
+      // all names are direct (no wildcards)
+      // so we don't need file_system's dir enumerator
+      CRecordVector<bool> needEnterVector;
+      for (i = 0; i < curNode.IncludeItems.Size(); i++)
+      {
+        const NWildcard::CItem &item = curNode.IncludeItems[i];
+        const UString &name = item.PathParts.Front();
+        const UString fullPath = diskPrefix + name;
+        NFind::CFileInfoW fileInfo;
+        if (!NFind::FindFile(fullPath, fileInfo))
+        {
+          errorCodes.Add(::GetLastError());
+          errorPaths.Add(fullPath);
+          continue;
+        }
+        bool isDir = fileInfo.IsDirectory();
+        if (isDir && !item.ForDir || !isDir && !item.ForFile)
+        {
+          errorCodes.Add((DWORD)E_FAIL);
+          errorPaths.Add(fullPath);
+          continue;
+        }
+        const UString realName = fileInfo.Name;
+        const UString realDiskPath = diskPrefix + realName;
+        {
+          UStringVector pathParts;
+          pathParts.Add(fileInfo.Name);
+          if (curNode.CheckPathToRoot(false, pathParts, !isDir))
+            continue;
+        }
+        AddDirFileInfo(archivePrefix, realDiskPath, fileInfo, dirItems);
+        if (!isDir)
+          continue;
+        
+        UStringVector addArchivePrefixNew;
+        const NWildcard::CCensorNode *nextNode = 0;
+        int index = curNode.FindSubNode(name);
+        if (index >= 0)
+        {
+          for (int t = needEnterVector.Size(); t <= index; t++)
+            needEnterVector.Add(true);
+          needEnterVector[index] = false;
+          nextNode = &curNode.SubNodes[index];
+        }
+        else
+        {
+          nextNode = &curNode;
+          addArchivePrefixNew.Add(name); // don't change it to realName. It's for shortnames support
+        }
+        RINOK(EnumerateDirItems(*nextNode,   
+            realDiskPath + wchar_t(kDirDelimiter), 
+            archivePrefix + realName + wchar_t(kDirDelimiter), 
+            addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));
+      }
+      for (i = 0; i < curNode.SubNodes.Size(); i++)
+      {
+        if (i < needEnterVector.Size())
+          if (!needEnterVector[i])
+            continue;
+        const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
+        const UString fullPath = diskPrefix + nextNode.Name;
+        NFind::CFileInfoW fileInfo;
+        if (!NFind::FindFile(fullPath, fileInfo))
+        {
+          if (!nextNode.AreThereIncludeItems())
+            continue;
+          errorCodes.Add(::GetLastError());
+          errorPaths.Add(fullPath);
+          continue;
+        }
+        if (!fileInfo.IsDirectory())
+        {
+          errorCodes.Add((DWORD)E_FAIL);
+          errorPaths.Add(fullPath);
+          continue;
+        }
+        RINOK(EnumerateDirItems(nextNode, 
+            diskPrefix + fileInfo.Name + wchar_t(kDirDelimiter), 
+            archivePrefix + fileInfo.Name + wchar_t(kDirDelimiter), 
+            UStringVector(), dirItems, false, callback, errorPaths, errorCodes));
+      }
+      return S_OK;
+    }
+  }
+
+
+  NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard));
+  for (;;)
+  {
+    NFind::CFileInfoW fileInfo;
+    bool found;
+    if (!enumerator.Next(fileInfo, found))
+    {
+      errorCodes.Add(::GetLastError());
+      errorPaths.Add(diskPrefix);
+      break;
+    }
+    if (!found)
+      break;
+
+    if (callback)
+      RINOK(callback->CheckBreak());
+    const UString &name = fileInfo.Name;
+    bool enterToSubFolders2 = enterToSubFolders;
+    UStringVector addArchivePrefixNew = addArchivePrefix;
+    addArchivePrefixNew.Add(name);
+    {
+      UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);
+      if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fileInfo.IsDirectory()))
+        continue;
+    }
+    if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fileInfo.IsDirectory()))
+    {
+      AddDirFileInfo(archivePrefix, diskPrefix + name, fileInfo, dirItems);
+      if (fileInfo.IsDirectory())
+        enterToSubFolders2 = true;
+    }
+    if (!fileInfo.IsDirectory())
+      continue;
+
+    const NWildcard::CCensorNode *nextNode = 0;
+    if (addArchivePrefix.IsEmpty())
+    {
+      int index = curNode.FindSubNode(name);
+      if (index >= 0)
+        nextNode = &curNode.SubNodes[index];
+    }
+    if (!enterToSubFolders2 && nextNode == 0)
+      continue;
+
+    addArchivePrefixNew = addArchivePrefix;
+    if (nextNode == 0)
+    {
+      nextNode = &curNode;
+      addArchivePrefixNew.Add(name);
+    }
+    RINOK(EnumerateDirItems(*nextNode,   
+        diskPrefix + name + wchar_t(kDirDelimiter), 
+        archivePrefix + name + wchar_t(kDirDelimiter), 
+        addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));
+  }
+  return S_OK;
+}
+
+HRESULT EnumerateItems(
+    const NWildcard::CCensor &censor, 
+    CObjectVector<CDirItem> &dirItems, 
+    IEnumDirItemCallback *callback,
+    UStringVector &errorPaths,
+    CRecordVector<DWORD> &errorCodes)
+{
+  for (int i = 0; i < censor.Pairs.Size(); i++)
+  {
+    const NWildcard::CPair &pair = censor.Pairs[i];
+    RINOK(EnumerateDirItems(pair.Head, pair.Prefix, L"", UStringVector(), dirItems, false, 
+        callback, errorPaths, errorCodes));
+  }
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/UI/Common/EnumDirItems.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/EnumDirItems.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/EnumDirItems.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,39 @@
+// EnumDirItems.h
+
+#ifndef __ENUM_DIR_ITEMS_H
+#define __ENUM_DIR_ITEMS_H
+
+#include "Common/Wildcard.h"
+#include "DirItem.h"
+
+#include "Windows/FileFind.h"
+
+void AddDirFileInfo(
+    const UString &prefix, 
+    const UString &fullPathName,
+    const NWindows::NFile::NFind::CFileInfoW &fileInfo, 
+    CObjectVector<CDirItem> &dirItems);
+
+
+void EnumerateDirItems(
+    const UString &baseFolderPrefix,
+    const UStringVector &fileNames,
+    const UString &archiveNamePrefix, 
+    CObjectVector<CDirItem> &dirItems, 
+    UStringVector &errorPaths,
+    CRecordVector<DWORD> &errorCodes);
+
+struct IEnumDirItemCallback
+{
+  virtual HRESULT CheckBreak() { return  S_OK; }
+};
+
+
+HRESULT EnumerateItems(
+    const NWildcard::CCensor &censor, 
+    CObjectVector<CDirItem> &dirItems, 
+    IEnumDirItemCallback *callback, 
+    UStringVector &errorPaths,
+    CRecordVector<DWORD> &errorCodes);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/ExitCode.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ExitCode.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ExitCode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,27 @@
+// ExitCode.h
+
+#ifndef __EXIT_CODE_H
+#define __EXIT_CODE_H
+
+namespace NExitCode {
+
+enum EEnum {
+
+  kSuccess       = 0,     // Successful operation
+  kWarning       = 1,     // Non fatal error(s) occurred
+  kFatalError    = 2,     // A fatal error occurred
+  // kCRCError      = 3,     // A CRC error occurred when unpacking     
+  // kLockedArchive = 4,     // Attempt to modify an archive previously locked
+  // kWriteError    = 5,     // Write to disk error
+  // kOpenError     = 6,     // Open file error
+  kUserError     = 7,     // Command line option error
+  kMemoryError   = 8,     // Not enough memory for operation
+  // kCreateFileError = 9,     // Create file error
+  
+  kUserBreak     = 255   // User stopped the process
+
+};
+
+}
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/Extract.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/Extract.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/Extract.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,187 @@
+// Extract.cpp
+
+#include "StdAfx.h"
+
+#include "Extract.h"
+
+#include "Windows/Defs.h"
+#include "Windows/FileDir.h"
+
+#include "OpenArchive.h"
+#include "SetProperties.h"
+
+using namespace NWindows;
+
+HRESULT DecompressArchive(
+    IInArchive *archive,
+    UInt64 packSize,
+    const UString &defaultName,
+    const NWildcard::CCensorNode &wildcardCensor,
+    const CExtractOptions &options,
+    IExtractCallbackUI *callback,
+    CArchiveExtractCallback *extractCallbackSpec,
+    UString &errorMessage)
+{
+  CRecordVector<UInt32> realIndices;
+  UInt32 numItems;
+  RINOK(archive->GetNumberOfItems(&numItems));
+
+  for(UInt32 i = 0; i < numItems; i++)
+  {
+    UString filePath;
+    RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath));
+    bool isFolder;
+    RINOK(IsArchiveItemFolder(archive, i, isFolder));
+    if (!wildcardCensor.CheckPath(filePath, !isFolder))
+      continue;
+    realIndices.Add(i);
+  }
+  if (realIndices.Size() == 0)
+  {
+    callback->ThereAreNoFiles();
+    return S_OK;
+  }
+
+  UStringVector removePathParts;
+
+  UString outDir = options.OutputDir;
+  outDir.Replace(L"*", defaultName);
+  if(!outDir.IsEmpty())
+    if(!NFile::NDirectory::CreateComplexDirectory(outDir))
+    {
+      HRESULT res = ::GetLastError();
+      if (res == S_OK)
+        res = E_FAIL;
+      errorMessage = ((UString)L"Can not create output directory ") + outDir;
+      return res;
+    }
+
+  extractCallbackSpec->Init(
+      archive, 
+      callback,
+      options.StdOutMode,
+      outDir, 
+      removePathParts, 
+      options.DefaultItemName, 
+      options.ArchiveFileInfo.LastWriteTime,
+      options.ArchiveFileInfo.Attributes,
+      packSize);
+
+  #ifdef COMPRESS_MT
+  RINOK(SetProperties(archive, options.Properties));
+  #endif
+
+  HRESULT result = archive->Extract(&realIndices.Front(), 
+    realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec);
+
+  return callback->ExtractResult(result);
+}
+
+HRESULT DecompressArchives(
+    CCodecs *codecs,
+    UStringVector &archivePaths, UStringVector &archivePathsFull,    
+    const NWildcard::CCensorNode &wildcardCensor,
+    const CExtractOptions &optionsSpec,
+    IOpenCallbackUI *openCallback,
+    IExtractCallbackUI *extractCallback, 
+    UString &errorMessage, 
+    CDecompressStat &stat)
+{
+  stat.Clear();
+  CExtractOptions options = optionsSpec;
+  int i;
+  UInt64 totalPackSize = 0;
+  CRecordVector<UInt64> archiveSizes;
+  for (i = 0; i < archivePaths.Size(); i++)
+  {
+    const UString &archivePath = archivePaths[i];
+    NFile::NFind::CFileInfoW archiveFileInfo;
+    if (!NFile::NFind::FindFile(archivePath, archiveFileInfo))
+      throw "there is no such archive";
+    if (archiveFileInfo.IsDirectory())
+      throw "can't decompress folder";
+    archiveSizes.Add(archiveFileInfo.Size);
+    totalPackSize += archiveFileInfo.Size;
+  }
+  CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+  CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);
+  bool multi = (archivePaths.Size() > 1);
+  extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);
+  if (multi)
+  {
+    RINOK(extractCallback->SetTotal(totalPackSize));  
+  }
+  for (i = 0; i < archivePaths.Size(); i++)
+  {
+    const UString &archivePath = archivePaths[i];
+    NFile::NFind::CFileInfoW archiveFileInfo;
+    if (!NFile::NFind::FindFile(archivePath, archiveFileInfo))
+      throw "there is no such archive";
+
+    if (archiveFileInfo.IsDirectory())
+      throw "there is no such archive";
+
+    options.ArchiveFileInfo = archiveFileInfo;
+
+    #ifndef _NO_CRYPTO
+    openCallback->ClearPasswordWasAskedFlag();
+    #endif
+
+    RINOK(extractCallback->BeforeOpen(archivePath));
+    CArchiveLink archiveLink;
+    HRESULT result = MyOpenArchive(codecs, archivePath, archiveLink, openCallback);
+
+    bool crypted = false;
+    #ifndef _NO_CRYPTO
+    crypted = openCallback->WasPasswordAsked();
+    #endif
+
+    RINOK(extractCallback->OpenResult(archivePath, result, crypted));
+    if (result != S_OK)
+      continue;
+
+    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
+    {
+      int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
+      if (index >= 0 && index > i)
+      {
+        archivePaths.Delete(index);
+        archivePathsFull.Delete(index);
+        totalPackSize -= archiveSizes[index];
+        archiveSizes.Delete(index);
+      }
+    }
+    if (archiveLink.VolumePaths.Size() != 0)
+    {
+      totalPackSize += archiveLink.VolumesSize;
+      RINOK(extractCallback->SetTotal(totalPackSize));  
+    }
+
+    #ifndef _NO_CRYPTO
+    UString password;
+    RINOK(openCallback->GetPasswordIfAny(password));
+    if (!password.IsEmpty())
+    {
+      RINOK(extractCallback->SetPassword(password));
+    }
+    #endif
+
+    options.DefaultItemName = archiveLink.GetDefaultItemName();
+    RINOK(DecompressArchive(
+        archiveLink.GetArchive(), 
+        archiveFileInfo.Size + archiveLink.VolumesSize,
+        archiveLink.GetDefaultItemName(),
+        wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage));
+    extractCallbackSpec->LocalProgressSpec->InSize += archiveFileInfo.Size + 
+        archiveLink.VolumesSize;
+    extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize;
+    if (!errorMessage.IsEmpty())
+      return E_FAIL;
+  }
+  stat.NumFolders = extractCallbackSpec->NumFolders;
+  stat.NumFiles = extractCallbackSpec->NumFiles;
+  stat.UnpackSize = extractCallbackSpec->UnpackSize;
+  stat.NumArchives = archivePaths.Size();
+  stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize;
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/UI/Common/Extract.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/Extract.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/Extract.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,77 @@
+// Extract.h
+
+#ifndef __EXTRACT_H
+#define __EXTRACT_H
+
+#include "Common/Wildcard.h"
+#include "Windows/FileFind.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "ArchiveExtractCallback.h"
+#include "ArchiveOpenCallback.h"
+#include "ExtractMode.h"
+#include "Property.h"
+
+#include "../Common/LoadCodecs.h"
+
+class CExtractOptions
+{
+public:
+  bool StdOutMode;
+  bool TestMode;
+  NExtract::NPathMode::EEnum PathMode;
+
+  UString OutputDir;
+  bool YesToAll;
+  UString DefaultItemName;
+  NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo;
+  
+  // bool ShowDialog;
+  // bool PasswordEnabled;
+  // UString Password;
+  #ifdef COMPRESS_MT
+  CObjectVector<CProperty> Properties;
+  #endif
+
+  NExtract::NOverwriteMode::EEnum OverwriteMode;
+
+  #ifdef EXTERNAL_CODECS
+  CCodecs *Codecs;
+  #endif
+
+  CExtractOptions(): 
+      StdOutMode(false), 
+      YesToAll(false), 
+      TestMode(false),
+      PathMode(NExtract::NPathMode::kFullPathnames),
+      OverwriteMode(NExtract::NOverwriteMode::kAskBefore)
+      {}
+
+  /*
+    bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || 
+    (ExtractMode == NExtractMode::kFullPath); }
+  */
+};
+
+struct CDecompressStat
+{
+  UInt64 NumArchives;
+  UInt64 UnpackSize;
+  UInt64 PackSize;
+  UInt64 NumFolders;
+  UInt64 NumFiles;
+  void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; }
+};
+
+HRESULT DecompressArchives(
+    CCodecs *codecs,
+    UStringVector &archivePaths, UStringVector &archivePathsFull,
+    const NWildcard::CCensorNode &wildcardCensor,
+    const CExtractOptions &options,
+    IOpenCallbackUI *openCallback,
+    IExtractCallbackUI *extractCallback,
+    UString &errorMessage, 
+    CDecompressStat &stat);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/ExtractMode.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ExtractMode.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ExtractMode.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,31 @@
+// ExtractMode.h
+
+#ifndef __EXTRACT_MODE_H
+#define __EXTRACT_MODE_H
+
+namespace NExtract {
+  
+  namespace NPathMode
+  {
+    enum EEnum
+    {
+      kFullPathnames,
+      kCurrentPathnames,
+      kNoPathnames
+    };
+  }
+  
+  namespace NOverwriteMode
+  {
+    enum EEnum
+    {
+      kAskBefore,
+      kWithoutPrompt,
+      kSkipExisting,
+      kAutoRename,
+      kAutoRenameExisting
+    };
+  }
+}  
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ExtractingFilePath.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,96 @@
+// ExtractingFilePath.cpp
+
+#include "StdAfx.h"
+#include "ExtractingFilePath.h"
+
+static UString ReplaceIncorrectChars(const UString &s)
+{
+  #ifdef _WIN32
+  UString res;
+  for (int i = 0; i < s.Length(); i++)
+  {
+    wchar_t c = s[i];
+    if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>'  || c == '|' || c == ':' || c == '"')
+      c = '_';
+    res += c;
+  }
+  return res;
+  #else
+  return s;
+  #endif
+}
+
+#ifdef _WIN32
+static const wchar_t *g_ReservedNames[] =
+{
+  L"CON", L"PRN", L"AUX", L"NUL"
+};
+
+static bool CheckTail(const UString &name, int len)
+{
+  int dotPos = name.Find(L'.');
+  if (dotPos < 0)
+    dotPos = name.Length();
+  UString s = name.Left(dotPos);
+  s.TrimRight();
+  return (s.Length() != len);
+}
+
+static bool CheckNameNum(const UString &name, const wchar_t *reservedName)
+{
+  int len = MyStringLen(reservedName);
+  if (name.Length() <= len)
+    return true;
+  if (name.Left(len).CompareNoCase(reservedName) != 0)
+    return true;
+  wchar_t c = name[len];
+  if (c < L'0' || c > L'9')
+    return true;
+  return CheckTail(name, len + 1);
+}
+
+static bool IsSupportedName(const UString &name)
+{
+  for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++)
+  {
+    const wchar_t *reservedName = g_ReservedNames[i];
+    int len = MyStringLen(reservedName);
+    if (name.Length() < len)
+      continue;
+    if (name.Left(len).CompareNoCase(reservedName) != 0)
+      continue;
+    if (!CheckTail(name, len))
+      return false;
+  }
+  if (!CheckNameNum(name, L"COM"))
+    return false;
+  return CheckNameNum(name, L"LPT");
+}
+#endif
+
+static UString GetCorrectFileName(const UString &path)
+{
+  if (path == L".." || path == L".")
+    return UString();
+  return ReplaceIncorrectChars(path);
+}
+
+void MakeCorrectPath(UStringVector &pathParts)
+{
+  for (int i = 0; i < pathParts.Size();)
+  {
+    UString &s = pathParts[i];
+    s = GetCorrectFileName(s);
+    if (s.IsEmpty())
+      pathParts.Delete(i);
+    else
+    {
+      #ifdef _WIN32
+      if (!IsSupportedName(s))
+        s = (UString)L"_" + s;
+      #endif
+      i++;
+    }
+  }
+}
+

Added: trunk/lzma/CPP/7zip/UI/Common/ExtractingFilePath.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ExtractingFilePath.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ExtractingFilePath.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// ExtractingFilePath.h
+
+#ifndef __EXTRACTINGFILEPATH_H
+#define __EXTRACTINGFILEPATH_H
+
+#include "Common/MyString.h"
+
+void MakeCorrectPath(UStringVector &pathParts);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/IFileExtractCallback.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/IFileExtractCallback.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/IFileExtractCallback.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,43 @@
+// IFileExtractCallback.h
+
+#ifndef __IFILEEXTRACTCALLBACK_H
+#define __IFILEEXTRACTCALLBACK_H
+
+#include "Common/MyString.h"
+#include "../../IDecl.h"
+
+namespace NOverwriteAnswer
+{
+  enum EEnum
+  {
+    kYes,
+    kYesToAll,
+    kNo,
+    kNoToAll,
+    kAutoRename,
+    kCancel
+  };
+}
+
+DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07)
+{
+public:
+  STDMETHOD(AskOverwrite)(
+      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
+      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
+      Int32 *answer) PURE;
+  STDMETHOD(PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position) PURE;
+  STDMETHOD(MessageError)(const wchar_t *message) PURE;
+  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted) PURE;
+};
+
+struct IExtractCallbackUI: IFolderArchiveExtractCallback
+{
+  virtual HRESULT BeforeOpen(const wchar_t *name) = 0;
+  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0;
+  virtual HRESULT ThereAreNoFiles() = 0;
+  virtual HRESULT ExtractResult(HRESULT result) = 0;
+  virtual HRESULT SetPassword(const UString &password) = 0;
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/LoadCodecs.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/LoadCodecs.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/LoadCodecs.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,644 @@
+// LoadCodecs.cpp
+
+#include "StdAfx.h"
+
+#include "LoadCodecs.h"
+
+#include "../../../Common/MyCom.h"
+#ifdef NEW_FOLDER_INTERFACE
+#include "../../../Common/StringToInt.h"
+#endif
+#include "../../../Windows/PropVariant.h"
+
+#include "../../ICoder.h"
+#include "../../Common/RegisterArc.h"
+
+#ifdef EXTERNAL_CODECS
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/DLL.h"
+#ifdef NEW_FOLDER_INTERFACE
+#include "../../../Windows/ResourceString.h"
+static const UINT kIconTypesResId = 100;
+#endif
+
+#ifdef _WIN32
+#include "Windows/Registry.h"
+#endif
+
+using namespace NWindows;
+using namespace NFile;
+
+#ifdef _WIN32
+extern HINSTANCE g_hInstance;
+#endif
+
+static CSysString GetLibraryFolderPrefix()
+{
+  #ifdef _WIN32
+  TCHAR fullPath[MAX_PATH + 1];
+  ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
+  CSysString path = fullPath;
+  int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
+  return path.Left(pos + 1);
+  #else
+  return CSysString(); // FIX IT
+  #endif
+}
+
+#define kCodecsFolderName TEXT("Codecs")
+#define kFormatsFolderName TEXT("Formats")
+static TCHAR *kMainDll = TEXT("7z.dll");
+
+#ifdef _WIN32
+static LPCTSTR kRegistryPath = TEXT("Software\\7-zip");
+static LPCTSTR kProgramPathValue = TEXT("Path");
+static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path)
+{
+  NRegistry::CKey key;
+  if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
+    if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS)
+    {
+      NName::NormalizeDirPathPrefix(path);
+      return true;
+    }
+  return false;
+}
+
+#endif
+
+CSysString GetBaseFolderPrefixFromRegistry()
+{
+  CSysString moduleFolderPrefix = GetLibraryFolderPrefix();
+  NFind::CFileInfo fileInfo;
+  if (NFind::FindFile(moduleFolderPrefix + kMainDll, fileInfo))
+    if (!fileInfo.IsDirectory())
+      return moduleFolderPrefix;
+  if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fileInfo))
+    if (fileInfo.IsDirectory())
+      return moduleFolderPrefix;
+  if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fileInfo))
+    if (fileInfo.IsDirectory())
+      return moduleFolderPrefix;
+  #ifdef _WIN32
+  CSysString path;
+  if (ReadPathFromRegistry(HKEY_CURRENT_USER, path))
+    return path;
+  if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))
+    return path;
+  #endif
+  return moduleFolderPrefix;
+}
+
+typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods);
+typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats);
+typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value);
+typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value);
+typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject);
+typedef UInt32 (WINAPI *SetLargePageModeFunc)();
+
+
+static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, 
+    PROPID propId, CLSID &clsId, bool &isAssigned)
+{
+  NWindows::NCOM::CPropVariant prop;
+  isAssigned = false;
+  RINOK(getMethodProperty(index, propId, &prop));
+  if (prop.vt == VT_BSTR)
+  {
+    isAssigned = true;
+    clsId = *(const GUID *)prop.bstrVal;
+  }
+  else if (prop.vt != VT_EMPTY)
+    return E_FAIL;
+  return S_OK;
+}
+
+HRESULT CCodecs::LoadCodecs()
+{
+  CCodecLib &lib = Libs.Back();
+  lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProcAddress("GetMethodProperty");
+  if (lib.GetMethodProperty == NULL)
+    return S_OK;
+
+  UInt32 numMethods = 1;
+  GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProcAddress("GetNumberOfMethods");
+  if (getNumberOfMethodsFunc != NULL)
+  {
+    RINOK(getNumberOfMethodsFunc(&numMethods));
+  }
+
+  for(UInt32 i = 0; i < numMethods; i++)
+  {
+    CDllCodecInfo info;
+    info.LibIndex = Libs.Size() - 1;
+    info.CodecIndex = i;
+
+    RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));
+    RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));
+
+    Codecs.Add(info);
+  }
+  return S_OK;
+}
+
+static HRESULT ReadProp(
+    GetHandlerPropertyFunc getProp, 
+    GetHandlerPropertyFunc2 getProp2, 
+    UInt32 index, PROPID propID, NCOM::CPropVariant &prop)
+{
+  if (getProp2)
+    return getProp2(index, propID, &prop);;
+  return getProp(propID, &prop);
+}
+
+static HRESULT ReadBoolProp(
+    GetHandlerPropertyFunc getProp, 
+    GetHandlerPropertyFunc2 getProp2, 
+    UInt32 index, PROPID propID, bool &res)
+{
+  NCOM::CPropVariant prop;
+  RINOK(ReadProp(getProp, getProp2, index, propID, prop));
+  if (prop.vt == VT_BOOL)
+    res = VARIANT_BOOLToBool(prop.boolVal);
+  else if (prop.vt != VT_EMPTY)
+    return E_FAIL;
+  return S_OK;
+}
+
+static HRESULT ReadStringProp(
+    GetHandlerPropertyFunc getProp, 
+    GetHandlerPropertyFunc2 getProp2, 
+    UInt32 index, PROPID propID, UString &res)
+{
+  NCOM::CPropVariant prop;
+  RINOK(ReadProp(getProp, getProp2, index, propID, prop));
+  if (prop.vt == VT_BSTR)
+    res = prop.bstrVal;
+  else if (prop.vt != VT_EMPTY)
+    return E_FAIL;
+  return S_OK;
+}
+
+#endif
+
+static const unsigned int kNumArcsMax = 32;
+static unsigned int g_NumArcs = 0;
+static const CArcInfo *g_Arcs[kNumArcsMax]; 
+void RegisterArc(const CArcInfo *arcInfo) 
+{ 
+  if (g_NumArcs < kNumArcsMax)
+    g_Arcs[g_NumArcs++] = arcInfo; 
+}
+
+static void SplitString(const UString &srcString, UStringVector &destStrings)
+{
+  destStrings.Clear();
+  UString s;
+  int len = srcString.Length();
+  if (len == 0)
+    return;
+  for (int i = 0; i < len; i++)
+  {
+    wchar_t c = srcString[i];
+    if (c == L' ')
+    {
+      if (!s.IsEmpty())
+      {
+        destStrings.Add(s);
+        s.Empty();
+      }
+    }
+    else
+      s += c;
+  }
+  if (!s.IsEmpty())
+    destStrings.Add(s);
+}
+
+void CArcInfoEx::AddExts(const wchar_t* ext, const wchar_t* addExt)
+{
+  UStringVector exts, addExts;
+  SplitString(ext, exts);
+  if (addExt != 0)
+    SplitString(addExt, addExts);
+  for (int i = 0; i < exts.Size(); i++)
+  {
+    CArcExtInfo extInfo;
+    extInfo.Ext = exts[i];
+    if (i < addExts.Size())
+    {
+      extInfo.AddExt = addExts[i];
+      if (extInfo.AddExt == L"*")
+        extInfo.AddExt.Empty();
+    }
+    Exts.Add(extInfo);
+  }
+}
+
+#ifdef EXTERNAL_CODECS
+
+HRESULT CCodecs::LoadFormats()
+{
+  const NDLL::CLibrary &lib = Libs.Back().Lib;
+  GetHandlerPropertyFunc getProp = 0;
+  GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)
+      lib.GetProcAddress("GetHandlerProperty2");
+  if (getProp2 == NULL)
+  {
+    getProp = (GetHandlerPropertyFunc)
+        lib.GetProcAddress("GetHandlerProperty");
+    if (getProp == NULL)
+      return S_OK;
+  }
+
+  UInt32 numFormats = 1;
+  GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)
+    lib.GetProcAddress("GetNumberOfFormats");
+  if (getNumberOfFormats != NULL)
+  {
+    RINOK(getNumberOfFormats(&numFormats));
+  }
+  if (getProp2 == NULL)
+    numFormats = 1;
+
+  for(UInt32 i = 0; i < numFormats; i++)
+  {
+    CArcInfoEx item;
+    item.LibIndex = Libs.Size() - 1;
+    item.FormatIndex = i;
+
+    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name));
+
+    NCOM::CPropVariant prop;
+    if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK)
+      continue;
+    if (prop.vt != VT_BSTR)
+      continue;
+    item.ClassID = *(const GUID *)prop.bstrVal;
+    prop.Clear();
+
+    UString ext, addExt;
+    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext));
+    RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt));
+    item.AddExts(ext, addExt);
+
+    ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled);
+    if (item.UpdateEnabled)
+      ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName);
+    
+    if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK)
+      if (prop.vt == VT_BSTR)
+      {
+        UINT len = ::SysStringByteLen(prop.bstrVal);
+        item.StartSignature.SetCapacity(len);
+        memmove(item.StartSignature, prop.bstrVal, len);
+      }
+    Formats.Add(item);
+  }
+  return S_OK;
+}
+
+#ifdef NEW_FOLDER_INTERFACE
+void CCodecLib::LoadIcons()
+{
+  UString iconTypes = MyLoadStringW((HMODULE)Lib, kIconTypesResId);
+  UStringVector pairs;
+  SplitString(iconTypes, pairs);
+  for (int i = 0; i < pairs.Size(); i++)
+  {
+    const UString &s = pairs[i];
+    int pos = s.Find(L':');
+    if (pos < 0)
+      continue;
+    CIconPair iconPair;
+    const wchar_t *end;
+    UString num = s.Mid(pos + 1);
+    iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end);
+    if (*end != L'\0')
+      continue;
+    iconPair.Ext = s.Left(pos);
+    IconPairs.Add(iconPair);
+  }
+}
+
+int CCodecLib::FindIconIndex(const UString &ext) const
+{
+  for (int i = 0; i < IconPairs.Size(); i++)
+  {
+    const CIconPair &pair = IconPairs[i];
+    if (ext.CompareNoCase(pair.Ext) == 0)
+      return pair.IconIndex;
+  }
+  return -1;
+}
+#endif
+
+#ifdef _7ZIP_LARGE_PAGES
+extern "C" 
+{
+  extern SIZE_T g_LargePageSize;
+}
+#endif
+
+HRESULT CCodecs::LoadDll(const CSysString &dllPath)
+{
+  {
+    NDLL::CLibrary library;
+    if (!library.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))
+      return S_OK;
+  }
+  Libs.Add(CCodecLib());
+  CCodecLib &lib = Libs.Back();
+  #ifdef NEW_FOLDER_INTERFACE
+  lib.Path = dllPath;
+  #endif
+  bool used = false;
+  HRESULT res = S_OK;
+  if (lib.Lib.Load(dllPath))
+  {
+    #ifdef NEW_FOLDER_INTERFACE
+    lib.LoadIcons();
+    #endif
+
+    #ifdef _7ZIP_LARGE_PAGES
+    if (g_LargePageSize != 0)
+    {
+      SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProcAddress("SetLargePageMode");
+      if (setLargePageMode != 0)
+        setLargePageMode();
+    }
+    #endif
+
+    lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProcAddress("CreateObject");
+    if (lib.CreateObject != 0)
+    {
+      int startSize = Codecs.Size();
+      res = LoadCodecs();
+      used = (Codecs.Size() != startSize);
+      if (res == S_OK)
+      {
+        startSize = Formats.Size();
+        res = LoadFormats();
+        used = used || (Formats.Size() != startSize);
+      }
+    }
+  }
+  if (!used)
+    Libs.DeleteBack();
+  return res;
+}
+
+HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix)
+{
+  NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*")));
+  NFile::NFind::CFileInfo fileInfo;
+  while (enumerator.Next(fileInfo))
+  {
+    if (fileInfo.IsDirectory())
+      continue;
+    RINOK(LoadDll(folderPrefix + fileInfo.Name));
+  }
+  return S_OK;
+}
+
+#endif
+
+#ifndef _SFX
+static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size)
+{
+  bb.SetCapacity(size);
+  memmove((Byte *)bb, data, size);
+}
+#endif
+
+HRESULT CCodecs::Load()
+{
+  Formats.Clear();
+  #ifdef EXTERNAL_CODECS
+  Codecs.Clear();
+  #endif
+  for (UInt32 i = 0; i < g_NumArcs; i++)
+  {
+    const CArcInfo &arc = *g_Arcs[i];
+    CArcInfoEx item;
+    item.Name = arc.Name;
+    item.CreateInArchive = arc.CreateInArchive;
+    item.CreateOutArchive = arc.CreateOutArchive;
+    item.AddExts(arc.Ext, arc.AddExt);
+    item.UpdateEnabled = (arc.CreateOutArchive != 0);
+    item.KeepName = arc.KeepName;
+
+    #ifndef _SFX
+    SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize);
+    #endif
+    Formats.Add(item);
+  }
+  #ifdef EXTERNAL_CODECS
+  const CSysString baseFolder = GetBaseFolderPrefixFromRegistry();
+  RINOK(LoadDll(baseFolder + kMainDll));
+  RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR)));
+  RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR)));
+  #endif
+  return S_OK;
+}
+
+int CCodecs::FindFormatForArchiveName(const UString &archivePath) const
+{
+  int slashPos1 = archivePath.ReverseFind(L'\\');
+  int slashPos2 = archivePath.ReverseFind(L'.');
+  int dotPos = archivePath.ReverseFind(L'.');
+  if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2)
+    return -1;
+  UString ext = archivePath.Mid(dotPos + 1);
+  for (int i = 0; i < Formats.Size(); i++)
+  {
+    const CArcInfoEx &arc = Formats[i];
+    if (!arc.UpdateEnabled)
+      continue;
+    // if (arc.FindExtension(ext) >= 0)
+    UString mainExt = arc.GetMainExt();
+    if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0)
+      return i;
+  }
+  return -1;
+}
+
+int CCodecs::FindFormatForArchiveType(const UString &arcType) const
+{
+  for (int i = 0; i < Formats.Size(); i++)
+  {
+    const CArcInfoEx &arc = Formats[i];
+    if (!arc.UpdateEnabled)
+      continue;
+    if (arc.Name.CompareNoCase(arcType) == 0)
+      return i;
+  }
+  return -1;
+}
+
+#ifdef EXTERNAL_CODECS
+
+#ifdef EXPORT_CODECS
+extern unsigned int g_NumCodecs;
+STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);
+STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
+// STDAPI GetNumberOfMethods(UINT32 *numCodecs);
+#endif
+
+STDMETHODIMP CCodecs::GetNumberOfMethods(UINT32 *numMethods)
+{
+  *numMethods = 
+      #ifdef EXPORT_CODECS
+      g_NumCodecs + 
+      #endif
+      Codecs.Size();
+  return S_OK;
+}
+
+STDMETHODIMP CCodecs::GetProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
+{
+  #ifdef EXPORT_CODECS
+  if (index < g_NumCodecs)
+    return GetMethodProperty(index, propID, value);
+  #endif
+
+  const CDllCodecInfo &ci = Codecs[index 
+      #ifdef EXPORT_CODECS
+      - g_NumCodecs
+      #endif
+      ];
+
+  if (propID == NMethodPropID::kDecoderIsAssigned)
+  {
+    NWindows::NCOM::CPropVariant propVariant;
+    propVariant = ci.DecoderIsAssigned;
+    propVariant.Detach(value);
+    return S_OK;
+  }
+  if (propID == NMethodPropID::kEncoderIsAssigned)
+  {
+    NWindows::NCOM::CPropVariant propVariant;
+    propVariant = ci.EncoderIsAssigned;
+    propVariant.Detach(value);
+    return S_OK;
+  }
+  return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);
+}
+
+STDMETHODIMP CCodecs::CreateDecoder(UINT32 index, const GUID *iid, void **coder)
+{
+  #ifdef EXPORT_CODECS
+  if (index < g_NumCodecs)
+    return CreateCoder2(false, index, iid, coder);
+  #endif
+  const CDllCodecInfo &ci = Codecs[index 
+      #ifdef EXPORT_CODECS
+      - g_NumCodecs
+      #endif
+      ];
+  if (ci.DecoderIsAssigned)
+    return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder);
+  return S_OK;
+}
+
+STDMETHODIMP CCodecs::CreateEncoder(UINT32 index, const GUID *iid, void **coder)
+{
+  #ifdef EXPORT_CODECS
+  if (index < g_NumCodecs)
+    return CreateCoder2(true, index, iid, coder);
+  #endif
+  const CDllCodecInfo &ci = Codecs[index 
+      #ifdef EXPORT_CODECS
+      - g_NumCodecs
+      #endif
+      ];
+  if (ci.EncoderIsAssigned)
+    return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder);
+  return S_OK;
+}
+
+HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const
+{ 
+  for (int i = 0; i < Codecs.Size(); i++)
+  {
+    const CDllCodecInfo &codec = Codecs[i];
+    if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned)
+      continue;
+    const CCodecLib &lib = Libs[codec.LibIndex];
+    UString res;
+    NWindows::NCOM::CPropVariant prop;
+    RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop));
+    if (prop.vt == VT_BSTR)
+      res = prop.bstrVal;
+    else if (prop.vt != VT_EMPTY)
+      continue;
+    if (name.CompareNoCase(res) == 0)
+      return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder);
+  }
+  return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+int CCodecs::GetCodecLibIndex(UInt32 index)
+{
+  #ifdef EXPORT_CODECS
+  if (index < g_NumCodecs)
+    return -1;
+  #endif
+  #ifdef EXTERNAL_CODECS
+  const CDllCodecInfo &ci = Codecs[index 
+      #ifdef EXPORT_CODECS
+      - g_NumCodecs
+      #endif
+      ];
+  return ci.LibIndex;
+  #else
+  return -1;
+  #endif
+}
+
+bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)
+{
+  #ifdef EXPORT_CODECS
+  if (index < g_NumCodecs)
+  {
+    NWindows::NCOM::CPropVariant prop;
+    if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)
+      if (prop.vt != VT_EMPTY)
+        return true;
+    return false;
+  }
+  #endif
+  #ifdef EXTERNAL_CODECS
+  const CDllCodecInfo &ci = Codecs[index 
+      #ifdef EXPORT_CODECS
+      - g_NumCodecs
+      #endif
+      ];
+  return ci.EncoderIsAssigned;
+  #else
+  return false;
+  #endif
+}
+
+HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)
+{
+  UString s;
+  NWindows::NCOM::CPropVariant prop;
+  RINOK(GetProperty(index, NMethodPropID::kID, &prop));
+  if (prop.vt != VT_UI8)
+    return E_INVALIDARG;
+  id = prop.uhVal.QuadPart;
+  return S_OK;
+}
+
+UString CCodecs::GetCodecName(UInt32 index)
+{
+  UString s;
+  NWindows::NCOM::CPropVariant prop;
+  if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
+    if (prop.vt == VT_BSTR)
+      s = prop.bstrVal;
+  return s;
+}
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/LoadCodecs.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/LoadCodecs.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/LoadCodecs.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,215 @@
+// LoadCodecs.h
+
+#ifndef __LOADCODECS_H
+#define __LOADCODECS_H
+
+#include "../../../Common/Types.h"
+#include "../../../Common/MyCom.h"
+#include "../../../Common/MyString.h"
+#include "../../../Common/Buffer.h"
+#include "../../ICoder.h"
+
+#ifdef EXTERNAL_CODECS
+#include "../../../Windows/DLL.h"
+#endif
+
+struct CDllCodecInfo
+{
+  CLSID Encoder;
+  CLSID Decoder;
+  bool EncoderIsAssigned;
+  bool DecoderIsAssigned;
+  int LibIndex;
+  UInt32 CodecIndex;
+};
+
+#include "../../Archive/IArchive.h"
+
+typedef IInArchive * (*CreateInArchiveP)();
+typedef IOutArchive * (*CreateOutArchiveP)();
+
+struct CArcExtInfo
+{
+  UString Ext;
+  UString AddExt;
+  CArcExtInfo() {}
+  CArcExtInfo(const UString &ext): Ext(ext) {}
+  CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}
+};
+
+
+struct CArcInfoEx
+{
+  #ifdef EXTERNAL_CODECS
+  int LibIndex;
+  UInt32 FormatIndex;
+  CLSID ClassID;
+  #endif
+  bool UpdateEnabled;
+  CreateInArchiveP CreateInArchive;
+  CreateOutArchiveP CreateOutArchive;
+  UString Name;
+  CObjectVector<CArcExtInfo> Exts;
+  #ifndef _SFX
+  CByteBuffer StartSignature;
+  // CByteBuffer FinishSignature;
+  #ifdef NEW_FOLDER_INTERFACE
+  UStringVector AssociateExts;
+  #endif
+  #endif
+  bool KeepName;
+  UString GetMainExt() const
+  {
+    if (Exts.IsEmpty())
+      return UString();
+    return Exts[0].Ext;
+  }
+  int FindExtension(const UString &ext) const
+  {
+    for (int i = 0; i < Exts.Size(); i++)
+      if (ext.CompareNoCase(Exts[i].Ext) == 0)
+        return i;
+    return -1;
+  }
+  UString GetAllExtensions() const
+  {
+    UString s;
+    for (int i = 0; i < Exts.Size(); i++)
+    {
+      if (i > 0)
+        s += ' ';
+      s += Exts[i].Ext;
+    }
+    return s;
+  }
+
+  void AddExts(const wchar_t* ext, const wchar_t* addExt);
+
+  CArcInfoEx(): 
+    #ifdef EXTERNAL_CODECS
+    LibIndex(-1),
+    #endif
+    UpdateEnabled(false),
+    CreateInArchive(0), CreateOutArchive(0),
+    KeepName(false)
+    #ifndef _SFX
+    #endif
+  {}
+};
+
+#ifdef EXTERNAL_CODECS
+typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value);
+typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject);
+
+
+struct CCodecLib
+{
+  NWindows::NDLL::CLibrary Lib;
+  GetMethodPropertyFunc GetMethodProperty;
+  CreateObjectFunc CreateObject;
+  #ifdef NEW_FOLDER_INTERFACE
+  struct CIconPair
+  {
+    UString Ext;
+    UInt32 IconIndex;
+  };
+  CSysString Path;
+  CObjectVector<CIconPair> IconPairs;
+  void LoadIcons();
+  int FindIconIndex(const UString &ext) const;
+  #endif
+  CCodecLib(): GetMethodProperty(0) {}
+};
+#endif
+
+class CCodecs:
+  #ifdef EXTERNAL_CODECS
+  public ICompressCodecsInfo,
+  #else
+  public IUnknown,
+  #endif
+  public CMyUnknownImp
+{
+public:  
+  #ifdef EXTERNAL_CODECS
+  CObjectVector<CCodecLib> Libs;
+  CObjectVector<CDllCodecInfo> Codecs;
+  HRESULT LoadCodecs();
+  HRESULT LoadFormats();
+  HRESULT LoadDll(const CSysString &path);
+  HRESULT LoadDllsFromFolder(const CSysString &folderPrefix);
+
+  HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const
+  {
+    return Libs[ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);
+  }
+  #endif
+
+public:
+  CObjectVector<CArcInfoEx> Formats;
+  HRESULT Load();
+  int FindFormatForArchiveName(const UString &archivePath) const;
+  int FindFormatForArchiveType(const UString &arcType) const;
+
+  MY_UNKNOWN_IMP
+
+  #ifdef EXTERNAL_CODECS
+  STDMETHOD(GetNumberOfMethods)(UINT32 *numMethods);
+  STDMETHOD(GetProperty)(UINT32 index, PROPID propID, PROPVARIANT *value);
+  STDMETHOD(CreateDecoder)(UINT32 index, const GUID *interfaceID, void **coder);
+  STDMETHOD(CreateEncoder)(UINT32 index, const GUID *interfaceID, void **coder);
+  #endif
+
+  int GetCodecLibIndex(UInt32 index);
+  bool GetCodecEncoderIsAssigned(UInt32 index);
+  HRESULT GetCodecId(UInt32 index, UInt64 &id);
+  UString GetCodecName(UInt32 index);
+
+  HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const
+  { 
+    const CArcInfoEx &ai = Formats[formatIndex]; 
+    #ifdef EXTERNAL_CODECS
+    if (ai.LibIndex < 0)
+    #endif
+    {
+      archive = ai.CreateInArchive();
+      return S_OK;
+    }
+    #ifdef EXTERNAL_CODECS
+    return CreateArchiveHandler(ai, (void **)&archive, false); 
+    #endif
+  }
+  HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const
+  { 
+    const CArcInfoEx &ai = Formats[formatIndex]; 
+    #ifdef EXTERNAL_CODECS
+    if (ai.LibIndex < 0)
+    #endif
+    {
+      archive = ai.CreateOutArchive();
+      return S_OK;
+    }
+    #ifdef EXTERNAL_CODECS
+    return CreateArchiveHandler(ai, (void **)&archive, true); 
+    #endif
+  }
+  int FindOutFormatFromName(const UString &name) const
+  {
+    for (int i = 0; i < Formats.Size(); i++)
+    {
+      const CArcInfoEx &arc = Formats[i];
+      if (!arc.UpdateEnabled)
+        continue;
+      if (arc.Name.CompareNoCase(name) == 0)
+        return i;
+    }
+    return -1;
+  }
+
+  #ifdef EXTERNAL_CODECS
+  HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const;
+  #endif
+
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/OpenArchive.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/OpenArchive.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/OpenArchive.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,461 @@
+// OpenArchive.cpp
+
+#include "StdAfx.h"
+
+#include "OpenArchive.h"
+
+#include "Common/Wildcard.h"
+
+#include "Windows/FileName.h"
+#include "Windows/FileDir.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "Common/StringConvert.h"
+
+#include "DefaultName.h"
+
+using namespace NWindows;
+
+HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result)
+{
+  NCOM::CPropVariant prop;
+  RINOK(archive->GetProperty(index, kpidPath, &prop));
+  if(prop.vt == VT_BSTR)
+    result = prop.bstrVal;
+  else if (prop.vt == VT_EMPTY)
+    result.Empty();
+  else
+    return E_FAIL;
+  return S_OK;
+}
+
+HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result)
+{
+  RINOK(GetArchiveItemPath(archive, index, result));
+  if (result.IsEmpty())
+    result = defaultName;
+  return S_OK;
+}
+
+HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, 
+    const FILETIME &defaultFileTime, FILETIME &fileTime)
+{
+  NCOM::CPropVariant prop;
+  RINOK(archive->GetProperty(index, kpidLastWriteTime, &prop));
+  if (prop.vt == VT_FILETIME)
+    fileTime = prop.filetime;
+  else if (prop.vt == VT_EMPTY)
+    fileTime = defaultFileTime;
+  else
+    return E_FAIL;
+  return S_OK;
+}
+
+HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
+{
+  NCOM::CPropVariant prop;
+  RINOK(archive->GetProperty(index, propID, &prop));
+  if(prop.vt == VT_BOOL)
+    result = VARIANT_BOOLToBool(prop.boolVal);
+  else if (prop.vt == VT_EMPTY)
+    result = false;
+  else
+    return E_FAIL;
+  return S_OK;
+}
+
+HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
+{
+  return IsArchiveItemProp(archive, index, kpidIsFolder, result);
+}
+
+HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result)
+{
+  return IsArchiveItemProp(archive, index, kpidIsAnti, result);
+}
+
+// Static-SFX (for Linux) can be big.
+const UInt64 kMaxCheckStartPosition = 1 << 22;
+
+HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback)
+{
+  CInFileStream *inStreamSpec = new CInFileStream;
+  CMyComPtr<IInStream> inStream(inStreamSpec);
+  inStreamSpec->Open(fileName);
+  return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback);
+}
+
+#ifndef _SFX
+static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
+{
+  for (size_t i = 0; i < size; i++)
+    if (p1[i] != p2[i])
+      return false;
+  return true;
+}
+#endif
+
+HRESULT OpenArchive(
+    CCodecs *codecs,
+    IInStream *inStream,
+    const UString &fileName, 
+    IInArchive **archiveResult, 
+    int &formatIndex,
+    UString &defaultItemName,
+    IArchiveOpenCallback *openArchiveCallback)
+{
+  *archiveResult = NULL;
+  UString extension;
+  {
+    int dotPos = fileName.ReverseFind(L'.');
+    if (dotPos >= 0)
+      extension = fileName.Mid(dotPos + 1);
+  }
+  CIntVector orderIndices;
+  int i;
+  int numFinded = 0;
+  for (i = 0; i < codecs->Formats.Size(); i++)
+    if (codecs->Formats[i].FindExtension(extension) >= 0)
+      orderIndices.Insert(numFinded++, i);
+    else
+      orderIndices.Add(i);
+  
+  #ifndef _SFX
+  if (numFinded != 1)
+  {
+    CIntVector orderIndices2;
+    CByteBuffer byteBuffer;
+    const UInt32 kBufferSize = (200 << 10);
+    byteBuffer.SetCapacity(kBufferSize);
+    Byte *buffer = byteBuffer;
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+    UInt32 processedSize;
+    RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize));
+    for (UInt32 pos = 0; pos < processedSize; pos++)
+    {
+      for (int i = 0; i < orderIndices.Size(); i++)
+      {
+        int index = orderIndices[i];
+        const CArcInfoEx &ai = codecs->Formats[index];
+        const CByteBuffer &sig = ai.StartSignature;
+        if (sig.GetCapacity() == 0)
+          continue;
+        if (pos + sig.GetCapacity() > processedSize)
+          continue;
+        if (TestSignature(buffer + pos, sig, sig.GetCapacity()))
+        {
+          orderIndices2.Add(index);
+          orderIndices.Delete(i--);
+        }
+      }
+    }
+    orderIndices2 += orderIndices;
+    orderIndices = orderIndices2;
+  }
+  else if (extension == L"000" || extension == L"001")
+  {
+    CByteBuffer byteBuffer;
+    const UInt32 kBufferSize = (1 << 10);
+    byteBuffer.SetCapacity(kBufferSize);
+    Byte *buffer = byteBuffer;
+    RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+    UInt32 processedSize;
+    RINOK(ReadStream(inStream, buffer, kBufferSize, &processedSize));
+    if (processedSize >= 16)
+    {
+      Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};
+      if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] && 1) != 0)
+      {
+        for (int i = 0; i < orderIndices.Size(); i++)
+        {
+          int index = orderIndices[i];
+          const CArcInfoEx &ai = codecs->Formats[index];
+          if (ai.Name.CompareNoCase(L"rar") != 0)
+            continue;
+          orderIndices.Delete(i--);
+          orderIndices.Insert(0, index);
+          break;
+        }
+      }
+    }
+  }
+  #endif
+
+  HRESULT badResult = S_OK;
+  for(i = 0; i < orderIndices.Size(); i++)
+  {
+    inStream->Seek(0, STREAM_SEEK_SET, NULL);
+
+    CMyComPtr<IInArchive> archive;
+
+    formatIndex = orderIndices[i];
+    RINOK(codecs->CreateInArchive(formatIndex, archive));
+    if (!archive)
+      continue;
+
+    #ifdef EXTERNAL_CODECS
+    {
+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
+      archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+      if (setCompressCodecsInfo)
+      {
+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
+      }
+    }
+    #endif
+
+    HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback);
+    if (result == S_FALSE)
+      continue;
+    if(result != S_OK)
+    {
+      badResult = result;
+      if(result == E_ABORT)
+        break;
+      continue;
+    }
+    *archiveResult = archive.Detach();
+    const CArcInfoEx &format = codecs->Formats[formatIndex];
+    if (format.Exts.Size() == 0)
+    {
+      defaultItemName = GetDefaultName2(fileName, L"", L"");
+    }
+    else
+    {
+      int subExtIndex = format.FindExtension(extension);
+      if (subExtIndex < 0)
+        subExtIndex = 0;
+      defaultItemName = GetDefaultName2(fileName, 
+          format.Exts[subExtIndex].Ext, 
+          format.Exts[subExtIndex].AddExt);
+    }
+    return S_OK;
+  }
+  if (badResult != S_OK)
+    return badResult;
+  return S_FALSE;
+}
+
+HRESULT OpenArchive(
+    CCodecs *codecs,
+    const UString &filePath, 
+    IInArchive **archiveResult, 
+    int &formatIndex,
+    UString &defaultItemName,
+    IArchiveOpenCallback *openArchiveCallback)
+{
+  CInFileStream *inStreamSpec = new CInFileStream;
+  CMyComPtr<IInStream> inStream(inStreamSpec);
+  if (!inStreamSpec->Open(filePath))
+    return GetLastError();
+  return OpenArchive(codecs, inStream, ExtractFileNameFromPath(filePath),
+    archiveResult, formatIndex,
+    defaultItemName, openArchiveCallback);
+}
+
+static void MakeDefaultName(UString &name)
+{
+  int dotPos = name.ReverseFind(L'.');
+  if (dotPos < 0)
+    return;
+  UString ext = name.Mid(dotPos + 1);
+  if (ext.IsEmpty())
+    return;
+  for (int pos = 0; pos < ext.Length(); pos++)
+    if (ext[pos] < L'0' || ext[pos] > L'9')
+      return;
+  name = name.Left(dotPos);
+}
+
+HRESULT OpenArchive(
+    CCodecs *codecs,
+    const UString &fileName, 
+    IInArchive **archive0, 
+    IInArchive **archive1, 
+    int &formatIndex0,
+    int &formatIndex1,
+    UString &defaultItemName0,
+    UString &defaultItemName1,
+    IArchiveOpenCallback *openArchiveCallback)
+{
+  HRESULT result = OpenArchive(codecs, fileName, 
+      archive0, formatIndex0, defaultItemName0, openArchiveCallback);
+  RINOK(result);
+  CMyComPtr<IInArchiveGetStream> getStream;
+  result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream);
+  if (result != S_OK || getStream == 0)
+    return S_OK;
+
+  CMyComPtr<ISequentialInStream> subSeqStream;
+  result = getStream->GetStream(0, &subSeqStream);
+  if (result != S_OK)
+    return S_OK;
+
+  CMyComPtr<IInStream> subStream;
+  if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK)
+    return S_OK;
+  if (!subStream)
+    return S_OK;
+
+  UInt32 numItems;
+  RINOK((*archive0)->GetNumberOfItems(&numItems));
+  if (numItems < 1)
+    return S_OK;
+
+  UString subPath;
+  RINOK(GetArchiveItemPath(*archive0, 0, subPath))
+  if (subPath.IsEmpty())
+  {
+    MakeDefaultName(defaultItemName0);
+    subPath = defaultItemName0;
+    const CArcInfoEx &format = codecs->Formats[formatIndex0];
+    if (format.Name.CompareNoCase(L"7z") == 0)
+    {
+      if (subPath.Right(3).CompareNoCase(L".7z") != 0)
+        subPath += L".7z";
+    }
+  }
+  else
+    subPath = ExtractFileNameFromPath(subPath);
+
+  CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
+  openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
+  if (setSubArchiveName)
+    setSubArchiveName->SetSubArchiveName(subPath);
+
+  result = OpenArchive(codecs, subStream, subPath,
+      archive1, formatIndex1, defaultItemName1, openArchiveCallback);
+  return S_OK;
+}
+
+static void SetCallback(const UString &archiveName,
+    IOpenCallbackUI *openCallbackUI, CMyComPtr<IArchiveOpenCallback> &openCallback)
+{
+  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
+  openCallback = openCallbackSpec;
+  openCallbackSpec->Callback = openCallbackUI;
+
+  UString fullName;
+  int fileNamePartStartIndex;
+  NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
+  openCallbackSpec->Init(
+      fullName.Left(fileNamePartStartIndex), 
+      fullName.Mid(fileNamePartStartIndex));
+}
+
+HRESULT MyOpenArchive(
+    CCodecs *codecs, 
+    const UString &archiveName,
+    IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI)
+{
+  CMyComPtr<IArchiveOpenCallback> openCallback;
+  SetCallback(archiveName, openCallbackUI, openCallback);
+  int formatInfo;
+  return OpenArchive(codecs, archiveName, archive, formatInfo, defaultItemName, openCallback);
+}
+
+HRESULT MyOpenArchive(
+    CCodecs *codecs,
+    const UString &archiveName,
+    IInArchive **archive0,
+    IInArchive **archive1,
+    UString &defaultItemName0,
+    UString &defaultItemName1,
+    UStringVector &volumePaths,
+    UInt64 &volumesSize,
+    IOpenCallbackUI *openCallbackUI)
+{
+  volumesSize = 0;
+  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
+  CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec;
+  openCallbackSpec->Callback = openCallbackUI;
+
+  UString fullName;
+  int fileNamePartStartIndex;
+  NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
+  UString prefix = fullName.Left(fileNamePartStartIndex);
+  UString name = fullName.Mid(fileNamePartStartIndex);
+  openCallbackSpec->Init(prefix, name);
+
+  int formatIndex0, formatIndex1;
+  RINOK(OpenArchive(codecs, archiveName,
+      archive0, 
+      archive1, 
+      formatIndex0, 
+      formatIndex1, 
+      defaultItemName0,
+      defaultItemName1,
+      openCallback));
+  volumePaths.Add(prefix + name);
+  for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)
+    volumePaths.Add(prefix + openCallbackSpec->FileNames[i]);
+  volumesSize = openCallbackSpec->TotalSize;
+  return S_OK;
+}
+
+HRESULT CArchiveLink::Close()
+{
+  if (Archive1 != 0)
+    RINOK(Archive1->Close());
+  if (Archive0 != 0)
+    RINOK(Archive0->Close());
+  IsOpen = false;
+  return S_OK;
+}
+
+void CArchiveLink::Release()
+{
+  IsOpen = false;
+  Archive1.Release();
+  Archive0.Release();
+}
+
+HRESULT OpenArchive(
+    CCodecs *codecs,
+    const UString &archiveName,
+    CArchiveLink &archiveLink,
+    IArchiveOpenCallback *openCallback)
+{
+  HRESULT res = OpenArchive(codecs, archiveName, 
+    &archiveLink.Archive0, &archiveLink.Archive1, 
+    archiveLink.FormatIndex0, archiveLink.FormatIndex1, 
+    archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, 
+    openCallback);
+  archiveLink.IsOpen = (res == S_OK);
+  return res;
+}
+
+HRESULT MyOpenArchive(CCodecs *codecs,
+    const UString &archiveName, 
+    CArchiveLink &archiveLink,
+    IOpenCallbackUI *openCallbackUI)
+{
+  HRESULT res = MyOpenArchive(codecs, archiveName,
+    &archiveLink.Archive0, &archiveLink.Archive1, 
+    archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, 
+    archiveLink.VolumePaths,
+    archiveLink.VolumesSize,
+    openCallbackUI);
+  archiveLink.IsOpen = (res == S_OK);
+  return res;
+}
+
+HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName)
+{
+  if (archiveLink.GetNumLevels() > 1)
+    return E_NOTIMPL;
+
+  if (archiveLink.GetNumLevels() == 0)
+    return MyOpenArchive(codecs, fileName, archiveLink, 0);
+
+  CMyComPtr<IArchiveOpenCallback> openCallback;
+  SetCallback(fileName, NULL, openCallback);
+
+  HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallback);
+  archiveLink.IsOpen = (res == S_OK);
+  return res;
+}

Added: trunk/lzma/CPP/7zip/UI/Common/OpenArchive.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/OpenArchive.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/OpenArchive.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,130 @@
+// OpenArchive.h
+
+#ifndef __OPENARCHIVE_H
+#define __OPENARCHIVE_H
+
+#include "Common/MyString.h"
+#include "Windows/FileFind.h"
+
+#include "../../Archive/IArchive.h"
+#include "LoadCodecs.h"
+#include "ArchiveOpenCallback.h"
+
+HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result);
+HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result);
+HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, 
+    const FILETIME &defaultFileTime, FILETIME &fileTime);
+HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result);
+HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result);
+HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result);
+
+struct ISetSubArchiveName
+{
+  virtual void SetSubArchiveName(const wchar_t *name) = 0;
+};
+
+HRESULT OpenArchive(
+    CCodecs *codecs,
+    IInStream *inStream,
+    const UString &fileName, 
+    IInArchive **archiveResult, 
+    int &formatIndex,
+    UString &defaultItemName,
+    IArchiveOpenCallback *openArchiveCallback);
+
+HRESULT OpenArchive(
+    CCodecs *codecs,
+    const UString &filePath, 
+    IInArchive **archive, 
+    int &formatIndex,
+    UString &defaultItemName,
+    IArchiveOpenCallback *openArchiveCallback);
+
+HRESULT OpenArchive(
+    CCodecs *codecs,
+    const UString &filePath, 
+    IInArchive **archive0, 
+    IInArchive **archive1, 
+    int &formatIndex0,
+    int &formatIndex1,
+    UString &defaultItemName0,
+    UString &defaultItemName1,
+    IArchiveOpenCallback *openArchiveCallback);
+
+
+HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback);
+
+HRESULT MyOpenArchive(
+    CCodecs *codecs,
+    const UString &archiveName, 
+    IInArchive **archive,
+    UString &defaultItemName,
+    IOpenCallbackUI *openCallbackUI);
+
+HRESULT MyOpenArchive(
+    CCodecs *codecs,
+    const UString &archiveName, 
+    IInArchive **archive0,
+    IInArchive **archive1,
+    UString &defaultItemName0,
+    UString &defaultItemName1,
+    UStringVector &volumePaths,
+    UInt64 &volumesSize,
+    IOpenCallbackUI *openCallbackUI);
+
+struct CArchiveLink
+{
+  CMyComPtr<IInArchive> Archive0;
+  CMyComPtr<IInArchive> Archive1;
+  UString DefaultItemName0;
+  UString DefaultItemName1;
+
+  int FormatIndex0;
+  int FormatIndex1;
+  
+  UStringVector VolumePaths;
+
+  UInt64 VolumesSize;
+
+  int GetNumLevels() const
+  { 
+    int result = 0;
+    if (Archive0)
+    {
+      result++;
+      if (Archive1)
+        result++;
+    }
+    return result;
+  }
+
+  bool IsOpen;
+
+  CArchiveLink(): IsOpen(false), VolumesSize(0) {};
+
+  IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; }
+  UString GetDefaultItemName()  { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; }
+  int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; }
+  HRESULT Close();
+  void Release();
+};
+
+HRESULT OpenArchive(
+    CCodecs *codecs,
+    const UString &archiveName, 
+    CArchiveLink &archiveLink,
+    IArchiveOpenCallback *openCallback);
+
+HRESULT MyOpenArchive(
+    CCodecs *codecs,
+    const UString &archiveName, 
+    CArchiveLink &archiveLink,
+    IOpenCallbackUI *openCallbackUI);
+
+HRESULT ReOpenArchive(
+    CCodecs *codecs,
+    CArchiveLink &archiveLink, 
+    const UString &fileName);
+
+#endif
+

Added: trunk/lzma/CPP/7zip/UI/Common/PropIDUtils.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/PropIDUtils.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/PropIDUtils.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,89 @@
+// PropIDUtils.cpp
+
+#include "StdAfx.h"
+
+#include "PropIDUtils.h"
+
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/FileFind.h"
+#include "Windows/PropVariantConversions.h"
+
+#include "../../PropID.h"
+
+using namespace NWindows;
+
+static UString ConvertUInt32ToString(UInt32 value)
+{
+  wchar_t buffer[32];
+  ConvertUInt64ToString(value, buffer);
+  return buffer;
+}
+
+static void ConvertUInt32ToHex(UInt32 value, wchar_t *s)
+{
+  for (int i = 0; i < 8; i++)
+  {
+    int t = value & 0xF;
+    value >>= 4;
+    s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));
+  }
+  s[8] = L'\0';
+}
+
+UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full)
+{
+  switch(propID)
+  {
+    case kpidCreationTime:
+    case kpidLastWriteTime:
+    case kpidLastAccessTime:
+    {
+      if (propVariant.vt != VT_FILETIME)
+        return UString(); // It is error;
+      FILETIME localFileTime;
+      if (propVariant.filetime.dwHighDateTime == 0 && 
+          propVariant.filetime.dwLowDateTime == 0)
+        return UString();
+      if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime))
+        return UString(); // It is error;
+      return ConvertFileTimeToString(localFileTime, true, full);
+    }
+    case kpidCRC:
+    {
+      if(propVariant.vt != VT_UI4)
+        break;
+      wchar_t temp[12];
+      ConvertUInt32ToHex(propVariant.ulVal, temp);
+      return temp;
+    }
+    case kpidAttributes:
+    {
+      if(propVariant.vt != VT_UI4)
+        break;
+      UString result;
+      UInt32 attributes = propVariant.ulVal;
+      if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R';
+      if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H';
+      if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S';
+      if (NFile::NFind::NAttributes::IsDirectory(attributes)) result += L'D';
+      if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A';
+      if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C';
+      if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E';
+      return result;
+    }
+    case kpidDictionarySize:
+    {
+      if(propVariant.vt != VT_UI4)
+        break;
+      UInt32 size = propVariant.ulVal;
+      if (size % (1 << 20) == 0)
+        return ConvertUInt32ToString(size >> 20) + L"MB";
+      if (size % (1 << 10) == 0)
+        return ConvertUInt32ToString(size >> 10) + L"KB";
+      return ConvertUInt32ToString(size);
+    }
+  }
+  return ConvertPropVariantToString(propVariant);
+}

Added: trunk/lzma/CPP/7zip/UI/Common/PropIDUtils.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/PropIDUtils.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/PropIDUtils.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// PropIDUtils.h
+
+#ifndef __PROPIDUTILS_H
+#define __PROPIDUTILS_H
+
+#include "Common/MyString.h"
+
+UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/Property.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/Property.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/Property.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,14 @@
+// Property.h
+
+#ifndef __PROPERTY_H
+#define __PROPERTY_H
+
+#include "Common/MyString.h"
+
+struct CProperty
+{
+  UString Name;
+  UString Value;
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/SetProperties.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/SetProperties.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/SetProperties.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,65 @@
+// SetProperties.cpp
+
+#include "StdAfx.h"
+
+#include "SetProperties.h"
+
+#include "Windows/PropVariant.h"
+#include "Common/MyString.h"
+#include "Common/StringToInt.h"
+#include "Common/MyCom.h"
+
+#include "../../Archive/IArchive.h"
+
+using namespace NWindows;
+using namespace NCOM;
+
+static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
+{
+  const wchar_t *endPtr;
+  UInt64 result = ConvertStringToUInt64(s, &endPtr);
+  if (endPtr - (const wchar_t *)s != s.Length())
+    prop = s;
+  else if (result <= 0xFFFFFFFF)
+    prop = (UInt32)result;
+  else 
+    prop = result;
+}
+
+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties)
+{
+  if (properties.IsEmpty())
+    return S_OK;
+  CMyComPtr<ISetProperties> setProperties;
+  unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties);
+  if (!setProperties)
+    return S_OK;
+
+  UStringVector realNames;
+  CPropVariant *values = new CPropVariant[properties.Size()];
+  try
+  {
+    int i;
+    for(i = 0; i < properties.Size(); i++)
+    {
+      const CProperty &property = properties[i];
+      NCOM::CPropVariant propVariant;
+      if (!property.Value.IsEmpty())
+        ParseNumberString(property.Value, propVariant);
+      realNames.Add(property.Name);
+      values[i] = propVariant;
+    }
+    CRecordVector<const wchar_t *> names;
+    for(i = 0; i < realNames.Size(); i++)
+      names.Add((const wchar_t *)realNames[i]);
+    
+    RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));
+  }
+  catch(...)
+  {
+    delete []values;
+    throw;
+  }
+  delete []values;
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/UI/Common/SetProperties.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/SetProperties.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/SetProperties.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// SetProperties.h
+
+#ifndef __SETPROPERTIES_H
+#define __SETPROPERTIES_H
+
+#include "Property.h"
+
+HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/SortUtils.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/SortUtils.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/SortUtils.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,22 @@
+// SortUtils.cpp
+
+#include "StdAfx.h"
+
+#include "SortUtils.h"
+#include "Common/Wildcard.h"
+
+static int CompareStrings(const int *p1, const int *p2, void *param)
+{
+  const UStringVector &strings = *(const UStringVector *)param;
+  return CompareFileNames(strings[*p1], strings[*p2]);
+}
+
+void SortFileNames(const UStringVector &strings, CIntVector &indices)
+{
+  indices.Clear();
+  int numItems = strings.Size();
+  indices.Reserve(numItems);
+  for(int i = 0; i < numItems; i++)
+    indices.Add(i);
+  indices.Sort(CompareStrings, (void *)&strings);
+}

Added: trunk/lzma/CPP/7zip/UI/Common/SortUtils.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/SortUtils.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/SortUtils.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// SortUtils.h
+
+#ifndef __SORTUTLS_H
+#define __SORTUTLS_H
+
+#include "Common/MyString.h"
+
+void SortFileNames(const UStringVector &strings, CIntVector &indices);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/TempFiles.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/TempFiles.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/TempFiles.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,22 @@
+// TempFiles.cpp
+
+#include "StdAfx.h"
+
+#include "TempFiles.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/FileIO.h"
+
+using namespace NWindows;
+using namespace NFile;
+
+void CTempFiles::Clear()
+{
+  while(!Paths.IsEmpty())
+  {
+    NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back());
+    Paths.DeleteBack();
+  }
+}
+
+

Added: trunk/lzma/CPP/7zip/UI/Common/TempFiles.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/TempFiles.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/TempFiles.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,16 @@
+// TempFiles.h
+
+#ifndef __TEMPFILES_H
+#define __TEMPFILES_H
+
+#include "Common/MyString.h"
+
+class CTempFiles
+{
+  void Clear();
+public:
+  UStringVector Paths;
+  ~CTempFiles() { Clear(); }
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/Update.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/Update.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/Update.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,852 @@
+// Update.cpp
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#include <mapi.h>
+#endif
+
+#include "Update.h"
+
+#include "Common/IntToString.h"
+#include "Common/StringConvert.h"
+#include "Common/CommandLineParser.h"
+
+#ifdef _WIN32
+#include "Windows/DLL.h"
+#endif
+
+#include "Windows/Defs.h"
+#include "Windows/FileDir.h"
+#include "Windows/FileFind.h"
+#include "Windows/FileName.h"
+#include "Windows/PropVariant.h"
+#include "Windows/PropVariantConversions.h"
+// #include "Windows/Synchronization.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Compress/Copy/CopyCoder.h"
+
+#include "../Common/DirItem.h"
+#include "../Common/EnumDirItems.h"
+#include "../Common/UpdateProduce.h"
+#include "../Common/OpenArchive.h"
+
+#include "TempFiles.h"
+#include "UpdateCallback.h"
+#include "EnumDirItems.h"
+#include "SetProperties.h"
+
+static const char *kUpdateIsNotSupoorted = 
+  "update operations are not supported for this archive";
+
+using namespace NCommandLineParser;
+using namespace NWindows;
+using namespace NCOM;
+using namespace NFile;
+using namespace NName;
+
+static const wchar_t *kTempFolderPrefix = L"7zE";
+
+using namespace NUpdateArchive;
+
+static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream)
+{
+  CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+  return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
+}
+
+class COutMultiVolStream: 
+  public IOutStream,
+  public CMyUnknownImp
+{
+  int _streamIndex; // required stream
+  UInt64 _offsetPos; // offset from start of _streamIndex index
+  UInt64 _absPos;
+  UInt64 _length;
+
+  struct CSubStreamInfo
+  {
+    COutFileStream *StreamSpec;
+    CMyComPtr<IOutStream> Stream;
+    UString Name;
+    UInt64 Pos;
+    UInt64 RealSize;
+  };
+  CObjectVector<CSubStreamInfo> Streams;
+public:
+  // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+  CRecordVector<UInt64> Sizes;
+  UString Prefix;
+  CTempFiles *TempFiles;
+
+  void Init()
+  {
+    _streamIndex = 0;
+    _offsetPos = 0;
+    _absPos = 0;
+    _length = 0;
+  }
+
+  HRESULT Close(); 
+
+  MY_UNKNOWN_IMP1(IOutStream)
+
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+  STDMETHOD(SetSize)(Int64 newSize);
+};
+
+// static NSynchronization::CCriticalSection g_TempPathsCS;
+
+HRESULT COutMultiVolStream::Close()
+{
+  HRESULT res = S_OK;
+  for (int i = 0; i < Streams.Size(); i++)
+  {
+    CSubStreamInfo &s = Streams[i];
+    if (s.StreamSpec)
+    {
+      HRESULT res2 = s.StreamSpec->Close();
+      if (res2 != S_OK)
+        res = res2;
+    }
+  }
+  return res;
+}
+
+STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  if(processedSize != NULL)
+    *processedSize = 0;
+  while(size > 0)
+  {
+    if (_streamIndex >= Streams.Size())
+    {
+      CSubStreamInfo subStream;
+
+      wchar_t temp[32];
+      ConvertUInt64ToString(_streamIndex + 1, temp);
+      UString res = temp;
+      while (res.Length() < 3)
+        res = UString(L'0') + res;
+      UString name = Prefix + res;
+      subStream.StreamSpec = new COutFileStream;
+      subStream.Stream = subStream.StreamSpec;
+      if(!subStream.StreamSpec->Create(name, false))
+        return ::GetLastError();
+      {
+        // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
+        TempFiles->Paths.Add(name);
+      }
+
+      subStream.Pos = 0;
+      subStream.RealSize = 0;
+      subStream.Name = name;
+      Streams.Add(subStream);
+      continue;
+    }
+    CSubStreamInfo &subStream = Streams[_streamIndex];
+
+    int index = _streamIndex;
+    if (index >= Sizes.Size())
+      index = Sizes.Size() - 1;
+    UInt64 volSize = Sizes[index];
+
+    if (_offsetPos >= volSize)
+    {
+      _offsetPos -= volSize;
+      _streamIndex++;
+      continue;
+    }
+    if (_offsetPos != subStream.Pos)
+    {
+      // CMyComPtr<IOutStream> outStream;
+      // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
+      RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
+      subStream.Pos = _offsetPos;
+    }
+
+    UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);
+    UInt32 realProcessed;
+    RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
+    data = (void *)((Byte *)data + realProcessed);
+    size -= realProcessed;
+    subStream.Pos += realProcessed;
+    _offsetPos += realProcessed;
+    _absPos += realProcessed;
+    if (_absPos > _length)
+      _length = _absPos;
+    if (_offsetPos > subStream.RealSize)
+      subStream.RealSize = _offsetPos;
+    if(processedSize != NULL)
+      *processedSize += realProcessed;
+    if (subStream.Pos == volSize)
+    {
+      _streamIndex++;
+      _offsetPos = 0;
+    }
+    if (realProcessed == 0 && curSize != 0)
+      return E_FAIL;
+    break;
+  }
+  return S_OK;
+}
+
+STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+  if(seekOrigin >= 3)
+    return STG_E_INVALIDFUNCTION;
+  switch(seekOrigin)
+  {
+    case STREAM_SEEK_SET:
+      _absPos = offset;
+      break;
+    case STREAM_SEEK_CUR:
+      _absPos += offset;
+      break;
+    case STREAM_SEEK_END:
+      _absPos = _length + offset;
+      break;
+  }
+  _offsetPos = _absPos;
+  if (newPosition != NULL)
+    *newPosition = _absPos;
+  _streamIndex = 0;
+  return S_OK;
+}
+
+STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize)
+{
+  if (newSize < 0)
+    return E_INVALIDARG;
+  int i = 0;
+  while (i < Streams.Size())
+  {
+    CSubStreamInfo &subStream = Streams[i++];
+    if ((UInt64)newSize < subStream.RealSize)
+    {
+      RINOK(subStream.Stream->SetSize(newSize));
+      subStream.RealSize = newSize;
+      break;
+    }
+    newSize -= subStream.RealSize;
+  }
+  while (i < Streams.Size())
+  {
+    {
+      CSubStreamInfo &subStream = Streams.Back();
+      subStream.Stream.Release();
+      NDirectory::DeleteFileAlways(subStream.Name);
+    }
+    Streams.DeleteBack();
+  }
+  _offsetPos = _absPos;
+  _streamIndex = 0;
+  _length = newSize;
+  return S_OK;
+}
+
+static const wchar_t *kDefaultArchiveType = L"7z";
+static const wchar_t *kSFXExtension =
+  #ifdef _WIN32
+    L"exe";
+  #else
+    L"";
+  #endif
+
+bool CUpdateOptions::Init(const CCodecs *codecs, const UString &arcPath, const UString &arcType)
+{
+  if (!arcType.IsEmpty())
+    MethodMode.FormatIndex = codecs->FindFormatForArchiveType(arcType);
+  else
+  {
+    MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath);
+    if (MethodMode.FormatIndex < 0)
+      MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType);
+  }
+  if (MethodMode.FormatIndex < 0)
+    return false;
+  const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex];
+  UString typeExt = arcInfo.GetMainExt();
+  UString ext = typeExt;
+  if (SfxMode)
+    ext = kSFXExtension;
+  ArchivePath.BaseExtension = ext;
+  ArchivePath.VolExtension = typeExt;
+  ArchivePath.ParseFromPath(arcPath);
+  for (int i = 0; i < Commands.Size(); i++)
+  {
+    CUpdateArchiveCommand &uc = Commands[i];
+    uc.ArchivePath.BaseExtension = ext;
+    uc.ArchivePath.VolExtension = typeExt;
+    uc.ArchivePath.ParseFromPath(uc.UserArchivePath);
+  }
+  return true;
+}
+
+
+static HRESULT Compress(
+    CCodecs *codecs,
+    const CActionSet &actionSet, 
+    IInArchive *archive,
+    const CCompressionMethodMode &compressionMethod,
+    CArchivePath &archivePath, 
+    const CObjectVector<CArchiveItem> &archiveItems,
+    bool shareForWrite,
+    bool stdInMode,
+    /* const UString & stdInFileName, */
+    bool stdOutMode,
+    const CObjectVector<CDirItem> &dirItems,
+    bool sfxMode,
+    const UString &sfxModule,
+    const CRecordVector<UInt64> &volumesSizes,
+    CTempFiles &tempFiles,
+    CUpdateErrorInfo &errorInfo,
+    IUpdateCallbackUI *callback)
+{
+  CMyComPtr<IOutArchive> outArchive;
+  if(archive != NULL)
+  {
+    CMyComPtr<IInArchive> archive2 = archive;
+    HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
+    if(result != S_OK)
+      throw kUpdateIsNotSupoorted;
+  }
+  else
+  {
+    RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive));
+
+    #ifdef EXTERNAL_CODECS
+    {
+      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
+      outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+      if (setCompressCodecsInfo)
+      {
+        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
+      }
+    }
+    #endif
+  }
+  if (outArchive == 0)
+    throw kUpdateIsNotSupoorted;
+  
+  NFileTimeType::EEnum fileTimeType;
+  UInt32 value;
+  RINOK(outArchive->GetFileTimeType(&value));
+
+  switch(value)
+  {
+    case NFileTimeType::kWindows:
+    case NFileTimeType::kDOS:
+    case NFileTimeType::kUnix:
+      fileTimeType = NFileTimeType::EEnum(value);
+      break;
+    default:
+      return E_FAIL;
+  }
+
+  CObjectVector<CUpdatePair> updatePairs;
+  GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); // must be done only once!!!
+  
+  CObjectVector<CUpdatePair2> updatePairs2;
+  UpdateProduce(updatePairs, actionSet, updatePairs2);
+
+  UInt32 numFiles = 0;
+  for (int i = 0; i < updatePairs2.Size(); i++)
+    if (updatePairs2[i].NewData)
+      numFiles++;
+  
+  RINOK(callback->SetNumFiles(numFiles));
+
+  
+  CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
+  CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+  
+  updateCallbackSpec->ShareForWrite = shareForWrite;
+  updateCallbackSpec->StdInMode = stdInMode;
+  updateCallbackSpec->Callback = callback;
+  updateCallbackSpec->DirItems = &dirItems;
+  updateCallbackSpec->ArchiveItems = &archiveItems;
+  updateCallbackSpec->UpdatePairs = &updatePairs2;
+
+  CMyComPtr<ISequentialOutStream> outStream;
+
+  const UString &archiveName = archivePath.GetFinalPath();
+  if (!stdOutMode)
+  {
+    UString resultPath;
+    int pos;
+    if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
+      throw 1417161;
+    NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
+  }
+
+  COutFileStream *outStreamSpec = NULL;
+  COutMultiVolStream *volStreamSpec = NULL;
+
+  if (volumesSizes.Size() == 0)
+  {
+    if (stdOutMode)
+      outStream = new CStdOutFileStream;
+    else
+    {
+      outStreamSpec = new COutFileStream;
+      outStream = outStreamSpec;
+      bool isOK = false;
+      UString realPath;
+      for (int i = 0; i < (1 << 16); i++)
+      {
+        if (archivePath.Temp)
+        {
+          if (i > 0)
+          {
+            wchar_t s[32];
+            ConvertUInt64ToString(i, s);
+            archivePath.TempPostfix = s;
+          }
+          realPath = archivePath.GetTempPath();
+        }
+        else
+          realPath = archivePath.GetFinalPath();
+        if (outStreamSpec->Create(realPath, false))
+        {
+          tempFiles.Paths.Add(realPath);
+          isOK = true;
+          break;
+        }
+        if (::GetLastError() != ERROR_FILE_EXISTS)
+          break;
+        if (!archivePath.Temp)
+          break;
+      }
+      if (!isOK)
+      {
+        errorInfo.SystemError = ::GetLastError();
+        errorInfo.FileName = realPath;
+        errorInfo.Message = L"Can not open file";
+        return E_FAIL;
+      }
+    }
+  }
+  else
+  {
+    if (stdOutMode)
+      return E_FAIL;
+    volStreamSpec = new COutMultiVolStream;
+    outStream = volStreamSpec;
+    volStreamSpec->Sizes = volumesSizes;
+    volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");
+    volStreamSpec->TempFiles = &tempFiles;
+    volStreamSpec->Init();
+
+    /*
+    updateCallbackSpec->VolumesSizes = volumesSizes;
+    updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
+    if (!archivePath.VolExtension.IsEmpty())
+      updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
+    */
+  }
+
+  RINOK(SetProperties(outArchive, compressionMethod.Properties));
+
+  if (sfxMode)
+  {
+    CInFileStream *sfxStreamSpec = new CInFileStream;
+    CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
+    if (!sfxStreamSpec->Open(sfxModule))
+    {
+      errorInfo.SystemError = ::GetLastError();
+      errorInfo.Message = L"Can't open sfx module";
+      errorInfo.FileName = sfxModule;
+      return E_FAIL;
+    }
+
+    CMyComPtr<ISequentialOutStream> sfxOutStream;
+    COutFileStream *outStreamSpec = NULL;
+    if (volumesSizes.Size() == 0)
+      sfxOutStream = outStream;
+    else
+    {
+      outStreamSpec = new COutFileStream;
+      sfxOutStream = outStreamSpec;
+      UString realPath = archivePath.GetFinalPath();
+      if (!outStreamSpec->Create(realPath, false))
+      {
+        errorInfo.SystemError = ::GetLastError();
+        errorInfo.FileName = realPath;
+        errorInfo.Message = L"Can not open file";
+        return E_FAIL;
+      }
+    }
+    RINOK(CopyBlock(sfxStream, sfxOutStream));
+    if (outStreamSpec)
+    {
+      RINOK(outStreamSpec->Close());
+    }
+  }
+
+  HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback);
+  callback->Finilize();
+  RINOK(result);
+  if (outStreamSpec)
+    result = outStreamSpec->Close();
+  else if (volStreamSpec)
+    result = volStreamSpec->Close();
+  return result;
+}
+
+HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
+    IInArchive *archive,
+    const UString &defaultItemName,
+    const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
+    CObjectVector<CArchiveItem> &archiveItems)
+{
+  archiveItems.Clear();
+  UInt32 numItems;
+  RINOK(archive->GetNumberOfItems(&numItems));
+  archiveItems.Reserve(numItems);
+  for(UInt32 i = 0; i < numItems; i++)
+  {
+    CArchiveItem ai;
+
+    RINOK(GetArchiveItemPath(archive, i, ai.Name));
+    RINOK(IsArchiveItemFolder(archive, i, ai.IsDirectory));
+    ai.Censored = censor.CheckPath(ai.Name.IsEmpty() ? defaultItemName : ai.Name, !ai.IsDirectory);
+    RINOK(GetArchiveItemFileTime(archive, i, 
+        archiveFileInfo.LastWriteTime, ai.LastWriteTime));
+
+    CPropVariant propertySize;
+    RINOK(archive->GetProperty(i, kpidSize, &propertySize));
+    ai.SizeIsDefined = (propertySize.vt != VT_EMPTY);
+    if (ai.SizeIsDefined)
+      ai.Size = ConvertPropVariantToUInt64(propertySize);
+
+    ai.IndexInServer = i;
+    archiveItems.Add(ai);
+  }
+  return S_OK;
+}
+
+
+static HRESULT UpdateWithItemLists(
+    CCodecs *codecs,
+    CUpdateOptions &options,
+    IInArchive *archive, 
+    const CObjectVector<CArchiveItem> &archiveItems,
+    const CObjectVector<CDirItem> &dirItems,
+    CTempFiles &tempFiles,
+    CUpdateErrorInfo &errorInfo,
+    IUpdateCallbackUI2 *callback)
+{
+  for(int i = 0; i < options.Commands.Size(); i++)
+  {
+    CUpdateArchiveCommand &command = options.Commands[i];
+    if (options.StdOutMode)
+    {
+      RINOK(callback->StartArchive(0, archive != 0));
+    }
+    else
+    {
+      RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(), 
+          i == 0 && options.UpdateArchiveItself && archive != 0));
+    }
+
+    RINOK(Compress(
+        codecs,
+        command.ActionSet, archive,
+        options.MethodMode, 
+        command.ArchivePath, 
+        archiveItems, 
+        options.OpenShareForWrite,
+        options.StdInMode, 
+        /* options.StdInFileName, */
+        options.StdOutMode,
+        dirItems, 
+        options.SfxMode, options.SfxModule, 
+        options.VolumesSizes,
+        tempFiles,
+        errorInfo, callback));
+
+    RINOK(callback->FinishArchive());
+  }
+  return S_OK;
+}
+
+#ifdef _WIN32
+class CCurrentDirRestorer
+{
+  UString m_CurrentDirectory;
+public:
+  CCurrentDirRestorer()
+    { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); }
+  ~CCurrentDirRestorer()
+    { RestoreDirectory();}
+  bool RestoreDirectory()
+    { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); }
+};
+#endif
+
+struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
+{
+  IUpdateCallbackUI2 *Callback;
+  HRESULT CheckBreak() { return Callback->CheckBreak(); }
+};
+
+HRESULT UpdateArchive(
+    CCodecs *codecs,
+    const NWildcard::CCensor &censor, 
+    CUpdateOptions &options,
+    CUpdateErrorInfo &errorInfo,
+    IOpenCallbackUI *openCallback,
+    IUpdateCallbackUI2 *callback)
+{
+  if (options.StdOutMode && options.EMailMode)
+    return E_FAIL;
+
+  if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))
+    return E_NOTIMPL;
+
+  if (options.SfxMode)
+  {
+    CProperty property;
+    property.Name = L"rsfx";
+    property.Value = L"on";
+    options.MethodMode.Properties.Add(property);
+    if (options.SfxModule.IsEmpty())
+    {
+      errorInfo.Message = L"sfx file is not specified";
+      return E_FAIL;
+    }
+    UString name = options.SfxModule;
+    if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))
+    {
+      errorInfo.Message = L"can't find specified sfx module";
+      return E_FAIL;
+    }
+  }
+
+  const UString archiveName = options.ArchivePath.GetFinalPath();
+
+  UString defaultItemName;
+  NFind::CFileInfoW archiveFileInfo;
+
+  CArchiveLink archiveLink;
+  IInArchive *archive = 0;
+  if (NFind::FindFile(archiveName, archiveFileInfo))
+  {
+    if (archiveFileInfo.IsDirectory())
+      throw "there is no such archive";
+    if (options.VolumesSizes.Size() > 0)
+      return E_NOTIMPL;
+    HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, openCallback);
+    RINOK(callback->OpenResult(archiveName, result));
+    RINOK(result);
+    if (archiveLink.VolumePaths.Size() > 1)
+    {
+      errorInfo.SystemError = (DWORD)E_NOTIMPL;
+      errorInfo.Message = L"Updating for multivolume archives is not implemented";
+      return E_NOTIMPL;
+    }
+    archive = archiveLink.GetArchive();
+    defaultItemName = archiveLink.GetDefaultItemName();
+  }
+  else
+  {
+    /*
+    if (archiveType.IsEmpty())
+      throw "type of archive is not specified";
+    */
+  }
+
+  CObjectVector<CDirItem> dirItems;
+  if (options.StdInMode)
+  {
+    CDirItem item;
+    item.FullPath = item.Name = options.StdInFileName;
+    item.Size = (UInt64)(Int64)-1;
+    item.Attributes = 0;
+    SYSTEMTIME st;
+    FILETIME ft;
+    GetSystemTime(&st);
+    SystemTimeToFileTime(&st, &ft);
+    item.CreationTime = item.LastAccessTime = item.LastWriteTime = ft;
+    dirItems.Add(item);
+  }
+  else
+  {
+    bool needScanning = false;
+    for(int i = 0; i < options.Commands.Size(); i++)
+      if (options.Commands[i].ActionSet.NeedScanning())
+        needScanning = true;
+    if (needScanning)
+    {
+      CEnumDirItemUpdateCallback enumCallback;
+      enumCallback.Callback = callback;
+      RINOK(callback->StartScanning());
+      UStringVector errorPaths;
+      CRecordVector<DWORD> errorCodes;
+      HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes);
+      for (int i = 0; i < errorPaths.Size(); i++)
+      {
+        RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i]));
+      }
+      if(res != S_OK) 
+      {
+        errorInfo.Message = L"Scanning error";
+        // errorInfo.FileName = errorPath;
+        return res;
+      }
+      RINOK(callback->FinishScanning());
+    }
+  }
+
+  UString tempDirPrefix;
+  bool usesTempDir = false;
+  
+  #ifdef _WIN32
+  NDirectory::CTempDirectoryW tempDirectory;
+  if (options.EMailMode && options.EMailRemoveAfter)
+  {
+    tempDirectory.Create(kTempFolderPrefix);
+    tempDirPrefix = tempDirectory.GetPath();
+    NormalizeDirPathPrefix(tempDirPrefix);
+    usesTempDir = true;
+  }
+  #endif
+
+  CTempFiles tempFiles;
+
+  bool createTempFile = false;
+  if(!options.StdOutMode && options.UpdateArchiveItself)
+  {
+    CArchivePath &ap = options.Commands[0].ArchivePath;
+    ap = options.ArchivePath;
+    // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())
+    if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)
+    {
+      createTempFile = true;
+      ap.Temp = true;
+      if (!options.WorkingDir.IsEmpty())
+      {
+        ap.TempPrefix = options.WorkingDir;
+        NormalizeDirPathPrefix(ap.TempPrefix);
+      }
+    }
+  }
+
+  for(int i = 0; i < options.Commands.Size(); i++)
+  {
+    CArchivePath &ap = options.Commands[i].ArchivePath;
+    if (usesTempDir)
+    {
+      // Check it
+      ap.Prefix = tempDirPrefix;
+      // ap.Temp = true;
+      // ap.TempPrefix = tempDirPrefix;
+    }
+    if (i > 0 || !createTempFile)
+    {
+      const UString &path = ap.GetFinalPath();
+      if (NFind::DoesFileExist(path))
+      {
+        errorInfo.SystemError = 0;
+        errorInfo.Message = L"File already exists";
+        errorInfo.FileName = path;
+        return E_FAIL;
+      }
+    }
+  }
+
+  CObjectVector<CArchiveItem> archiveItems;
+  if (archive != NULL)
+  {
+    RINOK(EnumerateInArchiveItems(censor, 
+        archive, defaultItemName, archiveFileInfo, archiveItems));
+  }
+
+  RINOK(UpdateWithItemLists(codecs, options, archive, archiveItems, dirItems, 
+      tempFiles, errorInfo, callback));
+
+  if (archive != NULL)
+  {
+    RINOK(archiveLink.Close());
+    archiveLink.Release();
+  }
+
+  tempFiles.Paths.Clear();
+  if(createTempFile)
+  {
+    try
+    {
+      CArchivePath &ap = options.Commands[0].ArchivePath;
+      const UString &tempPath = ap.GetTempPath();
+      if (archive != NULL)
+        if (!NDirectory::DeleteFileAlways(archiveName))
+        {
+          errorInfo.SystemError = ::GetLastError();
+          errorInfo.Message = L"delete file error";
+          errorInfo.FileName = archiveName;
+          return E_FAIL;
+        }
+      if (!NDirectory::MyMoveFile(tempPath, archiveName))
+      {
+        errorInfo.SystemError = ::GetLastError();
+        errorInfo.Message = L"move file error";
+        errorInfo.FileName = tempPath;
+        errorInfo.FileName2 = archiveName;
+        return E_FAIL;
+      }
+    }
+    catch(...)
+    {
+      throw;
+    }
+  }
+
+  #ifdef _WIN32
+  if (options.EMailMode)
+  {
+    NDLL::CLibrary mapiLib;
+    if (!mapiLib.Load(TEXT("Mapi32.dll")))
+    {
+      errorInfo.SystemError = ::GetLastError();
+      errorInfo.Message = L"can not load Mapi32.dll";
+      return E_FAIL;
+    }
+    LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)
+        mapiLib.GetProcAddress("MAPISendDocuments");
+    if (fnSend == 0)
+    {
+      errorInfo.SystemError = ::GetLastError();
+      errorInfo.Message = L"can not find MAPISendDocuments function";
+      return E_FAIL;
+    }
+    UStringVector fullPaths;
+    int i;
+    for(i = 0; i < options.Commands.Size(); i++)
+    {
+      CArchivePath &ap = options.Commands[i].ArchivePath;
+      UString arcPath;
+      if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))
+      {
+        errorInfo.SystemError = ::GetLastError();
+        return E_FAIL;
+      }
+      fullPaths.Add(arcPath);
+    }
+    CCurrentDirRestorer curDirRestorer;
+    for(i = 0; i < fullPaths.Size(); i++)
+    {
+      UString arcPath = fullPaths[i];
+      UString fileName = ExtractFileNameFromPath(arcPath);
+      AString path = GetAnsiString(arcPath);
+      AString name = GetAnsiString(fileName);
+      // Warning!!! MAPISendDocuments function changes Current directory
+      fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0); 
+    }
+  }
+  #endif
+  return S_OK;
+}
+

Added: trunk/lzma/CPP/7zip/UI/Common/Update.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/Update.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/Update.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,165 @@
+// Update.h
+
+#ifndef __UPDATE_H
+#define __UPDATE_H
+
+#include "Common/Wildcard.h"
+#include "Windows/FileFind.h"
+#include "../../Archive/IArchive.h"
+
+#include "UpdateAction.h"
+#include "ArchiveOpenCallback.h"
+#include "UpdateCallback.h"
+#include "Property.h"
+#include "LoadCodecs.h"
+
+struct CArchivePath
+{
+  UString Prefix;   // path(folder) prefix including slash
+  UString Name; // base name
+  UString BaseExtension; // archive type extension or "exe" extension 
+  UString VolExtension;  // archive type extension for volumes
+
+  bool Temp;
+  UString TempPrefix;  // path(folder) for temp location
+  UString TempPostfix;
+
+  CArchivePath(): Temp(false) {};
+  
+  void ParseFromPath(const UString &path)
+  {
+    SplitPathToParts(path, Prefix, Name);
+    if (Name.IsEmpty())
+      return;
+    int dotPos = Name.ReverseFind(L'.');
+    if (dotPos <= 0)
+      return;
+    if (dotPos == Name.Length() - 1)
+    {
+      Name = Name.Left(dotPos);
+      BaseExtension.Empty();
+      return;
+    }
+    if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0)
+    {
+      BaseExtension = Name.Mid(dotPos + 1);
+      Name = Name.Left(dotPos);
+    }
+    else
+      BaseExtension.Empty();
+  }
+
+  UString GetPathWithoutExt() const
+  {
+    return Prefix + Name;
+  }
+
+  UString GetFinalPath() const
+  {
+    UString path = GetPathWithoutExt();
+    if (!BaseExtension.IsEmpty())
+      path += UString(L'.') + BaseExtension;
+    return path;
+  }
+
+  
+  UString GetTempPath() const
+  {
+    UString path = TempPrefix + Name;
+    if (!BaseExtension.IsEmpty())
+      path += UString(L'.') + BaseExtension;
+    path += L".tmp";
+    path += TempPostfix;
+    return path; 
+  }
+};
+
+struct CUpdateArchiveCommand
+{
+  UString UserArchivePath;
+  CArchivePath ArchivePath;
+  NUpdateArchive::CActionSet ActionSet;
+};
+
+struct CCompressionMethodMode
+{
+  int FormatIndex;
+  CObjectVector<CProperty> Properties;
+  CCompressionMethodMode(): FormatIndex(-1) {}
+};
+
+struct CUpdateOptions
+{
+  CCompressionMethodMode MethodMode;
+
+  CObjectVector<CUpdateArchiveCommand> Commands;
+  bool UpdateArchiveItself;
+  CArchivePath ArchivePath;
+  
+  bool SfxMode;
+  UString SfxModule;
+  
+  bool OpenShareForWrite;
+
+  bool StdInMode;
+  UString StdInFileName;
+  bool StdOutMode;
+  
+  bool EMailMode;
+  bool EMailRemoveAfter;
+  UString EMailAddress;
+
+  UString WorkingDir;
+
+  bool Init(const CCodecs *codecs, const UString &arcPath, const UString &arcType);
+
+  CUpdateOptions():
+    UpdateArchiveItself(true),
+    SfxMode(false),
+    StdInMode(false),
+    StdOutMode(false),
+    EMailMode(false),
+    EMailRemoveAfter(false),
+    OpenShareForWrite(false)
+      {};
+  CRecordVector<UInt64> VolumesSizes;
+};
+
+struct CErrorInfo
+{
+  DWORD SystemError;
+  UString FileName;
+  UString FileName2;
+  UString Message;
+  // UStringVector ErrorPaths;
+  // CRecordVector<DWORD> ErrorCodes;
+  CErrorInfo(): SystemError(0) {};
+};
+
+struct CUpdateErrorInfo: public CErrorInfo
+{
+};
+
+#define INTERFACE_IUpdateCallbackUI2(x) \
+  INTERFACE_IUpdateCallbackUI(x) \
+  virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \
+  virtual HRESULT StartScanning() x; \
+  virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \
+  virtual HRESULT FinishScanning() x; \
+  virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \
+  virtual HRESULT FinishArchive() x; \
+
+struct IUpdateCallbackUI2: public IUpdateCallbackUI
+{
+  INTERFACE_IUpdateCallbackUI2(=0)
+};
+
+HRESULT UpdateArchive(
+    CCodecs *codecs,
+    const NWildcard::CCensor &censor, 
+    CUpdateOptions &options,
+    CUpdateErrorInfo &errorInfo,
+    IOpenCallbackUI *openCallback,
+    IUpdateCallbackUI2 *callback);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/UpdateAction.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/UpdateAction.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/UpdateAction.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,64 @@
+// UpdateAction.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateAction.h"
+
+namespace NUpdateArchive {
+
+const CActionSet kAddActionSet = 
+{
+  NPairAction::kCopy,
+  NPairAction::kCopy,
+  NPairAction::kCompress,
+  NPairAction::kCompress,
+  NPairAction::kCompress,
+  NPairAction::kCompress,
+  NPairAction::kCompress
+};
+
+const CActionSet kUpdateActionSet = 
+{
+  NPairAction::kCopy,
+  NPairAction::kCopy,
+  NPairAction::kCompress,
+  NPairAction::kCopy,
+  NPairAction::kCompress,
+  NPairAction::kCopy,
+  NPairAction::kCompress
+};
+
+const CActionSet kFreshActionSet = 
+{
+  NPairAction::kCopy,
+  NPairAction::kCopy,
+  NPairAction::kIgnore,
+  NPairAction::kCopy,
+  NPairAction::kCompress,
+  NPairAction::kCopy,
+  NPairAction::kCompress
+};
+
+const CActionSet kSynchronizeActionSet = 
+{
+  NPairAction::kCopy,
+  NPairAction::kIgnore,
+  NPairAction::kCompress,
+  NPairAction::kCopy,
+  NPairAction::kCompress,
+  NPairAction::kCopy,
+  NPairAction::kCompress,
+};
+
+const CActionSet kDeleteActionSet = 
+{
+  NPairAction::kCopy,
+  NPairAction::kIgnore,
+  NPairAction::kIgnore,
+  NPairAction::kIgnore,
+  NPairAction::kIgnore,
+  NPairAction::kIgnore,
+  NPairAction::kIgnore
+};
+
+}

Added: trunk/lzma/CPP/7zip/UI/Common/UpdateAction.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/UpdateAction.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/UpdateAction.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,57 @@
+// UpdateAction.h
+
+#ifndef __UPDATE_ACTION_H
+#define __UPDATE_ACTION_H
+
+namespace NUpdateArchive {
+
+  namespace NPairState 
+  {
+    const int kNumValues = 7;
+    enum EEnum
+    {
+      kNotMasked = 0,
+      kOnlyInArchive,
+      kOnlyOnDisk,
+      kNewInArchive,
+      kOldInArchive,
+      kSameFiles,
+      kUnknowNewerFiles
+    };
+  }
+  namespace NPairAction
+  {
+    enum EEnum
+    {
+      kIgnore = 0,
+      kCopy,
+      kCompress,
+      kCompressAsAnti
+    };
+  }
+  struct CActionSet
+  {
+    NPairAction::EEnum StateActions[NPairState::kNumValues];
+    bool NeedScanning() const
+    {
+      int i;
+      for (i = 0; i < NPairState::kNumValues; i++)
+        if (StateActions[i] == NPairAction::kCompress)
+          return true;
+      for (i = 1; i < NPairState::kNumValues; i++)
+        if (StateActions[i] != NPairAction::kIgnore)
+          return true;
+      return false;
+    }
+  };
+  extern const CActionSet kAddActionSet;
+  extern const CActionSet kUpdateActionSet;
+  extern const CActionSet kFreshActionSet;
+  extern const CActionSet kSynchronizeActionSet;
+  extern const CActionSet kDeleteActionSet;
+};
+
+
+#endif
+
+

Added: trunk/lzma/CPP/7zip/UI/Common/UpdateCallback.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/UpdateCallback.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/UpdateCallback.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,267 @@
+// UpdateCallback.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateCallback.h"
+
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+#include "Common/Defs.h"
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../../Common/FileStreams.h"
+
+using namespace NWindows;
+
+CArchiveUpdateCallback::CArchiveUpdateCallback():
+  Callback(0),
+  ShareForWrite(false),
+  StdInMode(false),
+  DirItems(0),
+  ArchiveItems(0),
+  UpdatePairs(0)
+  {}
+
+
+STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
+{
+  COM_TRY_BEGIN
+  return Callback->SetTotal(size);
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
+{
+  COM_TRY_BEGIN
+  return Callback->SetCompleted(completeValue);
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+  COM_TRY_BEGIN
+  return Callback->SetRatioInfo(inSize, outSize);
+  COM_TRY_END
+}
+
+
+/*
+STATPROPSTG kProperties[] = 
+{
+  { NULL, kpidPath, VT_BSTR},
+  { NULL, kpidIsFolder, VT_BOOL},
+  { NULL, kpidSize, VT_UI8},
+  { NULL, kpidLastAccessTime, VT_FILETIME},
+  { NULL, kpidCreationTime, VT_FILETIME},
+  { NULL, kpidLastWriteTime, VT_FILETIME},
+  { NULL, kpidAttributes, VT_UI4},
+  { NULL, kpidIsAnti, VT_BOOL}
+};
+*/
+
+STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)
+{
+  return E_NOTIMPL;
+  /*
+  return CStatPropEnumerator::CreateEnumerator(kProperties, 
+      sizeof(kProperties) / sizeof(kProperties[0]), enumerator);
+  */
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index, 
+      Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
+{
+  COM_TRY_BEGIN
+  RINOK(Callback->CheckBreak());
+  const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
+  if(newData != NULL)
+    *newData = BoolToInt(updatePair.NewData);
+  if(newProperties != NULL)
+    *newProperties = BoolToInt(updatePair.NewProperties);
+  if(indexInArchive != NULL)
+  {
+    if (updatePair.ExistInArchive)
+    {
+      if (ArchiveItems == 0)
+        *indexInArchive = updatePair.ArchiveItemIndex;
+      else
+        *indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
+    }
+    else
+      *indexInArchive = UInt32(-1);
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+  COM_TRY_BEGIN
+  const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
+  NWindows::NCOM::CPropVariant propVariant;
+  
+  if (propID == kpidIsAnti)
+  {
+    propVariant = updatePair.IsAnti;
+    propVariant.Detach(value);
+    return S_OK;
+  }
+
+  if (updatePair.IsAnti)
+  {
+    switch(propID)
+    {
+      case kpidIsFolder:
+      case kpidPath:
+        break;
+      case kpidSize:
+        propVariant = (UInt64)0;
+        propVariant.Detach(value);
+        return S_OK;
+      default:
+        propVariant.Detach(value);
+        return S_OK;
+    }
+  }
+  
+  if(updatePair.ExistOnDisk)
+  {
+    const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
+    switch(propID)
+    {
+      case kpidPath:
+        propVariant = dirItem.Name;
+        break;
+      case kpidIsFolder:
+        propVariant = dirItem.IsDirectory();
+        break;
+      case kpidSize:
+        propVariant = dirItem.Size;
+        break;
+      case kpidAttributes:
+        propVariant = dirItem.Attributes;
+        break;
+      case kpidLastAccessTime:
+        propVariant = dirItem.LastAccessTime;
+        break;
+      case kpidCreationTime:
+        propVariant = dirItem.CreationTime;
+        break;
+      case kpidLastWriteTime:
+        propVariant = dirItem.LastWriteTime;
+        break;
+    }
+  }
+  else
+  {
+    if (propID == kpidPath)
+    {
+      if (updatePair.NewNameIsDefined)
+      {
+        propVariant = updatePair.NewName;
+        propVariant.Detach(value);
+        return S_OK;
+      }
+    }
+    if (updatePair.ExistInArchive && Archive)
+    {
+      UInt32 indexInArchive;
+      if (ArchiveItems == 0)
+        indexInArchive = updatePair.ArchiveItemIndex;
+      else
+        indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
+      return Archive->GetProperty(indexInArchive, propID, value);
+    }
+  }
+  propVariant.Detach(value);
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
+{
+  COM_TRY_BEGIN
+  const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
+  if(!updatePair.NewData)
+    return E_FAIL;
+  
+  RINOK(Callback->CheckBreak());
+  RINOK(Callback->Finilize());
+
+  if(updatePair.IsAnti)
+  {
+    return Callback->GetStream((*ArchiveItems)[updatePair.ArchiveItemIndex].Name, true);
+  }
+  const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
+  RINOK(Callback->GetStream(dirItem.Name, false));
+ 
+  if(dirItem.IsDirectory())
+    return S_OK;
+
+  if (StdInMode)
+  {
+    CStdInFileStream *inStreamSpec = new CStdInFileStream;
+    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+    *inStream = inStreamLoc.Detach();
+  }
+  else
+  {
+    CInFileStream *inStreamSpec = new CInFileStream;
+    CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+    UString path = DirPrefix + dirItem.FullPath;
+    if(!inStreamSpec->OpenShared(path, ShareForWrite))
+    {
+      return Callback->OpenFileError(path, ::GetLastError());
+    }
+    *inStream = inStreamLoc.Detach();
+  }
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)
+{
+  COM_TRY_BEGIN
+  return Callback->SetOperationResult(operationResult);
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
+{
+  if (VolumesSizes.Size() == 0)
+    return S_FALSE;
+  if (index >= (UInt32)VolumesSizes.Size())
+    index = VolumesSizes.Size() - 1;
+  *size = VolumesSizes[index];
+  return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
+{
+  COM_TRY_BEGIN
+  wchar_t temp[32];
+  ConvertUInt64ToString(index + 1, temp);
+  UString res = temp;
+  while (res.Length() < 2)
+    res = UString(L'0') + res;
+  UString fileName = VolName;
+  fileName += L'.';
+  fileName += res;
+  fileName += VolExt;
+  COutFileStream *streamSpec = new COutFileStream;
+  CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
+  if(!streamSpec->Create(fileName, false))
+    return ::GetLastError();
+  *volumeStream = streamLoc.Detach();
+  return S_OK;
+  COM_TRY_END
+}
+
+STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
+{
+  COM_TRY_BEGIN
+  return Callback->CryptoGetTextPassword2(passwordIsDefined, password);
+  COM_TRY_END
+}

Added: trunk/lzma/CPP/7zip/UI/Common/UpdateCallback.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/UpdateCallback.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/UpdateCallback.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,82 @@
+// UpdateCallback.h
+
+#ifndef __UPDATECALLBACK_H
+#define __UPDATECALLBACK_H
+
+#include "Common/MyCom.h"
+#include "Common/MyString.h"
+
+#include "../../IPassword.h"
+#include "../../ICoder.h"
+
+#include "../Common/UpdatePair.h"
+#include "../Common/UpdateProduce.h"
+
+#define INTERFACE_IUpdateCallbackUI(x) \
+  virtual HRESULT SetTotal(UInt64 size) x; \
+  virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \
+  virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \
+  virtual HRESULT CheckBreak() x; \
+  virtual HRESULT Finilize() x; \
+  virtual HRESULT SetNumFiles(UInt64 numFiles) x; \
+  virtual HRESULT GetStream(const wchar_t *name, bool isAnti) x; \
+  virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \
+  virtual HRESULT SetOperationResult(Int32 operationResult) x; \
+  virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \
+
+  // virtual HRESULT CloseProgress() { return S_OK; };
+
+struct IUpdateCallbackUI
+{
+  INTERFACE_IUpdateCallbackUI(=0)
+};
+
+class CArchiveUpdateCallback: 
+  public IArchiveUpdateCallback2,
+  public ICryptoGetTextPassword2,
+  public ICompressProgressInfo,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP3(
+      IArchiveUpdateCallback2, 
+      ICryptoGetTextPassword2,
+      ICompressProgressInfo)
+
+  // IProgress
+  STDMETHOD(SetTotal)(UInt64 size);
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+
+  // IUpdateCallback
+  STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);  
+  STDMETHOD(GetUpdateItemInfo)(UInt32 index, 
+      Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
+  STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
+  STDMETHOD(SetOperationResult)(Int32 operationResult);
+
+  STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);
+  STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);
+
+  STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
+
+public:
+  CRecordVector<UInt64> VolumesSizes;
+  UString VolName;
+  UString VolExt;
+
+  IUpdateCallbackUI *Callback;
+
+  UString DirPrefix;
+  bool ShareForWrite;
+  bool StdInMode;
+  const CObjectVector<CDirItem> *DirItems;
+  const CObjectVector<CArchiveItem> *ArchiveItems;
+  const CObjectVector<CUpdatePair2> *UpdatePairs;
+  CMyComPtr<IInArchive> Archive;
+
+  CArchiveUpdateCallback();
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/UpdatePair.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/UpdatePair.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/UpdatePair.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,166 @@
+// UpdatePair.cpp
+
+#include "StdAfx.h"
+
+#include <time.h>
+
+#include "Common/Defs.h"
+#include "Common/Wildcard.h"
+#include "Windows/Time.h"
+
+#include "UpdatePair.h"
+#include "SortUtils.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+static int MyCompareTime(NFileTimeType::EEnum fileTimeType, 
+    const FILETIME &time1, const FILETIME &time2)
+{
+  switch(fileTimeType)
+  {
+    case NFileTimeType::kWindows:
+      return ::CompareFileTime(&time1, &time2);
+    case NFileTimeType::kUnix:
+      {
+        UInt32 unixTime1, unixTime2;
+        if (!FileTimeToUnixTime(time1, unixTime1))
+        {
+          unixTime1 = 0;
+          // throw 4191614;
+        }
+        if (!FileTimeToUnixTime(time2, unixTime2))
+        {
+          unixTime2 = 0;
+          // throw 4191615;
+        }
+        return MyCompare(unixTime1, unixTime2);
+      }
+    case NFileTimeType::kDOS:
+      {
+        UInt32 dosTime1, dosTime2;
+        FileTimeToDosTime(time1, dosTime1);
+        FileTimeToDosTime(time2, dosTime2);
+        /*
+        if (!FileTimeToDosTime(time1, dosTime1))
+          throw 4191616;
+        if (!FileTimeToDosTime(time2, dosTime2))
+          throw 4191617;
+        */
+        return MyCompare(dosTime1, dosTime2);
+      }
+  }
+  throw 4191618;
+}
+
+static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:";
+
+/*
+static const char *kNotCensoredCollisionMessaged = "Internal file name collision:\n";
+static const char *kSameTimeChangedSizeCollisionMessaged = 
+    "Collision between files with same date/time and different sizes:\n";
+*/
+
+static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices)
+{
+  for(int i = 0; i + 1 < indices.Size(); i++)
+    if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0)
+    {
+      UString message = kDuplicateFileNameMessage;
+      message += L"\n";
+      message += strings[indices[i]];
+      message += L"\n";
+      message += strings[indices[i + 1]];
+      throw message;
+    }
+}
+
+void GetUpdatePairInfoList(
+    const CObjectVector<CDirItem> &dirItems, 
+    const CObjectVector<CArchiveItem> &archiveItems,
+    NFileTimeType::EEnum fileTimeType,
+    CObjectVector<CUpdatePair> &updatePairs)
+{
+  CIntVector dirIndices, archiveIndices;
+  UStringVector dirNames, archiveNames;
+  
+  int numDirItems = dirItems.Size(); 
+  int i;
+  for(i = 0; i < numDirItems; i++)
+    dirNames.Add(dirItems[i].Name);
+  SortFileNames(dirNames, dirIndices);
+  TestDuplicateString(dirNames, dirIndices);
+
+  int numArchiveItems = archiveItems.Size(); 
+  for(i = 0; i < numArchiveItems; i++)
+    archiveNames.Add(archiveItems[i].Name);
+  SortFileNames(archiveNames, archiveIndices);
+  TestDuplicateString(archiveNames, archiveIndices);
+  
+  int dirItemIndex = 0, archiveItemIndex = 0; 
+  CUpdatePair pair;
+  while(dirItemIndex < numDirItems && archiveItemIndex < numArchiveItems)
+  {
+    int dirItemIndex2 = dirIndices[dirItemIndex],
+        archiveItemIndex2 = archiveIndices[archiveItemIndex]; 
+    const CDirItem &dirItem = dirItems[dirItemIndex2];
+    const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2];
+    int compareResult = CompareFileNames(dirItem.Name, archiveItem.Name);
+    if (compareResult < 0)
+    {
+        pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
+        pair.DirItemIndex = dirItemIndex2;
+        dirItemIndex++;
+    }
+    else if (compareResult > 0)
+    {
+      pair.State = archiveItem.Censored ? 
+        NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked;
+      pair.ArchiveItemIndex = archiveItemIndex2;
+      archiveItemIndex++;
+    }
+    else
+    {
+      if (!archiveItem.Censored)
+        throw 1082022;; // TTString(kNotCensoredCollisionMessaged + dirItem.Name);
+      pair.DirItemIndex = dirItemIndex2;
+      pair.ArchiveItemIndex = archiveItemIndex2;
+      switch (MyCompareTime(fileTimeType, dirItem.LastWriteTime, archiveItem.LastWriteTime))
+      {
+        case -1:
+          pair.State = NUpdateArchive::NPairState::kNewInArchive;
+          break;
+        case 1:
+          pair.State = NUpdateArchive::NPairState::kOldInArchive;
+          break;
+        default:
+          if (archiveItem.SizeIsDefined)
+            if (dirItem.Size != archiveItem.Size)
+              // throw 1082034; // kSameTimeChangedSizeCollisionMessaged;
+              pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles;
+            else
+              pair.State = NUpdateArchive::NPairState::kSameFiles;
+          else
+              pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles;
+      }
+      dirItemIndex++;
+      archiveItemIndex++;
+    }
+    updatePairs.Add(pair);
+  }
+  for(;dirItemIndex < numDirItems; dirItemIndex++)
+  {
+    pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
+    pair.DirItemIndex = dirIndices[dirItemIndex];
+    updatePairs.Add(pair);
+  }
+  for(;archiveItemIndex < numArchiveItems; archiveItemIndex++)
+  {
+    int archiveItemIndex2 = archiveIndices[archiveItemIndex]; 
+    const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2];
+    pair.State = archiveItem.Censored ?  
+        NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked;
+    pair.ArchiveItemIndex = archiveItemIndex2;
+    updatePairs.Add(pair);
+  }
+}

Added: trunk/lzma/CPP/7zip/UI/Common/UpdatePair.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/UpdatePair.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/UpdatePair.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// UpdatePair.h
+
+#ifndef __UPDATE_PAIR_H
+#define __UPDATE_PAIR_H
+
+#include "DirItem.h"
+#include "UpdateAction.h"
+
+#include "../../Archive/IArchive.h"
+
+struct CUpdatePair
+{
+  NUpdateArchive::NPairState::EEnum State;
+  int ArchiveItemIndex;
+  int DirItemIndex;
+};
+
+void GetUpdatePairInfoList(
+    const CObjectVector<CDirItem> &dirItems,
+    const CObjectVector<CArchiveItem> &archiveItems,
+    NFileTimeType::EEnum fileTimeType,
+    CObjectVector<CUpdatePair> &updatePairs);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/UpdateProduce.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/UpdateProduce.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/UpdateProduce.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,63 @@
+// UpdateProduce.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateProduce.h"
+
+using namespace NUpdateArchive;
+
+static const char *kUpdateActionSetCollision =
+    "Internal collision in update action set";
+
+void UpdateProduce(
+    const CObjectVector<CUpdatePair> &updatePairs,
+    const NUpdateArchive::CActionSet &actionSet,
+    CObjectVector<CUpdatePair2> &operationChain)
+{
+  for(int i = 0; i < updatePairs.Size(); i++)
+  {
+    // CUpdateArchiveRange aRange;
+    const CUpdatePair &pair = updatePairs[i];
+
+    CUpdatePair2 pair2;
+    pair2.IsAnti = false;
+    pair2.ArchiveItemIndex = pair.ArchiveItemIndex;
+    pair2.DirItemIndex = pair.DirItemIndex;
+    pair2.ExistInArchive = (pair.State != NPairState::kOnlyOnDisk);
+    pair2.ExistOnDisk = (pair.State != NPairState::kOnlyInArchive && pair.State != NPairState::kNotMasked);
+    switch(actionSet.StateActions[pair.State])
+    {
+      case NPairAction::kIgnore:
+        /*
+        if (pair.State != NPairState::kOnlyOnDisk)
+          IgnoreArchiveItem(m_ArchiveItems[pair.ArchiveItemIndex]);
+        // cout << "deleting";
+        */
+        break;
+      case NPairAction::kCopy:
+        {
+          if (pair.State == NPairState::kOnlyOnDisk)
+            throw kUpdateActionSetCollision;
+          pair2.NewData = pair2.NewProperties = false;
+          operationChain.Add(pair2);
+          break;
+        }
+      case NPairAction::kCompress:
+        {
+          if (pair.State == NPairState::kOnlyInArchive || 
+            pair.State == NPairState::kNotMasked)
+            throw kUpdateActionSetCollision;
+          pair2.NewData = pair2.NewProperties = true;
+          operationChain.Add(pair2);
+          break;
+        }
+      case NPairAction::kCompressAsAnti:
+        {
+          pair2.IsAnti = true;
+          pair2.NewData = pair2.NewProperties = true;
+          operationChain.Add(pair2);
+          break;
+        }
+    }
+  }
+}

Added: trunk/lzma/CPP/7zip/UI/Common/UpdateProduce.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/UpdateProduce.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/UpdateProduce.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,31 @@
+// UpdateProduce.h
+
+#ifndef __UPDATE_PRODUCE_H
+#define __UPDATE_PRODUCE_H
+
+#include "UpdatePair.h"
+
+struct CUpdatePair2
+{
+  // bool OperationIsCompress;
+  bool NewData;
+  bool NewProperties;
+
+  bool ExistInArchive;
+  bool ExistOnDisk;
+  bool IsAnti;
+  int ArchiveItemIndex;
+  int DirItemIndex;
+
+  bool NewNameIsDefined;
+  UString NewName;
+
+  CUpdatePair2(): NewNameIsDefined(false) {}
+};
+
+void UpdateProduce(
+    const CObjectVector<CUpdatePair> &updatePairs,
+    const NUpdateArchive::CActionSet &actionSet,
+    CObjectVector<CUpdatePair2> &operationChain);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/WorkDir.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/WorkDir.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/WorkDir.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,64 @@
+// WorkDir.cpp
+
+#include "StdAfx.h"
+
+#include "WorkDir.h"
+
+#include "Common/StringConvert.h"
+#include "Common/Wildcard.h"
+
+#include "Windows/FileName.h"
+#include "Windows/FileDir.h"
+
+static inline UINT GetCurrentCodePage() 
+  { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } 
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NName;
+
+UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path)
+{
+  NWorkDir::NMode::EEnum mode = workDirInfo.Mode;
+  if (workDirInfo.ForRemovableOnly)
+  {
+    mode = NWorkDir::NMode::kCurrent;
+    UString prefix = path.Left(3);
+    if (prefix[1] == L':' && prefix[2] == L'\\')
+    {
+      UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage()));
+      if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE)
+        mode = workDirInfo.Mode;
+    }
+    /*
+    CParsedPath parsedPath;
+    parsedPath.ParsePath(archiveName);
+    UINT driveType = GetDriveType(parsedPath.Prefix);
+    if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE))
+      mode = NZipSettings::NWorkDir::NMode::kCurrent;
+    */
+  }
+  switch(mode)
+  {
+    case NWorkDir::NMode::kCurrent:
+    {
+      return ExtractDirPrefixFromPath(path);
+    }
+    case NWorkDir::NMode::kSpecified:
+    {
+      UString tempDir = workDirInfo.Path;
+      NormalizeDirPathPrefix(tempDir);
+      return tempDir;
+    }
+    default:
+    {
+      UString tempDir;
+      if(!NFile::NDirectory::MyGetTempPath(tempDir))
+        throw 141717;
+      return tempDir;
+    }
+  }
+}
+
+
+

Added: trunk/lzma/CPP/7zip/UI/Common/WorkDir.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/WorkDir.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/WorkDir.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// WorkDir.h
+
+#ifndef __WORKDIR_H
+#define __WORKDIR_H
+
+#include "ZipRegistry.h"
+
+UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Common/ZipRegistry.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Common/ZipRegistry.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Common/ZipRegistry.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,98 @@
+// ZipRegistry.h
+
+#ifndef __ZIPREGISTRY_H
+#define __ZIPREGISTRY_H
+
+#include "Common/MyString.h"
+#include "Common/Types.h"
+#include "ExtractMode.h"
+
+namespace NExtract
+{
+  struct CInfo
+  {
+    NPathMode::EEnum PathMode;
+    NOverwriteMode::EEnum OverwriteMode;
+    UStringVector Paths;
+    bool ShowPassword;
+  };
+}
+
+namespace NCompression {
+  
+  struct CFormatOptions
+  {
+    CSysString FormatID;
+    UString Options;
+    UString Method;
+    UString EncryptionMethod;
+    UInt32 Level;
+    UInt32 Dictionary;
+    UInt32 Order;
+    UInt32 BlockLogSize;
+    UInt32 NumThreads;
+    void ResetForLevelChange() 
+    { 
+      BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1); 
+      Method.Empty();
+      // EncryptionMethod.Empty();
+      // Options.Empty();
+    }
+    CFormatOptions() { ResetForLevelChange(); }
+  };
+
+  struct CInfo
+  {
+    UStringVector HistoryArchives;
+    UInt32 Level;
+    UString ArchiveType;
+
+    CObjectVector<CFormatOptions> FormatOptionsVector;
+
+    bool ShowPassword;
+    bool EncryptHeaders;
+  };
+}
+
+namespace NWorkDir{
+  
+  namespace NMode
+  {
+    enum EEnum
+    {
+      kSystem,
+      kCurrent,
+      kSpecified
+    };
+  }
+  struct CInfo
+  {
+    NMode::EEnum Mode;
+    UString Path;
+    bool ForRemovableOnly;
+    void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }
+    void SetDefault()
+    {
+      Mode = NMode::kSystem;
+      Path.Empty();
+      SetForRemovableOnlyDefault();
+    }
+  };
+}
+
+void SaveExtractionInfo(const NExtract::CInfo &info);
+void ReadExtractionInfo(NExtract::CInfo &info);
+
+void SaveCompressionInfo(const NCompression::CInfo &info);
+void ReadCompressionInfo(NCompression::CInfo &info);
+
+void SaveWorkDirInfo(const NWorkDir::CInfo &info);
+void ReadWorkDirInfo(NWorkDir::CInfo &info);
+
+void SaveCascadedMenu(bool enabled);
+bool ReadCascadedMenu();
+
+void SaveContextMenuStatus(UInt32 value);
+bool ReadContextMenuStatus(UInt32 &value);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Console/ConsoleClose.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/ConsoleClose.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/ConsoleClose.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,63 @@
+// ConsoleClose.cpp
+
+#include "StdAfx.h"
+
+#include "ConsoleClose.h"
+
+static int g_BreakCounter = 0;
+static const int kBreakAbortThreshold = 2;
+
+namespace NConsoleClose {
+
+static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
+{
+  if (ctrlType == CTRL_LOGOFF_EVENT)
+  {
+    // printf("\nCTRL_LOGOFF_EVENT\n");
+    return TRUE;
+  }
+
+  g_BreakCounter++;
+  if (g_BreakCounter < kBreakAbortThreshold)
+    return TRUE;
+  return FALSE;
+  /*
+  switch(ctrlType)
+  {
+    case CTRL_C_EVENT:
+    case CTRL_BREAK_EVENT:
+      if (g_BreakCounter < kBreakAbortThreshold)
+      return TRUE;
+  }
+  return FALSE;
+  */
+}
+
+bool TestBreakSignal()
+{
+  /*
+  if (g_BreakCounter > 0)
+    return true;
+  */
+  return (g_BreakCounter > 0);
+}
+
+void CheckCtrlBreak()
+{
+  if (TestBreakSignal())
+    throw CCtrlBreakException();
+}
+
+CCtrlHandlerSetter::CCtrlHandlerSetter()
+{
+  if(!SetConsoleCtrlHandler(HandlerRoutine, TRUE))
+    throw "SetConsoleCtrlHandler fails";
+}
+
+CCtrlHandlerSetter::~CCtrlHandlerSetter()
+{
+  if(!SetConsoleCtrlHandler(HandlerRoutine, FALSE))
+    throw "SetConsoleCtrlHandler fails";
+}
+
+}

Added: trunk/lzma/CPP/7zip/UI/Console/ConsoleClose.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/ConsoleClose.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/ConsoleClose.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// ConsoleCloseUtils.h
+
+#ifndef __CONSOLECLOSEUTILS_H
+#define __CONSOLECLOSEUTILS_H
+
+namespace NConsoleClose {
+
+bool TestBreakSignal();
+
+class CCtrlHandlerSetter
+{
+public:
+  CCtrlHandlerSetter();
+  virtual ~CCtrlHandlerSetter();
+};
+
+class CCtrlBreakException 
+{};
+
+void CheckCtrlBreak();
+
+}
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,235 @@
+// ExtractCallbackConsole.h
+
+#include "StdAfx.h"
+
+#include "ExtractCallbackConsole.h"
+#include "UserInputUtils.h"
+#include "ConsoleClose.h"
+
+#include "Common/Wildcard.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/FileFind.h"
+#include "Windows/Time.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+#include "Windows/Error.h"
+#include "Windows/PropVariantConversions.h"
+
+#include "../../Common/FilePathAutoRename.h"
+
+#include "../Common/ExtractingFilePath.h"
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NDirectory;
+
+static const char *kTestingString    =  "Testing     ";
+static const char *kExtractingString =  "Extracting  ";
+static const char *kSkippingString   =  "Skipping    ";
+
+// static const char *kCantAutoRename = "can not create file with auto name\n";
+// static const char *kCantRenameFile = "can not rename existing file\n";
+// static const char *kCantDeleteOutputFile = "can not delete output file ";
+static const char *kError = "ERROR: ";
+static const char *kMemoryExceptionMessage = "Can't allocate required memory!";
+
+static const char *kProcessing = "Processing archive: ";
+static const char *kEverythingIsOk = "Everything is Ok";
+static const char *kNoFiles = "No files to process";
+
+static const char *kUnsupportedMethod = "Unsupported Method";
+static const char *kCrcFailed = "CRC Failed";
+static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
+static const char *kDataError = "Data Error";
+static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
+static const char *kUnknownError = "Unknown Error";
+
+STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)
+{
+  if (NConsoleClose::TestBreakSignal())
+    return E_ABORT;
+  return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *)
+{
+  if (NConsoleClose::TestBreakSignal())
+    return E_ABORT;
+  return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
+    const wchar_t *existName, const FILETIME *, const UInt64 *,
+    const wchar_t *newName, const FILETIME *, const UInt64 *,
+    Int32 *answer)
+{
+  (*OutStream) << "file " << existName << 
+    "\nalready exists. Overwrite with " << endl;
+  (*OutStream) << newName;
+  
+  NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);
+  
+  switch(overwriteAnswer)
+  {
+    case NUserAnswerMode::kQuit:
+      return E_ABORT;
+    case NUserAnswerMode::kNo:
+      *answer = NOverwriteAnswer::kNo;
+      break;
+    case NUserAnswerMode::kNoAll:
+      *answer = NOverwriteAnswer::kNoToAll;
+      break;
+    case NUserAnswerMode::kYesAll:
+      *answer = NOverwriteAnswer::kYesToAll;
+      break;
+    case NUserAnswerMode::kYes:
+      *answer = NOverwriteAnswer::kYes;
+      break;
+    case NUserAnswerMode::kAutoRename:
+      *answer = NOverwriteAnswer::kAutoRename;
+      break;
+    default:
+      return E_FAIL;
+  }
+  return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position)
+{
+  switch (askExtractMode)
+  {
+    case NArchive::NExtract::NAskMode::kExtract:
+      (*OutStream) << kExtractingString;
+      break;
+    case NArchive::NExtract::NAskMode::kTest:
+      (*OutStream) << kTestingString;
+      break;
+    case NArchive::NExtract::NAskMode::kSkip:
+      (*OutStream) << kSkippingString;
+      break;
+  };
+  (*OutStream) << name;
+  if (position != 0)
+    (*OutStream) << " <" << *position << ">";
+  return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
+{
+  (*OutStream) << message << endl;
+  NumFileErrorsInCurrentArchive++;
+  NumFileErrors++;
+  return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted)
+{
+  switch(operationResult)
+  {
+    case NArchive::NExtract::NOperationResult::kOK:
+      break;
+    default:
+    {
+      NumFileErrorsInCurrentArchive++;
+      NumFileErrors++;
+      (*OutStream) << "     ";
+      switch(operationResult)
+      {
+        case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
+          (*OutStream) << kUnsupportedMethod;
+          break;
+        case NArchive::NExtract::NOperationResult::kCRCError:
+          (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed);
+          break;
+        case NArchive::NExtract::NOperationResult::kDataError:
+          (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError);
+          break;
+        default:
+          (*OutStream) << kUnknownError;
+      }
+    }
+  }
+  (*OutStream) << endl;
+  return S_OK;
+}
+
+STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
+{
+  if (!PasswordIsDefined)
+  {
+    Password = GetPassword(OutStream); 
+    PasswordIsDefined = true;
+  }
+  CMyComBSTR tempName(Password);
+  *password = tempName.Detach();
+  return S_OK;
+}
+
+HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)
+{
+  NumArchives++;
+  NumFileErrorsInCurrentArchive = 0;
+  (*OutStream) << endl << kProcessing << name << endl;
+  return S_OK;
+}
+
+HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted)
+{
+  (*OutStream) << endl;
+  if (result != S_OK)
+  {
+    (*OutStream) << "Error: ";
+    if (encrypted)
+      (*OutStream) << "Can not open encrypted archive. Wrong password?";
+    else
+      (*OutStream) << "Can not open file as archive";
+    (*OutStream) << endl;
+    NumArchiveErrors++;
+  }
+  return S_OK;
+}
+  
+HRESULT CExtractCallbackConsole::ThereAreNoFiles()
+{
+  (*OutStream) << endl << kNoFiles << endl;
+  return S_OK;
+}
+
+HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
+{
+  if (result == S_OK)
+  {
+    (*OutStream) << endl;
+    if (NumFileErrorsInCurrentArchive == 0)
+      (*OutStream) << kEverythingIsOk << endl;
+    else 
+    {
+      NumArchiveErrors++;
+      (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl;
+    }
+  }
+  if (result == S_OK)
+    return result;
+  NumArchiveErrors++;
+  if (result == E_ABORT || result == ERROR_DISK_FULL)
+    return result;
+  (*OutStream) << endl << kError;
+  if (result == E_OUTOFMEMORY)
+    (*OutStream) << kMemoryExceptionMessage;
+  else
+  {
+    UString message;
+    NError::MyFormatMessage(result, message);
+    (*OutStream) << message;
+  }
+  (*OutStream) << endl;
+  return S_OK;
+}
+
+HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
+{
+  PasswordIsDefined = true;
+  Password = password;
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/ExtractCallbackConsole.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,65 @@
+// ExtractCallbackConsole.h
+
+#ifndef __EXTRACTCALLBACKCONSOLE_H
+#define __EXTRACTCALLBACKCONSOLE_H
+
+#include "Common/MyString.h"
+#include "Common/StdOutStream.h"
+#include "../../Common/FileStreams.h"
+#include "../../IPassword.h"
+#include "../../Archive/IArchive.h"
+#include "../Common/ArchiveExtractCallback.h"
+
+class CExtractCallbackConsole: 
+  public IExtractCallbackUI,
+  public ICryptoGetTextPassword,
+  public CMyUnknownImp
+{
+public:
+  MY_UNKNOWN_IMP2(IFolderArchiveExtractCallback, ICryptoGetTextPassword)
+
+  STDMETHOD(SetTotal)(UInt64 total);
+  STDMETHOD(SetCompleted)(const UInt64 *completeValue);
+
+  // IFolderArchiveExtractCallback
+  STDMETHOD(AskOverwrite)(
+      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
+      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
+      Int32 *answer);
+  STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);
+
+  STDMETHOD(MessageError)(const wchar_t *message);
+  STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);
+
+  // ICryptoGetTextPassword
+  STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+
+  HRESULT BeforeOpen(const wchar_t *name);
+  HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);
+  HRESULT ThereAreNoFiles();
+  HRESULT ExtractResult(HRESULT result);
+
+  HRESULT SetPassword(const UString &password);
+
+public:
+  bool PasswordIsDefined;
+  UString Password;
+  
+  UInt64 NumArchives;
+  UInt64 NumArchiveErrors;
+  UInt64 NumFileErrors;
+  UInt64 NumFileErrorsInCurrentArchive;
+
+  CStdOutStream *OutStream;
+
+  void Init()
+  {
+    NumArchives = 0;
+    NumArchiveErrors = 0;
+    NumFileErrors = 0;
+    NumFileErrorsInCurrentArchive = 0;
+  }
+
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Console/List.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/List.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/List.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,579 @@
+// List.cpp
+
+#include "StdAfx.h"
+
+#include "List.h"
+#include "ConsoleClose.h"
+
+#include "Common/StringConvert.h"
+#include "Common/StdOutStream.h"
+#include "Common/IntToString.h"
+#include "Common/MyCom.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Defs.h"
+#include "Windows/PropVariantConversions.h"
+#include "Windows/FileDir.h"
+
+#include "../../Archive/IArchive.h"
+
+#include "../Common/PropIDUtils.h"
+#include "../Common/OpenArchive.h"
+
+#include "OpenCallbackConsole.h"
+
+using namespace NWindows;
+
+struct CPropIdToName
+{
+  PROPID PropID;
+  const wchar_t *Name;
+};
+
+static CPropIdToName kPropIdToName[] =  
+{
+  { kpidPath, L"Path" },
+  { kpidName, L"Name" },
+  { kpidIsFolder, L"Folder" }, 
+  { kpidSize, L"Size" },
+  { kpidPackedSize, L"Packed Size" },
+  { kpidAttributes, L"Attributes" },
+  { kpidCreationTime, L"Created" },
+  { kpidLastAccessTime, L"Accessed" },
+  { kpidLastWriteTime, L"Modified" },
+  { kpidSolid, L"Solid" },
+  { kpidCommented, L"Commented" },
+  { kpidEncrypted, L"Encrypted" },
+  { kpidSplitBefore, L"Split Before" },
+  { kpidSplitAfter, L"Split After" },
+  { kpidDictionarySize, L"Dictionary Size" },
+  { kpidCRC, L"CRC" },
+  { kpidType, L"Type" },
+  { kpidIsAnti, L"Anti" },
+  { kpidMethod, L"Method" },
+  { kpidHostOS, L"Host OS" },
+  { kpidFileSystem, L"File System" },
+  { kpidUser, L"User" },
+  { kpidGroup, L"Group" },
+  { kpidBlock, L"Block" },
+  { kpidComment, L"Comment" },
+  { kpidPosition, L"Position" },
+  { kpidPrefix, L"Prefix" },
+  { kpidNumSubFolders, L"Folders" },
+  { kpidNumSubFiles, L"Files" },
+  { kpidUnpackVer, L"Version" },
+  { kpidVolume, L"Volume" },
+  { kpidIsVolume, L"Multivolume" },
+  { kpidOffset, L"Offset" },
+  { kpidLinks, L"Links" },
+  { kpidNumBlocks, L"Blocks" },
+  { kpidNumVolumes, L"Volumes" }
+};
+
+static const char kEmptyAttributeChar = '.';
+static const char kDirectoryAttributeChar = 'D';
+static const char kReadonlyAttributeChar  = 'R';
+static const char kHiddenAttributeChar    = 'H';
+static const char kSystemAttributeChar    = 'S';
+static const char kArchiveAttributeChar   = 'A';
+
+static const char *kListing = "Listing archive: ";
+static const wchar_t *kFilesMessage = L"files";
+static const wchar_t *kDirsMessage = L"folders";
+
+static void GetAttributesString(DWORD wa, bool directory, char *s)
+{
+  s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || directory) ? 
+      kDirectoryAttributeChar: kEmptyAttributeChar;
+  s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0)? 
+      kReadonlyAttributeChar: kEmptyAttributeChar;
+  s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 
+      kHiddenAttributeChar: kEmptyAttributeChar;
+  s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 
+      kSystemAttributeChar: kEmptyAttributeChar;
+  s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 
+      kArchiveAttributeChar: kEmptyAttributeChar;
+  s[5] = '\0';
+}
+
+enum EAdjustment
+{
+  kLeft,
+  kCenter,
+  kRight
+};
+
+struct CFieldInfo
+{
+  PROPID PropID;
+  UString Name;
+  EAdjustment TitleAdjustment;
+  EAdjustment TextAdjustment;
+  int PrefixSpacesWidth;
+  int Width;
+};
+
+struct CFieldInfoInit
+{
+  PROPID PropID;
+  const wchar_t *Name;
+  EAdjustment TitleAdjustment;
+  EAdjustment TextAdjustment;
+  int PrefixSpacesWidth;
+  int Width;
+};
+
+CFieldInfoInit kStandardFieldTable[] = 
+{
+  { kpidLastWriteTime, L"   Date      Time", kLeft, kLeft, 0, 19 },
+  { kpidAttributes, L"Attr", kRight, kCenter, 1, 5 },
+  { kpidSize, L"Size", kRight, kRight, 1, 12 },
+  { kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 },
+  { kpidPath, L"Name", kLeft, kLeft, 2, 24 }
+};
+
+void PrintSpaces(int numSpaces)
+{
+  for (int i = 0; i < numSpaces; i++)
+    g_StdOut << ' ';
+}
+
+void PrintString(EAdjustment adjustment, int width, const UString &textString)
+{
+  const int numSpaces = width - textString.Length();
+  int numLeftSpaces = 0;
+  switch (adjustment)
+  {
+    case kLeft:
+      numLeftSpaces = 0;
+      break;
+    case kCenter:
+      numLeftSpaces = numSpaces / 2;
+      break;
+    case kRight:
+      numLeftSpaces = numSpaces;
+      break;
+  }
+  PrintSpaces(numLeftSpaces);
+  g_StdOut << textString;
+  PrintSpaces(numSpaces - numLeftSpaces);
+}
+
+class CFieldPrinter
+{
+  CObjectVector<CFieldInfo> _fields;
+public:
+  void Clear() { _fields.Clear(); }
+  void Init(const CFieldInfoInit *standardFieldTable, int numItems);
+  HRESULT Init(IInArchive *archive);
+  void PrintTitle();
+  void PrintTitleLines();
+  HRESULT PrintItemInfo(IInArchive *archive, 
+      const UString &defaultItemName,
+      const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
+      UInt32 index,
+      bool techMode);
+  HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, 
+      const UInt64 *size, const UInt64 *compressedSize);
+};
+
+void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
+{
+  Clear();
+  for (int i = 0; i < numItems; i++)
+  {
+    CFieldInfo fieldInfo;
+    const CFieldInfoInit &fieldInfoInit = standardFieldTable[i];
+    fieldInfo.PropID = fieldInfoInit.PropID;
+    fieldInfo.Name = fieldInfoInit.Name;
+    fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment;
+    fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment;
+    fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth;
+    fieldInfo.Width = fieldInfoInit.Width;
+    _fields.Add(fieldInfo);
+  }
+}
+
+static UString GetPropName(PROPID propID, BSTR name)
+{
+  for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++)
+  {
+    const CPropIdToName &propIdToName = kPropIdToName[i];
+    if (propIdToName.PropID == propID)
+      return propIdToName.Name;
+  }
+  if (name)
+    return name;
+  return L"?";
+}
+
+HRESULT CFieldPrinter::Init(IInArchive *archive)
+{
+  Clear();
+  UInt32 numProps;
+  RINOK(archive->GetNumberOfProperties(&numProps));
+  for (UInt32 i = 0; i < numProps; i++)
+  {
+    CMyComBSTR name;
+    PROPID propID;
+    VARTYPE vt;
+    RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt));
+    CFieldInfo fieldInfo;
+    fieldInfo.PropID = propID;
+    fieldInfo.Name = GetPropName(propID, name);
+    _fields.Add(fieldInfo);
+  }
+  return S_OK;
+}
+
+void CFieldPrinter::PrintTitle()
+{
+  for (int i = 0; i < _fields.Size(); i++)
+  {
+    const CFieldInfo &fieldInfo = _fields[i];
+    PrintSpaces(fieldInfo.PrefixSpacesWidth);
+    PrintString(fieldInfo.TitleAdjustment, 
+      ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name);
+  }
+}
+
+void CFieldPrinter::PrintTitleLines()
+{
+  for (int i = 0; i < _fields.Size(); i++)
+  {
+    const CFieldInfo &fieldInfo = _fields[i];
+    PrintSpaces(fieldInfo.PrefixSpacesWidth);
+    for (int i = 0; i < fieldInfo.Width; i++)
+      g_StdOut << '-';
+  }
+}
+
+
+BOOL IsFileTimeZero(CONST FILETIME *lpFileTime)
+{
+  return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0);
+}
+
+static const char *kEmptyTimeString = "                   ";
+void PrintTime(const NCOM::CPropVariant &propVariant)
+{
+  if (propVariant.vt != VT_FILETIME)
+    throw "incorrect item";
+  if (IsFileTimeZero(&propVariant.filetime))
+    g_StdOut << kEmptyTimeString;
+  else
+  {
+    FILETIME localFileTime;
+    if (!FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime))
+      throw "FileTimeToLocalFileTime error";
+    char s[32];
+    if (ConvertFileTimeToString(localFileTime, s, true, true))
+      g_StdOut << s;
+    else
+      g_StdOut << kEmptyTimeString;
+  }
+}
+
+HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive, 
+    const UString &defaultItemName, 
+    const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
+    UInt32 index,
+    bool techMode)
+{
+  /*
+  if (techMode)
+  {
+    g_StdOut << "Index = ";
+    g_StdOut << (UInt64)index;
+    g_StdOut << endl;
+  }
+  */
+  for (int i = 0; i < _fields.Size(); i++)
+  {
+    const CFieldInfo &fieldInfo = _fields[i];
+    if (!techMode)
+      PrintSpaces(fieldInfo.PrefixSpacesWidth);
+
+    NCOM::CPropVariant propVariant;
+    RINOK(archive->GetProperty(index, fieldInfo.PropID, &propVariant));
+    if (techMode)
+    {
+      g_StdOut << fieldInfo.Name << " = ";
+    }
+    int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;
+    if (propVariant.vt == VT_EMPTY)
+    {
+      switch(fieldInfo.PropID)
+      {
+        case kpidPath:
+          propVariant = defaultItemName;
+          break;
+        case kpidLastWriteTime:
+          propVariant = archiveFileInfo.LastWriteTime;
+          break;
+        default:
+          if (techMode)
+            g_StdOut << endl;
+          else
+            PrintSpaces(width);
+          continue;
+      }
+    }
+    if (fieldInfo.PropID == kpidLastWriteTime)
+    {
+      PrintTime(propVariant);
+    }
+    else if (fieldInfo.PropID == kpidAttributes)
+    {
+      if (propVariant.vt != VT_UI4)
+        throw "incorrect item";
+      UInt32 attributes = propVariant.ulVal;
+      bool isFolder;
+      RINOK(IsArchiveItemFolder(archive, index, isFolder));
+      char s[8];
+      GetAttributesString(attributes, isFolder, s);
+      g_StdOut << s;
+    }
+    else if (propVariant.vt == VT_BSTR)
+    {
+      if (techMode)
+        g_StdOut << propVariant.bstrVal;
+      else
+        PrintString(fieldInfo.TextAdjustment, width, propVariant.bstrVal);
+    }
+    else
+    {
+      UString s = ConvertPropertyToString(propVariant, fieldInfo.PropID);
+      s.Replace(wchar_t(0xA), L' '); 
+      s.Replace(wchar_t(0xD), L' '); 
+
+      if (techMode)
+        g_StdOut << s;
+      else
+        PrintString(fieldInfo.TextAdjustment, width, s);
+    }
+    if (techMode)
+      g_StdOut << endl;
+  }
+  return S_OK;
+}
+
+void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)
+{
+  wchar_t textString[32] = { 0 };
+  if (value != NULL)
+    ConvertUInt64ToString(*value, textString);
+  PrintString(adjustment, width, textString);
+}
+
+
+HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs, 
+    const UInt64 *size, const UInt64 *compressedSize)
+{
+  for (int i = 0; i < _fields.Size(); i++)
+  {
+    const CFieldInfo &fieldInfo = _fields[i];
+    PrintSpaces(fieldInfo.PrefixSpacesWidth);
+    NCOM::CPropVariant propVariant;
+    if (fieldInfo.PropID == kpidSize)
+      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size);
+    else if (fieldInfo.PropID == kpidPackedSize)
+      PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize);
+    else if (fieldInfo.PropID == kpidPath)
+    {
+      wchar_t textString[32];
+      ConvertUInt64ToString(numFiles, textString);
+      UString temp = textString;
+      temp += L" ";
+      temp += kFilesMessage;
+      temp += L", ";
+      ConvertUInt64ToString(numDirs, textString);
+      temp += textString;
+      temp += L" ";
+      temp += kDirsMessage;
+      PrintString(fieldInfo.TextAdjustment, 0, temp);
+    }
+    else 
+      PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L"");
+  }
+  return S_OK;
+}
+
+bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value)
+{
+  NCOM::CPropVariant propVariant;
+  if (archive->GetProperty(index, propID, &propVariant) != S_OK)
+    throw "GetPropertyValue error";
+  if (propVariant.vt == VT_EMPTY)
+    return false;
+  value = ConvertPropVariantToUInt64(propVariant);
+  return true;
+}
+
+HRESULT ListArchives(
+    CCodecs *codecs,
+    UStringVector &archivePaths, UStringVector &archivePathsFull,
+    const NWildcard::CCensorNode &wildcardCensor,
+    bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &numErrors)
+{
+  numErrors = 0;
+  CFieldPrinter fieldPrinter;
+  if (!techMode)
+    fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));
+
+  UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
+  UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;
+  for (int i = 0; i < archivePaths.Size(); i++)
+  {
+    const UString &archiveName = archivePaths[i];
+    NFile::NFind::CFileInfoW archiveFileInfo;
+    if (!NFile::NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory())
+    {
+      g_StdOut << endl << "Error: " << archiveName << " is not archive" << endl;
+      numErrors++;
+      continue;
+    }
+    if (archiveFileInfo.IsDirectory())
+    {
+      g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;
+      numErrors++;
+      continue;
+    }
+
+    CArchiveLink archiveLink;
+
+    COpenCallbackConsole openCallback;
+    openCallback.OutStream = &g_StdOut;
+    openCallback.PasswordIsDefined = passwordEnabled;
+    openCallback.Password = password;
+
+    HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, &openCallback);
+    if (result != S_OK)
+    {
+      g_StdOut << endl << "Error: " << archiveName << " is not supported archive" << endl;
+      numErrors++;
+      continue;
+    }
+
+    for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
+    {
+      int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
+      if (index >= 0 && index > i)
+      {
+        archivePaths.Delete(index);
+        archivePathsFull.Delete(index);
+      }
+    }
+
+    IInArchive *archive = archiveLink.GetArchive();
+    const UString defaultItemName = archiveLink.GetDefaultItemName();
+
+    if (enableHeaders)
+    {
+      g_StdOut << endl << kListing << archiveName << endl << endl;
+
+      UInt32 numProps;
+      if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK)
+      {
+        for (UInt32 i = 0; i < numProps; i++)
+        {
+          CMyComBSTR name;
+          PROPID propID;
+          VARTYPE vt;
+          if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK)
+            continue;
+          NCOM::CPropVariant prop;
+          if (archive->GetArchiveProperty(propID, &prop) != S_OK)
+            continue;
+          UString s = ConvertPropertyToString(prop, propID);
+          if (!s.IsEmpty())
+            g_StdOut << GetPropName(propID, name) << " = " << s << endl;
+        }
+      }
+      if (techMode)
+        g_StdOut << "----------\n";
+      if (numProps > 0)
+        g_StdOut << endl;
+    }
+
+    if (enableHeaders && !techMode)
+    {
+      fieldPrinter.PrintTitle();
+      g_StdOut << endl;
+      fieldPrinter.PrintTitleLines();
+      g_StdOut << endl;
+    }
+
+    if (techMode)
+    {
+      RINOK(fieldPrinter.Init(archive));
+    }
+    UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0;
+    UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
+    UInt32 numItems;
+    RINOK(archive->GetNumberOfItems(&numItems));
+    for(UInt32 i = 0; i < numItems; i++)
+    {
+      if (NConsoleClose::TestBreakSignal())
+        return E_ABORT;
+
+      UString filePath;
+      RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath));
+
+      bool isFolder;
+      RINOK(IsArchiveItemFolder(archive, i, isFolder));
+      if (!wildcardCensor.CheckPath(filePath, !isFolder))
+        continue;
+      
+      fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i, techMode);
+      
+      UInt64 packSize, unpackSize;
+      if (!GetUInt64Value(archive, i, kpidSize, unpackSize))
+        unpackSize = 0;
+      else
+        totalUnPackSizePointer = &totalUnPackSize;
+      if (!GetUInt64Value(archive, i, kpidPackedSize, packSize))
+        packSize = 0;
+      else
+        totalPackSizePointer = &totalPackSize;
+      
+      g_StdOut << endl;
+
+      if (isFolder)
+        numDirs++;
+      else
+        numFiles++;
+      totalPackSize += packSize;
+      totalUnPackSize += unpackSize;
+    }
+    if (enableHeaders && !techMode)
+    {
+      fieldPrinter.PrintTitleLines();
+      g_StdOut << endl;
+      fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer);
+      g_StdOut << endl;
+    }
+    if (totalPackSizePointer != 0)
+    {
+      totalPackSizePointer2 = &totalPackSize2;
+      totalPackSize2 += totalPackSize;
+    }
+    if (totalUnPackSizePointer != 0)
+    {
+      totalUnPackSizePointer2 = &totalUnPackSize2;
+      totalUnPackSize2 += totalUnPackSize;
+    }
+    numFiles2 += numFiles;
+    numDirs2 += numDirs;
+  }
+  if (enableHeaders && !techMode && archivePaths.Size() > 1)
+  {
+    g_StdOut << endl;
+    fieldPrinter.PrintTitleLines();
+    g_StdOut << endl;
+    fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2);
+    g_StdOut << endl;
+    g_StdOut << "Archives: " << archivePaths.Size() << endl;
+  }
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/UI/Console/List.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/List.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/List.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,16 @@
+// List.h
+
+#ifndef __LIST_H
+#define __LIST_H
+
+#include "Common/Wildcard.h"
+#include "../Common/LoadCodecs.h"
+
+HRESULT ListArchives(
+    CCodecs *codecs,
+    UStringVector &archivePaths, UStringVector &archivePathsFull,
+    const NWildcard::CCensorNode &wildcardCensor,
+    bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &errors);
+
+#endif
+

Added: trunk/lzma/CPP/7zip/UI/Console/Main.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/Main.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/Main.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,563 @@
+// Main.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+
+#include "Common/CommandLineParser.h"
+#include "Common/MyException.h"
+#include "Common/IntToString.h"
+#include "Common/StdOutStream.h"
+#include "Common/StringConvert.h"
+#include "Common/StringToInt.h"
+
+#include "Windows/FileDir.h"
+#include "Windows/FileName.h"
+#include "Windows/Defs.h"
+#include "Windows/Error.h"
+#ifdef _WIN32
+#include "Windows/MemoryLock.h"
+#endif
+
+#include "../../IPassword.h"
+#include "../../ICoder.h"
+#include "../Common/UpdateAction.h"
+#include "../Common/Update.h"
+#include "../Common/Extract.h"
+#include "../Common/ArchiveCommandLine.h"
+#include "../Common/ExitCode.h"
+#ifdef EXTERNAL_CODECS
+#include "../Common/LoadCodecs.h"
+#endif
+
+#include "../../Compress/LZMA_Alone/LzmaBenchCon.h"
+
+#include "List.h"
+#include "OpenCallbackConsole.h"
+#include "ExtractCallbackConsole.h"
+#include "UpdateCallbackConsole.h"
+
+#include "../../MyVersion.h"
+
+#if defined( _WIN32) && defined( _7ZIP_LARGE_PAGES)
+extern "C" 
+{ 
+#include "../../../../C/Alloc.h"
+}
+#endif
+
+using namespace NWindows;
+using namespace NFile;
+using namespace NCommandLineParser;
+
+HINSTANCE g_hInstance = 0;
+extern CStdOutStream *g_StdStream;
+
+static const char *kCopyrightString = "\n7-Zip"
+#ifndef EXTERNAL_CODECS
+" (A)"
+#endif
+
+#ifdef _WIN64
+" [64]"
+#endif
+
+" " MY_VERSION_COPYRIGHT_DATE "\n";
+
+static const char *kHelpString = 
+    "\nUsage: 7z"
+#ifdef _NO_CRYPTO
+    "r"
+#else
+#ifndef EXTERNAL_CODECS
+    "a"
+#endif
+#endif
+    " <command> [<switches>...] <archive_name> [<file_names>...]\n"
+    "       [<@listfiles...>]\n"
+    "\n"
+    "<Commands>\n"
+    "  a: Add files to archive\n"
+    "  b: Benchmark\n"
+    "  d: Delete files from archive\n"
+    "  e: Extract files from archive (without using directory names)\n"
+    "  l: List contents of archive\n"
+//    "  l[a|t][f]: List contents of archive\n"
+//    "    a - with Additional fields\n"
+//    "    t - with all fields\n"
+//    "    f - with Full pathnames\n"
+    "  t: Test integrity of archive\n"
+    "  u: Update files to archive\n"
+    "  x: eXtract files with full paths\n"
+    "<Switches>\n"
+    "  -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n"
+    "  -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n"
+    "  -bd: Disable percentage indicator\n"
+    "  -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n"
+    "  -m{Parameters}: set compression Method\n"
+    "  -o{Directory}: set Output directory\n"
+    "  -p{Password}: set Password\n"
+    "  -r[-|0]: Recurse subdirectories\n"
+    "  -scs{UTF-8 | WIN | DOS}: set charset for list files\n"
+    "  -sfx[{name}]: Create SFX archive\n"
+    "  -si[{name}]: read data from stdin\n"
+    "  -slt: show technical information for l (List) command\n"
+    "  -so: write data to stdout\n"
+    "  -ssc[-]: set sensitive case mode\n"
+    "  -ssw: compress shared files\n"
+    "  -t{Type}: Set type of archive\n"
+    "  -v{Size}[b|k|m|g]: Create volumes\n"
+    "  -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n"
+    "  -w[{path}]: assign Work directory. Empty path means a temporary directory\n"
+    "  -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n"
+    "  -y: assume Yes on all queries\n";
+
+// ---------------------------
+// exception messages
+
+static const char *kEverythingIsOk = "Everything is Ok";
+static const char *kUserErrorMessage  = "Incorrect command line"; // NExitCode::kUserError
+
+static const wchar_t *kDefaultSfxModule = L"7zCon.sfx";
+
+static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code)
+{
+  s << message << endl;
+  throw code;
+}
+
+static void PrintHelpAndExit(CStdOutStream &s) // yyy
+{
+  s << kHelpString;
+  ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError);
+}
+
+#ifndef _WIN32
+static void GetArguments(int numArguments, const char *arguments[], UStringVector &parts)
+{
+  parts.Clear();
+  for(int i = 0; i < numArguments; i++)
+  {
+    UString s = MultiByteToUnicodeString(arguments[i]);
+    parts.Add(s);
+  }
+}
+#endif
+
+static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp)
+{
+  s << kCopyrightString;
+  // s << "# CPUs: " << (UInt64)NWindows::NSystem::GetNumberOfProcessors() << "\n";
+  if (needHelp) 
+    s << kHelpString;
+}
+
+#ifdef EXTERNAL_CODECS
+static void PrintString(CStdOutStream &stdStream, const AString &s, int size)
+{
+  int len = s.Length();
+  stdStream << s;
+  for (int i = len; i < size; i++)
+    stdStream << ' ';
+}
+#endif
+
+static void PrintString(CStdOutStream &stdStream, const UString &s, int size)
+{
+  int len = s.Length();
+  stdStream << s;
+  for (int i = len; i < size; i++)
+    stdStream << ' ';
+}
+
+static inline char GetHex(Byte value)
+{
+  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+int Main2(
+  #ifndef _WIN32  
+  int numArguments, const char *arguments[]
+  #endif
+)
+{
+  #ifdef _WIN32  
+  SetFileApisToOEM();
+  #endif
+  
+  UStringVector commandStrings;
+  #ifdef _WIN32  
+  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
+  #else
+  GetArguments(numArguments, arguments, commandStrings);
+  #endif
+
+  if(commandStrings.Size() == 1)
+  {
+    ShowCopyrightAndHelp(g_StdOut, true);
+    return 0;
+  }
+  commandStrings.Delete(0);
+
+  CArchiveCommandLineOptions options;
+
+  CArchiveCommandLineParser parser;
+
+  parser.Parse1(commandStrings, options);
+
+  if(options.HelpMode)
+  {
+    ShowCopyrightAndHelp(g_StdOut, true);
+    return 0;
+  }
+
+  #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES)
+  if (options.LargePages)
+  {
+    SetLargePageSize();
+    NSecurity::EnableLockMemoryPrivilege();
+  }
+  #endif
+
+  CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut;
+  g_StdStream = &stdStream;
+
+  if (options.EnableHeaders)
+    ShowCopyrightAndHelp(stdStream, false);
+
+  parser.Parse2(options);
+
+  CCodecs *codecs = new CCodecs;
+  CMyComPtr<
+    #ifdef EXTERNAL_CODECS
+    ICompressCodecsInfo
+    #else
+    IUnknown
+    #endif
+    > compressCodecsInfo = codecs;
+  HRESULT result = codecs->Load();
+  if (result != S_OK)
+    throw CSystemException(result);
+
+  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
+  if (options.Command.CommandType == NCommandType::kInfo)
+  {
+    stdStream << endl << "Formats:" << endl;
+    int i;
+    for (i = 0; i < codecs->Formats.Size(); i++)
+    {
+      const CArcInfoEx &arc = codecs->Formats[i];
+      #ifdef EXTERNAL_CODECS
+      if (arc.LibIndex >= 0)
+      {
+        char s[32];
+        ConvertUInt64ToString(arc.LibIndex, s);
+        PrintString(stdStream, s, 2);
+      }
+      else
+      #endif
+        stdStream << "  ";
+      stdStream << ' ';
+      stdStream << (char)(arc.UpdateEnabled ? 'C' : ' ');
+      stdStream << (char)(arc.KeepName ? 'K' : ' ');
+      stdStream << "  ";
+      PrintString(stdStream, arc.Name, 6);
+      stdStream << "  ";
+      UString s;
+      for (int t = 0; t < arc.Exts.Size(); t++)
+      {
+        const CArcExtInfo &ext = arc.Exts[t];
+        s += ext.Ext;
+        if (!ext.AddExt.IsEmpty())
+        {
+          s += L" (";
+          s += ext.AddExt;
+          s += L')';
+        }
+        s += L' ';
+      }
+      PrintString(stdStream, s, 14);
+      stdStream << "  ";
+      const CByteBuffer &sig = arc.StartSignature;
+      for (size_t j = 0; j < sig.GetCapacity(); j++)
+      {
+        Byte b = sig[j];
+        if (b > 0x20 && b < 0x80)
+        {
+          stdStream << (char)b;
+        }
+        else
+        {
+          stdStream << GetHex((Byte)((b >> 4) & 0xF));
+          stdStream << GetHex((Byte)(b & 0xF));
+        }
+        stdStream << ' ';
+      }
+      stdStream << endl;
+    }
+    stdStream << endl << "Codecs:" << endl;
+
+    #ifdef EXTERNAL_CODECS
+    UINT32 numMethods;
+    if (codecs->GetNumberOfMethods(&numMethods) == S_OK)
+    for (UInt32 j = 0; j < numMethods; j++)
+    {
+      int libIndex = codecs->GetCodecLibIndex(j);
+      if (libIndex >= 0)
+      {
+        char s[32];
+        ConvertUInt64ToString(libIndex, s);
+        PrintString(stdStream, s, 2);
+      }
+      else
+        stdStream << "  ";
+      stdStream << ' ';
+      stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' ');
+      UInt64 id;
+      stdStream << "  ";
+      HRESULT res = codecs->GetCodecId(j, id);
+      if (res != S_OK)
+        id = (UInt64)(Int64)-1;
+      char s[32];
+      ConvertUInt64ToString(id, s, 16);
+      PrintString(stdStream, s, 8);
+      stdStream << "  ";
+      PrintString(stdStream, codecs->GetCodecName(j), 11);
+      stdStream << endl;
+      /*
+      if (res != S_OK)
+        throw "incorrect Codec ID";
+      */
+    }
+    #endif
+    return S_OK;
+  }
+  else if (options.Command.CommandType == NCommandType::kBenchmark)
+  {
+    if (options.Method.CompareNoCase(L"CRC") == 0)
+    {
+      HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);
+      if (res != S_OK)
+      {
+        if (res == S_FALSE)
+        {
+          stdStream << "\nCRC Error\n";
+          return NExitCode::kFatalError;
+        }
+        throw CSystemException(res);
+      }
+    }
+    else
+    {
+      HRESULT res = LzmaBenchCon(
+        #ifdef EXTERNAL_LZMA
+        codecs,
+        #endif
+        (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);
+      if (res != S_OK)
+      {
+        if (res == S_FALSE)
+        {
+          stdStream << "\nDecoding Error\n";
+          return NExitCode::kFatalError;
+        }
+        throw CSystemException(res);
+      }
+    }
+  }
+  else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
+  {
+    if(isExtractGroupCommand)
+    {
+      CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
+      CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
+
+      ecs->OutStream = &stdStream;
+      ecs->PasswordIsDefined = options.PasswordEnabled;
+      ecs->Password = options.Password;
+      ecs->Init();
+
+      COpenCallbackConsole openCallback;
+      openCallback.OutStream = &stdStream;
+      openCallback.PasswordIsDefined = options.PasswordEnabled;
+      openCallback.Password = options.Password;
+
+      CExtractOptions eo;
+      eo.StdOutMode = options.StdOutMode;
+      eo.PathMode = options.Command.GetPathMode();
+      eo.TestMode = options.Command.IsTestMode();
+      eo.OverwriteMode = options.OverwriteMode;
+      eo.OutputDir = options.OutputDir;
+      eo.YesToAll = options.YesToAll;
+      #ifdef COMPRESS_MT
+      eo.Properties = options.ExtractProperties;
+      #endif
+      UString errorMessage;
+      CDecompressStat stat;
+      HRESULT result = DecompressArchives(
+          codecs,
+          options.ArchivePathsSorted, 
+          options.ArchivePathsFullSorted,
+          options.WildcardCensor.Pairs.Front().Head, 
+          eo, &openCallback, ecs, errorMessage, stat);
+      if (!errorMessage.IsEmpty())
+      {
+        stdStream << endl << "Error: " << errorMessage;
+        if (result == S_OK)
+          result = E_FAIL;
+      }
+
+      stdStream << endl;
+      if (ecs->NumArchives > 1)
+        stdStream << "Archives: " << ecs->NumArchives << endl;
+      if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0)
+      {
+        if (ecs->NumArchives > 1)
+        {
+          stdStream << endl;
+          if (ecs->NumArchiveErrors != 0)
+            stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl;
+          if (ecs->NumFileErrors != 0)
+            stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl;
+        }
+        if (result != S_OK)
+          throw CSystemException(result);
+        return NExitCode::kFatalError;
+      }
+      if (result != S_OK)
+        throw CSystemException(result);
+      if (stat.NumFolders != 0)
+        stdStream << "Folders: " << stat.NumFolders << endl;
+      if (stat.NumFiles != 1 || stat.NumFolders != 0)
+          stdStream << "Files: " << stat.NumFiles << endl;
+      stdStream 
+           << "Size:       " << stat.UnpackSize << endl
+           << "Compressed: " << stat.PackSize << endl;
+    }
+    else
+    {
+      UInt64 numErrors = 0;
+      HRESULT result = ListArchives(
+          codecs,
+          options.ArchivePathsSorted, 
+          options.ArchivePathsFullSorted,
+          options.WildcardCensor.Pairs.Front().Head, 
+          options.EnableHeaders, 
+          options.TechMode,
+          options.PasswordEnabled, 
+          options.Password, numErrors);
+      if (numErrors > 0)
+      {
+        g_StdOut << endl << "Errors: " << numErrors;
+        return NExitCode::kFatalError;
+      }
+      if (result != S_OK)
+        throw CSystemException(result);
+    }
+  }
+  else if(options.Command.IsFromUpdateGroup())
+  {
+    UString workingDir;
+
+    CUpdateOptions &uo = options.UpdateOptions;
+    if (uo.SfxMode && uo.SfxModule.IsEmpty())
+      uo.SfxModule = kDefaultSfxModule;
+
+    bool passwordIsDefined = 
+        options.PasswordEnabled && !options.Password.IsEmpty();
+
+    COpenCallbackConsole openCallback;
+    openCallback.OutStream = &stdStream;
+    openCallback.PasswordIsDefined = passwordIsDefined;
+    openCallback.Password = options.Password;
+
+    CUpdateCallbackConsole callback;
+    callback.EnablePercents = options.EnablePercents;
+    callback.PasswordIsDefined = passwordIsDefined;
+    callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();
+    callback.Password = options.Password;
+    callback.StdOutMode = uo.StdOutMode;
+    callback.Init(&stdStream);
+
+    CUpdateErrorInfo errorInfo;
+
+    if (!uo.Init(codecs, options.ArchiveName, options.ArcType))
+      throw "Unsupported archive type";
+    HRESULT result = UpdateArchive(codecs, 
+        options.WildcardCensor, uo, 
+        errorInfo, &openCallback, &callback);
+
+    int exitCode = NExitCode::kSuccess;
+    if (callback.CantFindFiles.Size() > 0)
+    {
+      stdStream << endl;
+      stdStream << "WARNINGS for files:" << endl << endl;
+      int numErrors = callback.CantFindFiles.Size();
+      for (int i = 0; i < numErrors; i++)
+      {
+        stdStream << callback.CantFindFiles[i] << " : ";
+        stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl;
+      }
+      stdStream << "----------------" << endl;
+      stdStream << "WARNING: Cannot find " << numErrors << " file";
+      if (numErrors > 1)
+        stdStream << "s";
+      stdStream << endl;
+      exitCode = NExitCode::kWarning;
+    }
+
+    if (result != S_OK)
+    {
+      UString message;
+      if (!errorInfo.Message.IsEmpty())
+      {
+        message += errorInfo.Message;
+        message += L"\n";
+      }
+      if (!errorInfo.FileName.IsEmpty())
+      {
+        message += errorInfo.FileName;
+        message += L"\n";
+      }
+      if (!errorInfo.FileName2.IsEmpty())
+      {
+        message += errorInfo.FileName2;
+        message += L"\n";
+      }
+      if (errorInfo.SystemError != 0)
+      {
+        message += NError::MyFormatMessageW(errorInfo.SystemError);
+        message += L"\n";
+      }
+      if (!message.IsEmpty())
+        stdStream << L"\nError:\n" << message;
+      throw CSystemException(result);
+    }
+    int numErrors = callback.FailedFiles.Size();
+    if (numErrors == 0)
+    {
+      if (callback.CantFindFiles.Size() == 0)
+        stdStream << kEverythingIsOk << endl;
+    }
+    else
+    {
+      stdStream << endl;
+      stdStream << "WARNINGS for files:" << endl << endl;
+      for (int i = 0; i < numErrors; i++)
+      {
+        stdStream << callback.FailedFiles[i] << " : ";
+        stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl;
+      }
+      stdStream << "----------------" << endl;
+      stdStream << "WARNING: Cannot open " << numErrors << " file";
+      if (numErrors > 1)
+        stdStream << "s";
+      stdStream << endl;
+      exitCode = NExitCode::kWarning;
+    }
+    return exitCode;
+  }
+  else 
+    PrintHelpAndExit(stdStream);
+  return 0;
+}

Added: trunk/lzma/CPP/7zip/UI/Console/MainAr.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/MainAr.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/MainAr.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,161 @@
+// MainAr.cpp
+
+#include "StdAfx.h"
+
+// #include <locale.h>
+
+#include "Windows/Error.h"
+
+#include "Common/StdOutStream.h"
+#include "Common/NewHandler.h"
+#include "Common/MyException.h"
+#include "Common/StringConvert.h"
+
+#include "../Common/ExitCode.h"
+#include "../Common/ArchiveCommandLine.h"
+#include "ConsoleClose.h"
+
+using namespace NWindows;
+
+CStdOutStream *g_StdStream = 0;
+
+#ifdef _WIN32
+#ifndef _UNICODE
+bool g_IsNT = false;
+#endif
+#if !defined(_UNICODE) || !defined(_WIN64)
+static inline bool IsItWindowsNT()
+{
+  OSVERSIONINFO versionInfo;
+  versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+  if (!::GetVersionEx(&versionInfo)) 
+    return false;
+  return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+#endif
+#endif
+
+extern int Main2(
+  #ifndef _WIN32  
+  int numArguments, const char *arguments[]
+  #endif
+);
+
+static const char *kExceptionErrorMessage = "\n\nError:\n";
+static const char *kUserBreak  = "\nBreak signaled\n";
+
+static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n";
+static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n";
+static const char *kInternalExceptionMessage = "\n\nInternal Error #";
+
+int 
+#ifdef _MSC_VER
+__cdecl 
+#endif
+main
+(
+#ifndef _WIN32  
+int numArguments, const char *arguments[]
+#endif
+)
+{
+  g_StdStream = &g_StdOut;
+  #ifdef _WIN32
+  
+  #ifdef _UNICODE
+  #ifndef _WIN64
+  if (!IsItWindowsNT())
+  {
+    (*g_StdStream) << "This program requires Windows NT/2000/XP/2003/Vista";
+    return NExitCode::kFatalError;
+  }
+  #endif
+  #else
+  g_IsNT = IsItWindowsNT();
+  #endif
+  
+  #endif
+
+  // setlocale(LC_COLLATE, ".OCP");
+  NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
+  int res = 0;
+  try
+  {
+    res = Main2(
+#ifndef _WIN32
+      numArguments, arguments
+#endif
+    );
+  }
+  catch(const CNewException &)
+  {
+    (*g_StdStream) << kMemoryExceptionMessage;
+    return (NExitCode::kMemoryError);
+  }
+  catch(const NConsoleClose::CCtrlBreakException &)
+  {
+    (*g_StdStream) << endl << kUserBreak;
+    return (NExitCode::kUserBreak);
+  }
+  catch(const CArchiveCommandLineException &e)
+  {
+    (*g_StdStream) << kExceptionErrorMessage << e << endl;
+    return (NExitCode::kUserError);
+  }
+  catch(const CSystemException &systemError)
+  {
+    if (systemError.ErrorCode == E_OUTOFMEMORY)
+    {
+      (*g_StdStream) << kMemoryExceptionMessage;
+      return (NExitCode::kMemoryError);
+    }
+    if (systemError.ErrorCode == E_ABORT)
+    {
+      (*g_StdStream) << endl << kUserBreak;
+      return (NExitCode::kUserBreak);
+    }
+    UString message;
+    NError::MyFormatMessage(systemError.ErrorCode, message);
+    (*g_StdStream) << endl << endl << "System error:" << endl << 
+        message << endl;
+    return (NExitCode::kFatalError);
+  }
+  catch(NExitCode::EEnum &exitCode)
+  {
+    (*g_StdStream) << kInternalExceptionMessage << exitCode << endl;
+    return (exitCode);
+  }
+  /*
+  catch(const NExitCode::CMultipleErrors &multipleErrors)
+  {
+    (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl;
+    return (NExitCode::kFatalError);
+  }
+  */
+  catch(const UString &s)
+  {
+    (*g_StdStream) << kExceptionErrorMessage << s << endl;
+    return (NExitCode::kFatalError);
+  }
+  catch(const AString &s)
+  {
+    (*g_StdStream) << kExceptionErrorMessage << s << endl;
+    return (NExitCode::kFatalError);
+  }
+  catch(const char *s)
+  {
+    (*g_StdStream) << kExceptionErrorMessage << s << endl;
+    return (NExitCode::kFatalError);
+  }
+  catch(int t)
+  {
+    (*g_StdStream) << kInternalExceptionMessage << t << endl;
+    return (NExitCode::kFatalError);
+  }
+  catch(...)
+  {
+    (*g_StdStream) << kUnknownExceptionMessage;
+    return (NExitCode::kFatalError);
+  }
+  return  res;
+}

Added: trunk/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,58 @@
+// OpenCallbackConsole.cpp
+
+#include "StdAfx.h"
+
+#include "OpenCallbackConsole.h"
+
+#include "ConsoleClose.h"
+#include "UserInputUtils.h"
+
+HRESULT COpenCallbackConsole::CheckBreak()
+{
+  if (NConsoleClose::TestBreakSignal())
+    return E_ABORT;
+  return S_OK;
+}
+
+HRESULT COpenCallbackConsole::SetTotal(const UInt64 *, const UInt64 *)
+{
+  return CheckBreak();
+}
+
+HRESULT COpenCallbackConsole::SetCompleted(const UInt64 *, const UInt64 *)
+{
+  return CheckBreak();
+}
+ 
+HRESULT COpenCallbackConsole::CryptoGetTextPassword(BSTR *password)
+{
+  PasswordWasAsked = true;
+  RINOK(CheckBreak());
+  if (!PasswordIsDefined)
+  {
+    Password = GetPassword(OutStream); 
+    PasswordIsDefined = true;
+  }
+  CMyComBSTR temp(Password);
+  *password = temp.Detach();
+  return S_OK;
+}
+
+HRESULT COpenCallbackConsole::GetPasswordIfAny(UString &password)
+{
+  if (PasswordIsDefined)
+    password = Password;
+  return S_OK;
+}
+
+bool COpenCallbackConsole::WasPasswordAsked()
+{
+  return PasswordWasAsked;
+}
+
+void COpenCallbackConsole::ClearPasswordWasAskedFlag()
+{
+  PasswordWasAsked = false;
+}
+
+  

Added: trunk/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/OpenCallbackConsole.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,27 @@
+// OpenCallbackConsole.h
+
+#ifndef __OPENCALLBACKCONSOLE_H
+#define __OPENCALLBACKCONSOLE_H
+
+#include "Common/StdOutStream.h"
+#include "../Common/ArchiveOpenCallback.h"
+
+class COpenCallbackConsole: public IOpenCallbackUI
+{
+public:
+  HRESULT CheckBreak();
+  HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes);
+  HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes);
+  HRESULT CryptoGetTextPassword(BSTR *password);
+  HRESULT GetPasswordIfAny(UString &password);
+  bool WasPasswordAsked();
+  void ClearPasswordWasAskedFlag();
+  
+  CStdOutStream *OutStream;
+  bool PasswordIsDefined;
+  UString Password;
+  bool PasswordWasAsked;
+  COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {}
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Console/PercentPrinter.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/PercentPrinter.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/PercentPrinter.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,90 @@
+// PercentPrinter.cpp
+
+#include "StdAfx.h"
+
+#include "Common/IntToString.h"
+#include "Common/MyString.h"
+
+#include "PercentPrinter.h"
+
+const int kPaddingSize = 2;
+const int kPercentsSize = 4;
+const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;
+
+static void ClearPrev(char *p, int num)
+{
+  int i;
+  for (i = 0; i < num; i++) *p++ = '\b';
+  for (i = 0; i < num; i++) *p++ = ' ';
+  for (i = 0; i < num; i++) *p++ = '\b';
+  *p = '\0';
+}
+
+void CPercentPrinter::ClosePrint()
+{
+  if (m_NumExtraChars == 0)
+    return;
+  char s[kMaxExtraSize * 3 + 1];
+  ClearPrev(s, m_NumExtraChars);
+  (*OutStream) << s;
+  m_NumExtraChars = 0;
+}
+
+void CPercentPrinter::PrintString(const char *s)
+{
+  ClosePrint();
+  (*OutStream) << s;
+}
+
+void CPercentPrinter::PrintString(const wchar_t *s)
+{
+  ClosePrint();
+  (*OutStream) << s;
+}
+
+void CPercentPrinter::PrintNewLine()
+{
+  ClosePrint();
+  (*OutStream) << "\n";
+}
+
+void CPercentPrinter::RePrintRatio()
+{
+  char s[32];
+  ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s);
+  int size = (int)strlen(s);
+  s[size++] = '%';
+  s[size] = '\0';
+
+  int extraSize = kPaddingSize + MyMax(size, kPercentsSize);
+  if (extraSize < m_NumExtraChars)
+    extraSize = m_NumExtraChars;
+
+  char fullString[kMaxExtraSize * 3];
+  char *p = fullString;
+  int i;
+  if (m_NumExtraChars == 0)
+  {
+    for (i = 0; i < extraSize; i++) 
+      *p++ = ' ';
+    m_NumExtraChars = extraSize;
+  }
+
+  for (i = 0; i < m_NumExtraChars; i++) 
+    *p++ = '\b';
+  m_NumExtraChars = extraSize;
+  for (; size < m_NumExtraChars; size++)
+    *p++ = ' ';
+  MyStringCopy(p, s);
+  (*OutStream) << fullString;
+  OutStream->Flush(); 
+  m_PrevValue = m_CurValue;
+}
+
+void CPercentPrinter::PrintRatio()
+{
+  if (m_CurValue < m_PrevValue + m_MinStepSize && 
+      m_CurValue + m_MinStepSize > m_PrevValue && m_NumExtraChars != 0)
+    return;
+  RePrintRatio();
+}

Added: trunk/lzma/CPP/7zip/UI/Console/PercentPrinter.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/PercentPrinter.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/PercentPrinter.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,31 @@
+// PercentPrinter.h
+
+#ifndef __PERCENTPRINTER_H
+#define __PERCENTPRINTER_H
+
+#include "Common/Types.h"
+#include "Common/StdOutStream.h"
+
+class CPercentPrinter
+{
+  UInt64 m_MinStepSize;
+  UInt64 m_PrevValue;
+  UInt64 m_CurValue;
+  UInt64 m_Total;
+  int m_NumExtraChars;
+public:
+  CStdOutStream *OutStream;
+
+  CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize), 
+      m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {}
+  void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; }
+  void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; }
+  void PrintString(const char *s);
+  void PrintString(const wchar_t *s);
+  void PrintNewLine();
+  void ClosePrint();
+  void RePrintRatio();
+  void PrintRatio();
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Console/StdAfx.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/StdAfx.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/StdAfx.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"

Added: trunk/lzma/CPP/7zip/UI/Console/StdAfx.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif 

Added: trunk/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,208 @@
+// UpdateCallbackConsole.cpp
+
+#include "StdAfx.h"
+
+#include "UpdateCallbackConsole.h"
+
+#include "Windows/Error.h"
+#ifdef COMPRESS_MT
+#include "Windows/Synchronization.h"
+#endif
+
+#include "ConsoleClose.h"
+#include "UserInputUtils.h"
+
+using namespace NWindows;
+
+#ifdef COMPRESS_MT
+static NSynchronization::CCriticalSection g_CriticalSection;
+#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+#else
+#define MT_LOCK
+#endif
+
+static const wchar_t *kEmptyFileAlias = L"[Content]";
+
+static const char *kCreatingArchiveMessage = "Creating archive ";
+static const char *kUpdatingArchiveMessage = "Updating archive ";
+static const char *kScanningMessage = "Scanning";
+
+
+HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result)
+{
+  (*OutStream) << endl;
+  if (result != S_OK)
+    (*OutStream) << "Error: " << name << " is not supported archive" << endl;
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::StartScanning()
+{
+  (*OutStream) << kScanningMessage;
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)
+{
+  CantFindFiles.Add(name);
+  CantFindCodes.Add(systemError);
+  // m_PercentPrinter.ClosePrint();
+  if (!m_WarningsMode)
+  {
+    (*OutStream) << endl << endl;
+    m_PercentPrinter.PrintNewLine();
+    m_WarningsMode = true;
+  }
+  m_PercentPrinter.PrintString(name);
+  m_PercentPrinter.PrintString(":  WARNING: ");
+  m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));
+  m_PercentPrinter.PrintNewLine();
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::FinishScanning()
+{
+  (*OutStream) << endl << endl;
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
+{
+  if(updating)
+    (*OutStream) << kUpdatingArchiveMessage;
+  else
+    (*OutStream) << kCreatingArchiveMessage; 
+  if (name != 0)
+    (*OutStream) << name;
+  else
+    (*OutStream) << "StdOut";
+  (*OutStream) << endl << endl;
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::FinishArchive()
+{
+  (*OutStream) << endl;
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::CheckBreak()
+{
+  if (NConsoleClose::TestBreakSignal())
+    return E_ABORT;
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::Finilize()
+{
+  MT_LOCK
+  if (m_NeedBeClosed)
+  {
+    if (EnablePercents)
+    {
+      m_PercentPrinter.ClosePrint();
+    }
+    if (!StdOutMode && m_NeedNewLine)
+    {
+      m_PercentPrinter.PrintNewLine();
+      m_NeedNewLine = false;
+    }
+    m_NeedBeClosed = false;
+  }
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */)
+{
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
+{
+  MT_LOCK
+  if (EnablePercents)
+    m_PercentPrinter.SetTotal(size);
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
+{
+  MT_LOCK
+  if (completeValue != NULL)
+  {
+    if (EnablePercents)
+    {
+      m_PercentPrinter.SetRatio(*completeValue);
+      m_PercentPrinter.PrintRatio();
+      m_NeedBeClosed = true;
+    }
+  }
+  if (NConsoleClose::TestBreakSignal())
+    return E_ABORT;
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
+{
+  /*
+  if (NConsoleClose::TestBreakSignal())
+    return E_ABORT;
+  */
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti)
+{
+  MT_LOCK
+  if (StdOutMode)
+    return S_OK;
+  if(isAnti)
+    m_PercentPrinter.PrintString("Anti item    ");
+  else
+    m_PercentPrinter.PrintString("Compressing  ");
+  if (name[0] == 0)
+    name = kEmptyFileAlias;
+  m_PercentPrinter.PrintString(name);
+  if (EnablePercents)
+    m_PercentPrinter.RePrintRatio();
+  return S_OK;
+}
+
+HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)
+{
+  MT_LOCK
+  FailedCodes.Add(systemError);
+  FailedFiles.Add(name);
+  // if (systemError == ERROR_SHARING_VIOLATION)
+  {
+    m_PercentPrinter.ClosePrint();
+    m_PercentPrinter.PrintNewLine();
+    m_PercentPrinter.PrintString("WARNING: ");
+    m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));
+    return S_FALSE;
+  }
+  // return systemError;
+}
+
+HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 )
+{
+  m_NeedBeClosed = true;
+  m_NeedNewLine = true;
+  return S_OK;  
+}
+
+HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
+{
+  if (!PasswordIsDefined) 
+  {
+    if (AskPassword)
+    {
+      Password = GetPassword(OutStream); 
+      PasswordIsDefined = true;
+    }
+  }
+  *passwordIsDefined = BoolToInt(PasswordIsDefined);
+  CMyComBSTR tempName(Password);
+  *password = tempName.Detach();
+  return S_OK;
+}

Added: trunk/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/UpdateCallbackConsole.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,58 @@
+// UpdateCallbackConsole.h
+
+#ifndef __UPDATECALLBACKCONSOLE_H
+#define __UPDATECALLBACKCONSOLE_H
+
+#include "Common/MyString.h"
+#include "Common/StdOutStream.h"
+#include "PercentPrinter.h"
+#include "../Common/Update.h"
+
+class CUpdateCallbackConsole: public IUpdateCallbackUI2
+{
+  CPercentPrinter m_PercentPrinter;
+  bool m_NeedBeClosed;
+  bool m_NeedNewLine;
+
+  bool m_WarningsMode;
+
+  CStdOutStream *OutStream;
+public:
+  bool EnablePercents;
+  bool StdOutMode;
+
+  bool PasswordIsDefined;
+  UString Password;
+  bool AskPassword;
+
+
+  CUpdateCallbackConsole(): 
+      m_PercentPrinter(1 << 16),
+      PasswordIsDefined(false),
+      AskPassword(false),
+      StdOutMode(false),
+      EnablePercents(true),
+      m_WarningsMode(false)
+      {}
+  
+  ~CUpdateCallbackConsole() { Finilize(); }
+  void Init(CStdOutStream *outStream)
+  {
+    m_NeedBeClosed = false;
+    m_NeedNewLine = false;
+    FailedFiles.Clear();
+    FailedCodes.Clear();
+    OutStream = outStream;
+    m_PercentPrinter.OutStream = outStream;
+  }
+
+  INTERFACE_IUpdateCallbackUI2(;)
+
+  UStringVector FailedFiles;
+  CRecordVector<HRESULT> FailedCodes;
+
+  UStringVector CantFindFiles;
+  CRecordVector<HRESULT> CantFindCodes;
+};
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Console/UserInputUtils.cpp
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/UserInputUtils.cpp	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/UserInputUtils.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,58 @@
+// UserInputUtils.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StdInStream.h"
+#include "Common/StringConvert.h"
+
+#include "UserInputUtils.h"
+
+static const char kYes = 'Y';
+static const char kNo = 'N';
+static const char kYesAll = 'A';
+static const char kNoAll = 'S';
+static const char kAutoRename = 'U';
+static const char kQuit = 'Q';
+
+static const char *kFirstQuestionMessage = "?\n";
+static const char *kHelpQuestionMessage = 
+  "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename / (Q)uit? ";
+
+// return true if pressed Quite;
+// in: anAll
+// out: anAll, anYes;
+
+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
+{
+  (*outStream) << kFirstQuestionMessage;
+  for(;;)
+  {
+    (*outStream) << kHelpQuestionMessage;
+    AString scannedString = g_StdIn.ScanStringUntilNewLine();
+    scannedString.Trim();
+    if(!scannedString.IsEmpty())
+      switch(::MyCharUpper(scannedString[0]))
+      {
+        case kYes:
+          return NUserAnswerMode::kYes;
+        case kNo:
+          return NUserAnswerMode::kNo;
+        case kYesAll:
+          return NUserAnswerMode::kYesAll;
+        case kNoAll:
+          return NUserAnswerMode::kNoAll;
+        case kAutoRename:
+          return NUserAnswerMode::kAutoRename;
+        case kQuit:
+          return NUserAnswerMode::kQuit;
+      }
+  }
+}
+
+UString GetPassword(CStdOutStream *outStream)
+{
+  (*outStream) << "\nEnter password:";
+  outStream->Flush();
+  AString oemPassword = g_StdIn.ScanStringUntilNewLine();
+  return MultiByteToUnicodeString(oemPassword, CP_OEMCP); 
+}

Added: trunk/lzma/CPP/7zip/UI/Console/UserInputUtils.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/UserInputUtils.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/UserInputUtils.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// UserInputUtils.h
+
+#ifndef __USERINPUTUTILS_H
+#define __USERINPUTUTILS_H
+
+#include "Common/StdOutStream.h"
+
+namespace NUserAnswerMode {
+
+enum EEnum
+{
+  kYes,
+  kNo,
+  kYesAll,
+  kNoAll,
+  kAutoRename,
+  kQuit
+};
+}
+
+NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);
+UString GetPassword(CStdOutStream *outStream);
+
+#endif

Added: trunk/lzma/CPP/7zip/UI/Console/afxres.h
===================================================================
--- trunk/lzma/CPP/7zip/UI/Console/afxres.h	                        (rev 0)
+++ trunk/lzma/CPP/7zip/UI/Console/afxres.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1 @@
+#include <winresrc.h>

Added: trunk/lzma/CPP/Build.mak
===================================================================
--- trunk/lzma/CPP/Build.mak	                        (rev 0)
+++ trunk/lzma/CPP/Build.mak	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,68 @@
+!IFDEF CPU
+LIBS = $(LIBS) bufferoverflowU.lib 
+CFLAGS = $(CFLAGS) -GS- -Zc:forScope
+!ENDIF
+
+!IFNDEF O
+!IFDEF CPU
+O=$(CPU)
+!ELSE
+O=O
+!ENDIF
+!ENDIF
+
+!IF "$(CPU)" != "IA64"
+!IF "$(CPU)" != "AMD64"
+MY_ML = ml
+!ELSE
+MY_ML = ml64
+!ENDIF
+!ENDIF
+
+COMPL_ASM = $(MY_ML) -c -Fo$O/ $**
+
+CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -EHsc -Gz -WX -Gy
+
+!IFDEF MY_STATIC_LINK
+!IFNDEF MY_SINGLE_THREAD
+CFLAGS = $(CFLAGS) -MT
+!ENDIF
+!ELSE
+CFLAGS = $(CFLAGS) -MD
+!ENDIF
+
+!IFDEF NEW_COMPILER
+CFLAGS_O1 = $(CFLAGS) -O1 -W4 -Wp64
+CFLAGS_O2 = $(CFLAGS) -O2 -W4 -Wp64
+!ELSE
+CFLAGS_O1 = $(CFLAGS) -O1 -W3
+CFLAGS_O2 = $(CFLAGS) -O2 -W3
+!ENDIF
+
+LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF 
+
+!IFDEF DEF_FILE
+LFLAGS = $(LFLAGS) -DLL -DEF:$(DEF_FILE)
+!ENDIF
+
+PROGPATH = $O\$(PROG)
+
+COMPL_O1   = $(CPP) $(CFLAGS_O1) $**
+COMPL_O2   = $(CPP) $(CFLAGS_O2) $**
+COMPL_PCH  = $(CPP) $(CFLAGS_O1) -Yc"StdAfx.h" -Fp$O/a.pch $** 
+COMPL      = $(CPP) $(CFLAGS_O1) -Yu"StdAfx.h" -Fp$O/a.pch $**
+
+all: $(PROGPATH) 
+
+clean:
+	-del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch 
+
+$O:
+	if not exist "$O" mkdir "$O"
+
+$(PROGPATH): $O $(OBJS) $(DEF_FILE)
+	link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
+$O\resource.res: $(*B).rc
+	rc -fo$@ $**
+$O\StdAfx.obj: $(*B).cpp
+	$(COMPL_PCH)

Added: trunk/lzma/CPP/Common/AutoPtr.h
===================================================================
--- trunk/lzma/CPP/Common/AutoPtr.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/AutoPtr.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,35 @@
+// Common/AutoPtr.h
+
+#ifndef __COMMON_AUTOPTR_H
+#define __COMMON_AUTOPTR_H
+
+template<class T> class CMyAutoPtr
+{
+  T *_p;
+public:
+  CMyAutoPtr(T *p = 0) : _p(p) {}
+  CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {}
+  CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p) 
+  {
+    reset(p.release());
+    return (*this);
+  }
+  ~CMyAutoPtr() { delete _p; }
+  T& operator*() const { return *_p; }
+  // T* operator->() const { return (&**this); }
+  T* get() const { return _p; }
+  T* release()
+  {
+    T *tmp = _p;
+    _p = 0;
+    return tmp;
+  }
+  void reset(T* p = 0)
+  {
+    if (p != _p)
+      delete _p;
+    _p = p;
+  }
+};
+
+#endif

Added: trunk/lzma/CPP/Common/Buffer.h
===================================================================
--- trunk/lzma/CPP/Common/Buffer.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/Buffer.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,77 @@
+// Common/Buffer.h
+
+#ifndef __COMMON_BUFFER_H
+#define __COMMON_BUFFER_H
+
+#include "Defs.h"
+
+template <class T> class CBuffer
+{    
+protected:
+  size_t _capacity;
+  T *_items;
+public:
+  void Free()
+  {
+    delete []_items;
+    _items = 0;
+    _capacity = 0;
+  }
+  CBuffer(): _capacity(0), _items(0) {};
+  CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; }
+  CBuffer(size_t size): _items(0),  _capacity(0) {  SetCapacity(size); }
+  virtual ~CBuffer() { delete []_items; }
+  operator T *() { return _items; };
+  operator const T *() const { return _items; };
+  size_t GetCapacity() const { return  _capacity; }
+  void SetCapacity(size_t newCapacity)
+  {
+    if (newCapacity == _capacity)
+      return;
+    T *newBuffer;
+    if (newCapacity > 0)
+    {
+      newBuffer = new T[newCapacity];
+      if(_capacity > 0)
+        memmove(newBuffer, _items, MyMin(_capacity, newCapacity) * sizeof(T));
+    }
+    else
+      newBuffer = 0;
+    delete []_items;
+    _items = newBuffer;
+    _capacity = newCapacity;
+  }
+  CBuffer& operator=(const CBuffer &buffer)
+  {
+    Free();
+    if(buffer._capacity > 0)
+    {
+      SetCapacity(buffer._capacity);
+      memmove(_items, buffer._items, buffer._capacity * sizeof(T));
+    }
+    return *this;
+  }
+};
+
+template <class T>
+bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)
+{
+  if (b1.GetCapacity() != b2.GetCapacity())
+    return false;
+  for (size_t i = 0; i < b1.GetCapacity(); i++)
+    if (b1[i] != b2[i])
+      return false;
+  return true;
+}
+
+template <class T>
+bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
+{
+  return !(b1 == b2);
+}
+
+typedef CBuffer<char> CCharBuffer;
+typedef CBuffer<wchar_t> CWCharBuffer;
+typedef CBuffer<unsigned char> CByteBuffer;
+
+#endif

Added: trunk/lzma/CPP/Common/CRC.cpp
===================================================================
--- trunk/lzma/CPP/Common/CRC.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/CRC.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,14 @@
+// Common/CRC.cpp
+
+#include "StdAfx.h"
+
+extern "C" 
+{ 
+#include "../../C/7zCrc.h"
+}
+
+class CCRCTableInit
+{
+public:
+  CCRCTableInit() { CrcGenerateTable(); }
+} g_CRCTableInit;

Added: trunk/lzma/CPP/Common/C_FileIO.cpp
===================================================================
--- trunk/lzma/CPP/Common/C_FileIO.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/C_FileIO.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,88 @@
+// Common/C_FileIO.h
+
+#include "C_FileIO.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+namespace NC {
+namespace NFile {
+namespace NIO {
+
+bool CFileBase::OpenBinary(const char *name, int flags)
+{
+  #ifdef O_BINARY
+  flags |= O_BINARY;
+  #endif
+  Close();
+  _handle = ::open(name, flags, 0666);
+  return _handle != -1;
+}
+
+bool CFileBase::Close()
+{
+  if(_handle == -1)
+    return true;
+  if (close(_handle) != 0)
+    return false;
+  _handle = -1;
+  return true;
+}
+
+bool CFileBase::GetLength(UInt64 &length) const
+{
+  off_t curPos = Seek(0, SEEK_CUR);
+  off_t lengthTemp = Seek(0, SEEK_END);
+  Seek(curPos, SEEK_SET);
+  length = (UInt64)lengthTemp;
+  return true;
+}
+
+off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const
+{
+  return ::lseek(_handle, distanceToMove, moveMethod);
+}
+
+/////////////////////////
+// CInFile
+
+bool CInFile::Open(const char *name)
+{
+  return CFileBase::OpenBinary(name, O_RDONLY);
+}
+
+bool CInFile::OpenShared(const char *name, bool)
+{
+  return Open(name);
+}
+
+ssize_t CInFile::Read(void *data, size_t size)
+{
+  return read(_handle, data, size);
+}
+
+/////////////////////////
+// COutFile
+
+bool COutFile::Create(const char *name, bool createAlways)
+{
+  if (createAlways)
+  {
+    Close();
+    _handle = ::creat(name, 0666);
+    return _handle != -1;
+  }
+  return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY);
+}
+
+bool COutFile::Open(const char *name, DWORD creationDisposition)
+{
+  return Create(name, false);
+}
+
+ssize_t COutFile::Write(const void *data, size_t size)
+{
+  return write(_handle, data, size);
+}
+
+}}}

Added: trunk/lzma/CPP/Common/C_FileIO.h
===================================================================
--- trunk/lzma/CPP/Common/C_FileIO.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/C_FileIO.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,47 @@
+// Common/C_FileIO.h
+
+#ifndef __COMMON_C_FILEIO_H
+#define __COMMON_C_FILEIO_H
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "Types.h"
+#include "MyWindows.h"
+
+namespace NC {
+namespace NFile {
+namespace NIO {
+
+class CFileBase
+{
+protected:
+  int _handle;
+  bool OpenBinary(const char *name, int flags);
+public:
+  CFileBase(): _handle(-1) {};
+  ~CFileBase() { Close(); }
+  bool Close();
+  bool GetLength(UInt64 &length) const;
+  off_t Seek(off_t distanceToMove, int moveMethod) const;
+};
+
+class CInFile: public CFileBase
+{
+public:
+  bool Open(const char *name);
+  bool OpenShared(const char *name, bool shareForWrite);
+  ssize_t Read(void *data, size_t size);
+};
+
+class COutFile: public CFileBase
+{
+public:
+  bool Create(const char *name, bool createAlways);
+  bool Open(const char *name, DWORD creationDisposition);
+  ssize_t Write(const void *data, size_t size);
+};
+
+}}}
+
+#endif

Added: trunk/lzma/CPP/Common/ComTry.h
===================================================================
--- trunk/lzma/CPP/Common/ComTry.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/ComTry.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,17 @@
+// ComTry.h
+
+#ifndef __COM_TRY_H
+#define __COM_TRY_H
+
+#include "MyWindows.h"
+// #include "Exception.h"
+// #include "NewHandler.h"
+
+#define COM_TRY_BEGIN try {
+#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; }
+  
+  // catch(const CNewException &) { return E_OUTOFMEMORY; }\
+  // catch(const CSystemException &e) { return e.ErrorCode; }\
+  // catch(...) { return E_FAIL; }
+
+#endif

Added: trunk/lzma/CPP/Common/CommandLineParser.cpp
===================================================================
--- trunk/lzma/CPP/Common/CommandLineParser.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/CommandLineParser.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,232 @@
+// CommandLineParser.cpp
+
+#include "StdAfx.h"
+
+#include "CommandLineParser.h"
+
+namespace NCommandLineParser {
+
+void SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
+{
+  dest1.Empty();
+  dest2.Empty();
+  bool quoteMode = false;
+  int i;
+  for (i = 0; i < src.Length(); i++)
+  {
+    wchar_t c = src[i];
+    if (c == L'\"')
+      quoteMode = !quoteMode;
+    else if (c == L' ' && !quoteMode)
+    {
+      i++;
+      break;
+    }
+    else 
+      dest1 += c;
+  }
+  dest2 = src.Mid(i);
+}
+
+void SplitCommandLine(const UString &s, UStringVector &parts)
+{
+  UString sTemp = s;
+  sTemp.Trim();
+  parts.Clear();
+  for (;;)
+  {
+    UString s1, s2;
+    SplitCommandLine(sTemp, s1, s2);
+    // s1.Trim();
+    // s2.Trim();
+    if (!s1.IsEmpty())
+      parts.Add(s1);
+    if (s2.IsEmpty())
+      break;
+    sTemp = s2;
+  }
+}
+
+
+static const wchar_t kSwitchID1 = '-';
+// static const wchar_t kSwitchID2 = '/';
+
+static const wchar_t kSwitchMinus = '-';
+static const wchar_t *kStopSwitchParsing = L"--";
+
+static bool IsItSwitchChar(wchar_t c)
+{ 
+  return (c == kSwitchID1 /*|| c == kSwitchID2 */); 
+}
+
+CParser::CParser(int numSwitches):
+  _numSwitches(numSwitches)
+{
+  _switches = new CSwitchResult[_numSwitches];
+}
+
+CParser::~CParser()
+{
+  delete []_switches;
+}
+
+void CParser::ParseStrings(const CSwitchForm *switchForms, 
+  const UStringVector &commandStrings)
+{
+  int numCommandStrings = commandStrings.Size();
+  bool stopSwitch = false;
+  for (int i = 0; i < numCommandStrings; i++)
+  {
+    const UString &s = commandStrings[i];
+    if (stopSwitch)
+      NonSwitchStrings.Add(s);
+    else
+      if (s == kStopSwitchParsing)
+        stopSwitch = true;
+      else
+        if (!ParseString(s, switchForms))
+          NonSwitchStrings.Add(s);
+  }
+}
+
+// if string contains switch then function updates switch structures
+// out: (string is a switch)
+bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
+{
+  int len = s.Length();
+  if (len == 0) 
+    return false;
+  int pos = 0;
+  if (!IsItSwitchChar(s[pos]))
+    return false;
+  while(pos < len)
+  {
+    if (IsItSwitchChar(s[pos]))
+      pos++;
+    const int kNoLen = -1;
+    int matchedSwitchIndex = 0; // GCC Warning
+    int maxLen = kNoLen;
+    for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++)
+    {
+      int switchLen = MyStringLen(switchForms[switchIndex].IDString);
+      if (switchLen <= maxLen || pos + switchLen > len) 
+        continue;
+
+      UString temp = s + pos;
+      temp = temp.Left(switchLen);
+      if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0)
+      // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0)
+      {
+        matchedSwitchIndex = switchIndex;
+        maxLen = switchLen;
+      }
+    }
+    if (maxLen == kNoLen)
+      throw "maxLen == kNoLen";
+    CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex];
+    const CSwitchForm &switchForm = switchForms[matchedSwitchIndex];
+    if ((!switchForm.Multi) && matchedSwitch.ThereIs)
+      throw "switch must be single";
+    matchedSwitch.ThereIs = true;
+    pos += maxLen;
+    int tailSize = len - pos;
+    NSwitchType::EEnum type = switchForm.Type;
+    switch(type)
+    {
+      case NSwitchType::kPostMinus:
+        {
+          if (tailSize == 0)
+            matchedSwitch.WithMinus = false;
+          else
+          {
+            matchedSwitch.WithMinus = (s[pos] == kSwitchMinus);
+            if (matchedSwitch.WithMinus)
+              pos++;
+          }
+          break;
+        }
+      case NSwitchType::kPostChar:
+        {
+          if (tailSize < switchForm.MinLen)
+            throw "switch is not full";
+          UString set = switchForm.PostCharSet;
+          const int kEmptyCharValue = -1;
+          if (tailSize == 0)
+            matchedSwitch.PostCharIndex = kEmptyCharValue;
+          else
+          {
+            int index = set.Find(s[pos]);
+            if (index < 0)
+              matchedSwitch.PostCharIndex =  kEmptyCharValue;
+            else
+            {
+              matchedSwitch.PostCharIndex = index;
+              pos++;
+            }
+          }
+          break;
+        }
+      case NSwitchType::kLimitedPostString: 
+      case NSwitchType::kUnLimitedPostString: 
+        {
+          int minLen = switchForm.MinLen;
+          if (tailSize < minLen)
+            throw "switch is not full";
+          if (type == NSwitchType::kUnLimitedPostString)
+          {
+            matchedSwitch.PostStrings.Add(s.Mid(pos));
+            return true;
+          }
+          int maxLen = switchForm.MaxLen;
+          UString stringSwitch = s.Mid(pos, minLen);
+          pos += minLen;
+          for(int i = minLen; i < maxLen && pos < len; i++, pos++)
+          {
+            wchar_t c = s[pos];
+            if (IsItSwitchChar(c))
+              break;
+            stringSwitch += c;
+          }
+          matchedSwitch.PostStrings.Add(stringSwitch);
+          break;
+        }
+      case NSwitchType::kSimple:
+          break;
+    }
+  }
+  return true;
+}
+
+const CSwitchResult& CParser::operator[](size_t index) const
+{
+  return _switches[index];
+}
+
+/////////////////////////////////
+// Command parsing procedures
+
+int ParseCommand(int numCommandForms, const CCommandForm *commandForms, 
+    const UString &commandString, UString &postString)
+{
+  for(int i = 0; i < numCommandForms; i++)
+  {
+    const UString id = commandForms[i].IDString;
+    if (commandForms[i].PostStringMode)
+    {
+      if(commandString.Find(id) == 0)
+      {
+        postString = commandString.Mid(id.Length());
+        return i;
+      }
+    }
+    else
+      if (commandString == id)
+      {
+        postString.Empty();
+        return i;
+      }
+  }
+  return -1;
+}
+   
+}

Added: trunk/lzma/CPP/Common/CommandLineParser.h
===================================================================
--- trunk/lzma/CPP/Common/CommandLineParser.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/CommandLineParser.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,72 @@
+// Common/CommandLineParser.h
+
+#ifndef __COMMON_COMMANDLINEPARSER_H
+#define __COMMON_COMMANDLINEPARSER_H
+
+#include "MyString.h"
+
+namespace NCommandLineParser {
+
+void SplitCommandLine(const UString &src, UString &dest1, UString &dest2);
+void SplitCommandLine(const UString &s, UStringVector &parts);
+
+namespace NSwitchType {
+  enum EEnum
+  { 
+    kSimple,
+    kPostMinus,
+    kLimitedPostString,
+    kUnLimitedPostString,
+    kPostChar
+  };
+}
+
+struct CSwitchForm
+{
+  const wchar_t *IDString;
+  NSwitchType::EEnum Type;
+  bool Multi;
+  int MinLen;
+  int MaxLen;
+  const wchar_t *PostCharSet;
+};
+
+struct CSwitchResult
+{
+  bool ThereIs;
+  bool WithMinus;
+  UStringVector PostStrings;
+  int PostCharIndex;
+  CSwitchResult(): ThereIs(false) {};
+};
+  
+class CParser
+{
+  int _numSwitches;
+  CSwitchResult *_switches;
+  bool ParseString(const UString &s, const CSwitchForm *switchForms); 
+public:
+  UStringVector NonSwitchStrings;
+  CParser(int numSwitches);
+  ~CParser();
+  void ParseStrings(const CSwitchForm *switchForms, 
+    const UStringVector &commandStrings);
+  const CSwitchResult& operator[](size_t index) const;
+};
+
+/////////////////////////////////
+// Command parsing procedures
+
+struct CCommandForm
+{
+  wchar_t *IDString;
+  bool PostStringMode;
+};
+
+// Returns: Index of form and postString; -1, if there is no match
+int ParseCommand(int numCommandForms, const CCommandForm *commandForms, 
+    const UString &commandString, UString &postString);
+
+}
+
+#endif

Added: trunk/lzma/CPP/Common/Defs.h
===================================================================
--- trunk/lzma/CPP/Common/Defs.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/Defs.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,20 @@
+// Common/Defs.h
+
+#ifndef __COMMON_DEFS_H
+#define __COMMON_DEFS_H
+
+template <class T> inline T MyMin(T a, T b)
+  {  return a < b ? a : b; }
+template <class T> inline T MyMax(T a, T b)
+  {  return a > b ? a : b; }
+
+template <class T> inline int MyCompare(T a, T b)
+  {  return a < b ? -1 : (a == b ? 0 : 1); }
+
+inline int BoolToInt(bool value)
+  { return (value ? 1: 0); }
+
+inline bool IntToBool(int value)
+  { return (value != 0); }
+
+#endif

Added: trunk/lzma/CPP/Common/DynamicBuffer.h
===================================================================
--- trunk/lzma/CPP/Common/DynamicBuffer.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/DynamicBuffer.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,47 @@
+// Common/DynamicBuffer.h
+
+#ifndef __COMMON_DYNAMICBUFFER_H
+#define __COMMON_DYNAMICBUFFER_H
+
+#include "Buffer.h"
+
+template <class T> class CDynamicBuffer: public CBuffer<T>
+{    
+  void GrowLength(size_t size)
+  {
+    size_t delta;
+    if (this->_capacity > 64)
+      delta = this->_capacity / 4;
+    else if (this->_capacity > 8)
+      delta = 16;
+    else
+      delta = 4;
+    delta = MyMax(delta, size);
+    SetCapacity(this->_capacity + delta);
+  }
+public:
+  CDynamicBuffer(): CBuffer<T>() {};
+  CDynamicBuffer(const CDynamicBuffer &buffer): CBuffer<T>(buffer) {};
+  CDynamicBuffer(size_t size): CBuffer<T>(size) {};
+  CDynamicBuffer& operator=(const CDynamicBuffer &buffer)
+  {
+    this->Free();
+    if(buffer._capacity > 0)
+    {
+      SetCapacity(buffer._capacity);
+      memmove(this->_items, buffer._items, buffer._capacity * sizeof(T));
+    }
+    return *this;
+  }
+  void EnsureCapacity(size_t capacity)
+  {
+    if (this->_capacity < capacity)
+      GrowLength(capacity - this->_capacity);
+  }
+};
+
+typedef CDynamicBuffer<char> CCharDynamicBuffer;
+typedef CDynamicBuffer<wchar_t> CWCharDynamicBuffer;
+typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer;
+
+#endif

Added: trunk/lzma/CPP/Common/IntToString.cpp
===================================================================
--- trunk/lzma/CPP/Common/IntToString.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/IntToString.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,63 @@
+// Common/IntToString.cpp
+
+#include "StdAfx.h"
+
+#include "IntToString.h"
+
+void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base)
+{
+  if (base < 2 || base > 36)
+  {
+    *s = '\0';
+    return;
+  }
+  char temp[72];
+  int pos = 0;
+  do 
+  {
+    int delta = (int)(value % base);
+    temp[pos++] = (char)((delta < 10) ? ('0' + delta) : ('a' + (delta - 10)));
+    value /= base;
+  }
+  while (value != 0);
+  do
+    *s++ = temp[--pos];
+  while(pos > 0);
+  *s = '\0';
+}
+
+void ConvertUInt64ToString(UInt64 value, wchar_t *s)
+{
+  wchar_t temp[32];
+  int pos = 0;
+  do 
+  {
+    temp[pos++] = (wchar_t)(L'0' + (int)(value % 10));
+    value /= 10;
+  }
+  while (value != 0);
+  do 
+    *s++ = temp[--pos];
+  while(pos > 0);
+  *s = L'\0';
+}
+
+void ConvertInt64ToString(Int64 value, char *s)
+{
+  if (value < 0)
+  {
+    *s++ = '-';
+    value = -value;
+  }
+  ConvertUInt64ToString(value, s);
+}
+
+void ConvertInt64ToString(Int64 value, wchar_t *s)
+{
+  if (value < 0)
+  {
+    *s++ = L'-';
+    value = -value;
+  }
+  ConvertUInt64ToString(value, s);
+}

Added: trunk/lzma/CPP/Common/IntToString.h
===================================================================
--- trunk/lzma/CPP/Common/IntToString.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/IntToString.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,15 @@
+// Common/IntToString.h
+
+#ifndef __COMMON_INTTOSTRING_H
+#define __COMMON_INTTOSTRING_H
+
+#include <stddef.h>
+#include "Types.h"
+
+void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base = 10);
+void ConvertUInt64ToString(UInt64 value, wchar_t *s);
+
+void ConvertInt64ToString(Int64 value, char *s);
+void ConvertInt64ToString(Int64 value, wchar_t *s);
+
+#endif

Added: trunk/lzma/CPP/Common/ListFileUtils.cpp
===================================================================
--- trunk/lzma/CPP/Common/ListFileUtils.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/ListFileUtils.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,74 @@
+// Common/ListFileUtils.cpp
+
+#include "StdAfx.h"
+
+#include "../Windows/FileIO.h"
+
+#include "ListFileUtils.h"
+#include "StringConvert.h"
+#include "UTFConvert.h"
+
+static const char kQuoteChar     = '\"';
+static void RemoveQuote(UString &s)
+{
+  if (s.Length() >= 2)
+    if (s[0] == kQuoteChar && s[s.Length() - 1] == kQuoteChar)
+      s = s.Mid(1, s.Length() - 2);
+}
+
+bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &resultStrings, UINT codePage)
+{
+  NWindows::NFile::NIO::CInFile file;
+  if (!file.Open(fileName))
+    return false;
+  UInt64 length;
+  if (!file.GetLength(length))
+    return false;
+  if (length > ((UInt32)1 << 31))
+    return false;
+  AString s;
+  char *p = s.GetBuffer((int)length + 1);
+  UInt32 processed;
+  if (!file.Read(p, (UInt32)length, processed))
+    return false;
+  p[(UInt32)length] = 0;
+  s.ReleaseBuffer();
+  file.Close();
+
+  UString u;
+  #ifdef CP_UTF8
+  if (codePage == CP_UTF8)
+  {
+    if (!ConvertUTF8ToUnicode(s, u))
+      return false;
+  }
+  else
+  #endif
+    u = MultiByteToUnicodeString(s, codePage);
+  if (!u.IsEmpty())
+  {
+    if (u[0] == 0xFEFF)
+      u.Delete(0);
+  }
+
+  UString t;
+  for(int i = 0; i < u.Length(); i++)
+  {
+    wchar_t c = u[i];
+    if (c == L'\n' || c == 0xD)
+    {
+      t.Trim();
+      RemoveQuote(t);
+      if (!t.IsEmpty())
+        resultStrings.Add(t);
+      t.Empty();
+    }
+    else
+      t += c;
+  }
+  t.Trim();
+  RemoveQuote(t);
+  if (!t.IsEmpty())
+    resultStrings.Add(t);
+  return true;
+}

Added: trunk/lzma/CPP/Common/ListFileUtils.h
===================================================================
--- trunk/lzma/CPP/Common/ListFileUtils.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/ListFileUtils.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,11 @@
+// Common/ListFileUtils.h
+
+#ifndef __COMMON_LISTFILEUTILS_H
+#define __COMMON_LISTFILEUTILS_H
+
+#include "MyString.h"
+#include "Types.h"
+
+bool ReadNamesFromListFile(LPCWSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP);
+
+#endif

Added: trunk/lzma/CPP/Common/MyCom.h
===================================================================
--- trunk/lzma/CPP/Common/MyCom.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyCom.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,218 @@
+// MyCom.h
+
+#ifndef __MYCOM_H
+#define __MYCOM_H
+
+#include "MyWindows.h"
+
+#ifndef RINOK
+#define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; }
+#endif
+
+template <class T>
+class CMyComPtr
+{
+  T* _p;
+public:
+  // typedef T _PtrClass;
+  CMyComPtr() { _p = NULL;}
+  CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }
+  CMyComPtr(const CMyComPtr<T>& lp)
+  {
+    if ((_p = lp._p) != NULL)
+      _p->AddRef();
+  }
+  ~CMyComPtr() { if (_p) _p->Release(); }
+  void Release() { if (_p) { _p->Release(); _p = NULL; } }
+  operator T*() const {  return (T*)_p;  }
+  // T& operator*() const {  return *_p; }
+  T** operator&() { return &_p; }
+  T* operator->() const { return _p; }
+  T* operator=(T* p) 
+  { 
+    if (p != 0)
+      p->AddRef();
+    if (_p) 
+      _p->Release();
+    _p = p;
+    return p;
+  }
+  T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
+  bool operator!() const { return (_p == NULL); }
+  // bool operator==(T* pT) const {  return _p == pT; }
+  // Compare two objects for equivalence
+  void Attach(T* p2)
+  {
+    Release();
+    _p = p2;
+  }
+  T* Detach()
+  {
+    T* pt = _p;
+    _p = NULL;
+    return pt;
+  }
+  #ifdef _WIN32
+  HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
+  {
+    return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
+  }
+  #endif
+  /*
+  HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
+  {
+    CLSID clsid;
+    HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
+    ATLASSERT(_p == NULL);
+    if (SUCCEEDED(hr))
+      hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
+    return hr;
+  }
+  */
+  template <class Q>
+  HRESULT QueryInterface(REFGUID iid, Q** pp) const
+  {
+    return _p->QueryInterface(iid, (void**)pp);
+  }
+};
+
+//////////////////////////////////////////////////////////
+
+class CMyComBSTR
+{
+public:
+  BSTR m_str;
+  CMyComBSTR() { m_str = NULL; }
+  CMyComBSTR(LPCOLESTR pSrc) {  m_str = ::SysAllocString(pSrc);  }
+  // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
+  // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize);  }
+  CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
+  /*
+  CMyComBSTR(REFGUID src)
+  {
+    LPOLESTR szGuid;
+    StringFromCLSID(src, &szGuid);
+    m_str = ::SysAllocString(szGuid);
+    CoTaskMemFree(szGuid);
+  }
+  */
+  ~CMyComBSTR() { ::SysFreeString(m_str); }
+  CMyComBSTR& operator=(const CMyComBSTR& src)
+  {
+    if (m_str != src.m_str)
+    {
+      if (m_str)
+        ::SysFreeString(m_str);
+      m_str = src.MyCopy();
+    }
+    return *this;
+  }
+  CMyComBSTR& operator=(LPCOLESTR pSrc)
+  {
+    ::SysFreeString(m_str);
+    m_str = ::SysAllocString(pSrc);
+    return *this;
+  }
+  unsigned int Length() const { return ::SysStringLen(m_str); }
+  operator BSTR() const { return m_str; }
+  BSTR* operator&() { return &m_str; }
+  BSTR MyCopy() const 
+  { 
+    int byteLen = ::SysStringByteLen(m_str);
+    BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
+    memmove(res, m_str, byteLen);
+    return res;
+  }
+  void Attach(BSTR src) {  m_str = src; }
+  BSTR Detach()
+  {
+    BSTR s = m_str;
+    m_str = NULL;
+    return s;
+  }
+  void Empty()
+  {
+    ::SysFreeString(m_str);
+    m_str = NULL;
+  }
+  bool operator!() const {  return (m_str == NULL); }
+};
+
+
+//////////////////////////////////////////////////////////
+
+class CMyUnknownImp
+{
+public:
+  ULONG __m_RefCount;
+  CMyUnknownImp(): __m_RefCount(0) {}
+};
+
+#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
+    (REFGUID iid, void **outObject) { 
+
+#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \
+    { *outObject = (void *)(i *)this; AddRef(); return S_OK; }
+
+#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \
+    { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; }
+
+#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \
+    MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
+    MY_QUERYINTERFACE_ENTRY(i)
+
+#define MY_QUERYINTERFACE_END return E_NOINTERFACE; }
+
+#define MY_ADDREF_RELEASE \
+STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \
+STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0)  \
+  return __m_RefCount; delete this; return 0; }
+
+#define MY_UNKNOWN_IMP_SPEC(i) \
+  MY_QUERYINTERFACE_BEGIN \
+  i \
+  MY_QUERYINTERFACE_END \
+  MY_ADDREF_RELEASE
+
+
+#define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \
+  MY_QUERYINTERFACE_END \
+  MY_ADDREF_RELEASE
+
+#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
+  MY_QUERYINTERFACE_ENTRY(i) \
+  )
+
+#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
+  MY_QUERYINTERFACE_ENTRY(i1) \
+  MY_QUERYINTERFACE_ENTRY(i2) \
+  )
+
+#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
+  MY_QUERYINTERFACE_ENTRY(i1) \
+  MY_QUERYINTERFACE_ENTRY(i2) \
+  MY_QUERYINTERFACE_ENTRY(i3) \
+  )
+
+#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
+  MY_QUERYINTERFACE_ENTRY(i1) \
+  MY_QUERYINTERFACE_ENTRY(i2) \
+  MY_QUERYINTERFACE_ENTRY(i3) \
+  MY_QUERYINTERFACE_ENTRY(i4) \
+  )
+
+#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \
+  MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
+  MY_QUERYINTERFACE_ENTRY(i1) \
+  MY_QUERYINTERFACE_ENTRY(i2) \
+  MY_QUERYINTERFACE_ENTRY(i3) \
+  MY_QUERYINTERFACE_ENTRY(i4) \
+  MY_QUERYINTERFACE_ENTRY(i5) \
+  )
+
+#endif

Added: trunk/lzma/CPP/Common/MyException.h
===================================================================
--- trunk/lzma/CPP/Common/MyException.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyException.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,14 @@
+// Common/Exception.h
+
+#ifndef __COMMON_EXCEPTION_H
+#define __COMMON_EXCEPTION_H
+
+#include "MyWindows.h"
+
+struct CSystemException
+{
+  HRESULT ErrorCode;
+  CSystemException(HRESULT errorCode): ErrorCode(errorCode) {}
+};
+
+#endif

Added: trunk/lzma/CPP/Common/MyGuidDef.h
===================================================================
--- trunk/lzma/CPP/Common/MyGuidDef.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyGuidDef.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,54 @@
+// Common/MyGuidDef.h
+
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+
+#include "Types.h"
+
+typedef struct {
+  UInt32 Data1;
+  UInt16 Data2;
+  UInt16 Data3;
+  unsigned char Data4[8];
+} GUID;
+
+#ifdef __cplusplus
+#define REFGUID const GUID &
+#else
+#define REFGUID const GUID *
+#endif
+
+#define REFCLSID REFGUID
+#define REFIID REFGUID
+
+#ifdef __cplusplus
+inline int operator==(REFGUID g1, REFGUID g2)
+{ 
+  for (int i = 0; i < (int)sizeof(g1); i++)
+    if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i])
+      return 0;
+  return 1;
+}
+inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); }
+#endif
+
+#ifdef __cplusplus
+  #define MY_EXTERN_C extern "C"
+#else
+  #define MY_EXTERN_C extern
+#endif
+
+#endif // GUID_DEFINED
+
+
+#ifdef DEFINE_GUID
+#undef DEFINE_GUID
+#endif
+
+#ifdef INITGUID
+  #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+    MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }
+#else
+  #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+    MY_EXTERN_C const GUID name
+#endif

Added: trunk/lzma/CPP/Common/MyInitGuid.h
===================================================================
--- trunk/lzma/CPP/Common/MyInitGuid.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyInitGuid.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,15 @@
+// Common/MyInitGuid.h
+
+#ifndef __COMMON_MYINITGUID_H
+#define __COMMON_MYINITGUID_H
+
+#ifdef _WIN32
+#include <initguid.h>
+#else
+#define INITGUID
+#include "MyGuidDef.h"
+DEFINE_GUID(IID_IUnknown,
+0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
+#endif
+
+#endif

Added: trunk/lzma/CPP/Common/MyString.cpp
===================================================================
--- trunk/lzma/CPP/Common/MyString.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyString.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,198 @@
+// Common/MyString.cpp
+
+#include "StdAfx.h"
+
+#ifdef _WIN32
+#include "StringConvert.h"
+#else
+#include <ctype.h>
+#endif
+
+#include "MyString.h"
+
+
+#ifdef _WIN32
+
+#ifndef _UNICODE
+
+wchar_t MyCharUpper(wchar_t c)
+{
+  if (c == 0)
+    return 0;
+  wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c);
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+    return (wchar_t)(unsigned int)(UINT_PTR)res;
+  const int kBufferSize = 4;
+  char s[kBufferSize + 1];
+  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);
+  if (numChars == 0 || numChars > kBufferSize)
+    return c;
+  s[numChars] = 0;
+  ::CharUpperA(s);
+  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
+  return c;
+}
+
+wchar_t MyCharLower(wchar_t c)
+{
+  if (c == 0)
+    return 0;
+  wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c);
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+    return (wchar_t)(unsigned int)(UINT_PTR)res;
+  const int kBufferSize = 4;
+  char s[kBufferSize + 1];
+  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);
+  if (numChars == 0 || numChars > kBufferSize)
+    return c;
+  s[numChars] = 0;
+  ::CharLowerA(s);
+  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
+  return c;
+}
+
+wchar_t * MyStringUpper(wchar_t *s)
+{
+  if (s == 0)
+    return 0;
+  wchar_t *res = CharUpperW(s);
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+    return res;
+  AString a = UnicodeStringToMultiByte(s);
+  a.MakeUpper();
+  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
+}
+
+wchar_t * MyStringLower(wchar_t *s)
+{ 
+  if (s == 0)
+    return 0;
+  wchar_t *res = CharLowerW(s);
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+    return res;
+  AString a = UnicodeStringToMultiByte(s);
+  a.MakeLower();
+  return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
+}
+
+#endif
+
+/*
+inline int ConvertCompareResult(int r) { return r - 2; }
+
+int MyStringCollate(const wchar_t *s1, const wchar_t *s2)
+{ 
+  int res = CompareStringW(
+        LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); 
+  #ifdef _UNICODE
+  return ConvertCompareResult(res);
+  #else
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+    return ConvertCompareResult(res);
+  return MyStringCollate(UnicodeStringToMultiByte(s1), 
+        UnicodeStringToMultiByte(s2));
+  #endif
+}
+
+#ifndef _WIN32_WCE
+int MyStringCollate(const char *s1, const char *s2)
+{ 
+  return ConvertCompareResult(CompareStringA(
+    LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); 
+}
+
+int MyStringCollateNoCase(const char *s1, const char *s2)
+{ 
+  return ConvertCompareResult(CompareStringA(
+    LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); 
+}
+#endif
+
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)
+{ 
+  int res = CompareStringW(
+        LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); 
+  #ifdef _UNICODE
+  return ConvertCompareResult(res);
+  #else
+  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+    return ConvertCompareResult(res);
+  return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), 
+      UnicodeStringToMultiByte(s2));
+  #endif
+}
+*/
+
+#else
+
+wchar_t MyCharUpper(wchar_t c)
+{
+  return toupper(c);
+}
+
+/*
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)
+{ 
+  for (;;)
+  {
+    wchar_t c1 = *s1++;
+    wchar_t c2 = *s2++;
+    wchar_t u1 = MyCharUpper(c1);
+    wchar_t u2 = MyCharUpper(c2);
+
+    if (u1 < u2) return -1;
+    if (u1 > u2) return 1;
+    if (u1 == 0) return 0;
+  }
+}
+*/
+
+#endif
+
+int MyStringCompare(const char *s1, const char *s2)
+{ 
+  for (;;)
+  {
+    unsigned char c1 = (unsigned char)*s1++;
+    unsigned char c2 = (unsigned char)*s2++;
+    if (c1 < c2) return -1;
+    if (c1 > c2) return 1;
+    if (c1 == 0) return 0;
+  }
+}
+
+int MyStringCompare(const wchar_t *s1, const wchar_t *s2)
+{ 
+  for (;;)
+  {
+    wchar_t c1 = *s1++;
+    wchar_t c2 = *s2++;
+    if (c1 < c2) return -1;
+    if (c1 > c2) return 1;
+    if (c1 == 0) return 0;
+  }
+}
+
+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2)
+{ 
+  for (;;)
+  {
+    wchar_t c1 = *s1++;
+    wchar_t c2 = *s2++;
+    if (c1 != c2)
+    {
+      wchar_t u1 = MyCharUpper(c1);
+      wchar_t u2 = MyCharUpper(c2);
+      if (u1 < u2) return -1;
+      if (u1 > u2) return 1;
+    }
+    if (c1 == 0) return 0;
+  }
+}
+
+#ifdef _WIN32
+int MyStringCompareNoCase(const char *s1, const char *s2)
+{ 
+  return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
+}
+#endif

Added: trunk/lzma/CPP/Common/MyString.h
===================================================================
--- trunk/lzma/CPP/Common/MyString.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyString.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,636 @@
+// Common/String.h
+
+#ifndef __COMMON_STRING_H
+#define __COMMON_STRING_H
+
+#include <string.h>
+// #include <wchar.h>
+
+#include "MyVector.h"
+
+#ifdef _WIN32
+#include "MyWindows.h"
+#endif
+
+template <class T>
+inline int MyStringLen(const T *s)
+{ 
+  int i;
+  for (i = 0; s[i] != '\0'; i++);
+  return i;
+}
+
+template <class T>
+inline T * MyStringCopy(T *dest, const T *src)
+{ 
+  T *destStart = dest;
+  while((*dest++ = *src++) != 0);
+  return destStart;
+}
+
+inline wchar_t* MyStringGetNextCharPointer(wchar_t *p)
+  { return (p + 1); }
+inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p)
+  { return (p + 1); }
+inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p)
+  { return (p - 1); }
+inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p)
+  { return (p - 1); }
+
+#ifdef _WIN32
+
+inline char* MyStringGetNextCharPointer(char *p)
+  { return CharNextA(p); }
+inline const char* MyStringGetNextCharPointer(const char *p)
+  { return CharNextA(p); }
+
+inline char* MyStringGetPrevCharPointer(char *base, char *p)
+  { return CharPrevA(base, p); }
+inline const char* MyStringGetPrevCharPointer(const char *base, const char *p)
+  { return CharPrevA(base, p); }
+
+inline char MyCharUpper(char c)
+  { return (char)(unsigned int)(UINT_PTR)CharUpperA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }
+#ifdef _UNICODE
+inline wchar_t MyCharUpper(wchar_t c)
+  { return (wchar_t)(unsigned int)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned int)c); }
+#else
+wchar_t MyCharUpper(wchar_t c);
+#endif
+
+inline char MyCharLower(char c)
+  { return (char)(unsigned int)(UINT_PTR)CharLowerA((LPSTR)(UINT_PTR)(unsigned int)(unsigned char)c); }
+#ifdef _UNICODE
+inline wchar_t MyCharLower(wchar_t c)
+  { return (wchar_t)(unsigned int)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned int)c); }
+#else
+wchar_t MyCharLower(wchar_t c);
+#endif
+
+inline char * MyStringUpper(char *s) { return CharUpperA(s); }
+#ifdef _UNICODE
+inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
+#else
+wchar_t * MyStringUpper(wchar_t *s);
+#endif
+
+inline char * MyStringLower(char *s) { return CharLowerA(s); }
+#ifdef _UNICODE
+inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
+#else
+wchar_t * MyStringLower(wchar_t *s);
+#endif
+
+#else // Standard-C
+wchar_t MyCharUpper(wchar_t c);
+#endif
+
+//////////////////////////////////////
+// Compare
+
+/*
+#ifndef _WIN32_WCE
+int MyStringCollate(const char *s1, const char *s2);
+int MyStringCollateNoCase(const char *s1, const char *s2);
+#endif
+int MyStringCollate(const wchar_t *s1, const wchar_t *s2);
+int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2);
+*/
+
+int MyStringCompare(const char *s1, const char  *s2);
+int MyStringCompare(const wchar_t *s1, const wchar_t *s2);
+
+#ifdef _WIN32
+int MyStringCompareNoCase(const char *s1, const char  *s2);
+#endif
+
+int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2);
+
+template <class T>
+class CStringBase
+{
+  void TrimLeftWithCharSet(const CStringBase &charSet)
+  {
+    const T *p = _chars;
+    while (charSet.Find(*p) >= 0 && (*p != 0))
+      p = GetNextCharPointer(p);
+    Delete(0, (int)(p - _chars));
+  }
+  void TrimRightWithCharSet(const CStringBase &charSet)
+  {
+    const T *p = _chars;
+    const T *pLast = NULL;
+    while (*p != 0)
+    {
+      if (charSet.Find(*p) >= 0)
+      {
+        if (pLast == NULL)
+          pLast = p;
+      }
+      else
+        pLast = NULL;
+      p = GetNextCharPointer(p);
+    }
+    if(pLast != NULL)
+    {
+      int i = (int)(pLast - _chars);
+      Delete(i, _length - i);
+    }
+
+  }
+  void MoveItems(int destIndex, int srcIndex)
+  {
+    memmove(_chars + destIndex, _chars + srcIndex, 
+        sizeof(T) * (_length - srcIndex + 1));
+  }
+  
+  void InsertSpace(int &index, int size)
+  {
+    CorrectIndex(index);
+    GrowLength(size);
+    MoveItems(index + size, index);
+  }
+
+  static T *GetNextCharPointer(T *p)
+    { return MyStringGetNextCharPointer(p); }
+  static const T *GetNextCharPointer(const T *p)
+    { return MyStringGetNextCharPointer(p); }
+  static T *GetPrevCharPointer(T *base, T *p)
+    { return MyStringGetPrevCharPointer(base, p); }
+  static const T *GetPrevCharPointer(const T *base, const T *p)
+    { return MyStringGetPrevCharPointer(base, p); }
+protected:
+  T *_chars;
+  int _length;
+  int _capacity;
+  
+  void SetCapacity(int newCapacity)
+  {
+    int realCapacity = newCapacity + 1;
+    if(realCapacity == _capacity)
+      return;
+    /*
+    const int kMaxStringSize = 0x20000000;
+    #ifndef _WIN32_WCE
+    if(newCapacity > kMaxStringSize || newCapacity < _length)
+      throw 1052337;
+    #endif
+    */
+    T *newBuffer = new T[realCapacity];
+    if(_capacity > 0)
+    {
+      for (int i = 0; i < (_length + 1); i++)
+        newBuffer[i] = _chars[i];
+      delete []_chars;
+      _chars = newBuffer;
+    }
+    else
+    {
+      _chars = newBuffer;
+      _chars[0] = 0;
+    }
+    _capacity = realCapacity;
+  }
+
+  void GrowLength(int n)
+  {
+    int freeSize = _capacity - _length - 1;
+    if (n <= freeSize) 
+      return;
+    int delta;
+    if (_capacity > 64)
+      delta = _capacity / 2;
+    else if (_capacity > 8)
+      delta = 16;
+    else
+      delta = 4;
+    if (freeSize + delta < n)
+      delta = n - freeSize;
+    SetCapacity(_capacity + delta);
+  }
+
+  void CorrectIndex(int &index) const
+  {
+    if (index > _length)
+      index = _length;
+  }
+
+public:
+  CStringBase(): _chars(0), _length(0), _capacity(0)
+    { SetCapacity(16 - 1); }
+  CStringBase(T c):  _chars(0), _length(0), _capacity(0)
+  {
+    SetCapacity(1);
+    _chars[0] = c;
+    _chars[1] = 0;
+    _length = 1;
+  }
+  CStringBase(const T *chars): _chars(0), _length(0), _capacity(0)
+  {
+    int length = MyStringLen(chars);
+    SetCapacity(length);
+    MyStringCopy(_chars, chars); // can be optimized by memove()
+    _length = length;
+  }
+  CStringBase(const CStringBase &s):  _chars(0), _length(0), _capacity(0)
+  {
+    SetCapacity(s._length);
+    MyStringCopy(_chars, s._chars);
+    _length = s._length;
+  }
+  ~CStringBase() {  delete []_chars; }
+
+  operator const T*() const { return _chars;} 
+
+  // The minimum size of the character buffer in characters. 
+  // This value does not include space for a null terminator.
+  T* GetBuffer(int minBufLength)
+  {
+    if(minBufLength >= _capacity)
+      SetCapacity(minBufLength + 1);
+    return _chars;
+  }
+  void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); }
+  void ReleaseBuffer(int newLength)
+  {
+    /*
+    #ifndef _WIN32_WCE
+    if(newLength >= _capacity)
+      throw 282217;
+    #endif
+    */
+    _chars[newLength] = 0;
+    _length = newLength;
+  }
+
+  CStringBase& operator=(T c)
+  {
+    Empty();
+    SetCapacity(1);
+    _chars[0] = c;
+    _chars[1] = 0;
+    _length = 1;
+    return *this;
+  }
+  CStringBase& operator=(const T *chars)
+  {
+    Empty();
+    int length = MyStringLen(chars);
+    SetCapacity(length);
+    MyStringCopy(_chars, chars);
+    _length = length; 
+    return *this;
+  }  
+  CStringBase& operator=(const CStringBase& s)
+  {
+    if(&s == this)
+      return *this;
+    Empty();
+    SetCapacity(s._length);
+    MyStringCopy(_chars, s._chars);
+    _length = s._length;
+    return *this;
+  }
+  
+  CStringBase& operator+=(T c)
+  {
+    GrowLength(1);
+    _chars[_length] = c;
+    _chars[++_length] = 0;
+    return *this;
+  }
+  CStringBase& operator+=(const T *s)
+  {
+    int len = MyStringLen(s);
+    GrowLength(len);
+    MyStringCopy(_chars + _length, s);
+    _length += len;
+    return *this;
+  }
+  CStringBase& operator+=(const CStringBase &s)
+  {
+    GrowLength(s._length);
+    MyStringCopy(_chars + _length, s._chars);
+    _length += s._length;
+    return *this;
+  }
+  void Empty()
+  {
+    _length = 0;
+    _chars[0] = 0;
+  }
+  int Length() const { return _length; }
+  bool IsEmpty() const { return (_length == 0); }
+
+  CStringBase Mid(int startIndex) const
+    { return Mid(startIndex, _length - startIndex); }
+  CStringBase Mid(int startIndex, int count ) const
+  {
+    if (startIndex + count > _length)
+      count = _length - startIndex;
+    
+    if (startIndex == 0 && startIndex + count == _length)
+      return *this;
+    
+    CStringBase<T> result;
+    result.SetCapacity(count);
+    // MyStringNCopy(result._chars, _chars + startIndex, count);
+    for (int i = 0; i < count; i++)
+      result._chars[i] = _chars[startIndex + i];
+    result._chars[count] = 0;
+    result._length = count;
+    return result;
+  }
+  CStringBase Left(int count) const
+    { return Mid(0, count); }
+  CStringBase Right(int count) const
+  {
+    if (count > _length)
+      count = _length;
+    return Mid(_length - count, count);
+  }
+
+  void MakeUpper()
+    { MyStringUpper(_chars); }
+  void MakeLower()
+    { MyStringLower(_chars); }
+
+  int Compare(const CStringBase& s) const
+    { return MyStringCompare(_chars, s._chars); }
+
+  int Compare(const T *s) const
+    { return MyStringCompare(_chars, s); }
+
+  int CompareNoCase(const CStringBase& s) const
+    { return MyStringCompareNoCase(_chars, s._chars); }
+
+  int CompareNoCase(const T *s) const
+    { return MyStringCompareNoCase(_chars, s); }
+
+  /*
+  int Collate(const CStringBase& s) const
+    { return MyStringCollate(_chars, s._chars); }
+  int CollateNoCase(const CStringBase& s) const
+    { return MyStringCollateNoCase(_chars, s._chars); }
+  */
+
+  int Find(T c) const { return Find(c, 0); }
+  int Find(T c, int startIndex) const
+  {
+    T *p = _chars + startIndex;
+    for (;;)
+    {
+      if (*p == c)
+        return (int)(p - _chars);
+      if (*p == 0)
+        return -1;
+      p = GetNextCharPointer(p);
+    }
+  }
+  int Find(const CStringBase &s) const { return Find(s, 0); }
+  int Find(const CStringBase &s, int startIndex) const
+  {
+    if (s.IsEmpty())
+      return startIndex;
+    for (; startIndex < _length; startIndex++)
+    {
+      int j;
+      for (j = 0; j < s._length && startIndex + j < _length; j++)
+        if (_chars[startIndex+j] != s._chars[j])
+          break;
+      if (j == s._length)
+        return startIndex;
+    }
+    return -1;
+  }
+  int ReverseFind(T c) const
+  {
+    if (_length == 0)
+      return -1;
+    T *p = _chars + _length - 1;
+    for (;;)
+    {
+      if (*p == c)
+        return (int)(p - _chars);
+      if (p == _chars)
+        return -1;
+      p = GetPrevCharPointer(_chars, p);
+    }
+  }
+  int FindOneOf(const CStringBase &s) const
+  {
+    for(int i = 0; i < _length; i++)
+      if (s.Find(_chars[i]) >= 0)
+        return i;
+      return -1;
+  }
+
+  void TrimLeft(T c)
+  {
+    const T *p = _chars;
+    while (c == *p)
+      p = GetNextCharPointer(p);
+    Delete(0, p - _chars);
+  }
+  private:
+  CStringBase GetTrimDefaultCharSet()
+  {
+    CStringBase<T> charSet;
+    charSet += (T)' ';
+    charSet += (T)'\n';
+    charSet += (T)'\t';
+    return charSet;
+  }
+  public:
+
+  void TrimLeft()
+  {
+    TrimLeftWithCharSet(GetTrimDefaultCharSet());
+  }
+  void TrimRight()
+  {
+    TrimRightWithCharSet(GetTrimDefaultCharSet());
+  }
+  void TrimRight(T c)
+  {
+    const T *p = _chars;
+    const T *pLast = NULL;
+    while (*p != 0)
+    {
+      if (*p == c)
+      {
+        if (pLast == NULL)
+          pLast = p;
+      }
+      else
+        pLast = NULL;
+      p = GetNextCharPointer(p);
+    }
+    if(pLast != NULL)
+    {
+      int i = pLast - _chars;
+      Delete(i, _length - i);
+    }
+  }
+  void Trim()
+  {
+    TrimRight();
+    TrimLeft();
+  }
+
+  int Insert(int index, T c)
+  {
+    InsertSpace(index, 1);
+    _chars[index] = c;
+    _length++;
+    return _length;
+  }
+  int Insert(int index, const CStringBase &s)
+  {
+    CorrectIndex(index);
+    if (s.IsEmpty())
+      return _length;
+    int numInsertChars = s.Length();
+    InsertSpace(index, numInsertChars);
+    for(int i = 0; i < numInsertChars; i++)
+      _chars[index + i] = s[i];
+    _length += numInsertChars;
+    return _length;
+  }
+
+  // !!!!!!!!!!!!!!! test it if newChar = '\0'
+  int Replace(T oldChar, T newChar)
+  {
+    if (oldChar == newChar)
+      return 0;
+    int number  = 0;
+    int pos  = 0;
+    while (pos < Length())
+    {
+      pos = Find(oldChar, pos);
+      if (pos < 0) 
+        break;
+      _chars[pos] = newChar;
+      pos++;
+      number++;
+    }
+    return number;
+  }
+  int Replace(const CStringBase &oldString, const CStringBase &newString)
+  {
+    if (oldString.IsEmpty())
+      return 0;
+    if (oldString == newString)
+      return 0;
+    int oldStringLength = oldString.Length();
+    int newStringLength = newString.Length();
+    int number  = 0;
+    int pos  = 0;
+    while (pos < _length)
+    {
+      pos = Find(oldString, pos);
+      if (pos < 0) 
+        break;
+      Delete(pos, oldStringLength);
+      Insert(pos, newString);
+      pos += newStringLength;
+      number++;
+    }
+    return number;
+  }
+  int Delete(int index, int count = 1 )
+  {
+    if (index + count > _length)
+      count = _length - index;
+    if (count > 0)
+    {
+      MoveItems(index, index + count);
+      _length -= count;
+    }
+    return _length;
+  }
+};
+
+template <class T>
+CStringBase<T> operator+(const CStringBase<T>& s1, const CStringBase<T>& s2)
+{
+  CStringBase<T> result(s1);
+  result += s2;
+  return result; 
+}
+
+template <class T>
+CStringBase<T> operator+(const CStringBase<T>& s, T c)
+{
+  CStringBase<T> result(s);
+  result += c;
+  return result; 
+}
+
+template <class T>
+CStringBase<T> operator+(T c, const CStringBase<T>& s)
+{
+  CStringBase<T> result(c);
+  result += s;
+  return result; 
+}
+
+template <class T>
+CStringBase<T> operator+(const CStringBase<T>& s, const T * chars)
+{
+  CStringBase<T> result(s);
+  result += chars;
+  return result; 
+}
+
+template <class T>
+CStringBase<T> operator+(const T * chars, const CStringBase<T>& s)
+{
+  CStringBase<T> result(chars);
+  result += s;
+  return result; 
+}
+
+template <class T>
+bool operator==(const CStringBase<T>& s1, const CStringBase<T>& s2)
+  { return (s1.Compare(s2) == 0); }
+
+template <class T>
+bool operator<(const CStringBase<T>& s1, const CStringBase<T>& s2)
+  { return (s1.Compare(s2) < 0); }
+
+template <class T>
+bool operator==(const T *s1, const CStringBase<T>& s2)
+  { return (s2.Compare(s1) == 0); }
+
+template <class T>
+bool operator==(const CStringBase<T>& s1, const T *s2)
+  { return (s1.Compare(s2) == 0); }
+
+template <class T>
+bool operator!=(const CStringBase<T>& s1, const CStringBase<T>& s2)
+  { return (s1.Compare(s2) != 0); }
+
+template <class T>
+bool operator!=(const T *s1, const CStringBase<T>& s2)
+  { return (s2.Compare(s1) != 0); }
+
+template <class T>
+bool operator!=(const CStringBase<T>& s1, const T *s2)
+  { return (s1.Compare(s2) != 0); }
+
+typedef CStringBase<char> AString;
+typedef CStringBase<wchar_t> UString;
+
+typedef CObjectVector<AString> AStringVector;
+typedef CObjectVector<UString> UStringVector;
+
+#ifdef _UNICODE
+  typedef UString CSysString;
+#else
+  typedef AString CSysString;
+#endif
+
+typedef CObjectVector<CSysString> CSysStringVector;
+
+#endif

Added: trunk/lzma/CPP/Common/MyUnknown.h
===================================================================
--- trunk/lzma/CPP/Common/MyUnknown.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyUnknown.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// MyUnknown.h
+
+#ifndef __MYUNKNOWN_H
+#define __MYUNKNOWN_H
+
+#ifdef _WIN32
+
+#ifdef _WIN32_WCE
+#if (_WIN32_WCE > 300)
+#include <basetyps.h>
+#else
+#define MIDL_INTERFACE(x) struct 
+#endif
+#else
+#include <basetyps.h>
+#endif
+
+#include <unknwn.h>
+
+#else 
+#include "MyWindows.h"
+#endif
+  
+#endif

Added: trunk/lzma/CPP/Common/MyVector.cpp
===================================================================
--- trunk/lzma/CPP/Common/MyVector.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyVector.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,78 @@
+// Common/MyVector.cpp
+
+#include "StdAfx.h"
+
+#include <string.h>
+
+#include "MyVector.h"
+
+CBaseRecordVector::~CBaseRecordVector() { Free(); }
+
+void CBaseRecordVector::Free()
+{ 
+  delete []((unsigned char *)_items); 
+  _capacity = 0;
+  _size = 0;
+  _items = 0;
+}
+
+void CBaseRecordVector::Clear() { DeleteFrom(0); }
+void CBaseRecordVector::DeleteBack() { Delete(_size - 1); }
+void CBaseRecordVector::DeleteFrom(int index) { Delete(index, _size - index); }
+
+void CBaseRecordVector::ReserveOnePosition()
+{
+  if (_size != _capacity)
+    return;
+  int delta;
+  if (_capacity > 64)
+    delta = _capacity / 2;
+  else if (_capacity > 8)
+    delta = 8;
+  else
+    delta = 4;
+  Reserve(_capacity + delta);
+}
+
+void CBaseRecordVector::Reserve(int newCapacity)
+{
+  if (newCapacity <= _capacity)
+    return;
+  if ((unsigned)newCapacity >= ((unsigned)1 << (sizeof(unsigned) * 8 - 1)))
+    throw 1052353;
+  size_t newSize = (size_t)(unsigned)newCapacity * _itemSize;
+  if (newSize / _itemSize != (size_t)(unsigned)newCapacity)
+    throw 1052354;
+  unsigned char *p = new unsigned char[newSize];
+  if (p == 0)
+    throw 1052355;
+  int numRecordsToMove = _capacity;
+  memmove(p, _items, _itemSize * numRecordsToMove);
+  delete [](unsigned char *)_items;
+  _items = p;
+  _capacity = newCapacity;
+}
+
+void CBaseRecordVector::MoveItems(int destIndex, int srcIndex)
+{
+  memmove(((unsigned char *)_items) + destIndex * _itemSize, 
+    ((unsigned char  *)_items) + srcIndex * _itemSize, 
+    _itemSize * (_size - srcIndex));
+}
+
+void CBaseRecordVector::InsertOneItem(int index)
+{
+  ReserveOnePosition();
+  MoveItems(index + 1, index);
+  _size++;
+}
+
+void CBaseRecordVector::Delete(int index, int num)
+{
+  TestIndexAndCorrectNum(index, num);
+  if (num > 0)
+  {
+    MoveItems(index, index + num);
+    _size -= num;
+  }
+}

Added: trunk/lzma/CPP/Common/MyVector.h
===================================================================
--- trunk/lzma/CPP/Common/MyVector.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyVector.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,254 @@
+// Common/Vector.h
+
+#ifndef __COMMON_VECTOR_H
+#define __COMMON_VECTOR_H
+
+#include "Defs.h"
+
+class CBaseRecordVector
+{
+  void MoveItems(int destIndex, int srcIndex);
+protected:
+  int _capacity;
+  int _size;
+  void *_items;
+  size_t _itemSize;
+  
+  void ReserveOnePosition();
+  void InsertOneItem(int index);
+  void TestIndexAndCorrectNum(int index, int &num) const
+    { if (index + num > _size) num = _size - index; } 
+public:
+  CBaseRecordVector(size_t itemSize):
+      _capacity(0), _size(0), _items(0), _itemSize(itemSize) {}
+  virtual ~CBaseRecordVector();
+  void Free();
+  int Size() const { return _size; }
+  bool IsEmpty() const { return (_size == 0); }
+  void Reserve(int newCapacity);
+  virtual void Delete(int index, int num = 1);
+  void Clear();
+  void DeleteFrom(int index);
+  void DeleteBack();
+};
+
+template <class T>
+class CRecordVector: public CBaseRecordVector
+{
+public:
+  CRecordVector():CBaseRecordVector(sizeof(T)){};
+  CRecordVector(const CRecordVector &v):
+    CBaseRecordVector(sizeof(T)) { *this = v;}
+  CRecordVector& operator=(const CRecordVector &v)
+  {
+    Clear();
+    return (*this += v);
+  }
+  CRecordVector& operator+=(const CRecordVector &v)
+  {
+    int size = v.Size();
+    Reserve(Size() + size);
+    for(int i = 0; i < size; i++)
+      Add(v[i]);
+    return *this;
+  }
+  int Add(T item)
+  {
+    ReserveOnePosition();
+    ((T *)_items)[_size] = item;
+    return _size++;
+  }
+  void Insert(int index, T item)
+  {
+    InsertOneItem(index);
+    ((T *)_items)[index] = item;
+  }
+  // T* GetPointer() const { return (T*)_items; }
+  // operator const T *() const { return _items; };
+  const T& operator[](int index) const { return ((T *)_items)[index]; }
+  T& operator[](int index) { return ((T *)_items)[index]; }
+  const T& Front() const { return operator[](0); }
+  T& Front()   { return operator[](0); }
+  const T& Back() const { return operator[](_size - 1); }
+  T& Back()   { return operator[](_size - 1); }
+
+  void Swap(int i, int j)
+  {
+    T temp = operator[](i);
+    operator[](i) = operator[](j);
+    operator[](j) = temp;
+  }
+
+  int FindInSorted(const T& item) const
+  {
+    int left = 0, right = Size(); 
+    while (left != right)
+    {
+      int mid = (left + right) / 2;
+      const T& midValue = (*this)[mid];
+      if (item == midValue)
+        return mid;
+      if (item < midValue)
+        right = mid;
+      else
+        left = mid + 1;
+    }
+    return -1;
+  }
+
+  int AddToUniqueSorted(const T& item)
+  {
+    int left = 0, right = Size(); 
+    while (left != right)
+    {
+      int mid = (left + right) / 2;
+      const T& midValue = (*this)[mid];
+      if (item == midValue)
+        return mid;
+      if (item < midValue)
+        right = mid;
+      else
+        left = mid + 1;
+    }
+    Insert(right, item);
+    return right;
+  }
+
+  static void SortRefDown(T* p, int k, int size, int (*compare)(const T*, const T*, void *), void *param)
+  { 
+    T temp = p[k];
+    for (;;)
+    {
+      int s = (k << 1);
+      if (s > size)
+        break;
+      if (s < size && compare(p + s + 1, p + s, param) > 0)
+        s++;
+      if (compare(&temp, p + s, param) >= 0)
+        break;
+      p[k] = p[s]; 
+      k = s;
+    } 
+    p[k] = temp; 
+  }
+
+  void Sort(int (*compare)(const T*, const T*, void *), void *param)
+  {
+    int size = _size;
+    if (size <= 1)
+      return;
+    T* p = (&Front()) - 1;
+    {
+      int i = size / 2;
+      do
+        SortRefDown(p, i, size, compare, param);
+      while(--i != 0);
+    }
+    do
+    {
+      T temp = p[size];
+      p[size--] = p[1];
+      p[1] = temp;
+      SortRefDown(p, 1, size, compare, param);
+    }
+    while (size > 1);
+  }
+};
+
+typedef CRecordVector<int> CIntVector;
+typedef CRecordVector<unsigned int> CUIntVector;
+typedef CRecordVector<bool> CBoolVector;
+typedef CRecordVector<unsigned char> CByteVector;
+typedef CRecordVector<void *> CPointerVector;
+
+template <class T>
+class CObjectVector: public CPointerVector
+{
+public:
+  CObjectVector(){};
+  ~CObjectVector() { Clear(); }
+  CObjectVector(const CObjectVector &objectVector)
+    { *this = objectVector; }
+  CObjectVector& operator=(const CObjectVector &objectVector)
+  {
+    Clear();
+    return (*this += objectVector);
+  }
+  CObjectVector& operator+=(const CObjectVector &objectVector)
+  {
+    int size = objectVector.Size();
+    Reserve(Size() + size);
+    for(int i = 0; i < size; i++)
+      Add(objectVector[i]);
+    return *this;
+  }
+  const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); }
+  T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); }
+  T& Front() { return operator[](0); }
+  const T& Front() const { return operator[](0); }
+  T& Back() { return operator[](_size - 1); }
+  const T& Back() const { return operator[](_size - 1); }
+  int Add(const T& item)
+    { return CPointerVector::Add(new T(item)); }
+  void Insert(int index, const T& item)
+    { CPointerVector::Insert(index, new T(item)); }
+  virtual void Delete(int index, int num = 1)
+  {
+    TestIndexAndCorrectNum(index, num);
+    for(int i = 0; i < num; i++)
+      delete (T *)(((void **)_items)[index + i]);
+    CPointerVector::Delete(index, num);
+  }
+  int Find(const T& item) const
+  {
+    for(int i = 0; i < Size(); i++)
+      if (item == (*this)[i])
+        return i;
+      return -1;
+  }
+  int FindInSorted(const T& item) const
+  {
+    int left = 0, right = Size(); 
+    while (left != right)
+    {
+      int mid = (left + right) / 2;
+      const T& midValue = (*this)[mid];
+      if (item == midValue)
+        return mid;
+      if (item < midValue)
+        right = mid;
+      else
+        left = mid + 1;
+    }
+    return -1;
+  }
+  int AddToSorted(const T& item)
+  {
+    int left = 0, right = Size(); 
+    while (left != right)
+    {
+      int mid = (left + right) / 2;
+      const T& midValue = (*this)[mid];
+      if (item == midValue)
+      {
+        right = mid + 1;
+        break;
+      }
+      if (item < midValue)
+        right = mid;
+      else
+        left = mid + 1;
+    }
+    Insert(right, item);
+    return right;
+  }
+
+  void Sort(int (*compare)(void *const *, void *const *, void *), void *param) 
+    { CPointerVector::Sort(compare, param); }
+
+  static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */)
+    { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); }
+  void Sort() { CPointerVector::Sort(CompareObjectItems, 0); }
+};
+
+#endif 

Added: trunk/lzma/CPP/Common/MyWindows.h
===================================================================
--- trunk/lzma/CPP/Common/MyWindows.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/MyWindows.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,214 @@
+// MyWindows.h
+
+#ifndef __MYWINDOWS_H
+#define __MYWINDOWS_H
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+#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"/"
+
+#include <stddef.h> // for wchar_t
+#include <string.h>
+
+#include "MyGuidDef.h"
+
+typedef char CHAR;
+typedef unsigned char UCHAR;
+
+#undef BYTE
+typedef unsigned char BYTE;
+
+typedef short SHORT;
+typedef unsigned short USHORT;
+
+#undef WORD
+typedef unsigned short WORD;
+typedef short VARIANT_BOOL;
+
+typedef int INT;
+typedef Int32 INT32;
+typedef unsigned int UINT;
+typedef UInt32 UINT32;
+typedef INT32 LONG;   // LONG, ULONG and DWORD must be 32-bit
+typedef UINT32 ULONG;
+
+#undef DWORD
+typedef UINT32 DWORD;
+
+typedef Int64 LONGLONG;
+typedef UInt64 ULONGLONG;
+
+typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER;
+typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER;
+
+typedef const CHAR *LPCSTR;
+typedef CHAR TCHAR;
+typedef const TCHAR *LPCTSTR;
+typedef wchar_t WCHAR;
+typedef WCHAR OLECHAR;
+typedef const WCHAR *LPCWSTR;
+typedef OLECHAR *BSTR;
+typedef const OLECHAR *LPCOLESTR;
+typedef OLECHAR *LPOLESTR;
+
+typedef struct _FILETIME
+{
+  DWORD dwLowDateTime;
+  DWORD dwHighDateTime;
+}FILETIME;
+
+#define HRESULT LONG
+#define FAILED(Status) ((HRESULT)(Status)<0)
+typedef ULONG PROPID;
+typedef LONG SCODE;
+
+#define S_OK    ((HRESULT)0x00000000L)
+#define S_FALSE ((HRESULT)0x00000001L)
+#define E_NOTIMPL ((HRESULT)0x80004001L)
+#define E_NOINTERFACE ((HRESULT)0x80004002L)
+#define E_ABORT ((HRESULT)0x80004004L)
+#define E_FAIL ((HRESULT)0x80004005L)
+#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)
+#define E_OUTOFMEMORY ((HRESULT)0x8007000EL)
+#define E_INVALIDARG ((HRESULT)0x80070057L)
+
+#ifdef _MSC_VER
+#define STDMETHODCALLTYPE __stdcall 
+#else
+#define STDMETHODCALLTYPE 
+#endif
+
+#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f
+#define STDMETHOD(f) STDMETHOD_(HRESULT, f)
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
+#define STDMETHODIMP STDMETHODIMP_(HRESULT)
+
+#define PURE = 0
+
+#define MIDL_INTERFACE(x) struct 
+
+#ifdef __cplusplus
+
+DEFINE_GUID(IID_IUnknown,
+0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
+struct IUnknown
+{
+  STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE;
+  STDMETHOD_(ULONG, AddRef)() PURE;
+  STDMETHOD_(ULONG, Release)() PURE;
+  #ifndef _WIN32
+  virtual ~IUnknown() {}
+  #endif
+};
+
+typedef IUnknown *LPUNKNOWN;
+
+#endif
+
+#define VARIANT_TRUE ((VARIANT_BOOL)-1)
+#define VARIANT_FALSE ((VARIANT_BOOL)0)
+
+enum VARENUM
+{
+  VT_EMPTY = 0,
+  VT_NULL = 1,
+  VT_I2 = 2,
+  VT_I4 = 3,
+  VT_R4 = 4,
+  VT_R8 = 5,
+  VT_CY = 6,
+  VT_DATE = 7,
+  VT_BSTR = 8,
+  VT_DISPATCH = 9,
+  VT_ERROR = 10,
+  VT_BOOL = 11,
+  VT_VARIANT = 12,
+  VT_UNKNOWN = 13,
+  VT_DECIMAL = 14,
+  VT_I1 = 16,
+  VT_UI1 = 17,
+  VT_UI2 = 18,
+  VT_UI4 = 19,
+  VT_I8 = 20,
+  VT_UI8 = 21,
+  VT_INT = 22,
+  VT_UINT = 23,
+  VT_VOID = 24,
+  VT_HRESULT = 25,
+  VT_FILETIME = 64
+};
+
+typedef unsigned short VARTYPE;
+typedef WORD PROPVAR_PAD1;
+typedef WORD PROPVAR_PAD2;
+typedef WORD PROPVAR_PAD3;
+
+#ifdef __cplusplus
+
+typedef struct tagPROPVARIANT
+{
+  VARTYPE vt;
+  PROPVAR_PAD1 wReserved1;
+  PROPVAR_PAD2 wReserved2;
+  PROPVAR_PAD3 wReserved3;
+  union 
+  {
+    CHAR cVal;
+    UCHAR bVal;
+    SHORT iVal;
+    USHORT uiVal;
+    LONG lVal;
+    ULONG ulVal;
+    INT intVal;
+    UINT uintVal;
+    LARGE_INTEGER hVal;
+    ULARGE_INTEGER uhVal;
+    VARIANT_BOOL boolVal;
+    SCODE scode;
+    FILETIME filetime;
+    BSTR bstrVal;
+  };
+} PROPVARIANT;
+
+typedef PROPVARIANT tagVARIANT;
+typedef tagVARIANT VARIANT;
+typedef VARIANT VARIANTARG;
+
+MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop);
+MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src);
+
+#endif
+
+MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);
+MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz);
+MY_EXTERN_C void SysFreeString(BSTR bstr);
+MY_EXTERN_C UINT SysStringByteLen(BSTR bstr);
+MY_EXTERN_C UINT SysStringLen(BSTR bstr);
+
+MY_EXTERN_C DWORD GetLastError();
+MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);
+
+#define CP_ACP    0
+#define CP_OEMCP  1
+
+typedef enum tagSTREAM_SEEK
+{
+  STREAM_SEEK_SET = 0,
+  STREAM_SEEK_CUR = 1,
+  STREAM_SEEK_END = 2
+} STREAM_SEEK;
+
+#endif
+#endif

Added: trunk/lzma/CPP/Common/NewHandler.cpp
===================================================================
--- trunk/lzma/CPP/Common/NewHandler.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/NewHandler.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,116 @@
+// NewHandler.cpp
+ 
+#include "StdAfx.h"
+
+#include <stdlib.h>
+
+#include "NewHandler.h"
+
+// #define DEBUG_MEMORY_LEAK
+
+#ifndef DEBUG_MEMORY_LEAK
+
+#ifdef _WIN32
+void * 
+#ifdef _MSC_VER
+__cdecl 
+#endif
+operator new(size_t size)
+{
+  // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);
+  void *p = ::malloc(size);
+  if (p == 0)
+    throw CNewException();
+  return p;
+}
+
+void 
+#ifdef _MSC_VER
+__cdecl 
+#endif
+operator delete(void *p) throw()
+{
+  /*
+  if (p == 0)
+    return;
+  ::HeapFree(::GetProcessHeap(), 0, p);
+  */
+  ::free(p);
+}
+#endif
+
+#else
+
+#pragma init_seg(lib)
+const int kDebugSize = 1000000;
+static void *a[kDebugSize];
+static int index = 0;
+
+static int numAllocs = 0;
+void * __cdecl operator new(size_t size)
+{
+  numAllocs++;
+  void *p = HeapAlloc(GetProcessHeap(), 0, size);
+  if (index == 40)
+  {
+    int t = 1;
+  }
+  if (index < kDebugSize)
+  {
+    a[index] = p;
+    index++;
+  }
+  if (p == 0)
+    throw CNewException();
+  printf("Alloc %6d, size = %8d\n", numAllocs, size);
+  return p;
+}
+
+class CC
+{
+public:
+  CC()
+  {
+    for (int i = 0; i < kDebugSize; i++)
+      a[i] = 0;
+  }
+  ~CC()
+  {
+    for (int i = 0; i < kDebugSize; i++)
+      if (a[i] != 0)
+        return;
+  }
+} g_CC;
+
+
+void __cdecl operator delete(void *p)
+{
+  if (p == 0)
+    return;
+  /*
+  for (int i = 0; i < index; i++)
+    if (a[i] == p)
+      a[i] = 0;
+  */
+  HeapFree(GetProcessHeap(), 0, p);
+  numAllocs--;
+  printf("Free %d\n", numAllocs);
+}
+
+#endif
+
+/*
+int MemErrorVC(size_t)
+{
+  throw CNewException();
+  // return 1;
+}
+CNewHandlerSetter::CNewHandlerSetter()
+{
+  // MemErrorOldVCFunction = _set_new_handler(MemErrorVC);
+}
+CNewHandlerSetter::~CNewHandlerSetter()
+{
+  // _set_new_handler(MemErrorOldVCFunction);
+}
+*/

Added: trunk/lzma/CPP/Common/NewHandler.h
===================================================================
--- trunk/lzma/CPP/Common/NewHandler.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/NewHandler.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,16 @@
+// Common/NewHandler.h
+
+#ifndef __COMMON_NEWHANDLER_H
+#define __COMMON_NEWHANDLER_H
+
+class CNewException {};
+
+#ifdef _WIN32
+void 
+#ifdef _MSC_VER
+__cdecl 
+#endif
+operator delete(void *p) throw();
+#endif 
+
+#endif 

Added: trunk/lzma/CPP/Common/StdAfx.h
===================================================================
--- trunk/lzma/CPP/Common/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+// #include "MyWindows.h"
+#include "NewHandler.h"
+
+#endif 

Added: trunk/lzma/CPP/Common/StdInStream.cpp
===================================================================
--- trunk/lzma/CPP/Common/StdInStream.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/StdInStream.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,84 @@
+// Common/StdInStream.cpp
+
+#include "StdAfx.h"
+
+#include <tchar.h>
+#include "StdInStream.h"
+
+#ifdef _MSC_VER
+// "was declared deprecated" disabling
+#pragma warning(disable : 4996 )
+#endif
+
+static const char kIllegalChar = '\0';
+static const char kNewLineChar = '\n';
+
+static const char *kEOFMessage = "Unexpected end of input stream";
+static const char *kReadErrorMessage  ="Error reading input stream"; 
+static const char *kIllegalCharMessage = "Illegal character in input stream";
+
+static LPCTSTR kFileOpenMode = TEXT("r");
+
+CStdInStream g_StdIn(stdin);
+
+bool CStdInStream::Open(LPCTSTR fileName)
+{
+  Close();
+  _stream = _tfopen(fileName, kFileOpenMode);
+  _streamIsOpen = (_stream != 0);
+  return _streamIsOpen;
+}
+
+bool CStdInStream::Close()
+{
+  if(!_streamIsOpen)
+    return true;
+  _streamIsOpen = (fclose(_stream) != 0);
+  return !_streamIsOpen;
+}
+
+CStdInStream::~CStdInStream()
+{
+  Close();
+}
+
+AString CStdInStream::ScanStringUntilNewLine()
+{
+  AString s;
+  for (;;)
+  {
+    int intChar = GetChar();
+    if(intChar == EOF)
+      throw kEOFMessage;
+    char c = char(intChar);
+    if (c == kIllegalChar)
+      throw kIllegalCharMessage;
+    if(c == kNewLineChar)
+      break;
+    s += c;
+  }
+  return s;
+}
+
+void CStdInStream::ReadToString(AString &resultString)
+{
+  resultString.Empty();
+  int c;
+  while((c = GetChar()) != EOF)
+    resultString += char(c);
+}
+
+bool CStdInStream::Eof()
+{
+  return (feof(_stream) != 0);
+}
+
+int CStdInStream::GetChar()
+{
+  int c = fgetc(_stream); // getc() doesn't work in BeOS?
+  if(c == EOF && !Eof())
+    throw kReadErrorMessage;
+  return c;
+}
+
+

Added: trunk/lzma/CPP/Common/StdInStream.h
===================================================================
--- trunk/lzma/CPP/Common/StdInStream.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/StdInStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,31 @@
+// Common/StdInStream.h
+
+#ifndef __COMMON_STDINSTREAM_H
+#define __COMMON_STDINSTREAM_H
+
+#include <stdio.h>
+
+#include "MyString.h"
+#include "Types.h"
+
+class CStdInStream 
+{
+  bool _streamIsOpen;
+  FILE *_stream;
+public:
+  CStdInStream(): _streamIsOpen(false) {};
+  CStdInStream(FILE *stream): _streamIsOpen(false), _stream(stream) {};
+  ~CStdInStream();
+  bool Open(LPCTSTR fileName);
+  bool Close();
+
+  AString ScanStringUntilNewLine();
+  void ReadToString(AString &resultString);
+
+  bool Eof();
+  int GetChar();
+};
+
+extern CStdInStream g_StdIn;
+
+#endif

Added: trunk/lzma/CPP/Common/StdOutStream.cpp
===================================================================
--- trunk/lzma/CPP/Common/StdOutStream.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/StdOutStream.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,93 @@
+// Common/StdOutStream.cpp
+
+#include "StdAfx.h"
+
+#include <tchar.h>
+
+#include "StdOutStream.h"
+#include "IntToString.h"
+#include "StringConvert.h"
+
+#ifdef _MSC_VER
+// "was declared deprecated" disabling
+#pragma warning(disable : 4996 )
+#endif
+
+static const char kNewLineChar =  '\n';
+
+static const char *kFileOpenMode = "wt";
+
+CStdOutStream  g_StdOut(stdout);
+CStdOutStream  g_StdErr(stderr);
+
+bool CStdOutStream::Open(const char *fileName)
+{
+  Close();
+  _stream = fopen(fileName, kFileOpenMode);
+  _streamIsOpen = (_stream != 0);
+  return _streamIsOpen;
+}
+
+bool CStdOutStream::Close()
+{
+  if(!_streamIsOpen)
+    return true;
+  if (fclose(_stream) != 0)
+    return false;
+  _stream = 0;
+  _streamIsOpen = false;
+  return true;
+}
+
+bool CStdOutStream::Flush()
+{
+  return (fflush(_stream) == 0);
+}
+
+CStdOutStream::~CStdOutStream ()
+{
+  Close();
+}
+
+CStdOutStream & CStdOutStream::operator<<(CStdOutStream & (*aFunction)(CStdOutStream  &))
+{
+  (*aFunction)(*this);    
+  return *this;
+}
+
+CStdOutStream & endl(CStdOutStream & outStream)
+{
+  return outStream << kNewLineChar;
+}
+
+CStdOutStream & CStdOutStream::operator<<(const char *string)
+{
+  fputs(string, _stream);
+  return *this;
+}
+
+CStdOutStream & CStdOutStream::operator<<(const wchar_t *string)
+{
+  *this << (const char *)UnicodeStringToMultiByte(string, CP_OEMCP);
+  return *this;
+}
+
+CStdOutStream & CStdOutStream::operator<<(char c)
+{
+  fputc(c, _stream);
+  return *this;
+}
+
+CStdOutStream & CStdOutStream::operator<<(int number)
+{
+  char textString[32];
+  ConvertInt64ToString(number, textString);
+  return operator<<(textString);
+}
+
+CStdOutStream & CStdOutStream::operator<<(UInt64 number)
+{
+  char textString[32];
+  ConvertUInt64ToString(number, textString);
+  return operator<<(textString);
+}

Added: trunk/lzma/CPP/Common/StdOutStream.h
===================================================================
--- trunk/lzma/CPP/Common/StdOutStream.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/StdOutStream.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,35 @@
+// Common/StdOutStream.h
+
+#ifndef __COMMON_STDOUTSTREAM_H
+#define __COMMON_STDOUTSTREAM_H
+
+#include <stdio.h>
+
+#include "Types.h"
+
+class CStdOutStream 
+{
+  bool _streamIsOpen;
+  FILE *_stream;
+public:
+  CStdOutStream (): _streamIsOpen(false), _stream(0) {};
+  CStdOutStream (FILE *stream): _streamIsOpen(false), _stream(stream) {};
+  ~CStdOutStream ();
+  operator FILE *() { return _stream; }
+  bool Open(const char *fileName);
+  bool Close();
+  bool Flush();
+  CStdOutStream & operator<<(CStdOutStream & (* aFunction)(CStdOutStream  &));
+  CStdOutStream & operator<<(const char *string);
+  CStdOutStream & operator<<(const wchar_t *string);
+  CStdOutStream & operator<<(char c);
+  CStdOutStream & operator<<(int number);
+  CStdOutStream & operator<<(UInt64 number);
+};
+
+CStdOutStream & endl(CStdOutStream & outStream);
+
+extern CStdOutStream g_StdOut;
+extern CStdOutStream g_StdErr;
+
+#endif

Added: trunk/lzma/CPP/Common/StringConvert.cpp
===================================================================
--- trunk/lzma/CPP/Common/StringConvert.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/StringConvert.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,94 @@
+// Common/StringConvert.cpp
+
+#include "StdAfx.h"
+
+#include "StringConvert.h"
+
+#ifndef _WIN32
+#include <stdlib.h>
+#endif
+
+#ifdef _WIN32
+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)
+{
+  UString resultString;
+  if(!srcString.IsEmpty())
+  {
+    int numChars = MultiByteToWideChar(codePage, 0, srcString, 
+      srcString.Length(), resultString.GetBuffer(srcString.Length()), 
+      srcString.Length() + 1);
+    #ifndef _WIN32_WCE
+    if(numChars == 0)
+      throw 282228;
+    #endif
+    resultString.ReleaseBuffer(numChars);
+  }
+  return resultString;
+}
+
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)
+{
+  AString resultString;
+  if(!srcString.IsEmpty())
+  {
+    int numRequiredBytes = srcString.Length() * 2;
+    char defaultChar = '_';
+    int numChars = WideCharToMultiByte(codePage, 0, srcString, 
+      srcString.Length(), resultString.GetBuffer(numRequiredBytes), 
+      numRequiredBytes + 1, &defaultChar, NULL);
+    #ifndef _WIN32_WCE
+    if(numChars == 0)
+      throw 282229;
+    #endif
+    resultString.ReleaseBuffer(numChars);
+  }
+  return resultString;
+}
+
+#ifndef _WIN32_WCE
+AString SystemStringToOemString(const CSysString &srcString)
+{
+  AString result;
+  CharToOem(srcString, result.GetBuffer(srcString.Length() * 2));
+  result.ReleaseBuffer();
+  return result;
+}
+#endif
+
+#else
+
+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage)
+{
+  UString resultString;
+  for (int i = 0; i < srcString.Length(); i++)
+    resultString += wchar_t(srcString[i]);
+  /*
+  if(!srcString.IsEmpty())
+  {
+    int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1);
+    if (numChars < 0) throw "Your environment does not support UNICODE";
+    resultString.ReleaseBuffer(numChars);
+  }
+  */
+  return resultString;
+}
+
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage)
+{
+  AString resultString;
+  for (int i = 0; i < srcString.Length(); i++)
+    resultString += char(srcString[i]);
+  /*
+  if(!srcString.IsEmpty())
+  {
+    int numRequiredBytes = srcString.Length() * 6 + 1;
+    int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes);
+    if (numChars < 0) throw "Your environment does not support UNICODE";
+    resultString.ReleaseBuffer(numChars);
+  }
+  */
+  return resultString;
+}
+
+#endif
+

Added: trunk/lzma/CPP/Common/StringConvert.h
===================================================================
--- trunk/lzma/CPP/Common/StringConvert.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/StringConvert.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,71 @@
+// Common/StringConvert.h
+
+#ifndef __COMMON_STRINGCONVERT_H
+#define __COMMON_STRINGCONVERT_H
+
+#include "MyWindows.h"
+#include "MyString.h"
+#include "Types.h"
+
+UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP);
+AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP);
+
+inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString)
+  { return unicodeString; }
+inline const UString& GetUnicodeString(const UString &unicodeString)
+  { return unicodeString; }
+inline UString GetUnicodeString(const AString &ansiString)
+  { return MultiByteToUnicodeString(ansiString); }
+inline UString GetUnicodeString(const AString &multiByteString, UINT codePage)
+  { return MultiByteToUnicodeString(multiByteString, codePage); }
+inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT)
+  { return unicodeString; }
+inline const UString& GetUnicodeString(const UString &unicodeString, UINT)
+  { return unicodeString; }
+
+inline const char* GetAnsiString(const char* ansiString)
+  { return ansiString; }
+inline const AString& GetAnsiString(const AString &ansiString)
+  { return ansiString; }
+inline AString GetAnsiString(const UString &unicodeString)
+  { return UnicodeStringToMultiByte(unicodeString); }
+
+inline const char* GetOemString(const char* oemString)
+  { return oemString; }
+inline const AString& GetOemString(const AString &oemString)
+  { return oemString; }
+inline AString GetOemString(const UString &unicodeString)
+  { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); }
+
+
+#ifdef _UNICODE
+  inline const wchar_t* GetSystemString(const wchar_t* unicodeString)
+    { return unicodeString;}
+  inline const UString& GetSystemString(const UString &unicodeString)
+    { return unicodeString;}
+  inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT /* codePage */)
+    { return unicodeString;}
+  inline const UString& GetSystemString(const UString &unicodeString, UINT /* codePage */)
+    { return unicodeString;}
+  inline UString GetSystemString(const AString &multiByteString, UINT codePage)
+    { return MultiByteToUnicodeString(multiByteString, codePage);}
+  inline UString GetSystemString(const AString &multiByteString)
+    { return MultiByteToUnicodeString(multiByteString);}
+#else
+  inline const char* GetSystemString(const char *ansiString)
+    { return ansiString; }
+  inline const AString& GetSystemString(const AString &multiByteString, UINT)
+    { return multiByteString; }
+  inline const char * GetSystemString(const char *multiByteString, UINT)
+    { return multiByteString; }
+  inline AString GetSystemString(const UString &unicodeString)
+    { return UnicodeStringToMultiByte(unicodeString); }
+  inline AString GetSystemString(const UString &unicodeString, UINT codePage)
+    { return UnicodeStringToMultiByte(unicodeString, codePage); }
+#endif
+
+#ifndef _WIN32_WCE
+AString SystemStringToOemString(const CSysString &srcString);
+#endif
+
+#endif

Added: trunk/lzma/CPP/Common/StringToInt.cpp
===================================================================
--- trunk/lzma/CPP/Common/StringToInt.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/StringToInt.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,68 @@
+// Common/StringToInt.cpp
+
+#include "StdAfx.h"
+
+#include "StringToInt.h"
+
+UInt64 ConvertStringToUInt64(const char *s, const char **end)
+{
+  UInt64 result = 0;
+  for (;;)
+  {
+    char c = *s;
+    if (c < '0' || c > '9')
+    {
+      if (end != NULL)
+        *end = s;
+      return result;
+    }
+    result *= 10;
+    result += (c - '0');
+    s++;
+  }
+}
+
+UInt64 ConvertOctStringToUInt64(const char *s, const char **end)
+{
+  UInt64 result = 0;
+  for (;;)
+  {
+    char c = *s;
+    if (c < '0' || c > '7')
+    {
+      if (end != NULL)
+        *end = s;
+      return result;
+    }
+    result <<= 3;
+    result += (c - '0');
+    s++;
+  }
+}
+
+
+UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end)
+{
+  UInt64 result = 0;
+  for (;;)
+  {
+    wchar_t c = *s;
+    if (c < '0' || c > '9')
+    {
+      if (end != NULL)
+        *end = s;
+      return result;
+    }
+    result *= 10;
+    result += (c - '0');
+    s++;
+  }
+}
+
+
+Int64 ConvertStringToInt64(const char *s, const char **end)
+{
+  if (*s == '-')
+    return -(Int64)ConvertStringToUInt64(s + 1, end);
+  return ConvertStringToUInt64(s, end);
+}

Added: trunk/lzma/CPP/Common/StringToInt.h
===================================================================
--- trunk/lzma/CPP/Common/StringToInt.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/StringToInt.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,17 @@
+// Common/StringToInt.h
+
+#ifndef __COMMON_STRINGTOINT_H
+#define __COMMON_STRINGTOINT_H
+
+#include <string.h>
+#include "Types.h"
+
+UInt64 ConvertStringToUInt64(const char *s, const char **end);
+UInt64 ConvertOctStringToUInt64(const char *s, const char **end);
+UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end);
+
+Int64 ConvertStringToInt64(const char *s, const char **end);
+
+#endif
+
+

Added: trunk/lzma/CPP/Common/Types.h
===================================================================
--- trunk/lzma/CPP/Common/Types.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/Types.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,57 @@
+// Common/Types.h
+
+#ifndef __COMMON_TYPES_H
+#define __COMMON_TYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif 
+
+#ifndef _7ZIP_INT16_DEFINED
+#define _7ZIP_INT16_DEFINED
+typedef short Int16;
+#endif 
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif 
+
+#ifndef _7ZIP_INT32_DEFINED
+#define _7ZIP_INT32_DEFINED
+typedef int Int32;
+#endif 
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+typedef unsigned int UInt32;
+#endif 
+
+#ifdef _MSC_VER
+
+#ifndef _7ZIP_INT64_DEFINED
+#define _7ZIP_INT64_DEFINED
+typedef __int64 Int64;
+#endif 
+
+#ifndef _7ZIP_UINT64_DEFINED
+#define _7ZIP_UINT64_DEFINED
+typedef unsigned __int64 UInt64;
+#endif 
+
+#else
+
+#ifndef _7ZIP_INT64_DEFINED
+#define _7ZIP_INT64_DEFINED
+typedef long long int Int64;
+#endif 
+
+#ifndef _7ZIP_UINT64_DEFINED
+#define _7ZIP_UINT64_DEFINED
+typedef unsigned long long int UInt64;
+#endif 
+
+#endif
+
+#endif

Added: trunk/lzma/CPP/Common/UTFConvert.cpp
===================================================================
--- trunk/lzma/CPP/Common/UTFConvert.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/UTFConvert.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,91 @@
+// UTFConvert.cpp
+
+#include "StdAfx.h"
+
+#include "UTFConvert.h"
+#include "Types.h"
+
+static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+// These functions are for UTF8 <-> UTF16 conversion.
+
+bool ConvertUTF8ToUnicode(const AString &src, UString &dest)
+{
+  dest.Empty();
+  for(int i = 0; i < src.Length();)
+  {
+    Byte c = (Byte)src[i++];
+    if (c < 0x80)
+    {
+      dest += (wchar_t)c;
+      continue;
+    }
+    if(c < 0xC0)
+      return false;
+    int numAdds;
+    for (numAdds = 1; numAdds < 5; numAdds++)
+      if (c < kUtf8Limits[numAdds])
+        break;
+    UInt32 value = (c - kUtf8Limits[numAdds - 1]);
+    do
+    {
+      if (i >= src.Length())
+        return false;
+      Byte c2 = (Byte)src[i++];
+      if (c2 < 0x80 || c2 >= 0xC0)
+        return false;
+      value <<= 6;
+      value |= (c2 - 0x80);
+      numAdds--;
+    }
+    while(numAdds > 0);
+    if (value < 0x10000)
+      dest += (wchar_t)(value);
+    else
+    {
+      value -= 0x10000;
+      if (value >= 0x100000)
+        return false;
+      dest += (wchar_t)(0xD800 + (value >> 10));
+      dest += (wchar_t)(0xDC00 + (value & 0x3FF));
+    }
+  }
+  return true; 
+}
+
+bool ConvertUnicodeToUTF8(const UString &src, AString &dest)
+{
+  dest.Empty();
+  for(int i = 0; i < src.Length();)
+  {
+    UInt32 value = (UInt32)src[i++];
+    if (value < 0x80)
+    {
+      dest += (char)value;
+      continue;
+    }
+    if (value >= 0xD800 && value < 0xE000)
+    {
+      if (value >= 0xDC00)
+        return false;
+      if (i >= src.Length())
+        return false;
+      UInt32 c2 = (UInt32)src[i++];
+      if (c2 < 0xDC00 || c2 >= 0xE000)
+        return false;
+      value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+    }
+    int numAdds;
+    for (numAdds = 1; numAdds < 5; numAdds++)
+      if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+        break;
+    dest += (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
+    do
+    {
+      numAdds--;
+      dest += (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
+    }
+    while(numAdds > 0);
+  }
+  return true;
+}

Added: trunk/lzma/CPP/Common/UTFConvert.h
===================================================================
--- trunk/lzma/CPP/Common/UTFConvert.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/UTFConvert.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,11 @@
+// Common/UTFConvert.h
+
+#ifndef __COMMON_UTFCONVERT_H
+#define __COMMON_UTFCONVERT_H
+
+#include "MyString.h"
+
+bool ConvertUTF8ToUnicode(const AString &utfString, UString &resultString);
+bool ConvertUnicodeToUTF8(const UString &unicodeString, AString &resultString);
+
+#endif

Added: trunk/lzma/CPP/Common/Wildcard.cpp
===================================================================
--- trunk/lzma/CPP/Common/Wildcard.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Common/Wildcard.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,458 @@
+// Common/Wildcard.cpp
+
+#include "StdAfx.h"
+
+#include "Wildcard.h"
+
+bool g_CaseSensitive = 
+  #ifdef _WIN32
+    false;
+  #else
+    true;
+  #endif
+
+static const wchar_t kAnyCharsChar = L'*';
+static const wchar_t kAnyCharChar = L'?';
+
+#ifdef _WIN32
+static const wchar_t kDirDelimiter1 = L'\\';
+#endif
+static const wchar_t kDirDelimiter2 = L'/';
+
+static const UString kWildCardCharSet = L"?*";
+
+static const UString kIllegalWildCardFileNameChars=
+  L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF"
+  L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
+  L"\"/:<>\\|";
+
+
+static inline bool IsCharDirLimiter(wchar_t c)
+{
+  return (
+    #ifdef _WIN32
+    c == kDirDelimiter1 || 
+    #endif
+    c == kDirDelimiter2);
+}
+
+int CompareFileNames(const UString &s1, const UString &s2)
+{
+  if (g_CaseSensitive)
+    return s1.Compare(s2);
+  return s1.CompareNoCase(s2);
+}
+
+// -----------------------------------------
+// this function compares name with mask
+// ? - any char
+// * - any char or empty
+
+static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name)
+{
+  for (;;)
+  {
+    wchar_t m = *mask;
+    wchar_t c = *name;
+    if (m == 0) 
+      return (c == 0);
+    if (m == kAnyCharsChar)
+    {
+      if (EnhancedMaskTest(mask + 1, name))
+        return true;
+      if (c == 0) 
+        return false;
+    }
+    else
+    {
+      if (m == kAnyCharChar)
+      {
+        if (c == 0) 
+          return false;
+      }
+      else if (m != c)
+        if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c))
+          return false;
+      mask++;
+    }
+    name++;
+  }
+}
+
+// --------------------------------------------------
+// Splits path to strings
+
+void SplitPathToParts(const UString &path, UStringVector &pathParts)
+{
+  pathParts.Clear();
+  UString name;
+  int len = path.Length();
+  if (len == 0)
+    return;
+  for (int i = 0; i < len; i++)
+  {
+    wchar_t c = path[i];
+    if (IsCharDirLimiter(c))
+    {
+      pathParts.Add(name);
+      name.Empty();
+    }
+    else
+      name += c;
+  }
+  pathParts.Add(name);
+}
+
+void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name)
+{
+  int i;
+  for(i = path.Length() - 1; i >= 0; i--)
+    if(IsCharDirLimiter(path[i]))
+      break;
+  dirPrefix = path.Left(i + 1);
+  name = path.Mid(i + 1);
+}
+
+UString ExtractDirPrefixFromPath(const UString &path)
+{
+  int i;
+  for(i = path.Length() - 1; i >= 0; i--)
+    if(IsCharDirLimiter(path[i]))
+      break;
+  return path.Left(i + 1);
+}
+
+UString ExtractFileNameFromPath(const UString &path)
+{
+  int i;
+  for(i = path.Length() - 1; i >= 0; i--)
+    if(IsCharDirLimiter(path[i]))
+      break;
+  return path.Mid(i + 1);
+}
+
+
+bool CompareWildCardWithName(const UString &mask, const UString &name)
+{
+  return EnhancedMaskTest(mask, name);
+}
+
+bool DoesNameContainWildCard(const UString &path)
+{
+  return (path.FindOneOf(kWildCardCharSet) >= 0);
+}
+
+
+// ----------------------------------------------------------'
+// NWildcard
+
+namespace NWildcard {
+
+
+/*
+M = MaskParts.Size();
+N = TestNameParts.Size();
+
+                           File                          Dir
+ForFile     req   M<=N  [N-M, N)                          -
+         nonreq   M=N   [0, M)                            -  
+ 
+ForDir      req   M<N   [0, M) ... [N-M-1, N-1)  same as ForBoth-File
+         nonreq         [0, M)                   same as ForBoth-File
+
+ForBoth     req   m<=N  [0, M) ... [N-M, N)      same as ForBoth-File
+         nonreq         [0, M)                   same as ForBoth-File
+
+*/
+
+bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const
+{
+  if (!isFile && !ForDir)
+    return false;
+  int delta = (int)pathParts.Size() - (int)PathParts.Size();
+  if (delta < 0)
+    return false;
+  int start = 0;
+  int finish = 0;
+  if (isFile)
+  {
+    if (!ForDir && !Recursive && delta !=0)
+      return false;
+    if (!ForFile && delta == 0)
+      return false;
+    if (!ForDir && Recursive)
+      start = delta;
+  }
+  if (Recursive)
+  {
+    finish = delta;
+    if (isFile && !ForFile)
+      finish = delta - 1;
+  }
+  for (int d = start; d <= finish; d++)
+  {
+    int i;
+    for (i = 0; i < PathParts.Size(); i++)
+      if (!CompareWildCardWithName(PathParts[i], pathParts[i + d]))
+        break;
+    if (i == PathParts.Size())
+      return true;
+  }
+  return false;
+}
+
+int CCensorNode::FindSubNode(const UString &name) const
+{
+  for (int i = 0; i < SubNodes.Size(); i++)
+    if (CompareFileNames(SubNodes[i].Name, name) == 0)
+      return i;
+  return -1;
+}
+
+void CCensorNode::AddItemSimple(bool include, CItem &item)
+{
+  if (include)
+    IncludeItems.Add(item);
+  else
+    ExcludeItems.Add(item);
+}
+
+void CCensorNode::AddItem(bool include, CItem &item)
+{
+  if (item.PathParts.Size() <= 1)
+  {
+    AddItemSimple(include, item);
+    return;
+  }
+  const UString &front = item.PathParts.Front();
+  if (DoesNameContainWildCard(front))
+  {
+    AddItemSimple(include, item);
+    return;
+  }
+  int index = FindSubNode(front);
+  if (index < 0)
+    index = SubNodes.Add(CCensorNode(front, this));
+  item.PathParts.Delete(0);
+  SubNodes[index].AddItem(include, item);
+}
+
+void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir)
+{
+  CItem item;
+  SplitPathToParts(path, item.PathParts);
+  item.Recursive = recursive;
+  item.ForFile = forFile;
+  item.ForDir = forDir;
+  AddItem(include, item);
+}
+
+bool CCensorNode::NeedCheckSubDirs() const
+{
+  for (int i = 0; i < IncludeItems.Size(); i++)
+  {
+    const CItem &item = IncludeItems[i];
+    if (item.Recursive || item.PathParts.Size() > 1)
+      return true;
+  }
+  return false;
+}
+
+bool CCensorNode::AreThereIncludeItems() const
+{
+  if (IncludeItems.Size() > 0)
+    return true;
+  for (int i = 0; i < SubNodes.Size(); i++)
+    if (SubNodes[i].AreThereIncludeItems())
+      return true;
+  return false;
+}
+
+bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const
+{
+  const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;
+  for (int i = 0; i < items.Size(); i++)
+    if (items[i].CheckPath(pathParts, isFile))
+      return true;
+  return false;
+}
+
+bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const
+{
+  if (CheckPathCurrent(false, pathParts, isFile))
+  {
+    include = false;
+    return true;
+  }
+  include = true;
+  bool finded = CheckPathCurrent(true, pathParts, isFile);
+  if (pathParts.Size() == 1)
+    return finded;
+  int index = FindSubNode(pathParts.Front());
+  if (index >= 0)
+  {
+    UStringVector pathParts2 = pathParts;
+    pathParts2.Delete(0);
+    if (SubNodes[index].CheckPath(pathParts2, isFile, include))
+      return true;
+  }
+  return finded;
+}
+
+bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const
+{
+  UStringVector pathParts; 
+  SplitPathToParts(path, pathParts);
+  return CheckPath(pathParts, isFile, include);
+}
+
+bool CCensorNode::CheckPath(const UString &path, bool isFile) const
+{
+  bool include;
+  if(CheckPath(path, isFile, include))
+    return include;
+  return false;
+}
+
+bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const
+{
+  if (CheckPathCurrent(include, pathParts, isFile))
+    return true;
+  if (Parent == 0)
+    return false;
+  pathParts.Insert(0, Name);
+  return Parent->CheckPathToRoot(include, pathParts, isFile);
+}
+
+/*
+bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const
+{
+  UStringVector pathParts; 
+  SplitPathToParts(path, pathParts);
+  return CheckPathToRoot(include, pathParts, isFile);
+}
+*/
+
+void CCensorNode::AddItem2(bool include, const UString &path, bool recursive)
+{
+  if (path.IsEmpty())
+    return;
+  bool forFile = true;
+  bool forFolder = true;
+  UString path2 = path;
+  if (IsCharDirLimiter(path[path.Length() - 1]))
+  {
+    path2.Delete(path.Length() - 1);
+    forFile = false;
+  }
+  AddItem(include, path2, recursive, forFile, forFolder);
+}
+
+void CCensorNode::ExtendExclude(const CCensorNode &fromNodes)
+{
+  ExcludeItems += fromNodes.ExcludeItems;
+  for (int i = 0; i < fromNodes.SubNodes.Size(); i++)
+  {
+    const CCensorNode &node = fromNodes.SubNodes[i];
+    int subNodeIndex = FindSubNode(node.Name);
+    if (subNodeIndex < 0)
+      subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this));
+    SubNodes[subNodeIndex].ExtendExclude(node);
+  }
+}
+
+int CCensor::FindPrefix(const UString &prefix) const
+{
+  for (int i = 0; i < Pairs.Size(); i++)
+    if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)
+      return i;
+  return -1;
+}
+
+void CCensor::AddItem(bool include, const UString &path, bool recursive)
+{
+  UStringVector pathParts;
+  SplitPathToParts(path, pathParts);
+  bool forFile = true;
+  if (pathParts.Back().IsEmpty())
+  {
+    forFile = false;
+    pathParts.DeleteBack();
+  }
+  const UString &front = pathParts.Front();
+  bool isAbs = false;
+  if (front.IsEmpty())
+    isAbs = true;
+  else if (front.Length() == 2 && front[1] == L':')
+    isAbs = true;
+  else
+  {
+    for (int i = 0; i < pathParts.Size(); i++)
+    {
+      const UString &part = pathParts[i];
+      if (part == L".." || part == L".")
+      {
+        isAbs = true;
+        break;
+      }
+    }
+  }
+  int numAbsParts = 0;
+  if (isAbs)
+    if (pathParts.Size() > 1)
+      numAbsParts = pathParts.Size() - 1;
+    else
+      numAbsParts = 1;
+  UString prefix;
+  for (int i = 0; i < numAbsParts; i++)
+  {
+    const UString &front = pathParts.Front();
+    if (DoesNameContainWildCard(front))
+      break;
+    prefix += front;
+    prefix += WCHAR_PATH_SEPARATOR;
+    pathParts.Delete(0);
+  }
+  int index = FindPrefix(prefix);
+  if (index < 0)
+    index = Pairs.Add(CPair(prefix));
+
+  CItem item;
+  item.PathParts = pathParts;
+  item.ForDir = true;
+  item.ForFile = forFile;
+  item.Recursive = recursive;
+  Pairs[index].Head.AddItem(include, item);
+}
+
+bool CCensor::CheckPath(const UString &path, bool isFile) const
+{
+  bool finded = false;
+  for (int i = 0; i < Pairs.Size(); i++)
+  {
+    bool include;
+    if (Pairs[i].Head.CheckPath(path, isFile, include))
+    {
+      if (!include)
+        return false;
+      finded = true;
+    }
+  }
+  return finded;
+}
+
+void CCensor::ExtendExclude()
+{
+  int i;
+  for (i = 0; i < Pairs.Size(); i++)
+    if (Pairs[i].Prefix.IsEmpty())
+      break;
+  if (i == Pairs.Size())
+    return;
+  int index = i;
+  for (i = 0; i < Pairs.Size(); i++)
+    if (index != i)
+      Pairs[i].Head.ExtendExclude(Pairs[index].Head);
+}
+
+}

Added: trunk/lzma/CPP/Common/Wildcard.h
===================================================================
--- trunk/lzma/CPP/Common/Wildcard.h	                        (rev 0)
+++ trunk/lzma/CPP/Common/Wildcard.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,80 @@
+// Common/Wildcard.h
+
+#ifndef __COMMON_WILDCARD_H
+#define __COMMON_WILDCARD_H
+
+#include "MyString.h"
+
+int CompareFileNames(const UString &s1, const UString &s2);
+
+void SplitPathToParts(const UString &path, UStringVector &pathParts);
+void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name);
+UString ExtractDirPrefixFromPath(const UString &path);
+UString ExtractFileNameFromPath(const UString &path);
+bool DoesNameContainWildCard(const UString &path);
+bool CompareWildCardWithName(const UString &mask, const UString &name);
+
+namespace NWildcard {
+
+struct CItem
+{
+  UStringVector PathParts;
+  bool Recursive;
+  bool ForFile;
+  bool ForDir;
+  bool CheckPath(const UStringVector &pathParts, bool isFile) const;
+};
+
+class CCensorNode
+{
+  CCensorNode *Parent;
+  bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;
+  void AddItemSimple(bool include, CItem &item);
+  bool CheckPath(UStringVector &pathParts, bool isFile, bool &include) const;
+public:
+  CCensorNode(): Parent(0) { };
+  CCensorNode(const UString &name, CCensorNode *parent): Name(name), Parent(parent) { };
+  UString Name;
+  CObjectVector<CCensorNode> SubNodes;
+  CObjectVector<CItem> IncludeItems;
+  CObjectVector<CItem> ExcludeItems;
+
+  int FindSubNode(const UString &path) const;
+
+  void AddItem(bool include, CItem &item);
+  void AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir);
+  void AddItem2(bool include, const UString &path, bool recursive);
+
+  bool NeedCheckSubDirs() const;
+  bool AreThereIncludeItems() const;
+
+  bool CheckPath(const UString &path, bool isFile, bool &include) const;
+  bool CheckPath(const UString &path, bool isFile) const;
+
+  bool CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const;
+  // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const;
+  void ExtendExclude(const CCensorNode &fromNodes);
+};
+
+struct CPair
+{
+  UString Prefix;
+  CCensorNode Head;
+  CPair(const UString &prefix): Prefix(prefix) { };
+};
+
+class CCensor
+{
+  int FindPrefix(const UString &prefix) const;
+public:
+  CObjectVector<CPair> Pairs;
+  bool AllAreRelative() const
+    { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }
+  void AddItem(bool include, const UString &path, bool recursive);
+  bool CheckPath(const UString &path, bool isFile) const;
+  void ExtendExclude();
+};
+
+}
+
+#endif

Added: trunk/lzma/CPP/Windows/DLL.cpp
===================================================================
--- trunk/lzma/CPP/Windows/DLL.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/DLL.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,115 @@
+// Windows/DLL.cpp
+
+#include "StdAfx.h"
+
+#include "DLL.h"
+#include "Defs.h"
+#ifndef _UNICODE
+#include "../Common/StringConvert.h"
+#endif
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+namespace NWindows {
+namespace NDLL {
+
+CLibrary::~CLibrary()
+{
+  Free();
+}
+
+bool CLibrary::Free()
+{
+  if (_module == 0)
+    return true;
+  // MessageBox(0, TEXT(""), TEXT("Free"), 0);
+  // Sleep(5000);
+  if (!::FreeLibrary(_module))
+    return false;
+  _module = 0;
+  return true;
+}
+
+bool CLibrary::LoadOperations(HMODULE newModule)
+{
+  if (newModule == NULL)
+    return false;
+  if(!Free())
+    return false;
+  _module = newModule;
+  return true;
+}
+
+bool CLibrary::LoadEx(LPCTSTR fileName, DWORD flags)
+{
+  // MessageBox(0, fileName, TEXT("LoadEx"), 0);
+  return LoadOperations(::LoadLibraryEx(fileName, NULL, flags));
+}
+
+bool CLibrary::Load(LPCTSTR fileName)
+{
+  // MessageBox(0, fileName, TEXT("Load"), 0);
+  // Sleep(5000);
+  // OutputDebugString(fileName);
+  // OutputDebugString(TEXT("\n"));
+  return LoadOperations(::LoadLibrary(fileName));
+}
+
+#ifndef _UNICODE
+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } 
+CSysString GetSysPath(LPCWSTR sysPath)
+  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }
+
+bool CLibrary::LoadEx(LPCWSTR fileName, DWORD flags)
+{
+  if (g_IsNT)
+    return LoadOperations(::LoadLibraryExW(fileName, NULL, flags));
+  return LoadEx(GetSysPath(fileName), flags);
+}
+bool CLibrary::Load(LPCWSTR fileName)
+{
+  if (g_IsNT)
+    return LoadOperations(::LoadLibraryW(fileName));
+  return Load(GetSysPath(fileName));
+}
+#endif
+
+bool MyGetModuleFileName(HMODULE hModule, CSysString &result)
+{
+  result.Empty();
+  TCHAR fullPath[MAX_PATH + 2];
+  DWORD size = ::GetModuleFileName(hModule, fullPath, MAX_PATH + 1);
+  if (size <= MAX_PATH && size != 0)
+  {
+    result = fullPath;
+    return true;
+  }
+  return false;
+}
+
+#ifndef _UNICODE
+bool MyGetModuleFileName(HMODULE hModule, UString &result)
+{
+  result.Empty();
+  if (g_IsNT)
+  {
+    wchar_t fullPath[MAX_PATH + 2];
+    DWORD size = ::GetModuleFileNameW(hModule, fullPath, MAX_PATH + 1);
+    if (size <= MAX_PATH && size != 0)
+    {
+      result = fullPath;
+      return true;
+    }
+    return false;
+  }
+  CSysString resultSys;
+  if (!MyGetModuleFileName(hModule, resultSys))
+    return false;
+  result = MultiByteToUnicodeString(resultSys, GetCurrentCodePage());
+  return true;
+}
+#endif
+
+}}

Added: trunk/lzma/CPP/Windows/DLL.h
===================================================================
--- trunk/lzma/CPP/Windows/DLL.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/DLL.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,54 @@
+// Windows/DLL.h
+
+#ifndef __WINDOWS_DLL_H
+#define __WINDOWS_DLL_H
+
+#include "../Common/MyString.h"
+
+namespace NWindows {
+namespace NDLL {
+
+class CLibrary
+{
+  bool LoadOperations(HMODULE newModule);
+protected:
+  HMODULE _module;
+public:
+  operator HMODULE() const { return _module; }
+  HMODULE* operator&() { return &_module; }
+
+  CLibrary():_module(NULL) {};
+  ~CLibrary();
+  void Attach(HMODULE m)
+  {
+    Free();
+    _module = m;
+  }
+  HMODULE Detach()
+  {
+    HMODULE m = _module;
+    _module = NULL;
+    return m;
+  }
+
+  // operator HMODULE() const { return _module; };
+  bool IsLoaded() const { return (_module != NULL); };
+  bool Free();
+  bool LoadEx(LPCTSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE);
+  bool Load(LPCTSTR fileName);
+  #ifndef _UNICODE
+  bool LoadEx(LPCWSTR fileName, DWORD flags = LOAD_LIBRARY_AS_DATAFILE);
+  bool Load(LPCWSTR fileName);
+  #endif
+  FARPROC GetProcAddress(LPCSTR procName) const
+    { return ::GetProcAddress(_module, procName); }
+};
+
+bool MyGetModuleFileName(HMODULE hModule, CSysString &result);
+#ifndef _UNICODE
+bool MyGetModuleFileName(HMODULE hModule, UString &result);
+#endif
+
+}}
+
+#endif

Added: trunk/lzma/CPP/Windows/Defs.h
===================================================================
--- trunk/lzma/CPP/Windows/Defs.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/Defs.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,23 @@
+// Windows/Defs.h
+
+#ifndef __WINDOWS_DEFS_H
+#define __WINDOWS_DEFS_H
+
+inline bool BOOLToBool(BOOL value)
+  { return (value != FALSE); }
+
+#ifdef _WIN32
+inline bool LRESULTToBool(LRESULT value)
+  { return (value != FALSE); }
+#endif
+
+inline BOOL BoolToBOOL(bool value)
+  { return (value ? TRUE: FALSE); }
+
+inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value)
+  { return (value ? VARIANT_TRUE: VARIANT_FALSE); }
+
+inline bool VARIANT_BOOLToBool(VARIANT_BOOL value)
+  { return (value != VARIANT_FALSE); }
+
+#endif

Added: trunk/lzma/CPP/Windows/Error.cpp
===================================================================
--- trunk/lzma/CPP/Windows/Error.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/Error.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,50 @@
+// Windows/Error.h
+
+#include "StdAfx.h"
+
+#include "Windows/Error.h"
+#ifndef _UNICODE
+#include "Common/StringConvert.h"
+#endif
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+namespace NWindows {
+namespace NError {
+
+bool MyFormatMessage(DWORD messageID, CSysString &message)
+{
+  LPVOID msgBuf;
+  if(::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+      NULL,messageID, 0, (LPTSTR) &msgBuf,0, NULL) == 0)
+    return false;
+  message = (LPCTSTR)msgBuf;
+  ::LocalFree(msgBuf);
+  return true;
+}
+
+#ifndef _UNICODE
+bool MyFormatMessage(DWORD messageID, UString &message)
+{
+  if (g_IsNT)
+  {
+    LPVOID msgBuf;
+    if(::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+        NULL, messageID, 0, (LPWSTR) &msgBuf, 0, NULL) == 0)
+      return false;
+    message = (LPCWSTR)msgBuf;
+    ::LocalFree(msgBuf);
+    return true;
+  }
+  CSysString messageSys;
+  bool result = MyFormatMessage(messageID, messageSys);
+  message = GetUnicodeString(messageSys);
+  return result;
+}
+#endif
+
+}}

Added: trunk/lzma/CPP/Windows/Error.h
===================================================================
--- trunk/lzma/CPP/Windows/Error.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/Error.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,33 @@
+// Windows/Error.h
+
+#ifndef __WINDOWS_ERROR_H
+#define __WINDOWS_ERROR_H
+
+#include "Common/MyString.h"
+
+namespace NWindows {
+namespace NError {
+
+bool MyFormatMessage(DWORD messageID, CSysString &message);
+inline CSysString MyFormatMessage(DWORD messageID)
+{
+  CSysString message;
+  MyFormatMessage(messageID, message);
+  return message;
+}
+#ifdef _UNICODE
+inline UString MyFormatMessageW(DWORD messageID)
+  { return MyFormatMessage(messageID); }
+#else
+bool MyFormatMessage(DWORD messageID, UString &message);
+inline UString MyFormatMessageW(DWORD messageID)
+{
+  UString message;
+  MyFormatMessage(messageID, message);
+  return message;
+}
+#endif
+
+}}
+
+#endif

Added: trunk/lzma/CPP/Windows/FileDir.cpp
===================================================================
--- trunk/lzma/CPP/Windows/FileDir.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileDir.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,841 @@
+// Windows/FileDir.cpp
+
+#include "StdAfx.h"
+
+#include "FileDir.h"
+#include "FileName.h"
+#include "FileFind.h"
+#include "Defs.h"
+#ifndef _UNICODE
+#include "../Common/StringConvert.h"
+#endif
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+namespace NWindows {
+namespace NFile {
+
+#if defined(WIN_LONG_PATH) && defined(_UNICODE)
+#define WIN_LONG_PATH2
+#endif
+
+// SetCurrentDirectory doesn't support \\?\ prefix
+
+#ifdef WIN_LONG_PATH
+bool GetLongPathBase(LPCWSTR fileName, UString &res);
+bool GetLongPath(LPCWSTR fileName, UString &res);
+#endif
+
+namespace NDirectory {
+
+#ifndef _UNICODE
+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } 
+static UString GetUnicodePath(const CSysString &sysPath)
+  { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); }
+static CSysString GetSysPath(LPCWSTR sysPath)
+  { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }
+#endif
+
+bool MyGetWindowsDirectory(CSysString &path)
+{
+  UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+  path.ReleaseBuffer();
+  return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+bool MyGetSystemDirectory(CSysString &path)
+{
+  UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+  path.ReleaseBuffer();
+  return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+#ifndef _UNICODE
+bool MyGetWindowsDirectory(UString &path)
+{
+  if (g_IsNT)
+  {
+    UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+    path.ReleaseBuffer();
+    return (needLength > 0 && needLength <= MAX_PATH);
+  }
+  CSysString sysPath;
+  if (!MyGetWindowsDirectory(sysPath))
+    return false;
+  path = GetUnicodePath(sysPath);
+  return true;
+}
+
+bool MyGetSystemDirectory(UString &path)
+{
+  if (g_IsNT)
+  {
+    UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+    path.ReleaseBuffer();
+    return (needLength > 0 && needLength <= MAX_PATH);
+  }
+  CSysString sysPath;
+  if (!MyGetSystemDirectory(sysPath))
+    return false;
+  path = GetUnicodePath(sysPath);
+  return true;
+}
+#endif
+
+bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime)
+{
+  #ifndef _UNICODE
+  if (!g_IsNT)
+  {
+    ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return false;
+  }
+  #endif 
+  HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE,
+      FILE_SHARE_READ | FILE_SHARE_WRITE,
+      NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+  #ifdef WIN_LONG_PATH
+  if (hDir == INVALID_HANDLE_VALUE)
+  {
+    UString longPath;
+    if (GetLongPath(fileName, longPath))
+      hDir = ::CreateFileW(longPath, GENERIC_WRITE,
+        FILE_SHARE_READ | FILE_SHARE_WRITE,
+        NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+  }
+  #endif
+
+  bool res = false;
+  if (hDir != INVALID_HANDLE_VALUE)
+  {
+    res = BOOLToBool(::SetFileTime(hDir, creationTime, lastAccessTime, lastWriteTime));
+    ::CloseHandle(hDir);
+  }
+  return res;
+}
+
+bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes)
+{
+  if (::SetFileAttributes(fileName, fileAttributes))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  UString longPath;
+  if (GetLongPath(fileName, longPath))
+    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));
+  #endif
+  return false;
+}
+
+bool MyRemoveDirectory(LPCTSTR pathName)
+{ 
+  if (::RemoveDirectory(pathName))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  UString longPath;
+  if (GetLongPath(pathName, longPath))
+    return BOOLToBool(::RemoveDirectoryW(longPath));
+  #endif
+  return false;
+}
+
+#ifdef WIN_LONG_PATH
+bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2)
+{
+  if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2))
+    return false;
+  if (d1.IsEmpty() && d2.IsEmpty()) return false;
+  if (d1.IsEmpty()) d1 = s1;
+  if (d2.IsEmpty()) d2 = s2;
+  return true;
+}
+#endif
+
+bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName)
+{ 
+  if (::MoveFile(existFileName, newFileName))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  UString d1, d2;
+  if (GetLongPaths(existFileName, newFileName, d1, d2)) 
+    return BOOLToBool(::MoveFileW(d1, d2));
+  #endif
+  return false;
+}
+
+#ifndef _UNICODE
+bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes)
+{  
+  if (!g_IsNT)
+    return MySetFileAttributes(GetSysPath(fileName), fileAttributes);
+  if (::SetFileAttributesW(fileName, fileAttributes))
+    return true;
+  #ifdef WIN_LONG_PATH
+  UString longPath;
+  if (GetLongPath(fileName, longPath))
+    return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));
+  #endif
+  return false;
+}
+
+
+bool MyRemoveDirectory(LPCWSTR pathName)
+{  
+  if (!g_IsNT)
+    return MyRemoveDirectory(GetSysPath(pathName));
+  if (::RemoveDirectoryW(pathName))
+    return true;
+  #ifdef WIN_LONG_PATH
+  UString longPath;
+  if (GetLongPath(pathName, longPath))
+    return BOOLToBool(::RemoveDirectoryW(longPath));
+  #endif
+  return false;
+}
+
+bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName)
+{  
+  if (!g_IsNT)
+    return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName));
+  if (::MoveFileW(existFileName, newFileName))
+    return true;
+  #ifdef WIN_LONG_PATH
+  UString d1, d2;
+  if (GetLongPaths(existFileName, newFileName, d1, d2)) 
+    return BOOLToBool(::MoveFileW(d1, d2));
+  #endif
+  return false;
+}
+#endif
+
+bool MyCreateDirectory(LPCTSTR pathName) 
+{ 
+  if (::CreateDirectory(pathName, NULL))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  if (::GetLastError() != ERROR_ALREADY_EXISTS)
+  {
+    UString longPath;
+    if (GetLongPath(pathName, longPath))
+      return BOOLToBool(::CreateDirectoryW(longPath, NULL));
+  }
+  #endif
+  return false;
+}
+
+#ifndef _UNICODE
+bool MyCreateDirectory(LPCWSTR pathName)
+{  
+  if (!g_IsNT)
+    return MyCreateDirectory(GetSysPath(pathName));
+  if (::CreateDirectoryW(pathName, NULL))
+    return true;
+  #ifdef WIN_LONG_PATH
+  if (::GetLastError() != ERROR_ALREADY_EXISTS)
+  {
+    UString longPath;
+    if (GetLongPath(pathName, longPath))
+      return BOOLToBool(::CreateDirectoryW(longPath, NULL));
+  }
+  #endif
+  return false;
+}
+#endif
+
+/*
+bool CreateComplexDirectory(LPCTSTR pathName)
+{
+  NName::CParsedPath path;
+  path.ParsePath(pathName);
+  CSysString fullPath = path.Prefix;
+  DWORD errorCode = ERROR_SUCCESS;
+  for(int i = 0; i < path.PathParts.Size(); i++)
+  {
+    const CSysString &string = path.PathParts[i];
+    if(string.IsEmpty())
+    {
+      if(i != path.PathParts.Size() - 1)
+        return false;
+      return true;
+    }
+    fullPath += path.PathParts[i];
+    if (!MyCreateDirectory(fullPath))
+    {
+      DWORD errorCode = GetLastError();
+      if(errorCode != ERROR_ALREADY_EXISTS)
+        return false;
+    }
+    fullPath += NName::kDirDelimiter;
+  }
+  return true;
+}
+*/
+
+bool CreateComplexDirectory(LPCTSTR _aPathName)
+{
+  CSysString pathName = _aPathName;
+  int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
+  if (pos > 0 && pos == pathName.Length() - 1)
+  {
+    if (pathName.Length() == 3 && pathName[1] == ':')
+      return true; // Disk folder;
+    pathName.Delete(pos);
+  }
+  CSysString pathName2 = pathName;
+  pos = pathName.Length();
+  for (;;)
+  {
+    if(MyCreateDirectory(pathName))
+      break;
+    if (::GetLastError() == ERROR_ALREADY_EXISTS)
+    {
+      NFind::CFileInfo fileInfo;
+      if (!NFind::FindFile(pathName, fileInfo)) // For network folders
+        return true;
+      if (!fileInfo.IsDirectory())
+        return false;
+      break;
+    }
+    pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
+    if (pos < 0 || pos == 0)
+      return false;
+    if (pathName[pos - 1] == ':')
+      return false;
+    pathName = pathName.Left(pos);
+  }
+  pathName = pathName2;
+  while(pos < pathName.Length())
+  {
+    pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1);
+    if (pos < 0)
+      pos = pathName.Length();
+    if (!MyCreateDirectory(pathName.Left(pos)))
+      return false;
+  }
+  return true;
+}
+
+#ifndef _UNICODE
+
+bool CreateComplexDirectory(LPCWSTR _aPathName)
+{
+  UString pathName = _aPathName;
+  int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);
+  if (pos > 0 && pos == pathName.Length() - 1)
+  {
+    if (pathName.Length() == 3 && pathName[1] == L':')
+      return true; // Disk folder;
+    pathName.Delete(pos);
+  }
+  UString pathName2 = pathName;
+  pos = pathName.Length();
+  for (;;)
+  {
+    if(MyCreateDirectory(pathName))
+      break;
+    if (::GetLastError() == ERROR_ALREADY_EXISTS)
+    {
+      NFind::CFileInfoW fileInfo;
+      if (!NFind::FindFile(pathName, fileInfo)) // For network folders
+        return true;
+      if (!fileInfo.IsDirectory())
+        return false;
+      break;
+    }
+    pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);
+    if (pos < 0 || pos == 0)
+      return false;
+    if (pathName[pos - 1] == L':')
+      return false;
+    pathName = pathName.Left(pos);
+  }
+  pathName = pathName2;
+  while(pos < pathName.Length())
+  {
+    pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1);
+    if (pos < 0)
+      pos = pathName.Length();
+    if (!MyCreateDirectory(pathName.Left(pos)))
+      return false;
+  }
+  return true;
+}
+
+#endif
+
+bool DeleteFileAlways(LPCTSTR name)
+{
+  if (!MySetFileAttributes(name, 0))
+    return false;
+  if (::DeleteFile(name))
+    return true;
+  #ifdef WIN_LONG_PATH2
+  UString longPath;
+  if (GetLongPath(name, longPath))
+    return BOOLToBool(::DeleteFileW(longPath));
+  #endif
+  return false;
+}
+
+#ifndef _UNICODE
+bool DeleteFileAlways(LPCWSTR name)
+{  
+  if (!g_IsNT)
+    return DeleteFileAlways(GetSysPath(name));
+  if (!MySetFileAttributes(name, 0))
+    return false;
+  if (::DeleteFileW(name))
+    return true;
+  #ifdef WIN_LONG_PATH
+  UString longPath;
+  if (GetLongPath(name, longPath))
+    return BOOLToBool(::DeleteFileW(longPath));
+  #endif
+  return false;
+}
+#endif
+
+static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo)
+{
+  if(fileInfo.IsDirectory())
+    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
+  return DeleteFileAlways(pathPrefix + fileInfo.Name);
+}
+
+bool RemoveDirectoryWithSubItems(const CSysString &path)
+{
+  NFind::CFileInfo fileInfo;
+  CSysString pathPrefix = path + NName::kDirDelimiter;
+  {
+    NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard));
+    while(enumerator.Next(fileInfo))
+      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))
+        return false;
+  }
+  if (!MySetFileAttributes(path, 0))
+    return false;
+  return MyRemoveDirectory(path);
+}
+
+#ifndef _UNICODE
+static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo)
+{
+  if(fileInfo.IsDirectory())
+    return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
+  return DeleteFileAlways(pathPrefix + fileInfo.Name);
+}
+bool RemoveDirectoryWithSubItems(const UString &path)
+{
+  NFind::CFileInfoW fileInfo;
+  UString pathPrefix = path + UString(NName::kDirDelimiter);
+  {
+    NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard));
+    while(enumerator.Next(fileInfo))
+      if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))
+        return false;
+  }
+  if (!MySetFileAttributes(path, 0))
+    return false;
+  return MyRemoveDirectory(path);
+}
+#endif
+
+#ifndef _WIN32_WCE
+
+bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath)
+{
+  DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
+  shortPath.ReleaseBuffer();
+  return (needLength > 0 && needLength < MAX_PATH);
+}
+
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex)
+{
+  resultPath.Empty();
+  LPTSTR fileNamePointer = 0;
+  LPTSTR buffer = resultPath.GetBuffer(MAX_PATH);
+  DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer);
+  resultPath.ReleaseBuffer();
+  if (needLength == 0)
+    return false;
+  if (needLength >= MAX_PATH)
+  {
+    #ifdef WIN_LONG_PATH2
+    needLength++;
+    buffer = resultPath.GetBuffer(needLength + 1);
+    DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);
+    resultPath.ReleaseBuffer();
+    if (needLength2 == 0 || needLength2 > needLength)
+    #endif
+      return false;
+  }
+  if (fileNamePointer == 0)
+    fileNamePartStartIndex = lstrlen(fileName);
+  else
+    fileNamePartStartIndex = (int)(fileNamePointer - buffer);
+  return true;
+}
+
+#ifndef _UNICODE
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)
+{
+  resultPath.Empty();
+  if (g_IsNT)
+  {
+    LPWSTR fileNamePointer = 0;
+    LPWSTR buffer = resultPath.GetBuffer(MAX_PATH);
+    DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer);
+    resultPath.ReleaseBuffer();
+    if (needLength == 0)
+      return false;
+    if (needLength >= MAX_PATH)
+    {
+      #ifdef WIN_LONG_PATH
+      needLength++;
+      buffer = resultPath.GetBuffer(needLength + 1);
+      DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);
+      resultPath.ReleaseBuffer();
+      if (needLength2 == 0 || needLength2 > needLength)
+      #endif
+        return false;
+    }
+    if (fileNamePointer == 0)
+      fileNamePartStartIndex = MyStringLen(fileName);
+    else
+      fileNamePartStartIndex = (int)(fileNamePointer - buffer);
+  }
+  else
+  {
+    CSysString sysPath;
+    if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex))
+      return false;
+    UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex));
+    UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex));
+    fileNamePartStartIndex = resultPath1.Length();
+    resultPath = resultPath1 + resultPath2;
+  }
+  return true;
+}
+#endif
+
+
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &path)
+{
+  int index;
+  return MyGetFullPathName(fileName, path, index);
+}
+
+#ifndef _UNICODE
+bool MyGetFullPathName(LPCWSTR fileName, UString &path)
+{
+  int index;
+  return MyGetFullPathName(fileName, path, index);
+}
+#endif
+
+bool GetOnlyName(LPCTSTR fileName, CSysString &resultName)
+{
+  int index;
+  if (!MyGetFullPathName(fileName, resultName, index))
+    return false;
+  resultName = resultName.Mid(index);
+  return true;
+}
+
+#ifndef _UNICODE
+bool GetOnlyName(LPCWSTR fileName, UString &resultName)
+{
+  int index;
+  if (!MyGetFullPathName(fileName, resultName, index))
+    return false;
+  resultName = resultName.Mid(index);
+  return true;
+}
+#endif
+
+bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName)
+{
+  int index;
+  if (!MyGetFullPathName(fileName, resultName, index))
+    return false;
+  resultName = resultName.Left(index);
+  return true;
+}
+
+#ifndef _UNICODE
+bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName)
+{
+  int index;
+  if (!MyGetFullPathName(fileName, resultName, index))
+    return false;
+  resultName = resultName.Left(index);
+  return true;
+}
+#endif
+
+bool MyGetCurrentDirectory(CSysString &path)
+{
+  DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
+  path.ReleaseBuffer();
+  return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+#ifndef _UNICODE
+bool MySetCurrentDirectory(LPCWSTR path)
+{
+  if (g_IsNT)
+    return BOOLToBool(::SetCurrentDirectoryW(path));
+  return MySetCurrentDirectory(GetSysPath(path));
+}
+bool MyGetCurrentDirectory(UString &path)
+{
+  if (g_IsNT)
+  {
+    DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
+    path.ReleaseBuffer();
+    return (needLength > 0 && needLength <= MAX_PATH);
+  }
+  CSysString sysPath;
+  if (!MyGetCurrentDirectory(sysPath))
+    return false;
+  path = GetUnicodePath(sysPath);
+  return true;
+}
+#endif
+#endif
+
+bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, 
+  CSysString &resultPath, UINT32 &filePart)
+{
+  LPTSTR filePartPointer;
+  DWORD value = ::SearchPath(path, fileName, extension, 
+    MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);
+  filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath);
+  resultPath.ReleaseBuffer();
+  return (value > 0 && value <= MAX_PATH);
+}
+
+#ifndef _UNICODE
+bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, 
+  UString &resultPath, UINT32 &filePart)
+{
+  if (g_IsNT)
+  {
+    LPWSTR filePartPointer = 0;
+    DWORD value = ::SearchPathW(path, fileName, extension, 
+        MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);
+    filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath);
+    resultPath.ReleaseBuffer();
+    return (value > 0 && value <= MAX_PATH);
+  }
+  
+  CSysString sysPath;
+  if (!MySearchPath(
+      path != 0 ? (LPCTSTR)GetSysPath(path): 0,
+      fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0,
+      extension != 0 ? (LPCTSTR)GetSysPath(extension): 0,
+      sysPath, filePart))
+    return false;
+  UString resultPath1 = GetUnicodePath(sysPath.Left(filePart));
+  UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart));
+  filePart = resultPath1.Length();
+  resultPath = resultPath1 + resultPath2;
+  return true;
+}
+#endif
+
+bool MyGetTempPath(CSysString &path)
+{
+  DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
+  path.ReleaseBuffer();
+  return (needLength > 0 && needLength <= MAX_PATH);
+}
+
+#ifndef _UNICODE
+bool MyGetTempPath(UString &path)
+{
+  path.Empty();
+  if (g_IsNT)
+  {
+    DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
+    path.ReleaseBuffer();
+    return (needLength > 0 && needLength <= MAX_PATH);
+  }
+  CSysString sysPath;
+  if (!MyGetTempPath(sysPath))
+    return false;
+  path = GetUnicodePath(sysPath);
+  return true;
+}
+#endif
+
+UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path)
+{
+  UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1));
+  path.ReleaseBuffer();
+  return number;
+}
+
+#ifndef _UNICODE
+UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path)
+{
+  if (g_IsNT)
+  {
+    UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH));
+    path.ReleaseBuffer();
+    return number;
+  }
+  CSysString sysPath;
+  UINT number = MyGetTempFileName(
+      dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, 
+      prefix ? (LPCTSTR)GetSysPath(prefix): 0, 
+      sysPath);
+  path = GetUnicodePath(sysPath);
+  return number;
+}
+#endif
+
+UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath)
+{
+  Remove();
+  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);
+  if(number != 0)
+  {
+    _fileName = resultPath;
+    _mustBeDeleted = true;
+  }
+  return number;
+}
+
+bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath)
+{
+  CSysString tempPath;
+  if (!MyGetTempPath(tempPath))
+    return false;
+  if (Create(tempPath, prefix, resultPath) != 0)
+    return true;
+  if (!MyGetWindowsDirectory(tempPath))
+    return false;
+  return (Create(tempPath, prefix, resultPath) != 0);
+}
+
+bool CTempFile::Remove()
+{
+  if (!_mustBeDeleted)
+    return true;
+  _mustBeDeleted = !DeleteFileAlways(_fileName);
+  return !_mustBeDeleted;
+}
+
+#ifndef _UNICODE
+
+UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath)
+{
+  Remove();
+  UINT number = MyGetTempFileName(dirPath, prefix, resultPath);
+  if(number != 0)
+  {
+    _fileName = resultPath;
+    _mustBeDeleted = true;
+  }
+  return number;
+}
+
+bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath)
+{
+  UString tempPath;
+  if (!MyGetTempPath(tempPath))
+    return false;
+  if (Create(tempPath, prefix, resultPath) != 0)
+    return true;
+  if (!MyGetWindowsDirectory(tempPath))
+    return false;
+  return (Create(tempPath, prefix, resultPath) != 0);
+}
+
+bool CTempFileW::Remove()
+{
+  if (!_mustBeDeleted)
+    return true;
+  _mustBeDeleted = !DeleteFileAlways(_fileName);
+  return !_mustBeDeleted;
+}
+
+#endif
+
+bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName)
+{
+  /*
+  CSysString prefix = tempPath + prefixChars;
+  CRandom random;
+  random.Init();
+  */
+  for (;;)
+  {
+    CTempFile tempFile;
+    if (!tempFile.Create(prefix, dirName))
+      return false;
+    if (!::DeleteFile(dirName))
+      return false;
+    /*
+    UINT32 randomNumber = random.Generate();
+    TCHAR randomNumberString[32];
+    _stprintf(randomNumberString, _T("%04X"), randomNumber);
+    dirName = prefix + randomNumberString;
+    */
+    if(NFind::DoesFileExist(dirName))
+      continue;
+    if (MyCreateDirectory(dirName))
+      return true;
+    if (::GetLastError() != ERROR_ALREADY_EXISTS)
+      return false;
+  }
+}
+
+bool CTempDirectory::Create(LPCTSTR prefix)
+{ 
+  Remove();
+  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); 
+}
+
+#ifndef _UNICODE
+
+bool CreateTempDirectory(LPCWSTR prefix, UString &dirName)
+{
+  /*
+  CSysString prefix = tempPath + prefixChars;
+  CRandom random;
+  random.Init();
+  */
+  for (;;)
+  {
+    CTempFileW tempFile;
+    if (!tempFile.Create(prefix, dirName))
+      return false;
+    if (!DeleteFileAlways(dirName))
+      return false;
+    /*
+    UINT32 randomNumber = random.Generate();
+    TCHAR randomNumberString[32];
+    _stprintf(randomNumberString, _T("%04X"), randomNumber);
+    dirName = prefix + randomNumberString;
+    */
+    if(NFind::DoesFileExist(dirName))
+      continue;
+    if (MyCreateDirectory(dirName))
+      return true;
+    if (::GetLastError() != ERROR_ALREADY_EXISTS)
+      return false;
+  }
+}
+
+bool CTempDirectoryW::Create(LPCWSTR prefix)
+{ 
+  Remove();
+  return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); 
+}
+
+#endif
+
+}}}

Added: trunk/lzma/CPP/Windows/FileDir.h
===================================================================
--- trunk/lzma/CPP/Windows/FileDir.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileDir.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,178 @@
+// Windows/FileDir.h
+
+#ifndef __WINDOWS_FILEDIR_H
+#define __WINDOWS_FILEDIR_H
+
+#include "../Common/MyString.h"
+#include "Defs.h"
+
+namespace NWindows {
+namespace NFile {
+namespace NDirectory {
+
+#ifdef WIN_LONG_PATH
+bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2);
+#endif
+
+bool MyGetWindowsDirectory(CSysString &path);
+bool MyGetSystemDirectory(CSysString &path);
+#ifndef _UNICODE
+bool MyGetWindowsDirectory(UString &path);
+bool MyGetSystemDirectory(UString &path);
+#endif
+
+bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime);
+
+bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes);
+bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName);
+bool MyRemoveDirectory(LPCTSTR pathName);
+bool MyCreateDirectory(LPCTSTR pathName);
+bool CreateComplexDirectory(LPCTSTR pathName);
+bool DeleteFileAlways(LPCTSTR name);
+bool RemoveDirectoryWithSubItems(const CSysString &path);
+
+#ifndef _UNICODE
+bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes);
+bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName);
+bool MyRemoveDirectory(LPCWSTR pathName);
+bool MyCreateDirectory(LPCWSTR pathName);
+bool CreateComplexDirectory(LPCWSTR pathName);
+bool DeleteFileAlways(LPCWSTR name);
+bool RemoveDirectoryWithSubItems(const UString &path);
+#endif
+
+#ifndef _WIN32_WCE
+bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath);
+
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, 
+    int &fileNamePartStartIndex);
+bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath);
+bool GetOnlyName(LPCTSTR fileName, CSysString &resultName);
+bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName);
+#ifndef _UNICODE
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, 
+    int &fileNamePartStartIndex);
+bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath);
+bool GetOnlyName(LPCWSTR fileName, UString &resultName);
+bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName);
+#endif
+
+inline bool MySetCurrentDirectory(LPCTSTR path)
+  { return BOOLToBool(::SetCurrentDirectory(path)); }
+bool MyGetCurrentDirectory(CSysString &resultPath);
+#ifndef _UNICODE
+bool MySetCurrentDirectory(LPCWSTR path);
+bool MyGetCurrentDirectory(UString &resultPath);
+#endif
+#endif
+
+bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, 
+  CSysString &resultPath, UINT32 &filePart);
+#ifndef _UNICODE
+bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, 
+  UString &resultPath, UINT32 &filePart);
+#endif
+
+inline bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, 
+  CSysString &resultPath)
+{
+  UINT32 value;
+  return MySearchPath(path, fileName, extension, resultPath, value);
+}
+
+#ifndef _UNICODE
+inline bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, 
+  UString &resultPath)
+{
+  UINT32 value;
+  return MySearchPath(path, fileName, extension, resultPath, value);
+}
+#endif
+
+bool MyGetTempPath(CSysString &resultPath);
+#ifndef _UNICODE
+bool MyGetTempPath(UString &resultPath);
+#endif
+
+UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath);
+#ifndef _UNICODE
+UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath);
+#endif
+
+class CTempFile
+{
+  bool _mustBeDeleted;
+  CSysString _fileName;
+public:
+  CTempFile(): _mustBeDeleted(false) {}
+  ~CTempFile() { Remove(); }
+  void DisableDeleting() { _mustBeDeleted = false; }
+  UINT Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath);
+  bool Create(LPCTSTR prefix, CSysString &resultPath);
+  bool Remove();
+};
+
+#ifdef _UNICODE
+typedef CTempFile CTempFileW;
+#else
+class CTempFileW
+{
+  bool _mustBeDeleted;
+  UString _fileName;
+public:
+  CTempFileW(): _mustBeDeleted(false) {}
+  ~CTempFileW() { Remove(); }
+  void DisableDeleting() { _mustBeDeleted = false; }
+  UINT Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath);
+  bool Create(LPCWSTR prefix, UString &resultPath);
+  bool Remove();
+};
+#endif
+
+bool CreateTempDirectory(LPCTSTR prefixChars, CSysString &dirName);
+
+class CTempDirectory
+{
+  bool _mustBeDeleted;
+  CSysString _tempDir;
+public:
+  const CSysString &GetPath() const { return _tempDir; }
+  CTempDirectory(): _mustBeDeleted(false) {}
+  ~CTempDirectory() { Remove();  }
+  bool Create(LPCTSTR prefix) ;
+  bool Remove()
+  {
+    if (!_mustBeDeleted)
+      return true;
+    _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir);
+    return (!_mustBeDeleted);
+  }
+  void DisableDeleting() { _mustBeDeleted = false; }
+};
+
+#ifdef _UNICODE
+typedef CTempDirectory CTempDirectoryW;
+#else
+class CTempDirectoryW
+{
+  bool _mustBeDeleted;
+  UString _tempDir;
+public:
+  const UString &GetPath() const { return _tempDir; }
+  CTempDirectoryW(): _mustBeDeleted(false) {}
+  ~CTempDirectoryW() { Remove();  }
+  bool Create(LPCWSTR prefix) ;
+  bool Remove()
+  {
+    if (!_mustBeDeleted)
+      return true;
+    _mustBeDeleted = !RemoveDirectoryWithSubItems(_tempDir);
+    return (!_mustBeDeleted);
+  }
+  void DisableDeleting() { _mustBeDeleted = false; }
+};
+#endif
+
+}}}
+
+#endif

Added: trunk/lzma/CPP/Windows/FileFind.cpp
===================================================================
--- trunk/lzma/CPP/Windows/FileFind.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileFind.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,408 @@
+// Windows/FileFind.cpp
+
+#include "StdAfx.h"
+
+#include "FileFind.h"
+#ifndef _UNICODE
+#include "../Common/StringConvert.h"
+#endif
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+namespace NWindows {
+namespace NFile {
+
+#if defined(WIN_LONG_PATH) && defined(_UNICODE)
+#define WIN_LONG_PATH2
+#endif
+
+bool GetLongPath(LPCWSTR fileName, UString &res);
+
+namespace NFind {
+
+static const TCHAR kDot = TEXT('.');
+
+bool CFileInfo::IsDots() const
+{ 
+  if (!IsDirectory() || Name.IsEmpty())
+    return false;
+  if (Name[0] != kDot)
+    return false;
+  return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
+}
+
+#ifndef _UNICODE
+bool CFileInfoW::IsDots() const
+{ 
+  if (!IsDirectory() || Name.IsEmpty())
+    return false;
+  if (Name[0] != kDot)
+    return false;
+  return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
+}
+#endif
+
+static void ConvertWIN32_FIND_DATA_To_FileInfo(
+    const WIN32_FIND_DATA &findData,
+    CFileInfo &fileInfo)
+{
+  fileInfo.Attributes = findData.dwFileAttributes; 
+  fileInfo.CreationTime = findData.ftCreationTime;  
+  fileInfo.LastAccessTime = findData.ftLastAccessTime; 
+  fileInfo.LastWriteTime = findData.ftLastWriteTime;
+  fileInfo.Size  = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; 
+  fileInfo.Name = findData.cFileName;
+  #ifndef _WIN32_WCE
+  fileInfo.ReparseTag = findData.dwReserved0;
+  #else
+  fileInfo.ObjectID = findData.dwOID;
+  #endif
+}
+
+#ifndef _UNICODE
+
+static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } 
+
+static void ConvertWIN32_FIND_DATA_To_FileInfo(
+    const WIN32_FIND_DATAW &findData,
+    CFileInfoW &fileInfo)
+{
+  fileInfo.Attributes = findData.dwFileAttributes; 
+  fileInfo.CreationTime = findData.ftCreationTime;  
+  fileInfo.LastAccessTime = findData.ftLastAccessTime; 
+  fileInfo.LastWriteTime = findData.ftLastWriteTime;
+  fileInfo.Size  = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; 
+  fileInfo.Name = findData.cFileName;
+  #ifndef _WIN32_WCE
+  fileInfo.ReparseTag = findData.dwReserved0;
+  #else
+  fileInfo.ObjectID = findData.dwOID;
+  #endif
+}
+
+static void ConvertWIN32_FIND_DATA_To_FileInfo(
+    const WIN32_FIND_DATA &findData,
+    CFileInfoW &fileInfo)
+{
+  fileInfo.Attributes = findData.dwFileAttributes; 
+  fileInfo.CreationTime = findData.ftCreationTime;  
+  fileInfo.LastAccessTime = findData.ftLastAccessTime; 
+  fileInfo.LastWriteTime = findData.ftLastWriteTime;
+  fileInfo.Size  = (((UInt64)findData.nFileSizeHigh) << 32) + findData.nFileSizeLow; 
+  fileInfo.Name = GetUnicodeString(findData.cFileName, GetCurrentCodePage());
+  #ifndef _WIN32_WCE
+  fileInfo.ReparseTag = findData.dwReserved0;
+  #else
+  fileInfo.ObjectID = findData.dwOID;
+  #endif
+}
+#endif
+  
+////////////////////////////////
+// CFindFile
+
+bool CFindFile::Close()
+{
+  if (_handle == INVALID_HANDLE_VALUE)
+    return true;
+  if (!::FindClose(_handle))
+    return false;
+  _handle = INVALID_HANDLE_VALUE;
+  return true;
+}
+
+          
+bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo)
+{
+  if (!Close())
+    return false;
+  WIN32_FIND_DATA findData;
+  _handle = ::FindFirstFile(wildcard, &findData);
+  #ifdef WIN_LONG_PATH2
+  if (_handle == INVALID_HANDLE_VALUE)
+  {
+    UString longPath;
+    if (GetLongPath(wildcard, longPath))
+      _handle = ::FindFirstFileW(longPath, &findData);
+  }
+  #endif
+  if (_handle == INVALID_HANDLE_VALUE)
+    return false;
+  ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
+  return true;
+}
+
+#ifndef _UNICODE
+bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo)
+{
+  if (!Close())
+    return false;
+  if (g_IsNT)
+  {
+    WIN32_FIND_DATAW findData;
+    _handle = ::FindFirstFileW(wildcard, &findData);
+    #ifdef WIN_LONG_PATH
+    if (_handle == INVALID_HANDLE_VALUE)
+    {
+      UString longPath;
+      if (GetLongPath(wildcard, longPath))
+        _handle = ::FindFirstFileW(longPath, &findData);
+    }
+    #endif
+    if (_handle != INVALID_HANDLE_VALUE)
+      ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
+  }
+  else
+  {
+    WIN32_FIND_DATAA findData;
+    _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard, 
+        GetCurrentCodePage()), &findData);
+    if (_handle != INVALID_HANDLE_VALUE)
+      ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
+  }
+  return (_handle != INVALID_HANDLE_VALUE);
+}
+#endif
+
+bool CFindFile::FindNext(CFileInfo &fileInfo)
+{
+  WIN32_FIND_DATA findData;
+  bool result = BOOLToBool(::FindNextFile(_handle, &findData));
+  if (result)
+    ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
+  return result;
+}
+
+#ifndef _UNICODE
+bool CFindFile::FindNext(CFileInfoW &fileInfo)
+{
+  if (g_IsNT)
+  {
+    WIN32_FIND_DATAW findData;
+    if (!::FindNextFileW(_handle, &findData))
+      return false;
+    ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
+  }
+  else
+  {
+    WIN32_FIND_DATAA findData;
+    if (!::FindNextFileA(_handle, &findData))
+      return false;
+    ConvertWIN32_FIND_DATA_To_FileInfo(findData, fileInfo);
+  }
+  return true;
+}
+#endif
+
+bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo)
+{
+  CFindFile finder;
+  return finder.FindFirst(wildcard, fileInfo);
+}
+
+#ifndef _UNICODE
+bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo)
+{
+  CFindFile finder;
+  return finder.FindFirst(wildcard, fileInfo);
+}
+#endif
+
+bool DoesFileExist(LPCTSTR name)
+{
+  CFileInfo fileInfo;
+  return FindFile(name, fileInfo);
+}
+
+#ifndef _UNICODE
+bool DoesFileExist(LPCWSTR name)
+{
+  CFileInfoW fileInfo;
+  return FindFile(name, fileInfo);
+}
+#endif
+
+/////////////////////////////////////
+// CEnumerator
+
+bool CEnumerator::NextAny(CFileInfo &fileInfo)
+{
+  if (_findFile.IsHandleAllocated())
+    return _findFile.FindNext(fileInfo);
+  else
+    return _findFile.FindFirst(_wildcard, fileInfo);
+}
+
+bool CEnumerator::Next(CFileInfo &fileInfo)
+{
+  for (;;)
+  {
+    if (!NextAny(fileInfo))
+      return false;
+    if (!fileInfo.IsDots())
+      return true;
+  }
+}
+
+bool CEnumerator::Next(CFileInfo &fileInfo, bool &found)
+{
+  if (Next(fileInfo))
+  {
+    found = true;
+    return true;
+  }
+  found = false;
+  return (::GetLastError() == ERROR_NO_MORE_FILES);
+}
+
+#ifndef _UNICODE
+bool CEnumeratorW::NextAny(CFileInfoW &fileInfo)
+{
+  if (_findFile.IsHandleAllocated())
+    return _findFile.FindNext(fileInfo);
+  else
+    return _findFile.FindFirst(_wildcard, fileInfo);
+}
+
+bool CEnumeratorW::Next(CFileInfoW &fileInfo)
+{
+  for (;;)
+  {
+    if (!NextAny(fileInfo))
+      return false;
+    if (!fileInfo.IsDots())
+      return true;
+  }
+}
+
+bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found)
+{
+  if (Next(fileInfo))
+  {
+    found = true;
+    return true;
+  }
+  found = false;
+  return (::GetLastError() == ERROR_NO_MORE_FILES);
+}
+
+#endif
+
+////////////////////////////////
+// CFindChangeNotification
+// FindFirstChangeNotification can return 0. MSDN doesn't tell about it.
+
+bool CFindChangeNotification::Close()
+{
+  if (!IsHandleAllocated())
+    return true;
+  if (!::FindCloseChangeNotification(_handle))
+    return false;
+  _handle = INVALID_HANDLE_VALUE;
+  return true;
+}
+           
+HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter)
+{
+  _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter);
+  #ifdef WIN_LONG_PATH2
+  if (!IsHandleAllocated())
+  {
+    UString longPath;
+    if (GetLongPath(pathName, longPath))
+      _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
+  }
+  #endif
+  return _handle;
+}
+
+#ifndef _UNICODE
+HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter)
+{
+  if (!g_IsNT)
+    return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter);
+  _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter);
+  #ifdef WIN_LONG_PATH
+  if (!IsHandleAllocated())
+  {
+    UString longPath;
+    if (GetLongPath(pathName, longPath))
+      _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
+  }
+  #endif
+  return _handle;
+}
+#endif
+
+#ifndef _WIN32_WCE
+bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings)
+{
+  driveStrings.Clear();
+  UINT32 size = GetLogicalDriveStrings(0, NULL); 
+  if (size == 0)
+    return false;
+  CSysString buffer;
+  UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size)); 
+  if (newSize == 0)
+    return false;
+  if (newSize > size)
+    return false;
+  CSysString string;
+  for(UINT32 i = 0; i < newSize; i++)
+  {
+    TCHAR c = buffer[i];
+    if (c == TEXT('\0'))
+    {
+      driveStrings.Add(string);
+      string.Empty();
+    }
+    else
+      string += c;
+  }
+  if (!string.IsEmpty())
+    return false;
+  return true;
+}
+
+#ifndef _UNICODE
+bool MyGetLogicalDriveStrings(UStringVector &driveStrings)
+{
+  driveStrings.Clear();
+  if (g_IsNT)
+  {
+    UINT32 size = GetLogicalDriveStringsW(0, NULL); 
+    if (size == 0)
+      return false;
+    UString buffer;
+    UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size)); 
+    if (newSize == 0)
+      return false;
+    if (newSize > size)
+      return false;
+    UString string;
+    for(UINT32 i = 0; i < newSize; i++)
+    {
+      WCHAR c = buffer[i];
+      if (c == L'\0')
+      {
+        driveStrings.Add(string);
+        string.Empty();
+      }
+      else
+        string += c;
+    }
+    return string.IsEmpty();
+  }
+  CSysStringVector driveStringsA;
+  bool res = MyGetLogicalDriveStrings(driveStringsA);
+  for (int i = 0; i < driveStringsA.Size(); i++)
+    driveStrings.Add(GetUnicodeString(driveStringsA[i]));
+  return res;
+}
+#endif
+
+#endif
+
+}}}

Added: trunk/lzma/CPP/Windows/FileFind.h
===================================================================
--- trunk/lzma/CPP/Windows/FileFind.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileFind.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,153 @@
+// Windows/FileFind.h
+
+#ifndef __WINDOWS_FILEFIND_H
+#define __WINDOWS_FILEFIND_H
+
+#include "../Common/MyString.h"
+#include "../Common/Types.h"
+#include "FileName.h"
+#include "Defs.h"
+
+namespace NWindows {
+namespace NFile {
+namespace NFind {
+
+namespace NAttributes
+{
+  inline bool IsReadOnly(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_READONLY) != 0; }
+  inline bool IsHidden(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_HIDDEN) != 0; }
+  inline bool IsSystem(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_SYSTEM) != 0; }
+  inline bool IsDirectory(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }
+  inline bool IsArchived(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_ARCHIVE) != 0; }
+  inline bool IsCompressed(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_COMPRESSED) != 0; }
+  inline bool IsEncrypted(DWORD attributes) { return (attributes & FILE_ATTRIBUTE_ENCRYPTED) != 0; }
+}
+
+class CFileInfoBase
+{ 
+  bool MatchesMask(UINT32 mask) const  { return ((Attributes & mask) != 0); }
+public:
+  DWORD Attributes;
+  FILETIME CreationTime;  
+  FILETIME LastAccessTime; 
+  FILETIME LastWriteTime;
+  UInt64 Size;
+  
+  #ifndef _WIN32_WCE
+  UINT32 ReparseTag;
+  #else
+  DWORD ObjectID; 
+  #endif
+
+  bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }
+  bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }
+  bool IsDirectory() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); }
+  bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); }
+  bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); }
+  bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); }
+  bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); }
+  bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); }
+  bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); }
+  bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); }
+  bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); }
+  bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); }
+};
+
+class CFileInfo: public CFileInfoBase
+{ 
+public:
+  CSysString Name;
+  bool IsDots() const;
+};
+
+#ifdef _UNICODE
+typedef CFileInfo CFileInfoW;
+#else
+class CFileInfoW: public CFileInfoBase
+{ 
+public:
+  UString Name;
+  bool IsDots() const;
+};
+#endif
+
+class CFindFile
+{
+  friend class CEnumerator;
+  HANDLE _handle;
+public:
+  bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; }
+  CFindFile(): _handle(INVALID_HANDLE_VALUE) {}
+  ~CFindFile() {  Close(); }
+  bool FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo);
+  bool FindNext(CFileInfo &fileInfo);
+  #ifndef _UNICODE
+  bool FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo);
+  bool FindNext(CFileInfoW &fileInfo);
+  #endif
+  bool Close();
+};
+
+bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo);
+
+bool DoesFileExist(LPCTSTR name);
+#ifndef _UNICODE
+bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo);
+bool DoesFileExist(LPCWSTR name);
+#endif
+
+class CEnumerator
+{
+  CFindFile _findFile;
+  CSysString _wildcard;
+  bool NextAny(CFileInfo &fileInfo);
+public:
+  CEnumerator(): _wildcard(NName::kAnyStringWildcard) {}
+  CEnumerator(const CSysString &wildcard): _wildcard(wildcard) {}
+  bool Next(CFileInfo &fileInfo);
+  bool Next(CFileInfo &fileInfo, bool &found);
+};
+
+#ifdef _UNICODE
+typedef CEnumerator CEnumeratorW;
+#else
+class CEnumeratorW
+{
+  CFindFile _findFile;
+  UString _wildcard;
+  bool NextAny(CFileInfoW &fileInfo);
+public:
+  CEnumeratorW(): _wildcard(NName::kAnyStringWildcard) {}
+  CEnumeratorW(const UString &wildcard): _wildcard(wildcard) {}
+  bool Next(CFileInfoW &fileInfo);
+  bool Next(CFileInfoW &fileInfo, bool &found);
+};
+#endif
+
+class CFindChangeNotification
+{
+  HANDLE _handle;
+public:
+  operator HANDLE () { return _handle; }
+  bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE && _handle != 0; }
+  CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {}
+  ~CFindChangeNotification() { Close(); }
+  bool Close();
+  HANDLE FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter);
+  #ifndef _UNICODE
+  HANDLE FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter);
+  #endif
+  bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); }
+};
+
+#ifndef _WIN32_WCE
+bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings);
+#ifndef _UNICODE
+bool MyGetLogicalDriveStrings(UStringVector &driveStrings);
+#endif
+#endif
+
+}}}
+
+#endif
+

Added: trunk/lzma/CPP/Windows/FileIO.cpp
===================================================================
--- trunk/lzma/CPP/Windows/FileIO.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileIO.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,318 @@
+// Windows/FileIO.cpp
+
+#include "StdAfx.h"
+
+#include "FileIO.h"
+#include "Defs.h"
+#ifdef WIN_LONG_PATH
+#include "../Common/MyString.h"
+#endif
+#ifndef _UNICODE
+#include "../Common/StringConvert.h"
+#endif
+
+#ifndef _UNICODE
+extern bool g_IsNT;
+#endif
+
+namespace NWindows {
+namespace NFile {
+
+#if defined(WIN_LONG_PATH) && defined(_UNICODE)
+#define WIN_LONG_PATH2
+#endif
+
+#ifdef WIN_LONG_PATH
+bool GetLongPathBase(LPCWSTR s, UString &res)
+{
+  res.Empty();
+  int len = MyStringLen(s);
+  wchar_t c = s[0];
+  if (len < 1 || c == L'\\' || c == L'.' && (len == 1 || len == 2 && s[1] == L'.'))
+    return true;
+  UString curDir;
+  bool isAbs = false;
+  if (len > 3)
+    isAbs = (s[1] == L':' && s[2] == L'\\' && (c >= L'a' && c <= L'z' || c >= L'A' && c <= L'Z'));
+
+  if (!isAbs)
+    {
+      DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, curDir.GetBuffer(MAX_PATH + 1));
+      curDir.ReleaseBuffer();
+      if (needLength == 0 || needLength > MAX_PATH)
+        return false;
+      if (curDir[curDir.Length() - 1] != L'\\')
+        curDir += L'\\';
+    }
+  res = UString(L"\\\\?\\") + curDir + s;
+  return true;
+}
+
+bool GetLongPath(LPCWSTR path, UString &longPath)
+{
+  if (GetLongPathBase(path, longPath)) 
+    return !longPath.IsEmpty();
+  return false;
+}
+#endif
+
+namespace NIO {
+
+CFileBase::~CFileBase() { Close(); }
+
+bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess,
+    DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+{
+  if (!Close())
+    return false;
+  _handle = ::CreateFile(fileName, desiredAccess, shareMode, 
+      (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, 
+      flagsAndAttributes, (HANDLE)NULL);
+  #ifdef WIN_LONG_PATH2
+  if (_handle == INVALID_HANDLE_VALUE)
+  {
+    UString longPath;
+    if (GetLongPath(fileName, longPath))
+      _handle = ::CreateFileW(longPath, desiredAccess, shareMode, 
+        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, 
+        flagsAndAttributes, (HANDLE)NULL);
+  }
+  #endif
+  return (_handle != INVALID_HANDLE_VALUE);
+}
+
+#ifndef _UNICODE
+bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess,
+    DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+{
+  if (!g_IsNT)
+    return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), 
+      desiredAccess, shareMode, creationDisposition, flagsAndAttributes);
+  if (!Close())
+    return false;
+  _handle = ::CreateFileW(fileName, desiredAccess, shareMode, 
+    (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, 
+    flagsAndAttributes, (HANDLE)NULL);
+  #ifdef WIN_LONG_PATH
+  if (_handle == INVALID_HANDLE_VALUE)
+  {
+    UString longPath;
+    if (GetLongPath(fileName, longPath))
+      _handle = ::CreateFileW(longPath, desiredAccess, shareMode, 
+        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, 
+        flagsAndAttributes, (HANDLE)NULL);
+  }
+  #endif
+  return (_handle != INVALID_HANDLE_VALUE);
+}
+#endif
+
+bool CFileBase::Close()
+{
+  if (_handle == INVALID_HANDLE_VALUE)
+    return true;
+  if (!::CloseHandle(_handle))
+    return false;
+  _handle = INVALID_HANDLE_VALUE;
+  return true;
+}
+
+bool CFileBase::GetPosition(UInt64 &position) const
+{
+  return Seek(0, FILE_CURRENT, position);
+}
+
+bool CFileBase::GetLength(UInt64 &length) const
+{
+  DWORD sizeHigh;
+  DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh);
+  if(sizeLow == 0xFFFFFFFF)
+    if(::GetLastError() != NO_ERROR)
+      return false;
+  length = (((UInt64)sizeHigh) << 32) + sizeLow;
+  return true;
+}
+
+bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const
+{
+  LARGE_INTEGER value;
+  value.QuadPart = distanceToMove;
+  value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod);
+  if (value.LowPart == 0xFFFFFFFF)
+    if(::GetLastError() != NO_ERROR) 
+      return false;
+  newPosition = value.QuadPart;
+  return true;
+}
+
+bool CFileBase::Seek(UInt64 position, UInt64 &newPosition)
+{
+  return Seek(position, FILE_BEGIN, newPosition);
+}
+
+bool CFileBase::SeekToBegin()
+{
+  UInt64 newPosition;
+  return Seek(0, newPosition);
+}
+
+bool CFileBase::SeekToEnd(UInt64 &newPosition)
+{
+  return Seek(0, FILE_END, newPosition);
+}
+
+bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const
+{
+  BY_HANDLE_FILE_INFORMATION winFileInfo;
+  if(!::GetFileInformationByHandle(_handle, &winFileInfo))
+    return false;
+  fileInfo.Attributes = winFileInfo.dwFileAttributes;
+  fileInfo.CreationTime = winFileInfo.ftCreationTime;
+  fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime;
+  fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime;
+  fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; 
+  fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) +  winFileInfo.nFileSizeLow;
+  fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks;
+  fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow;
+  return true;
+}
+
+/////////////////////////
+// CInFile
+
+bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+  { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); }
+
+bool CInFile::OpenShared(LPCTSTR fileName, bool shareForWrite)
+{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }
+
+bool CInFile::Open(LPCTSTR fileName)
+  { return OpenShared(fileName, false); }
+
+#ifndef _UNICODE
+bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+  { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); }
+
+bool CInFile::OpenShared(LPCWSTR fileName, bool shareForWrite)
+{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }
+
+bool CInFile::Open(LPCWSTR fileName)
+  { return OpenShared(fileName, false); }
+#endif
+
+// 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"
+
+static UInt32 kChunkSizeMax = (1 << 22);
+
+bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize)
+{
+  if (size > kChunkSizeMax)
+    size = kChunkSizeMax;
+  DWORD processedLoc = 0;
+  bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL));
+  processedSize = (UInt32)processedLoc;
+  return res;
+}
+
+bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize)
+{
+  processedSize = 0;
+  do
+  {
+    UInt32 processedLoc = 0;
+    bool res = ReadPart(data, size, processedLoc);
+    processedSize += processedLoc;
+    if (!res)
+      return false;
+    if (processedLoc == 0)
+      return true;
+    data = (void *)((unsigned char *)data + processedLoc);
+    size -= processedLoc;
+  }
+  while (size > 0);
+  return true;
+}
+
+/////////////////////////
+// COutFile
+
+bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+  { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }
+
+static inline DWORD GetCreationDisposition(bool createAlways)
+  { return createAlways? CREATE_ALWAYS: CREATE_NEW; }
+
+bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition)
+  { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }
+
+bool COutFile::Create(LPCTSTR fileName, bool createAlways)
+  { return Open(fileName, GetCreationDisposition(createAlways)); }
+
+#ifndef _UNICODE
+
+bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)
+  { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode,      creationDisposition, flagsAndAttributes); }
+
+bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition)
+  { return Open(fileName, FILE_SHARE_READ,  creationDisposition, FILE_ATTRIBUTE_NORMAL); }
+
+bool COutFile::Create(LPCWSTR fileName, bool createAlways)
+  { return Open(fileName, GetCreationDisposition(createAlways)); }
+
+#endif
+
+bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime)
+  { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); }
+
+bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime)
+  {  return SetTime(NULL, NULL, lastWriteTime); }
+
+bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize)
+{
+  if (size > kChunkSizeMax)
+    size = kChunkSizeMax;
+  DWORD processedLoc = 0;
+  bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL));
+  processedSize = (UInt32)processedLoc;
+  return res;
+}
+
+bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize)
+{
+  processedSize = 0;
+  do
+  {
+    UInt32 processedLoc = 0;
+    bool res = WritePart(data, size, processedLoc);
+    processedSize += processedLoc;
+    if (!res)
+      return false;
+    if (processedLoc == 0)
+      return true;
+    data = (const void *)((const unsigned char *)data + processedLoc);
+    size -= processedLoc;
+  }
+  while (size > 0);
+  return true;
+}
+
+bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); }
+
+bool COutFile::SetLength(UInt64 length)
+{
+  UInt64 newPosition;
+  if(!Seek(length, newPosition))
+    return false;
+  if(newPosition != length)
+    return false;
+  return SetEndOfFile();
+}
+
+}}}

Added: trunk/lzma/CPP/Windows/FileIO.h
===================================================================
--- trunk/lzma/CPP/Windows/FileIO.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileIO.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,99 @@
+// Windows/FileIO.h
+
+#ifndef __WINDOWS_FILEIO_H
+#define __WINDOWS_FILEIO_H
+
+#include "../Common/Types.h"
+
+namespace NWindows {
+namespace NFile {
+namespace NIO {
+
+struct CByHandleFileInfo
+{ 
+  DWORD    Attributes; 
+  FILETIME CreationTime; 
+  FILETIME LastAccessTime; 
+  FILETIME LastWriteTime; 
+  DWORD    VolumeSerialNumber; 
+  UInt64   Size;
+  DWORD    NumberOfLinks; 
+  UInt64   FileIndex; 
+};
+
+class CFileBase
+{
+protected:
+  HANDLE _handle;
+  bool Create(LPCTSTR fileName, DWORD desiredAccess,
+      DWORD shareMode, DWORD creationDisposition,  DWORD flagsAndAttributes);
+  #ifndef _UNICODE
+  bool Create(LPCWSTR fileName, DWORD desiredAccess,
+      DWORD shareMode, DWORD creationDisposition,  DWORD flagsAndAttributes);
+  #endif
+
+public:
+  CFileBase(): _handle(INVALID_HANDLE_VALUE){};
+  ~CFileBase();
+
+  bool Close();
+
+  bool GetPosition(UInt64 &position) const;
+  bool GetLength(UInt64 &length) const;
+
+  bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const;
+  bool Seek(UInt64 position, UInt64 &newPosition); 
+  bool SeekToBegin(); 
+  bool SeekToEnd(UInt64 &newPosition); 
+  
+  bool GetFileInformation(CByHandleFileInfo &fileInfo) const;
+};
+
+class CInFile: public CFileBase
+{
+public:
+  bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+  bool OpenShared(LPCTSTR fileName, bool shareForWrite);
+  bool Open(LPCTSTR fileName);
+  #ifndef _UNICODE
+  bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+  bool OpenShared(LPCWSTR fileName, bool shareForWrite);
+  bool Open(LPCWSTR fileName);
+  #endif
+  bool ReadPart(void *data, UInt32 size, UInt32 &processedSize);
+  bool Read(void *data, UInt32 size, UInt32 &processedSize);
+};
+
+class COutFile: public CFileBase
+{
+  // DWORD m_CreationDisposition;
+public:
+  // COutFile(): m_CreationDisposition(CREATE_NEW){};
+  bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+  bool Open(LPCTSTR fileName, DWORD creationDisposition);
+  bool Create(LPCTSTR fileName, bool createAlways);
+
+  #ifndef _UNICODE
+  bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);
+  bool Open(LPCWSTR fileName, DWORD creationDisposition);
+  bool Create(LPCWSTR fileName, bool createAlways);
+  #endif
+
+  /*
+  void SetOpenCreationDisposition(DWORD creationDisposition)
+    { m_CreationDisposition = creationDisposition; }
+  void SetOpenCreationDispositionCreateAlways()
+    { m_CreationDisposition = CREATE_ALWAYS; }
+  */
+
+  bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime);
+  bool SetLastWriteTime(const FILETIME *lastWriteTime);
+  bool WritePart(const void *data, UInt32 size, UInt32 &processedSize);
+  bool Write(const void *data, UInt32 size, UInt32 &processedSize);
+  bool SetEndOfFile();
+  bool SetLength(UInt64 length);
+};
+
+}}}
+
+#endif

Added: trunk/lzma/CPP/Windows/FileMapping.cpp
===================================================================
--- trunk/lzma/CPP/Windows/FileMapping.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileMapping.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,14 @@
+// Windows/FileMapping.cpp
+
+#include "StdAfx.h"
+
+#include "Windows/FileMapping.h"
+
+namespace NWindows {
+namespace NFile {
+namespace NMapping {
+
+
+
+
+}}}
\ No newline at end of file

Added: trunk/lzma/CPP/Windows/FileMapping.h
===================================================================
--- trunk/lzma/CPP/Windows/FileMapping.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileMapping.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,50 @@
+// Windows/FileMapping.h
+
+#ifndef __WINDOWS_FILEMAPPING_H
+#define __WINDOWS_FILEMAPPING_H
+
+#include "Windows/Handle.h"
+#include "Windows/Defs.h"
+
+namespace NWindows {
+// namespace NFile {
+// namespace NMapping {
+
+class CFileMapping: public CHandle
+{
+public:
+  bool Create(HANDLE file, LPSECURITY_ATTRIBUTES attributes,
+    DWORD protect, UINT64 maximumSize, LPCTSTR name)
+  {
+    _handle = ::CreateFileMapping(file, attributes,
+      protect, DWORD(maximumSize >> 32), DWORD(maximumSize), name);
+    return (_handle != NULL);
+  }
+
+  bool Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)
+  {
+    _handle = ::OpenFileMapping(desiredAccess, BoolToBOOL(inheritHandle), name);
+    return (_handle != NULL);
+  }
+
+  LPVOID MapViewOfFile(DWORD desiredAccess, UINT64 fileOffset, 
+      SIZE_T numberOfBytesToMap)
+  {
+    return ::MapViewOfFile(_handle, desiredAccess, 
+        DWORD(fileOffset >> 32), DWORD(fileOffset), numberOfBytesToMap);
+  }
+
+  LPVOID MapViewOfFileEx(DWORD desiredAccess, UINT64 fileOffset, 
+      SIZE_T numberOfBytesToMap, LPVOID baseAddress)
+  {
+    return ::MapViewOfFileEx(_handle, desiredAccess, 
+      DWORD(fileOffset >> 32), DWORD(fileOffset), 
+      numberOfBytesToMap, baseAddress);
+  }
+  
+
+};
+
+}
+
+#endif

Added: trunk/lzma/CPP/Windows/FileName.cpp
===================================================================
--- trunk/lzma/CPP/Windows/FileName.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileName.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,54 @@
+// Windows/FileName.cpp
+
+#include "StdAfx.h"
+
+#include "Windows/FileName.h"
+#include "Common/Wildcard.h"
+
+namespace NWindows {
+namespace NFile {
+namespace NName {
+
+void NormalizeDirPathPrefix(CSysString &dirPath)
+{
+  if (dirPath.IsEmpty())
+    return;
+  if (dirPath.ReverseFind(kDirDelimiter) != dirPath.Length() - 1)
+    dirPath += kDirDelimiter;
+}
+
+#ifndef _UNICODE
+void NormalizeDirPathPrefix(UString &dirPath)
+{
+  if (dirPath.IsEmpty())
+    return;
+  if (dirPath.ReverseFind(wchar_t(kDirDelimiter)) != dirPath.Length() - 1)
+    dirPath += wchar_t(kDirDelimiter);
+}
+#endif
+
+#ifdef _WIN32
+
+const wchar_t kExtensionDelimiter = L'.';
+
+void SplitNameToPureNameAndExtension(const UString &fullName, 
+    UString &pureName, UString &extensionDelimiter, UString &extension)
+{
+  int index = fullName.ReverseFind(kExtensionDelimiter);
+  if (index < 0)
+  {
+    pureName = fullName;
+    extensionDelimiter.Empty();
+    extension.Empty();
+  }
+  else
+  {
+    pureName = fullName.Left(index);
+    extensionDelimiter = kExtensionDelimiter;
+    extension = fullName.Mid(index + 1);
+  }
+}
+
+#endif
+
+}}}

Added: trunk/lzma/CPP/Windows/FileName.h
===================================================================
--- trunk/lzma/CPP/Windows/FileName.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/FileName.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,27 @@
+// Windows/FileName.h
+
+#ifndef __WINDOWS_FILENAME_H
+#define __WINDOWS_FILENAME_H
+
+#include "../Common/MyString.h"
+
+namespace NWindows {
+namespace NFile {
+namespace NName {
+
+const TCHAR kDirDelimiter = CHAR_PATH_SEPARATOR;
+const TCHAR kAnyStringWildcard = '*';
+
+void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with '\\'
+#ifndef _UNICODE
+void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\'
+#endif
+
+#ifdef _WIN32
+void SplitNameToPureNameAndExtension(const UString &fullName, 
+    UString &pureName, UString &extensionDelimiter, UString &extension); 
+#endif
+
+}}}
+
+#endif

Added: trunk/lzma/CPP/Windows/Handle.h
===================================================================
--- trunk/lzma/CPP/Windows/Handle.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/Handle.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,37 @@
+// Windows/Handle.h
+
+#ifndef __WINDOWS_HANDLE_H
+#define __WINDOWS_HANDLE_H
+
+namespace NWindows {
+
+class CHandle
+{
+protected:
+  HANDLE _handle;
+public:
+  operator HANDLE() { return _handle; }
+  CHandle(): _handle(NULL) {}
+  ~CHandle() { Close(); }
+  bool Close()
+  {
+    if (_handle == NULL)
+      return true;
+    if (!::CloseHandle(_handle))
+      return false;
+    _handle = NULL;
+    return true;
+  }
+  void Attach(HANDLE handle) 
+    { _handle = handle; }
+  HANDLE Detach() 
+  { 
+    HANDLE handle = _handle;
+    _handle = NULL; 
+    return handle;
+  }
+};
+
+}
+
+#endif

Added: trunk/lzma/CPP/Windows/MemoryLock.cpp
===================================================================
--- trunk/lzma/CPP/Windows/MemoryLock.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/MemoryLock.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,78 @@
+// Common/MemoryLock.cpp
+
+#include "StdAfx.h"
+
+namespace NWindows {
+namespace NSecurity {
+
+#ifndef _UNICODE
+typedef BOOL (WINAPI * OpenProcessTokenP)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
+typedef BOOL (WINAPI * LookupPrivilegeValueP)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID  lpLuid);
+typedef BOOL (WINAPI * AdjustTokenPrivilegesP)(HANDLE TokenHandle, BOOL DisableAllPrivileges,
+    PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState,PDWORD ReturnLength);
+#endif
+
+#ifdef _UNICODE
+bool EnableLockMemoryPrivilege(
+#else
+static bool EnableLockMemoryPrivilege2(HMODULE hModule,
+#endif
+bool enable)
+{
+  #ifndef _UNICODE
+  if (hModule == NULL)
+    return false;
+  OpenProcessTokenP openProcessToken = (OpenProcessTokenP)GetProcAddress(hModule, "OpenProcessToken");
+  LookupPrivilegeValueP lookupPrivilegeValue = (LookupPrivilegeValueP)GetProcAddress(hModule, "LookupPrivilegeValueA" );
+  AdjustTokenPrivilegesP adjustTokenPrivileges = (AdjustTokenPrivilegesP)GetProcAddress(hModule, "AdjustTokenPrivileges");
+  if (openProcessToken == NULL || adjustTokenPrivileges == NULL || lookupPrivilegeValue == NULL)
+    return false;
+  #endif
+
+  HANDLE token;
+  if (!
+    #ifdef _UNICODE
+    ::OpenProcessToken
+    #else
+    openProcessToken
+    #endif
+    (::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
+    return false;
+  TOKEN_PRIVILEGES tp;
+  bool res = false;
+  if (
+    #ifdef _UNICODE
+    ::LookupPrivilegeValue
+    #else
+    lookupPrivilegeValue
+    #endif
+    (NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)))
+  {
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED: 0;
+    if (
+      #ifdef _UNICODE
+      ::AdjustTokenPrivileges
+      #else
+      adjustTokenPrivileges
+      #endif
+      (token, FALSE, &tp, 0, NULL, NULL))
+      res = (GetLastError() == ERROR_SUCCESS);
+  }
+  ::CloseHandle(token);
+  return res;
+}
+
+#ifndef _UNICODE
+bool EnableLockMemoryPrivilege(bool enable)
+{
+  HMODULE hModule = LoadLibrary(TEXT("Advapi32.dll"));
+  if(hModule == NULL)
+    return false;
+  bool res = EnableLockMemoryPrivilege2(hModule, enable);
+  ::FreeLibrary(hModule);
+  return res;
+}
+#endif
+
+}}

Added: trunk/lzma/CPP/Windows/MemoryLock.h
===================================================================
--- trunk/lzma/CPP/Windows/MemoryLock.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/MemoryLock.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,13 @@
+// Windows/MemoryLock.h
+
+#ifndef __WINDOWS_MEMORYLOCK_H
+#define __WINDOWS_MEMORYLOCK_H
+
+namespace NWindows {
+namespace NSecurity {
+
+bool EnableLockMemoryPrivilege(bool enable = true);
+
+}}
+
+#endif 

Added: trunk/lzma/CPP/Windows/PropVariant.cpp
===================================================================
--- trunk/lzma/CPP/Windows/PropVariant.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/PropVariant.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,312 @@
+// Windows/PropVariant.cpp
+
+#include "StdAfx.h"
+
+#include "PropVariant.h"
+
+#include "../Common/Defs.h"
+
+namespace NWindows {
+namespace NCOM {
+
+CPropVariant::CPropVariant(const PROPVARIANT& varSrc)
+{
+  vt = VT_EMPTY;
+  InternalCopy(&varSrc);
+}
+
+CPropVariant::CPropVariant(const CPropVariant& varSrc)
+{
+  vt = VT_EMPTY;
+  InternalCopy(&varSrc);
+}
+
+CPropVariant::CPropVariant(BSTR bstrSrc)
+{
+  vt = VT_EMPTY;
+  *this = bstrSrc;
+}
+
+CPropVariant::CPropVariant(LPCOLESTR lpszSrc)
+{
+  vt = VT_EMPTY;
+  *this = lpszSrc;
+}
+
+CPropVariant& CPropVariant::operator=(const CPropVariant& varSrc)
+{
+  InternalCopy(&varSrc);
+  return *this;
+}
+CPropVariant& CPropVariant::operator=(const PROPVARIANT& varSrc)
+{
+  InternalCopy(&varSrc);
+  return *this;
+}
+
+CPropVariant& CPropVariant::operator=(BSTR bstrSrc)
+{
+  *this = (LPCOLESTR)bstrSrc;
+  return *this;
+}
+
+CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)
+{
+  InternalClear();
+  vt = VT_BSTR;
+  wReserved1 = 0;
+  bstrVal = ::SysAllocString(lpszSrc);
+  if (bstrVal == NULL && lpszSrc != NULL)
+  {
+    vt = VT_ERROR;
+    scode = E_OUTOFMEMORY;
+  }
+  return *this;
+}
+
+
+CPropVariant& CPropVariant::operator=(bool bSrc)
+{
+  if (vt != VT_BOOL)
+  {
+    InternalClear();
+    vt = VT_BOOL;
+  }
+  boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
+  return *this;
+}
+
+CPropVariant& CPropVariant::operator=(UInt32 value)
+{
+  if (vt != VT_UI4)
+  {
+    InternalClear();
+    vt = VT_UI4;
+  }
+  ulVal = value;
+  return *this;
+}
+
+CPropVariant& CPropVariant::operator=(UInt64 value)
+{
+  if (vt != VT_UI8)
+  {
+    InternalClear();
+    vt = VT_UI8;
+  }
+  uhVal.QuadPart = value;
+  return *this;
+}
+
+CPropVariant& CPropVariant::operator=(const FILETIME &value)
+{
+  if (vt != VT_FILETIME)
+  {
+    InternalClear();
+    vt = VT_FILETIME;
+  }
+  filetime = value;
+  return *this;
+}
+
+CPropVariant& CPropVariant::operator=(Int32 value)
+{
+  if (vt != VT_I4)
+  {
+    InternalClear();
+    vt = VT_I4;
+  }
+  lVal = value;
+  
+  return *this;
+}
+
+CPropVariant& CPropVariant::operator=(Byte value)
+{
+  if (vt != VT_UI1)
+  {
+    InternalClear();
+    vt = VT_UI1;
+  }
+  bVal = value;
+  return *this;
+}
+
+CPropVariant& CPropVariant::operator=(Int16 value)
+{
+  if (vt != VT_I2)
+  {
+    InternalClear();
+    vt = VT_I2;
+  }
+  iVal = value;
+  return *this;
+}
+
+/*
+CPropVariant& CPropVariant::operator=(LONG value)
+{
+  if (vt != VT_I4)
+  {
+    InternalClear();
+    vt = VT_I4;
+  }
+  lVal = value;
+  return *this;
+}
+*/
+
+static HRESULT MyPropVariantClear(PROPVARIANT *propVariant) 
+{ 
+  switch(propVariant->vt)
+  {
+    case VT_UI1:
+    case VT_I1:
+    case VT_I2:
+    case VT_UI2:
+    case VT_BOOL:
+    case VT_I4:
+    case VT_UI4:
+    case VT_R4:
+    case VT_INT:
+    case VT_UINT:
+    case VT_ERROR:
+    case VT_FILETIME:
+    case VT_UI8:
+    case VT_R8:
+    case VT_CY:
+    case VT_DATE:
+      propVariant->vt = VT_EMPTY;
+      propVariant->wReserved1 = 0; 
+      return S_OK;
+  }
+  return ::VariantClear((VARIANTARG *)propVariant); 
+}
+
+HRESULT CPropVariant::Clear() 
+{ 
+  return MyPropVariantClear(this);
+}
+
+HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) 
+{ 
+  ::VariantClear((tagVARIANT *)this); 
+  switch(pSrc->vt)
+  {
+    case VT_UI1:
+    case VT_I1:
+    case VT_I2:
+    case VT_UI2:
+    case VT_BOOL:
+    case VT_I4:
+    case VT_UI4:
+    case VT_R4:
+    case VT_INT:
+    case VT_UINT:
+    case VT_ERROR:
+    case VT_FILETIME:
+    case VT_UI8:
+    case VT_R8:
+    case VT_CY:
+    case VT_DATE:
+      memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
+      return S_OK;
+  }
+  return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)(pSrc)); 
+}
+
+
+HRESULT CPropVariant::Attach(PROPVARIANT* pSrc)
+{
+  HRESULT hr = Clear();
+  if (FAILED(hr))
+    return hr;
+  memcpy(this, pSrc, sizeof(PROPVARIANT));
+  pSrc->vt = VT_EMPTY;
+  return S_OK;
+}
+
+HRESULT CPropVariant::Detach(PROPVARIANT* pDest)
+{
+  HRESULT hr = MyPropVariantClear(pDest);
+  if (FAILED(hr))
+    return hr;
+  memcpy(pDest, this, sizeof(PROPVARIANT));
+  vt = VT_EMPTY;
+  return S_OK;
+}
+
+HRESULT CPropVariant::InternalClear()
+{
+  HRESULT hr = Clear();
+  if (FAILED(hr))
+  {
+    vt = VT_ERROR;
+    scode = hr;
+  }
+  return hr;
+}
+
+void CPropVariant::InternalCopy(const PROPVARIANT* pSrc)
+{
+  HRESULT hr = Copy(pSrc);
+  if (FAILED(hr))
+  {
+    vt = VT_ERROR;
+    scode = hr;
+  }
+}
+
+int CPropVariant::Compare(const CPropVariant &a)
+{
+  if(vt != a.vt)
+    return 0; // it's mean some bug
+  switch (vt)
+  {
+    case VT_EMPTY:
+      return 0;
+    
+    /*
+    case VT_I1:
+      return MyCompare(cVal, a.cVal);
+    */
+    case VT_UI1:
+      return MyCompare(bVal, a.bVal);
+
+    case VT_I2:
+      return MyCompare(iVal, a.iVal);
+    case VT_UI2:
+      return MyCompare(uiVal, a.uiVal);
+    
+    case VT_I4:
+      return MyCompare(lVal, a.lVal);
+    /*
+    case VT_INT:
+      return MyCompare(intVal, a.intVal);
+    */
+    case VT_UI4:
+      return MyCompare(ulVal, a.ulVal);
+    /*
+    case VT_UINT:
+      return MyCompare(uintVal, a.uintVal);
+    */
+    case VT_I8:
+      return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
+    case VT_UI8:
+      return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
+
+    case VT_BOOL:    
+      return -MyCompare(boolVal, a.boolVal);
+
+    case VT_FILETIME:
+      return ::CompareFileTime(&filetime, &a.filetime);
+    case VT_BSTR:
+      return 0; // Not implemented 
+      // return MyCompare(aPropVarint.cVal);
+
+    default:
+      return 0;
+  }
+}
+
+}}

Added: trunk/lzma/CPP/Windows/PropVariant.h
===================================================================
--- trunk/lzma/CPP/Windows/PropVariant.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/PropVariant.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,57 @@
+// Windows/PropVariant.h
+
+#ifndef __WINDOWS_PROPVARIANT_H
+#define __WINDOWS_PROPVARIANT_H
+
+#include "../Common/MyWindows.h"
+#include "../Common/Types.h"
+
+namespace NWindows {
+namespace NCOM {
+
+class CPropVariant : public tagPROPVARIANT
+{
+public:
+  CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; }
+  ~CPropVariant() { Clear(); }
+  CPropVariant(const PROPVARIANT& varSrc);
+  CPropVariant(const CPropVariant& varSrc);
+  CPropVariant(BSTR bstrSrc);
+  CPropVariant(LPCOLESTR lpszSrc);
+  CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); };
+  CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; }
+  CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal = *(ULARGE_INTEGER*)&value; }
+  CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; }
+  CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; }
+  CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }
+  CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; }
+  // CPropVariant(LONG value, VARTYPE vtSrc = VT_I4) { vt = vtSrc; lVal = value; }
+
+  CPropVariant& operator=(const CPropVariant& varSrc);
+  CPropVariant& operator=(const PROPVARIANT& varSrc);
+  CPropVariant& operator=(BSTR bstrSrc);
+  CPropVariant& operator=(LPCOLESTR lpszSrc);
+  CPropVariant& operator=(bool bSrc);
+  CPropVariant& operator=(UInt32 value);
+  CPropVariant& operator=(UInt64 value);
+  CPropVariant& operator=(const FILETIME &value);
+
+  CPropVariant& operator=(Int32 value);
+  CPropVariant& operator=(Byte value);
+  CPropVariant& operator=(Int16 value);
+  // CPropVariant& operator=(LONG  value);
+
+  HRESULT Clear();
+  HRESULT Copy(const PROPVARIANT* pSrc);
+  HRESULT Attach(PROPVARIANT* pSrc);
+  HRESULT Detach(PROPVARIANT* pDest);
+
+  HRESULT InternalClear();
+  void InternalCopy(const PROPVARIANT* pSrc);
+
+  int Compare(const CPropVariant &a1);
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/Windows/PropVariantConversions.cpp
===================================================================
--- trunk/lzma/CPP/Windows/PropVariantConversions.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/PropVariantConversions.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,150 @@
+// PropVariantConversions.cpp
+
+#include "StdAfx.h"
+
+// #include <stdio.h>
+
+#include "PropVariantConversions.h"
+
+#include "Windows/Defs.h"
+
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+
+static UString ConvertUInt64ToString(UInt64 value)
+{
+  wchar_t buffer[32];
+  ConvertUInt64ToString(value, buffer);
+  return buffer;
+}
+
+static UString ConvertInt64ToString(Int64 value)
+{
+  wchar_t buffer[32];
+  ConvertInt64ToString(value, buffer);
+  return buffer;
+}
+
+static char *UIntToStringSpec(UInt32 value, char *s, int numPos)
+{
+  char temp[16];
+  int pos = 0;
+  do 
+  {
+    temp[pos++] = (char)('0' + value % 10);
+    value /= 10;
+  }
+  while (value != 0);
+  int i;
+  for (i = 0; i < numPos - pos; i++)
+    *s++ = '0';
+  do
+    *s++ = temp[--pos];
+  while (pos > 0);
+  *s = '\0';
+  return s;
+}
+
+bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime, bool includeSeconds)
+{
+  s[0] = '\0';
+  SYSTEMTIME st;
+  if(!BOOLToBool(FileTimeToSystemTime(&ft, &st)))
+    return false;
+  s = UIntToStringSpec(st.wYear, s, 4);
+  *s++ = '-';
+  s = UIntToStringSpec(st.wMonth, s, 2);
+  *s++ = '-';
+  s = UIntToStringSpec(st.wDay, s, 2);
+  if (includeTime)
+  {
+    *s++ = ' ';
+    s = UIntToStringSpec(st.wHour, s, 2);
+    *s++ = ':';
+    s = UIntToStringSpec(st.wMinute, s, 2);
+    if (includeSeconds)
+    {
+      *s++ = ':';
+      UIntToStringSpec(st.wSecond, s, 2);
+    }
+  }
+  /*
+  sprintf(s, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay);
+  if (includeTime)
+  {
+    sprintf(s + strlen(s), " %02d:%02d", st.wHour, st.wMinute);
+    if (includeSeconds)
+      sprintf(s + strlen(s), ":%02d", st.wSecond);
+  }
+  */
+  return true;
+}
+
+UString ConvertFileTimeToString(const FILETIME &fileTime, bool includeTime, bool includeSeconds)
+{
+  char s[32];
+  ConvertFileTimeToString(fileTime, s,  includeTime, includeSeconds);
+  return GetUnicodeString(s);
+}
+ 
+
+UString ConvertPropVariantToString(const PROPVARIANT &propVariant)
+{
+  switch (propVariant.vt)
+  {
+    case VT_EMPTY:
+      return UString();
+    case VT_BSTR:
+      return propVariant.bstrVal;
+    case VT_UI1:
+      return ConvertUInt64ToString(propVariant.bVal);
+    case VT_UI2:
+      return ConvertUInt64ToString(propVariant.uiVal);
+    case VT_UI4:
+      return ConvertUInt64ToString(propVariant.ulVal);
+    case VT_UI8:
+      return ConvertUInt64ToString(propVariant.uhVal.QuadPart);
+    case VT_FILETIME:
+      return ConvertFileTimeToString(propVariant.filetime, true, true);
+    /*
+    case VT_I1:
+      return ConvertInt64ToString(propVariant.cVal);
+    */
+    case VT_I2:
+      return ConvertInt64ToString(propVariant.iVal);
+    case VT_I4:
+      return ConvertInt64ToString(propVariant.lVal);
+    case VT_I8:
+      return ConvertInt64ToString(propVariant.hVal.QuadPart);
+
+    case VT_BOOL:
+      return VARIANT_BOOLToBool(propVariant.boolVal) ? L"+" : L"-";
+    default:
+      #ifndef _WIN32_WCE
+      throw 150245;
+      #else
+      return UString();
+      #endif
+  }
+}
+
+UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant)
+{
+  switch (propVariant.vt)
+  {
+    case VT_UI1:
+      return propVariant.bVal;
+    case VT_UI2:
+      return propVariant.uiVal;
+    case VT_UI4:
+      return propVariant.ulVal;
+    case VT_UI8:
+      return (UInt64)propVariant.uhVal.QuadPart;
+    default:
+      #ifndef _WIN32_WCE
+      throw 151199;
+      #else
+      return 0;
+      #endif
+  }
+}

Added: trunk/lzma/CPP/Windows/PropVariantConversions.h
===================================================================
--- trunk/lzma/CPP/Windows/PropVariantConversions.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/PropVariantConversions.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,14 @@
+// Windows/PropVariantConversions.h
+
+#ifndef __PROPVARIANTCONVERSIONS_H
+#define __PROPVARIANTCONVERSIONS_H
+
+#include "Common/Types.h"
+#include "Common/MyString.h"
+
+bool ConvertFileTimeToString(const FILETIME &ft, char *s, bool includeTime = true, bool includeSeconds = true);
+UString ConvertFileTimeToString(const FILETIME &ft, bool includeTime = true, bool includeSeconds = true);
+UString ConvertPropVariantToString(const PROPVARIANT &propVariant);
+UInt64 ConvertPropVariantToUInt64(const PROPVARIANT &propVariant);
+
+#endif

Added: trunk/lzma/CPP/Windows/StdAfx.h
===================================================================
--- trunk/lzma/CPP/Windows/StdAfx.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/StdAfx.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../Common/MyWindows.h"
+#include "../Common/NewHandler.h"
+
+#endif 

Added: trunk/lzma/CPP/Windows/Synchronization.cpp
===================================================================
--- trunk/lzma/CPP/Windows/Synchronization.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/Synchronization.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,10 @@
+// Windows/Synchronization.cpp
+
+#include "StdAfx.h"
+
+#include "Synchronization.h"
+
+namespace NWindows {
+namespace NSynchronization {
+
+}}

Added: trunk/lzma/CPP/Windows/Synchronization.h
===================================================================
--- trunk/lzma/CPP/Windows/Synchronization.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/Synchronization.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,168 @@
+// Windows/Synchronization.h
+
+#ifndef __WINDOWS_SYNCHRONIZATION_H
+#define __WINDOWS_SYNCHRONIZATION_H
+
+#include "Defs.h"
+
+extern "C" 
+{ 
+#include "../../C/Threads.h"
+}
+
+#ifdef _WIN32
+#include "Handle.h"
+#endif
+
+namespace NWindows {
+namespace NSynchronization {
+
+class CBaseEvent
+{
+protected:
+  ::CEvent _object;
+public:
+  bool IsCreated() { return Event_IsCreated(&_object) != 0; }
+  operator HANDLE() { return _object.handle; }
+  CBaseEvent() { Event_Construct(&_object); }
+  ~CBaseEvent() { Close(); }
+  HRes Close() { return Event_Close(&_object); }
+  #ifdef _WIN32
+  HRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL,
+      LPSECURITY_ATTRIBUTES securityAttributes = NULL)
+  {
+    _object.handle = ::CreateEvent(securityAttributes, BoolToBOOL(manualReset),
+        BoolToBOOL(initiallyOwn), name);
+    if (_object.handle != 0)
+      return 0;
+    return ::GetLastError();
+  }
+  HRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)
+  {
+    _object.handle = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name);
+    if (_object.handle != 0)
+      return 0;
+    return ::GetLastError();
+  }
+  #endif
+
+  HRes Set() { return Event_Set(&_object); }
+  // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); }
+  HRes Reset() { return Event_Reset(&_object); }
+  HRes Lock() { return Event_Wait(&_object); }
+};
+
+class CManualResetEvent: public CBaseEvent
+{
+public:
+  HRes Create(bool initiallyOwn = false)
+  {
+    return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0);
+  }
+  HRes CreateIfNotCreated()
+  {
+    if (IsCreated())
+      return 0;
+    return ManualResetEvent_CreateNotSignaled(&_object);
+  }
+  #ifdef _WIN32
+  HRes CreateWithName(bool initiallyOwn, LPCTSTR name)
+  {
+    return CBaseEvent::Create(true, initiallyOwn, name);
+  }
+  #endif
+};
+
+class CAutoResetEvent: public CBaseEvent
+{
+public:
+  HRes Create()
+  {
+    return AutoResetEvent_CreateNotSignaled(&_object);
+  }
+  HRes CreateIfNotCreated()
+  {
+    if (IsCreated())
+      return 0;
+    return AutoResetEvent_CreateNotSignaled(&_object);
+  }
+};
+
+#ifdef _WIN32
+class CObject: public CHandle
+{
+public:
+  HRes Lock(DWORD timeoutInterval = INFINITE)
+    { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); }
+};
+class CMutex: public CObject
+{
+public:
+  HRes Create(bool initiallyOwn, LPCTSTR name = NULL,
+      LPSECURITY_ATTRIBUTES securityAttributes = NULL)
+  {
+    _handle = ::CreateMutex(securityAttributes, BoolToBOOL(initiallyOwn), name);
+    if (_handle != 0)
+      return 0;
+    return ::GetLastError();
+  }
+  HRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)
+  {
+    _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name);
+    if (_handle != 0)
+      return 0;
+    return ::GetLastError();
+  }
+  HRes Release() 
+  { 
+    return ::ReleaseMutex(_handle) ? 0 : ::GetLastError();
+  }
+};
+class CMutexLock
+{
+  CMutex *_object;
+public:
+  CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } 
+  ~CMutexLock() { _object->Release(); }
+};
+#endif
+
+class CSemaphore
+{
+  ::CSemaphore _object;
+public:
+  CSemaphore() { Semaphore_Construct(&_object); }
+  ~CSemaphore() { Close(); }
+  HRes Close() {  return Semaphore_Close(&_object); }
+  operator HANDLE() { return _object.handle; }
+  HRes Create(UInt32 initiallyCount, UInt32 maxCount)
+  {
+    return Semaphore_Create(&_object, initiallyCount, maxCount);
+  }
+  HRes Release() { return Semaphore_Release1(&_object); }
+  HRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); }
+  HRes Lock() { return Semaphore_Wait(&_object); }
+};
+
+class CCriticalSection
+{
+  ::CCriticalSection _object;
+public:
+  CCriticalSection() { CriticalSection_Init(&_object); }
+  ~CCriticalSection() { CriticalSection_Delete(&_object); }
+  void Enter() { CriticalSection_Enter(&_object); }
+  void Leave() { CriticalSection_Leave(&_object); }
+};
+
+class CCriticalSectionLock
+{
+  CCriticalSection *_object;
+  void Unlock()  { _object->Leave(); }
+public:
+  CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } 
+  ~CCriticalSectionLock() { Unlock(); }
+};
+
+}}
+
+#endif

Added: trunk/lzma/CPP/Windows/System.cpp
===================================================================
--- trunk/lzma/CPP/Windows/System.cpp	                        (rev 0)
+++ trunk/lzma/CPP/Windows/System.cpp	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,64 @@
+// Windows/System.cpp
+
+#include "StdAfx.h"
+
+#include "System.h"
+
+namespace NWindows {
+namespace NSystem {
+
+UInt32 GetNumberOfProcessors()
+{
+  SYSTEM_INFO systemInfo;
+  GetSystemInfo(&systemInfo);
+  return (UInt32)systemInfo.dwNumberOfProcessors;
+}
+
+#if !defined(_WIN64) && defined(__GNUC__)
+
+typedef struct _MY_MEMORYSTATUSEX {
+  DWORD dwLength;
+  DWORD dwMemoryLoad;
+  DWORDLONG ullTotalPhys;
+  DWORDLONG ullAvailPhys;
+  DWORDLONG ullTotalPageFile;
+  DWORDLONG ullAvailPageFile;
+  DWORDLONG ullTotalVirtual;
+  DWORDLONG ullAvailVirtual;
+  DWORDLONG ullAvailExtendedVirtual;
+} MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX;
+
+#else
+
+#define MY_MEMORYSTATUSEX MEMORYSTATUSEX
+#define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX
+
+#endif
+
+typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer);
+
+UInt64 GetRamSize()
+{
+  MY_MEMORYSTATUSEX stat;
+  stat.dwLength = sizeof(stat);
+  #ifdef _WIN64
+  if (!::GlobalMemoryStatusEx(&stat))
+    return 0;
+  return stat.ullTotalPhys;
+  #else
+  GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP)
+        ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")),
+        "GlobalMemoryStatusEx");
+  if (globalMemoryStatusEx != 0)
+    if (globalMemoryStatusEx(&stat))
+      return stat.ullTotalPhys;
+  {
+    MEMORYSTATUS stat;
+    stat.dwLength = sizeof(stat);
+    GlobalMemoryStatus(&stat);
+    return stat.dwTotalPhys;
+  }
+  #endif
+}
+
+}}

Added: trunk/lzma/CPP/Windows/System.h
===================================================================
--- trunk/lzma/CPP/Windows/System.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/System.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,16 @@
+// Windows/System.h
+
+#ifndef __WINDOWS_SYSTEM_H
+#define __WINDOWS_SYSTEM_H
+
+#include "../Common/Types.h"
+
+namespace NWindows {
+namespace NSystem {
+
+UInt32 GetNumberOfProcessors();
+UInt64 GetRamSize();
+
+}}
+
+#endif

Added: trunk/lzma/CPP/Windows/Thread.h
===================================================================
--- trunk/lzma/CPP/Windows/Thread.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/Thread.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,38 @@
+// Windows/Thread.h
+
+#ifndef __WINDOWS_THREAD_H
+#define __WINDOWS_THREAD_H
+
+#include "Defs.h"
+
+extern "C" 
+{ 
+#include "../../C/Threads.h"
+}
+
+namespace NWindows {
+
+class CThread
+{
+  ::CThread thread;
+public:
+  CThread() { Thread_Construct(&thread); }
+  ~CThread() { Close(); }
+  bool IsCreated() { return Thread_WasCreated(&thread) != 0; }
+  HRes Close()  { return Thread_Close(&thread); }
+  HRes Create(THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter)
+    { return Thread_Create(&thread, startAddress, parameter); }
+  HRes Wait() { return Thread_Wait(&thread); }
+  
+  #ifdef _WIN32
+  DWORD Resume() { return ::ResumeThread(thread.handle); }
+  DWORD Suspend() { return ::SuspendThread(thread.handle); }
+  bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread.handle, exitCode)); }
+  int GetPriority() { return ::GetThreadPriority(thread.handle); }
+  bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread.handle, priority)); }
+  #endif
+};
+
+}
+
+#endif

Added: trunk/lzma/CPP/Windows/Time.h
===================================================================
--- trunk/lzma/CPP/Windows/Time.h	                        (rev 0)
+++ trunk/lzma/CPP/Windows/Time.h	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,66 @@
+// Windows/Time.h
+
+#ifndef __WINDOWS_TIME_H
+#define __WINDOWS_TIME_H
+
+#include "Common/Types.h"
+#include "Windows/Defs.h"
+
+namespace NWindows {
+namespace NTime {
+
+inline bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime)
+{
+  return BOOLToBool(::DosDateTimeToFileTime(UInt16(dosTime >> 16), 
+      UInt16(dosTime & 0xFFFF), &fileTime));
+}
+
+const UInt32 kHighDosTime = 0xFF9FBF7D;
+const UInt32 kLowDosTime = 0x210000;
+
+inline bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime)
+{
+  WORD datePart, timePart;
+  if (!::FileTimeToDosDateTime(&fileTime, &datePart, &timePart))
+  {
+    if (fileTime.dwHighDateTime >= 0x01C00000) // 2000
+      dosTime = kHighDosTime;
+    else
+      dosTime = kLowDosTime;
+    return false;
+  }
+  dosTime = (((UInt32)datePart) << 16) + timePart;
+  return true;
+}
+
+const UInt32 kNumTimeQuantumsInSecond = 10000000;
+const UInt64 kUnixTimeStartValue = ((UInt64)kNumTimeQuantumsInSecond) * 60 * 60 * 24 * 134774;
+
+inline void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime)
+{
+  UInt64 v = kUnixTimeStartValue + ((UInt64)unixTime) * kNumTimeQuantumsInSecond;
+  fileTime.dwLowDateTime = (DWORD)v;
+  fileTime.dwHighDateTime = (DWORD)(v >> 32);
+}
+
+inline bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime)
+{
+  UInt64 winTime = (((UInt64)fileTime.dwHighDateTime) << 32) + fileTime.dwLowDateTime;
+  if (winTime < kUnixTimeStartValue)
+  {
+    unixTime = 0;
+    return false;
+  }
+  winTime = (winTime - kUnixTimeStartValue) / kNumTimeQuantumsInSecond;
+  if (winTime > 0xFFFFFFFF)
+  {
+    unixTime = 0xFFFFFFFF;
+    return false;
+  }
+  unixTime = (UInt32)winTime;
+  return true;
+}
+
+}}
+
+#endif

Added: trunk/lzma/CS/7zip/Common/CRC.cs
===================================================================
--- trunk/lzma/CS/7zip/Common/CRC.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Common/CRC.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,55 @@
+// Common/CRC.cs
+
+namespace SevenZip
+{
+	class CRC
+	{
+		public static readonly uint[] Table;
+
+		static CRC()
+		{
+			Table = new uint[256];
+			const uint kPoly = 0xEDB88320;
+			for (uint i = 0; i < 256; i++)
+			{
+				uint r = i;
+				for (int j = 0; j < 8; j++)
+					if ((r & 1) != 0)
+						r = (r >> 1) ^ kPoly;
+					else
+						r >>= 1;
+				Table[i] = r;
+			}
+		}
+
+		uint _value = 0xFFFFFFFF;
+
+		public void Init() { _value = 0xFFFFFFFF; }
+
+		public void UpdateByte(byte b)
+		{
+			_value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);
+		}
+
+		public void Update(byte[] data, uint offset, uint size)
+		{
+			for (uint i = 0; i < size; i++)
+				_value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);
+		}
+
+		public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
+
+		static uint CalculateDigest(byte[] data, uint offset, uint size)
+		{
+			CRC crc = new CRC();
+			// crc.Init();
+			crc.Update(data, offset, size);
+			return crc.GetDigest();
+		}
+
+		static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
+		{
+			return (CalculateDigest(data, offset, size) == digest);
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/Common/CommandLineParser.cs
===================================================================
--- trunk/lzma/CS/7zip/Common/CommandLineParser.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Common/CommandLineParser.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,274 @@
+// CommandLineParser.cs
+
+using System;
+using System.Collections;
+
+namespace SevenZip.CommandLineParser
+{
+	public enum SwitchType
+	{
+		Simple,
+		PostMinus,
+		LimitedPostString,
+		UnLimitedPostString,
+		PostChar
+	}
+
+	public class SwitchForm
+	{
+		public string IDString;
+		public SwitchType Type;
+		public bool Multi;
+		public int MinLen;
+		public int MaxLen;
+		public string PostCharSet;
+
+		public SwitchForm(string idString, SwitchType type, bool multi,
+			int minLen, int maxLen, string postCharSet)
+		{
+			IDString = idString;
+			Type = type;
+			Multi = multi;
+			MinLen = minLen;
+			MaxLen = maxLen;
+			PostCharSet = postCharSet;
+		}
+		public SwitchForm(string idString, SwitchType type, bool multi, int minLen):
+			this(idString, type, multi, minLen, 0, "")
+		{
+		}
+		public SwitchForm(string idString, SwitchType type, bool multi):
+			this(idString, type, multi, 0)
+		{
+		}
+	}
+
+	public class SwitchResult
+	{
+		public bool ThereIs;
+		public bool WithMinus;
+		public ArrayList PostStrings = new ArrayList();
+		public int PostCharIndex;
+		public SwitchResult()
+		{
+			ThereIs = false;
+		}
+	}
+
+	public class Parser
+	{
+		public ArrayList NonSwitchStrings = new ArrayList();
+		SwitchResult[] _switches;
+
+		public Parser(int numSwitches)
+		{
+			_switches = new SwitchResult[numSwitches];
+			for (int i = 0; i < numSwitches; i++)
+				_switches[i] = new SwitchResult();
+		}
+
+		bool ParseString(string srcString, SwitchForm[] switchForms)
+		{
+			int len = srcString.Length;
+			if (len == 0)
+				return false;
+			int pos = 0;
+			if (!IsItSwitchChar(srcString[pos]))
+				return false;
+			while (pos < len)
+			{
+				if (IsItSwitchChar(srcString[pos]))
+					pos++;
+				const int kNoLen = -1;
+				int matchedSwitchIndex = 0;
+				int maxLen = kNoLen;
+				for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
+				{
+					int switchLen = switchForms[switchIndex].IDString.Length;
+					if (switchLen <= maxLen || pos + switchLen > len)
+						continue;
+					if (String.Compare(switchForms[switchIndex].IDString, 0,
+							srcString, pos, switchLen, true) == 0)
+					{
+						matchedSwitchIndex = switchIndex;
+						maxLen = switchLen;
+					}
+				}
+				if (maxLen == kNoLen)
+					throw new Exception("maxLen == kNoLen");
+				SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
+				SwitchForm switchForm = switchForms[matchedSwitchIndex];
+				if ((!switchForm.Multi) && matchedSwitch.ThereIs)
+					throw new Exception("switch must be single");
+				matchedSwitch.ThereIs = true;
+				pos += maxLen;
+				int tailSize = len - pos;
+				SwitchType type = switchForm.Type;
+				switch (type)
+				{
+					case SwitchType.PostMinus:
+						{
+							if (tailSize == 0)
+								matchedSwitch.WithMinus = false;
+							else
+							{
+								matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus);
+								if (matchedSwitch.WithMinus)
+									pos++;
+							}
+							break;
+						}
+					case SwitchType.PostChar:
+						{
+							if (tailSize < switchForm.MinLen)
+								throw new Exception("switch is not full");
+							string charSet = switchForm.PostCharSet;
+							const int kEmptyCharValue = -1;
+							if (tailSize == 0)
+								matchedSwitch.PostCharIndex = kEmptyCharValue;
+							else
+							{
+								int index = charSet.IndexOf(srcString[pos]);
+								if (index < 0)
+									matchedSwitch.PostCharIndex = kEmptyCharValue;
+								else
+								{
+									matchedSwitch.PostCharIndex = index;
+									pos++;
+								}
+							}
+							break;
+						}
+					case SwitchType.LimitedPostString:
+					case SwitchType.UnLimitedPostString:
+						{
+							int minLen = switchForm.MinLen;
+							if (tailSize < minLen)
+								throw new Exception("switch is not full");
+							if (type == SwitchType.UnLimitedPostString)
+							{
+								matchedSwitch.PostStrings.Add(srcString.Substring(pos));
+								return true;
+							}
+							String stringSwitch = srcString.Substring(pos, minLen);
+							pos += minLen;
+							for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
+							{
+								char c = srcString[pos];
+								if (IsItSwitchChar(c))
+									break;
+								stringSwitch += c;
+							}
+							matchedSwitch.PostStrings.Add(stringSwitch);
+							break;
+						}
+				}
+			}
+			return true;
+
+		}
+
+		public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
+		{
+			int numCommandStrings = commandStrings.Length;
+			bool stopSwitch = false;
+			for (int i = 0; i < numCommandStrings; i++)
+			{
+				string s = commandStrings[i];
+				if (stopSwitch)
+					NonSwitchStrings.Add(s);
+				else
+					if (s == kStopSwitchParsing)
+					stopSwitch = true;
+				else
+					if (!ParseString(s, switchForms))
+					NonSwitchStrings.Add(s);
+			}
+		}
+
+		public SwitchResult this[int index] { get { return _switches[index]; } }
+
+		public static int ParseCommand(CommandForm[] commandForms, string commandString,
+			out string postString)
+		{
+			for (int i = 0; i < commandForms.Length; i++)
+			{
+				string id = commandForms[i].IDString;
+				if (commandForms[i].PostStringMode)
+				{
+					if (commandString.IndexOf(id) == 0)
+					{
+						postString = commandString.Substring(id.Length);
+						return i;
+					}
+				}
+				else
+					if (commandString == id)
+				{
+					postString = "";
+					return i;
+				}
+			}
+			postString = "";
+			return -1;
+		}
+
+		static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
+			string commandString, ArrayList indices)
+		{
+			indices.Clear();
+			int numUsedChars = 0;
+			for (int i = 0; i < numForms; i++)
+			{
+				CommandSubCharsSet charsSet = forms[i];
+				int currentIndex = -1;
+				int len = charsSet.Chars.Length;
+				for (int j = 0; j < len; j++)
+				{
+					char c = charsSet.Chars[j];
+					int newIndex = commandString.IndexOf(c);
+					if (newIndex >= 0)
+					{
+						if (currentIndex >= 0)
+							return false;
+						if (commandString.IndexOf(c, newIndex + 1) >= 0)
+							return false;
+						currentIndex = j;
+						numUsedChars++;
+					}
+				}
+				if (currentIndex == -1 && !charsSet.EmptyAllowed)
+					return false;
+				indices.Add(currentIndex);
+			}
+			return (numUsedChars == commandString.Length);
+		}
+		const char kSwitchID1 = '-';
+		const char kSwitchID2 = '/';
+
+		const char kSwitchMinus = '-';
+		const string kStopSwitchParsing = "--";
+
+		static bool IsItSwitchChar(char c)
+		{
+			return (c == kSwitchID1 || c == kSwitchID2);
+		}
+	}
+
+	public class CommandForm
+	{
+		public string IDString = "";
+		public bool PostStringMode = false;
+		public CommandForm(string idString, bool postStringMode)
+		{
+			IDString = idString;
+			PostStringMode = postStringMode;
+		}
+	}
+
+	class CommandSubCharsSet
+	{
+		public string Chars = "";
+		public bool EmptyAllowed = false;
+	}
+}

Added: trunk/lzma/CS/7zip/Common/InBuffer.cs
===================================================================
--- trunk/lzma/CS/7zip/Common/InBuffer.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Common/InBuffer.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,72 @@
+// InBuffer.cs
+
+namespace SevenZip.Buffer
+{
+	public class InBuffer
+	{
+		byte[] m_Buffer;
+		uint m_Pos;
+		uint m_Limit;
+		uint m_BufferSize;
+		System.IO.Stream m_Stream;
+		bool m_StreamWasExhausted;
+		ulong m_ProcessedSize;
+
+		public InBuffer(uint bufferSize)
+		{
+			m_Buffer = new byte[bufferSize];
+			m_BufferSize = bufferSize;
+		}
+
+		public void Init(System.IO.Stream stream)
+		{
+			m_Stream = stream;
+			m_ProcessedSize = 0;
+			m_Limit = 0;
+			m_Pos = 0;
+			m_StreamWasExhausted = false;
+		}
+
+		public bool ReadBlock()
+		{
+			if (m_StreamWasExhausted)
+				return false;
+			m_ProcessedSize += m_Pos;
+			int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
+			m_Pos = 0;
+			m_Limit = (uint)aNumProcessedBytes;
+			m_StreamWasExhausted = (aNumProcessedBytes == 0);
+			return (!m_StreamWasExhausted);
+		}
+
+
+		public void ReleaseStream()
+		{
+			// m_Stream.Close(); 
+			m_Stream = null;
+		}
+
+		public bool ReadByte(byte b) // check it
+		{
+			if (m_Pos >= m_Limit)
+				if (!ReadBlock())
+					return false;
+			b = m_Buffer[m_Pos++];
+			return true;
+		}
+
+		public byte ReadByte()
+		{
+			// return (byte)m_Stream.ReadByte();
+			if (m_Pos >= m_Limit)
+				if (!ReadBlock())
+					return 0xFF;
+			return m_Buffer[m_Pos++];
+		}
+
+		public ulong GetProcessedSize()
+		{
+			return m_ProcessedSize + m_Pos;
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/Common/OutBuffer.cs
===================================================================
--- trunk/lzma/CS/7zip/Common/OutBuffer.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Common/OutBuffer.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,47 @@
+// OutBuffer.cs
+
+namespace SevenZip.Buffer
+{
+	public class OutBuffer
+	{
+		byte[] m_Buffer;
+		uint m_Pos;
+		uint m_BufferSize;
+		System.IO.Stream m_Stream;
+		ulong m_ProcessedSize;
+
+		public OutBuffer(uint bufferSize)
+		{
+			m_Buffer = new byte[bufferSize];
+			m_BufferSize = bufferSize;
+		}
+
+		public void SetStream(System.IO.Stream stream) { m_Stream = stream; }
+		public void FlushStream() { m_Stream.Flush(); }
+		public void CloseStream() { m_Stream.Close(); }
+		public void ReleaseStream() { m_Stream = null; }
+
+		public void Init()
+		{
+			m_ProcessedSize = 0;
+			m_Pos = 0;
+		}
+
+		public void WriteByte(byte b)
+		{
+			m_Buffer[m_Pos++] = b;
+			if (m_Pos >= m_BufferSize)
+				FlushData();
+		}
+
+		public void FlushData()
+		{
+			if (m_Pos == 0)
+				return;
+			m_Stream.Write(m_Buffer, 0, (int)m_Pos);
+			m_Pos = 0;
+		}
+
+		public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LZ/IMatchFinder.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,24 @@
+// IMatchFinder.cs
+
+using System;
+
+namespace SevenZip.Compression.LZ
+{
+	interface IInWindowStream
+	{
+		void SetStream(System.IO.Stream inStream);
+		void Init();
+		void ReleaseStream();
+		Byte GetIndexByte(Int32 index);
+		UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
+		UInt32 GetNumAvailableBytes();
+	}
+
+	interface IMatchFinder : IInWindowStream
+	{
+		void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+				UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
+		UInt32 GetMatches(UInt32[] distances);
+		void Skip(UInt32 num);
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LZ/LzBinTree.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LZ/LzBinTree.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LZ/LzBinTree.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,367 @@
+// LzBinTree.cs
+
+using System;
+
+namespace SevenZip.Compression.LZ
+{
+	public class BinTree : InWindow, IMatchFinder
+	{
+		UInt32 _cyclicBufferPos;
+		UInt32 _cyclicBufferSize = 0;
+		UInt32 _matchMaxLen;
+
+		UInt32[] _son;
+		UInt32[] _hash;
+
+		UInt32 _cutValue = 0xFF;
+		UInt32 _hashMask;
+		UInt32 _hashSizeSum = 0;
+
+		bool HASH_ARRAY = true;
+
+		const UInt32 kHash2Size = 1 << 10;
+		const UInt32 kHash3Size = 1 << 16;
+		const UInt32 kBT2HashSize = 1 << 16;
+		const UInt32 kStartMaxLen = 1;
+		const UInt32 kHash3Offset = kHash2Size;
+		const UInt32 kEmptyHashValue = 0;
+		const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
+	
+		UInt32 kNumHashDirectBytes = 0;
+		UInt32 kMinMatchCheck = 4;
+		UInt32 kFixHashSize = kHash2Size + kHash3Size;
+		
+		public void SetType(int numHashBytes)
+		{
+			HASH_ARRAY = (numHashBytes > 2);
+			if (HASH_ARRAY)
+			{
+				kNumHashDirectBytes = 0;
+				kMinMatchCheck = 4;
+				kFixHashSize = kHash2Size + kHash3Size;
+			}
+			else
+			{
+				kNumHashDirectBytes = 2;
+				kMinMatchCheck = 2 + 1;
+				kFixHashSize = 0;
+			}
+		}
+
+		public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
+		public new void ReleaseStream() { base.ReleaseStream(); }
+		
+		public new void Init()
+		{
+			base.Init();
+			for (UInt32 i = 0; i < _hashSizeSum; i++)
+				_hash[i] = kEmptyHashValue;
+			_cyclicBufferPos = 0;
+			ReduceOffsets(-1);
+		}
+
+		public new void MovePos()
+		{
+			if (++_cyclicBufferPos >= _cyclicBufferSize)
+				_cyclicBufferPos = 0;
+			base.MovePos();
+			if (_pos == kMaxValForNormalize)
+				Normalize();
+		}
+
+		public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
+
+		public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
+		{ return base.GetMatchLen(index, distance, limit); }
+
+		public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
+
+		public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+				UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
+		{
+			if (historySize > kMaxValForNormalize - 256)
+				throw new Exception();
+			_cutValue = 16 + (matchMaxLen >> 1);
+				
+			UInt32 windowReservSize = (historySize + keepAddBufferBefore +
+					matchMaxLen + keepAddBufferAfter) / 2 + 256;
+
+			base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
+
+			_matchMaxLen = matchMaxLen;
+
+			UInt32 cyclicBufferSize = historySize + 1;
+			if (_cyclicBufferSize != cyclicBufferSize)
+				_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
+
+			UInt32 hs = kBT2HashSize;
+
+			if (HASH_ARRAY)
+			{
+				hs = historySize - 1;
+				hs |= (hs >> 1);
+				hs |= (hs >> 2);
+				hs |= (hs >> 4);
+				hs |= (hs >> 8);
+				hs >>= 1;
+				hs |= 0xFFFF;
+				if (hs > (1 << 24))
+					hs >>= 1;
+				_hashMask = hs;
+				hs++;
+				hs += kFixHashSize;
+			}
+			if (hs != _hashSizeSum)
+				_hash = new UInt32[_hashSizeSum = hs];
+		}
+
+		public UInt32 GetMatches(UInt32[] distances)
+		{
+			UInt32 lenLimit;
+			if (_pos + _matchMaxLen <= _streamPos)
+				lenLimit = _matchMaxLen;
+			else
+			{
+				lenLimit = _streamPos - _pos;
+				if (lenLimit < kMinMatchCheck)
+				{
+					MovePos();
+					return 0;
+				}
+			}
+
+			UInt32 offset = 0;
+			UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+			UInt32 cur = _bufferOffset + _pos;
+			UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
+			UInt32 hashValue, hash2Value = 0, hash3Value = 0;
+
+			if (HASH_ARRAY)
+			{
+				UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
+				hash2Value = temp & (kHash2Size - 1);
+				temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
+				hash3Value = temp & (kHash3Size - 1);
+				hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
+			}
+			else
+				hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
+
+			UInt32 curMatch = _hash[kFixHashSize + hashValue];
+			if (HASH_ARRAY)
+			{
+				UInt32 curMatch2 = _hash[hash2Value];
+				UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
+				_hash[hash2Value] = _pos;
+				_hash[kHash3Offset + hash3Value] = _pos;
+				if (curMatch2 > matchMinPos)
+					if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
+					{
+						distances[offset++] = maxLen = 2;
+						distances[offset++] = _pos - curMatch2 - 1;
+					}
+				if (curMatch3 > matchMinPos)
+					if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
+					{
+						if (curMatch3 == curMatch2)
+							offset -= 2;
+						distances[offset++] = maxLen = 3;
+						distances[offset++] = _pos - curMatch3 - 1;
+						curMatch2 = curMatch3;
+					}
+				if (offset != 0 && curMatch2 == curMatch)
+				{
+					offset -= 2;
+					maxLen = kStartMaxLen;
+				}
+			}
+
+			_hash[kFixHashSize + hashValue] = _pos;
+
+			UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
+			UInt32 ptr1 = (_cyclicBufferPos << 1);
+
+			UInt32 len0, len1;
+			len0 = len1 = kNumHashDirectBytes;
+			
+			if (kNumHashDirectBytes != 0)
+			{
+				if (curMatch > matchMinPos)
+				{
+					if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
+							_bufferBase[cur + kNumHashDirectBytes])
+					{
+						distances[offset++] = maxLen = kNumHashDirectBytes;
+						distances[offset++] = _pos - curMatch - 1;
+					}
+				}
+			}
+			
+			UInt32 count = _cutValue;
+			
+			while(true)
+			{
+				if(curMatch <= matchMinPos || count-- == 0)
+				{
+					_son[ptr0] = _son[ptr1] = kEmptyHashValue;
+					break;
+				}
+				UInt32 delta = _pos - curMatch;
+				UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
+							(_cyclicBufferPos - delta) :
+							(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
+
+				UInt32 pby1 = _bufferOffset + curMatch;
+				UInt32 len = Math.Min(len0, len1);
+				if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
+				{
+					while(++len != lenLimit)
+						if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
+							break;
+					if (maxLen < len)
+					{
+						distances[offset++] = maxLen = len;
+						distances[offset++] = delta - 1;
+						if (len == lenLimit)
+						{
+							_son[ptr1] = _son[cyclicPos];
+							_son[ptr0] = _son[cyclicPos + 1];
+							break;
+						}
+					}
+				}
+				if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
+				{
+					_son[ptr1] = curMatch;
+					ptr1 = cyclicPos + 1;
+					curMatch = _son[ptr1];
+					len1 = len;
+				}
+				else
+				{
+					_son[ptr0] = curMatch;
+					ptr0 = cyclicPos;
+					curMatch = _son[ptr0];
+					len0 = len;
+				}
+			}
+			MovePos();
+			return offset;
+		}
+
+		public void Skip(UInt32 num)
+		{
+			do
+			{
+				UInt32 lenLimit;
+				if (_pos + _matchMaxLen <= _streamPos)
+					lenLimit = _matchMaxLen;
+				else
+				{
+					lenLimit = _streamPos - _pos;
+					if (lenLimit < kMinMatchCheck)
+					{
+						MovePos();
+						continue;
+					}
+				}
+
+				UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+				UInt32 cur = _bufferOffset + _pos;
+
+				UInt32 hashValue;
+
+				if (HASH_ARRAY)
+				{
+					UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
+					UInt32 hash2Value = temp & (kHash2Size - 1);
+					_hash[hash2Value] = _pos;
+					temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
+					UInt32 hash3Value = temp & (kHash3Size - 1);
+					_hash[kHash3Offset + hash3Value] = _pos;
+					hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
+				}
+				else
+					hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
+
+				UInt32 curMatch = _hash[kFixHashSize + hashValue];
+				_hash[kFixHashSize + hashValue] = _pos;
+
+				UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
+				UInt32 ptr1 = (_cyclicBufferPos << 1);
+
+				UInt32 len0, len1;
+				len0 = len1 = kNumHashDirectBytes;
+
+				UInt32 count = _cutValue;
+				while (true)
+				{
+					if (curMatch <= matchMinPos || count-- == 0)
+					{
+						_son[ptr0] = _son[ptr1] = kEmptyHashValue;
+						break;
+					}
+
+					UInt32 delta = _pos - curMatch;
+					UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
+								(_cyclicBufferPos - delta) :
+								(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
+
+					UInt32 pby1 = _bufferOffset + curMatch;
+					UInt32 len = Math.Min(len0, len1);
+					if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
+					{
+						while (++len != lenLimit)
+							if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
+								break;
+						if (len == lenLimit)
+						{
+							_son[ptr1] = _son[cyclicPos];
+							_son[ptr0] = _son[cyclicPos + 1];
+							break;
+						}
+					}
+					if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
+					{
+						_son[ptr1] = curMatch;
+						ptr1 = cyclicPos + 1;
+						curMatch = _son[ptr1];
+						len1 = len;
+					}
+					else
+					{
+						_son[ptr0] = curMatch;
+						ptr0 = cyclicPos;
+						curMatch = _son[ptr0];
+						len0 = len;
+					}
+				}
+				MovePos();
+			}
+			while (--num != 0);
+		}
+
+		void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
+		{
+			for (UInt32 i = 0; i < numItems; i++)
+			{
+				UInt32 value = items[i];
+				if (value <= subValue)
+					value = kEmptyHashValue;
+				else
+					value -= subValue;
+				items[i] = value;
+			}
+		}
+
+		void Normalize()
+		{
+			UInt32 subValue = _pos - _cyclicBufferSize;
+			NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
+			NormalizeLinks(_hash, _hashSizeSum, subValue);
+			ReduceOffsets((Int32)subValue);
+		}
+
+		public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LZ/LzInWindow.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LZ/LzInWindow.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LZ/LzInWindow.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,132 @@
+// LzInWindow.cs
+
+using System;
+
+namespace SevenZip.Compression.LZ
+{
+	public class InWindow
+	{
+		public Byte[] _bufferBase = null; // pointer to buffer with data
+		System.IO.Stream _stream;
+		UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
+		bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
+
+		UInt32 _pointerToLastSafePosition;
+
+		public UInt32 _bufferOffset;
+
+		public UInt32 _blockSize; // Size of Allocated memory block
+		public UInt32 _pos; // offset (from _buffer) of curent byte
+		UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
+		UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
+		public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
+
+		public void MoveBlock()
+		{
+			UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;
+			// we need one additional byte, since MovePos moves on 1 byte.
+			if (offset > 0)
+				offset--;
+			
+			UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;
+
+			// check negative offset ????
+			for (UInt32 i = 0; i < numBytes; i++)
+				_bufferBase[i] = _bufferBase[offset + i];
+			_bufferOffset -= offset;
+		}
+
+		public virtual void ReadBlock()
+		{
+			if (_streamEndWasReached)
+				return;
+			while (true)
+			{
+				int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);
+				if (size == 0)
+					return;
+				int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
+				if (numReadBytes == 0)
+				{
+					_posLimit = _streamPos;
+					UInt32 pointerToPostion = _bufferOffset + _posLimit;
+					if (pointerToPostion > _pointerToLastSafePosition)
+						_posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);
+
+					_streamEndWasReached = true;
+					return;
+				}
+				_streamPos += (UInt32)numReadBytes;
+				if (_streamPos >= _pos + _keepSizeAfter)
+					_posLimit = _streamPos - _keepSizeAfter;
+			}
+		}
+
+		void Free() { _bufferBase = null; }
+
+		public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
+		{
+			_keepSizeBefore = keepSizeBefore;
+			_keepSizeAfter = keepSizeAfter;
+			UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
+			if (_bufferBase == null || _blockSize != blockSize)
+			{
+				Free();
+				_blockSize = blockSize;
+				_bufferBase = new Byte[_blockSize];
+			}
+			_pointerToLastSafePosition = _blockSize - keepSizeAfter;
+		}
+
+		public void SetStream(System.IO.Stream stream) { _stream = stream; }
+		public void ReleaseStream() { _stream = null; }
+
+		public void Init()
+		{
+			_bufferOffset = 0;
+			_pos = 0;
+			_streamPos = 0;
+			_streamEndWasReached = false;
+			ReadBlock();
+		}
+
+		public void MovePos()
+		{
+			_pos++;
+			if (_pos > _posLimit)
+			{
+				UInt32 pointerToPostion = _bufferOffset + _pos;
+				if (pointerToPostion > _pointerToLastSafePosition)
+					MoveBlock();
+				ReadBlock();
+			}
+		}
+
+		public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
+
+		// index + limit have not to exceed _keepSizeAfter;
+		public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
+		{
+			if (_streamEndWasReached)
+				if ((_pos + index) + limit > _streamPos)
+					limit = _streamPos - (UInt32)(_pos + index);
+			distance++;
+			// Byte *pby = _buffer + (size_t)_pos + index;
+			UInt32 pby = _bufferOffset + _pos + (UInt32)index;
+
+			UInt32 i;
+			for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);
+			return i;
+		}
+
+		public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
+
+		public void ReduceOffsets(Int32 subValue)
+		{
+			_bufferOffset += (UInt32)subValue;
+			_posLimit -= (UInt32)subValue;
+			_pos -= (UInt32)subValue;
+			_streamPos -= (UInt32)subValue;
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LZ/LzOutWindow.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,110 @@
+// LzOutWindow.cs
+
+namespace SevenZip.Compression.LZ
+{
+	public class OutWindow
+	{
+		byte[] _buffer = null;
+		uint _pos;
+		uint _windowSize = 0;
+		uint _streamPos;
+		System.IO.Stream _stream;
+
+		public uint TrainSize = 0;
+
+		public void Create(uint windowSize)
+		{
+			if (_windowSize != windowSize)
+			{
+				// System.GC.Collect();
+				_buffer = new byte[windowSize];
+			}
+			_windowSize = windowSize;
+			_pos = 0;
+			_streamPos = 0;
+		}
+
+		public void Init(System.IO.Stream stream, bool solid)
+		{
+			ReleaseStream();
+			_stream = stream;
+			if (!solid)
+			{
+				_streamPos = 0;
+				_pos = 0;
+				TrainSize = 0;
+			}
+		}
+	
+		public bool Train(System.IO.Stream stream)
+		{
+			long len = stream.Length;
+			uint size = (len < _windowSize) ? (uint)len : _windowSize;
+			TrainSize = size;
+			stream.Position = len - size;
+			_streamPos = _pos = 0;
+			while (size > 0)
+			{
+				uint curSize = _windowSize - _pos;
+				if (size < curSize)
+					curSize = size;
+				int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
+				if (numReadBytes == 0)
+					return false;
+				size -= (uint)numReadBytes;
+				_pos += (uint)numReadBytes;
+				_streamPos += (uint)numReadBytes;
+				if (_pos == _windowSize)
+					_streamPos = _pos = 0;
+			}
+			return true;
+		}
+
+		public void ReleaseStream()
+		{
+			Flush();
+			_stream = null;
+		}
+
+		public void Flush()
+		{
+			uint size = _pos - _streamPos;
+			if (size == 0)
+				return;
+			_stream.Write(_buffer, (int)_streamPos, (int)size);
+			if (_pos >= _windowSize)
+				_pos = 0;
+			_streamPos = _pos;
+		}
+
+		public void CopyBlock(uint distance, uint len)
+		{
+			uint pos = _pos - distance - 1;
+			if (pos >= _windowSize)
+				pos += _windowSize;
+			for (; len > 0; len--)
+			{
+				if (pos >= _windowSize)
+					pos = 0;
+				_buffer[_pos++] = _buffer[pos++];
+				if (_pos >= _windowSize)
+					Flush();
+			}
+		}
+
+		public void PutByte(byte b)
+		{
+			_buffer[_pos++] = b;
+			if (_pos >= _windowSize)
+				Flush();
+		}
+
+		public byte GetByte(uint distance)
+		{
+			uint pos = _pos - distance - 1;
+			if (pos >= _windowSize)
+				pos += _windowSize;
+			return _buffer[pos];
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LZMA/LzmaBase.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,76 @@
+// LzmaBase.cs
+
+namespace SevenZip.Compression.LZMA
+{
+	internal abstract class Base
+	{
+		public const uint kNumRepDistances = 4;
+		public const uint kNumStates = 12;
+
+		// static byte []kLiteralNextStates  = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
+		// static byte []kMatchNextStates    = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+		// static byte []kRepNextStates      = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+		// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+		public struct State
+		{
+			public uint Index;
+			public void Init() { Index = 0; }
+			public void UpdateChar()
+			{
+				if (Index < 4) Index = 0;
+				else if (Index < 10) Index -= 3;
+				else Index -= 6;
+			}
+			public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
+			public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
+			public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
+			public bool IsCharState() { return Index < 7; }
+		}
+
+		public const int kNumPosSlotBits = 6;
+		public const int kDicLogSizeMin = 0;
+		// public const int kDicLogSizeMax = 30;
+		// public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
+
+		public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
+		public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
+
+		public const uint kMatchMinLen = 2;
+
+		public static uint GetLenToPosState(uint len)
+		{
+			len -= kMatchMinLen;
+			if (len < kNumLenToPosStates)
+				return len;
+			return (uint)(kNumLenToPosStates - 1);
+		}
+
+		public const int kNumAlignBits = 4;
+		public const uint kAlignTableSize = 1 << kNumAlignBits;
+		public const uint kAlignMask = (kAlignTableSize - 1);
+
+		public const uint kStartPosModelIndex = 4;
+		public const uint kEndPosModelIndex = 14;
+		public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
+
+		public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
+
+		public const uint kNumLitPosStatesBitsEncodingMax = 4;
+		public const uint kNumLitContextBitsMax = 8;
+
+		public const int kNumPosStatesBitsMax = 4;
+		public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
+		public const int kNumPosStatesBitsEncodingMax = 4;
+		public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
+
+		public const int kNumLowLenBits = 3;
+		public const int kNumMidLenBits = 3;
+		public const int kNumHighLenBits = 8;
+		public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
+		public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
+		public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
+				(1 << kNumHighLenBits);
+		public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LZMA/LzmaDecoder.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,398 @@
+// LzmaDecoder.cs
+
+using System;
+
+namespace SevenZip.Compression.LZMA
+{
+	using RangeCoder;
+
+	public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
+	{
+		class LenDecoder
+		{
+			BitDecoder m_Choice = new BitDecoder();
+			BitDecoder m_Choice2 = new BitDecoder();
+			BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
+			BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
+			BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
+			uint m_NumPosStates = 0;
+
+			public void Create(uint numPosStates)
+			{
+				for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
+				{
+					m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
+					m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
+				}
+				m_NumPosStates = numPosStates;
+			}
+
+			public void Init()
+			{
+				m_Choice.Init();
+				for (uint posState = 0; posState < m_NumPosStates; posState++)
+				{
+					m_LowCoder[posState].Init();
+					m_MidCoder[posState].Init();
+				}
+				m_Choice2.Init();
+				m_HighCoder.Init();
+			}
+
+			public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
+			{
+				if (m_Choice.Decode(rangeDecoder) == 0)
+					return m_LowCoder[posState].Decode(rangeDecoder);
+				else
+				{
+					uint symbol = Base.kNumLowLenSymbols;
+					if (m_Choice2.Decode(rangeDecoder) == 0)
+						symbol += m_MidCoder[posState].Decode(rangeDecoder);
+					else
+					{
+						symbol += Base.kNumMidLenSymbols;
+						symbol += m_HighCoder.Decode(rangeDecoder);
+					}
+					return symbol;
+				}
+			}
+		}
+
+		class LiteralDecoder
+		{
+			struct Decoder2
+			{
+				BitDecoder[] m_Decoders;
+				public void Create() { m_Decoders = new BitDecoder[0x300]; }
+				public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }
+
+				public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
+				{
+					uint symbol = 1;
+					do
+						symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
+					while (symbol < 0x100);
+					return (byte)symbol;
+				}
+
+				public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
+				{
+					uint symbol = 1;
+					do
+					{
+						uint matchBit = (uint)(matchByte >> 7) & 1;
+						matchByte <<= 1;
+						uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
+						symbol = (symbol << 1) | bit;
+						if (matchBit != bit)
+						{
+							while (symbol < 0x100)
+								symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
+							break;
+						}
+					}
+					while (symbol < 0x100);
+					return (byte)symbol;
+				}
+			}
+
+			Decoder2[] m_Coders;
+			int m_NumPrevBits;
+			int m_NumPosBits;
+			uint m_PosMask;
+
+			public void Create(int numPosBits, int numPrevBits)
+			{
+				if (m_Coders != null && m_NumPrevBits == numPrevBits &&
+					m_NumPosBits == numPosBits)
+					return;
+				m_NumPosBits = numPosBits;
+				m_PosMask = ((uint)1 << numPosBits) - 1;
+				m_NumPrevBits = numPrevBits;
+				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+				m_Coders = new Decoder2[numStates];
+				for (uint i = 0; i < numStates; i++)
+					m_Coders[i].Create();
+			}
+
+			public void Init()
+			{
+				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+				for (uint i = 0; i < numStates; i++)
+					m_Coders[i].Init();
+			}
+
+			uint GetState(uint pos, byte prevByte)
+			{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
+
+			public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
+			{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
+
+			public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
+			{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
+		};
+
+		LZ.OutWindow m_OutWindow = new LZ.OutWindow();
+		RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder();
+
+		BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+		BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
+		BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
+		BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
+		BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
+		BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+
+		BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
+		BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
+
+		BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
+
+		LenDecoder m_LenDecoder = new LenDecoder();
+		LenDecoder m_RepLenDecoder = new LenDecoder();
+
+		LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
+
+		uint m_DictionarySize;
+		uint m_DictionarySizeCheck;
+
+		uint m_PosStateMask;
+
+		public Decoder()
+		{
+			m_DictionarySize = 0xFFFFFFFF;
+			for (int i = 0; i < Base.kNumLenToPosStates; i++)
+				m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
+		}
+
+		void SetDictionarySize(uint dictionarySize)
+		{
+			if (m_DictionarySize != dictionarySize)
+			{
+				m_DictionarySize = dictionarySize;
+				m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
+				uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12));
+				m_OutWindow.Create(blockSize);
+			}
+		}
+
+		void SetLiteralProperties(int lp, int lc)
+		{
+			if (lp > 8)
+				throw new InvalidParamException();
+			if (lc > 8)
+				throw new InvalidParamException();
+			m_LiteralDecoder.Create(lp, lc);
+		}
+
+		void SetPosBitsProperties(int pb)
+		{
+			if (pb > Base.kNumPosStatesBitsMax)
+				throw new InvalidParamException();
+			uint numPosStates = (uint)1 << pb;
+			m_LenDecoder.Create(numPosStates);
+			m_RepLenDecoder.Create(numPosStates);
+			m_PosStateMask = numPosStates - 1;
+		}
+
+		bool _solid = false;
+		void Init(System.IO.Stream inStream, System.IO.Stream outStream)
+		{
+			m_RangeDecoder.Init(inStream);
+			m_OutWindow.Init(outStream, _solid);
+
+			uint i;
+			for (i = 0; i < Base.kNumStates; i++)
+			{
+				for (uint j = 0; j <= m_PosStateMask; j++)
+				{
+					uint index = (i << Base.kNumPosStatesBitsMax) + j;
+					m_IsMatchDecoders[index].Init();
+					m_IsRep0LongDecoders[index].Init();
+				}
+				m_IsRepDecoders[i].Init();
+				m_IsRepG0Decoders[i].Init();
+				m_IsRepG1Decoders[i].Init();
+				m_IsRepG2Decoders[i].Init();
+			}
+
+			m_LiteralDecoder.Init();
+			for (i = 0; i < Base.kNumLenToPosStates; i++)
+				m_PosSlotDecoder[i].Init();
+			// m_PosSpecDecoder.Init();
+			for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
+				m_PosDecoders[i].Init();
+
+			m_LenDecoder.Init();
+			m_RepLenDecoder.Init();
+			m_PosAlignDecoder.Init();
+		}
+
+		public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
+			Int64 inSize, Int64 outSize, ICodeProgress progress)
+		{
+			Init(inStream, outStream);
+
+			Base.State state = new Base.State();
+			state.Init();
+			uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
+
+			UInt64 nowPos64 = 0;
+			UInt64 outSize64 = (UInt64)outSize;
+			if (nowPos64 < outSize64)
+			{
+				if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
+					throw new DataErrorException();
+				state.UpdateChar();
+				byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
+				m_OutWindow.PutByte(b);
+				nowPos64++;
+			}
+			while (nowPos64 < outSize64)
+			{
+				// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
+					// while(nowPos64 < next)
+				{
+					uint posState = (uint)nowPos64 & m_PosStateMask;
+					if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
+					{
+						byte b;
+						byte prevByte = m_OutWindow.GetByte(0);
+						if (!state.IsCharState())
+							b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
+								(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0));
+						else
+							b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
+						m_OutWindow.PutByte(b);
+						state.UpdateChar();
+						nowPos64++;
+					}
+					else
+					{
+						uint len;
+						if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
+						{
+							if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
+							{
+								if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
+								{
+									state.UpdateShortRep();
+									m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
+									nowPos64++;
+									continue;
+								}
+							}
+							else
+							{
+								UInt32 distance;
+								if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
+								{
+									distance = rep1;
+								}
+								else
+								{
+									if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
+										distance = rep2;
+									else
+									{
+										distance = rep3;
+										rep3 = rep2;
+									}
+									rep2 = rep1;
+								}
+								rep1 = rep0;
+								rep0 = distance;
+							}
+							len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
+							state.UpdateRep();
+						}
+						else
+						{
+							rep3 = rep2;
+							rep2 = rep1;
+							rep1 = rep0;
+							len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
+							state.UpdateMatch();
+							uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
+							if (posSlot >= Base.kStartPosModelIndex)
+							{
+								int numDirectBits = (int)((posSlot >> 1) - 1);
+								rep0 = ((2 | (posSlot & 1)) << numDirectBits);
+								if (posSlot < Base.kEndPosModelIndex)
+									rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
+											rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
+								else
+								{
+									rep0 += (m_RangeDecoder.DecodeDirectBits(
+										numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
+									rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
+								}
+							}
+							else
+								rep0 = posSlot;
+						}
+						if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
+						{
+							if (rep0 == 0xFFFFFFFF)
+								break;
+							throw new DataErrorException();
+						}
+						m_OutWindow.CopyBlock(rep0, len);
+						nowPos64 += len;
+					}
+				}
+			}
+			m_OutWindow.Flush();
+			m_OutWindow.ReleaseStream();
+			m_RangeDecoder.ReleaseStream();
+		}
+
+		public void SetDecoderProperties(byte[] properties)
+		{
+			if (properties.Length < 5)
+				throw new InvalidParamException();
+			int lc = properties[0] % 9;
+			int remainder = properties[0] / 9;
+			int lp = remainder % 5;
+			int pb = remainder / 5;
+			if (pb > Base.kNumPosStatesBitsMax)
+				throw new InvalidParamException();
+			UInt32 dictionarySize = 0;
+			for (int i = 0; i < 4; i++)
+				dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
+			SetDictionarySize(dictionarySize);
+			SetLiteralProperties(lp, lc);
+			SetPosBitsProperties(pb);
+		}
+
+		public bool Train(System.IO.Stream stream)
+		{
+			_solid = true;
+			return m_OutWindow.Train(stream);
+		}
+
+		/*
+		public override bool CanRead { get { return true; }}
+		public override bool CanWrite { get { return true; }}
+		public override bool CanSeek { get { return true; }}
+		public override long Length { get { return 0; }}
+		public override long Position
+		{
+			get { return 0;	}
+			set { }
+		}
+		public override void Flush() { }
+		public override int Read(byte[] buffer, int offset, int count) 
+		{
+			return 0;
+		}
+		public override void Write(byte[] buffer, int offset, int count)
+		{
+		}
+		public override long Seek(long offset, System.IO.SeekOrigin origin)
+		{
+			return 0;
+		}
+		public override void SetLength(long value) {}
+		*/
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LZMA/LzmaEncoder.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1480 @@
+// LzmaEncoder.cs
+
+using System;
+
+namespace SevenZip.Compression.LZMA
+{
+	using RangeCoder;
+
+	public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
+	{
+		enum EMatchFinderType
+		{
+			BT2,
+			BT4,
+		};
+
+		const UInt32 kIfinityPrice = 0xFFFFFFF;
+
+		static Byte[] g_FastPos = new Byte[1 << 11];
+
+		static Encoder()
+		{
+			const Byte kFastSlots = 22;
+			int c = 2;
+			g_FastPos[0] = 0;
+			g_FastPos[1] = 1;
+			for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
+			{
+				UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1));
+				for (UInt32 j = 0; j < k; j++, c++)
+					g_FastPos[c] = slotFast;
+			}
+		}
+
+		static UInt32 GetPosSlot(UInt32 pos)
+		{
+			if (pos < (1 << 11))
+				return g_FastPos[pos];
+			if (pos < (1 << 21))
+				return (UInt32)(g_FastPos[pos >> 10] + 20);
+			return (UInt32)(g_FastPos[pos >> 20] + 40);
+		}
+
+		static UInt32 GetPosSlot2(UInt32 pos)
+		{
+			if (pos < (1 << 17))
+				return (UInt32)(g_FastPos[pos >> 6] + 12);
+			if (pos < (1 << 27))
+				return (UInt32)(g_FastPos[pos >> 16] + 32);
+			return (UInt32)(g_FastPos[pos >> 26] + 52);
+		}
+
+		Base.State _state = new Base.State();
+		Byte _previousByte;
+		UInt32[] _repDistances = new UInt32[Base.kNumRepDistances];
+
+		void BaseInit()
+		{
+			_state.Init();
+			_previousByte = 0;
+			for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
+				_repDistances[i] = 0;
+		}
+
+		const int kDefaultDictionaryLogSize = 22;
+		const UInt32 kNumFastBytesDefault = 0x20;
+
+		class LiteralEncoder
+		{
+			public struct Encoder2
+			{
+				BitEncoder[] m_Encoders;
+
+				public void Create() { m_Encoders = new BitEncoder[0x300]; }
+
+				public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); }
+
+				public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol)
+				{
+					uint context = 1;
+					for (int i = 7; i >= 0; i--)
+					{
+						uint bit = (uint)((symbol >> i) & 1);
+						m_Encoders[context].Encode(rangeEncoder, bit);
+						context = (context << 1) | bit;
+					}
+				}
+
+				public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
+				{
+					uint context = 1;
+					bool same = true;
+					for (int i = 7; i >= 0; i--)
+					{
+						uint bit = (uint)((symbol >> i) & 1);
+						uint state = context;
+						if (same)
+						{
+							uint matchBit = (uint)((matchByte >> i) & 1);
+							state += ((1 + matchBit) << 8);
+							same = (matchBit == bit);
+						}
+						m_Encoders[state].Encode(rangeEncoder, bit);
+						context = (context << 1) | bit;
+					}
+				}
+
+				public uint GetPrice(bool matchMode, byte matchByte, byte symbol)
+				{
+					uint price = 0;
+					uint context = 1;
+					int i = 7;
+					if (matchMode)
+					{
+						for (; i >= 0; i--)
+						{
+							uint matchBit = (uint)(matchByte >> i) & 1;
+							uint bit = (uint)(symbol >> i) & 1;
+							price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit);
+							context = (context << 1) | bit;
+							if (matchBit != bit)
+							{
+								i--;
+								break;
+							}
+						}
+					}
+					for (; i >= 0; i--)
+					{
+						uint bit = (uint)(symbol >> i) & 1;
+						price += m_Encoders[context].GetPrice(bit);
+						context = (context << 1) | bit;
+					}
+					return price;
+				}
+			}
+
+			Encoder2[] m_Coders;
+			int m_NumPrevBits;
+			int m_NumPosBits;
+			uint m_PosMask;
+
+			public void Create(int numPosBits, int numPrevBits)
+			{
+				if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
+					return;
+				m_NumPosBits = numPosBits;
+				m_PosMask = ((uint)1 << numPosBits) - 1;
+				m_NumPrevBits = numPrevBits;
+				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+				m_Coders = new Encoder2[numStates];
+				for (uint i = 0; i < numStates; i++)
+					m_Coders[i].Create();
+			}
+
+			public void Init()
+			{
+				uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+				for (uint i = 0; i < numStates; i++)
+					m_Coders[i].Init();
+			}
+
+			public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte)
+			{ return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; }
+		}
+
+		class LenEncoder
+		{
+			RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder();
+			RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder();
+			RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];
+			RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];
+			RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits);
+
+			public LenEncoder()
+			{
+				for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)
+				{
+					_lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits);
+					_midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits);
+				}
+			}
+
+			public void Init(UInt32 numPosStates)
+			{
+				_choice.Init();
+				_choice2.Init();
+				for (UInt32 posState = 0; posState < numPosStates; posState++)
+				{
+					_lowCoder[posState].Init();
+					_midCoder[posState].Init();
+				}
+				_highCoder.Init();
+			}
+
+			public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
+			{
+				if (symbol < Base.kNumLowLenSymbols)
+				{
+					_choice.Encode(rangeEncoder, 0);
+					_lowCoder[posState].Encode(rangeEncoder, symbol);
+				}
+				else
+				{
+					symbol -= Base.kNumLowLenSymbols;
+					_choice.Encode(rangeEncoder, 1);
+					if (symbol < Base.kNumMidLenSymbols)
+					{
+						_choice2.Encode(rangeEncoder, 0);
+						_midCoder[posState].Encode(rangeEncoder, symbol);
+					}
+					else
+					{
+						_choice2.Encode(rangeEncoder, 1);
+						_highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
+					}
+				}
+			}
+
+			public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st)
+			{
+				UInt32 a0 = _choice.GetPrice0();
+				UInt32 a1 = _choice.GetPrice1();
+				UInt32 b0 = a1 + _choice2.GetPrice0();
+				UInt32 b1 = a1 + _choice2.GetPrice1();
+				UInt32 i = 0;
+				for (i = 0; i < Base.kNumLowLenSymbols; i++)
+				{
+					if (i >= numSymbols)
+						return;
+					prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
+				}
+				for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)
+				{
+					if (i >= numSymbols)
+						return;
+					prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);
+				}
+				for (; i < numSymbols; i++)
+					prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);
+			}
+		};
+
+		const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
+
+		class LenPriceTableEncoder : LenEncoder
+		{
+			UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];
+			UInt32 _tableSize;
+			UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax];
+
+			public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
+
+			public UInt32 GetPrice(UInt32 symbol, UInt32 posState)
+			{
+				return _prices[posState * Base.kNumLenSymbols + symbol];
+			}
+
+			void UpdateTable(UInt32 posState)
+			{
+				SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);
+				_counters[posState] = _tableSize;
+			}
+
+			public void UpdateTables(UInt32 numPosStates)
+			{
+				for (UInt32 posState = 0; posState < numPosStates; posState++)
+					UpdateTable(posState);
+			}
+
+			public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
+			{
+				base.Encode(rangeEncoder, symbol, posState);
+				if (--_counters[posState] == 0)
+					UpdateTable(posState);
+			}
+		}
+
+		const UInt32 kNumOpts = 1 << 12;
+		class Optimal
+		{
+			public Base.State State;
+
+			public bool Prev1IsChar;
+			public bool Prev2;
+
+			public UInt32 PosPrev2;
+			public UInt32 BackPrev2;
+
+			public UInt32 Price;
+			public UInt32 PosPrev;
+			public UInt32 BackPrev;
+
+			public UInt32 Backs0;
+			public UInt32 Backs1;
+			public UInt32 Backs2;
+			public UInt32 Backs3;
+
+			public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; }
+			public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
+			public bool IsShortRep() { return (BackPrev == 0); }
+		};
+		Optimal[] _optimum = new Optimal[kNumOpts];
+		LZ.IMatchFinder _matchFinder = null;
+		RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder();
+
+		RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+		RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates];
+		RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates];
+		RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates];
+		RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates];
+		RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+
+		RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates];
+		
+		RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
+		RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits);
+
+		LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
+		LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
+
+		LiteralEncoder _literalEncoder = new LiteralEncoder();
+
+		UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2];
+		
+		UInt32 _numFastBytes = kNumFastBytesDefault;
+		UInt32 _longestMatchLength;
+		UInt32 _numDistancePairs;
+
+		UInt32 _additionalOffset;
+
+		UInt32 _optimumEndIndex;
+		UInt32 _optimumCurrentIndex;
+
+		bool _longestMatchWasFound;
+
+		UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)];
+		UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];
+		UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize];
+		UInt32 _alignPriceCount;
+
+		UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2);
+
+		int _posStateBits = 2;
+		UInt32 _posStateMask = (4 - 1);
+		int _numLiteralPosStateBits = 0;
+		int _numLiteralContextBits = 3;
+
+		UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize);
+		UInt32 _dictionarySizePrev = 0xFFFFFFFF;
+		UInt32 _numFastBytesPrev = 0xFFFFFFFF;
+
+		Int64 nowPos64;
+		bool _finished;
+		System.IO.Stream _inStream;
+
+		EMatchFinderType _matchFinderType = EMatchFinderType.BT4;
+		bool _writeEndMark = false;
+		
+		bool _needReleaseMFStream;
+
+		void Create()
+		{
+			if (_matchFinder == null)
+			{
+				LZ.BinTree bt = new LZ.BinTree();
+				int numHashBytes = 4;
+				if (_matchFinderType == EMatchFinderType.BT2)
+					numHashBytes = 2;
+				bt.SetType(numHashBytes);
+				_matchFinder = bt;
+			}
+			_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
+
+			if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
+				return;
+			_matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);
+			_dictionarySizePrev = _dictionarySize;
+			_numFastBytesPrev = _numFastBytes;
+		}
+
+		public Encoder()
+		{
+			for (int i = 0; i < kNumOpts; i++)
+				_optimum[i] = new Optimal();
+			for (int i = 0; i < Base.kNumLenToPosStates; i++)
+				_posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits);
+		}
+
+		void SetWriteEndMarkerMode(bool writeEndMarker)
+		{
+			_writeEndMark = writeEndMarker;
+		}
+
+		void Init()
+		{
+			BaseInit();
+			_rangeEncoder.Init();
+
+			uint i;
+			for (i = 0; i < Base.kNumStates; i++)
+			{
+				for (uint j = 0; j <= _posStateMask; j++)
+				{
+					uint complexState = (i << Base.kNumPosStatesBitsMax) + j;
+					_isMatch[complexState].Init();
+					_isRep0Long[complexState].Init();
+				}
+				_isRep[i].Init();
+				_isRepG0[i].Init();
+				_isRepG1[i].Init();
+				_isRepG2[i].Init();
+			}
+			_literalEncoder.Init();
+			for (i = 0; i < Base.kNumLenToPosStates; i++)
+				_posSlotEncoder[i].Init();
+			for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
+				_posEncoders[i].Init();
+
+			_lenEncoder.Init((UInt32)1 << _posStateBits);
+			_repMatchLenEncoder.Init((UInt32)1 << _posStateBits);
+
+			_posAlignEncoder.Init();
+
+			_longestMatchWasFound = false;
+			_optimumEndIndex = 0;
+			_optimumCurrentIndex = 0;
+			_additionalOffset = 0;
+		}
+
+		void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs)
+		{
+			lenRes = 0;
+			numDistancePairs = _matchFinder.GetMatches(_matchDistances);
+			if (numDistancePairs > 0)
+			{
+				lenRes = _matchDistances[numDistancePairs - 2];
+				if (lenRes == _numFastBytes)
+					lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1],
+						Base.kMatchMaxLen - lenRes);
+			}
+			_additionalOffset++;
+		}
+
+
+		void MovePos(UInt32 num)
+		{
+			if (num > 0)
+			{
+				_matchFinder.Skip(num);
+				_additionalOffset += num;
+			}
+		}
+
+		UInt32 GetRepLen1Price(Base.State state, UInt32 posState)
+		{
+			return _isRepG0[state.Index].GetPrice0() +
+					_isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0();
+		}
+
+		UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState)
+		{
+			UInt32 price;
+			if (repIndex == 0)
+			{
+				price = _isRepG0[state.Index].GetPrice0();
+				price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
+			}
+			else
+			{
+				price = _isRepG0[state.Index].GetPrice1();
+				if (repIndex == 1)
+					price += _isRepG1[state.Index].GetPrice0();
+				else
+				{
+					price += _isRepG1[state.Index].GetPrice1();
+					price += _isRepG2[state.Index].GetPrice(repIndex - 2);
+				}
+			}
+			return price;
+		}
+
+		UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState)
+		{
+			UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
+			return price + GetPureRepPrice(repIndex, state, posState);
+		}
+	
+		UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState)
+		{
+			UInt32 price;
+			UInt32 lenToPosState = Base.GetLenToPosState(len);
+			if (pos < Base.kNumFullDistances)
+				price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos];
+			else
+				price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +
+					_alignPrices[pos & Base.kAlignMask];
+			return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
+		}
+
+		UInt32 Backward(out UInt32 backRes, UInt32 cur)
+		{
+			_optimumEndIndex = cur;
+			UInt32 posMem = _optimum[cur].PosPrev;
+			UInt32 backMem = _optimum[cur].BackPrev;
+			do
+			{
+				if (_optimum[cur].Prev1IsChar)
+				{
+					_optimum[posMem].MakeAsChar();
+					_optimum[posMem].PosPrev = posMem - 1;
+					if (_optimum[cur].Prev2)
+					{
+						_optimum[posMem - 1].Prev1IsChar = false;
+						_optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
+						_optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
+					}
+				}
+				UInt32 posPrev = posMem;
+				UInt32 backCur = backMem;
+
+				backMem = _optimum[posPrev].BackPrev;
+				posMem = _optimum[posPrev].PosPrev;
+
+				_optimum[posPrev].BackPrev = backCur;
+				_optimum[posPrev].PosPrev = cur;
+				cur = posPrev;
+			}
+			while (cur > 0);
+			backRes = _optimum[0].BackPrev;
+			_optimumCurrentIndex = _optimum[0].PosPrev;
+			return _optimumCurrentIndex;
+		}
+
+		UInt32[] reps = new UInt32[Base.kNumRepDistances];
+		UInt32[] repLens = new UInt32[Base.kNumRepDistances];
+
+
+		UInt32 GetOptimum(UInt32 position, out UInt32 backRes)
+		{
+			if (_optimumEndIndex != _optimumCurrentIndex)
+			{
+				UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
+				backRes = _optimum[_optimumCurrentIndex].BackPrev;
+				_optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
+				return lenRes;
+			}
+			_optimumCurrentIndex = _optimumEndIndex = 0;
+
+			UInt32 lenMain, numDistancePairs;
+			if (!_longestMatchWasFound)
+			{
+				ReadMatchDistances(out lenMain, out numDistancePairs);
+			}
+			else
+			{
+				lenMain = _longestMatchLength;
+				numDistancePairs = _numDistancePairs;
+				_longestMatchWasFound = false;
+			}
+
+			UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
+			if (numAvailableBytes < 2)
+			{
+				backRes = 0xFFFFFFFF;
+				return 1;
+			}
+			if (numAvailableBytes > Base.kMatchMaxLen)
+				numAvailableBytes = Base.kMatchMaxLen;
+
+			UInt32 repMaxIndex = 0;
+			UInt32 i;			
+			for (i = 0; i < Base.kNumRepDistances; i++)
+			{
+				reps[i] = _repDistances[i];
+				repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
+				if (repLens[i] > repLens[repMaxIndex])
+					repMaxIndex = i;
+			}
+			if (repLens[repMaxIndex] >= _numFastBytes)
+			{
+				backRes = repMaxIndex;
+				UInt32 lenRes = repLens[repMaxIndex];
+				MovePos(lenRes - 1);
+				return lenRes;
+			}
+
+			if (lenMain >= _numFastBytes)
+			{
+				backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;
+				MovePos(lenMain - 1);
+				return lenMain;
+			}
+			
+			Byte currentByte = _matchFinder.GetIndexByte(0 - 1);
+			Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1));
+
+			if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
+			{
+				backRes = (UInt32)0xFFFFFFFF;
+				return 1;
+			}
+
+			_optimum[0].State = _state;
+
+			UInt32 posState = (position & _posStateMask);
+
+			_optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
+					_literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte);
+			_optimum[1].MakeAsChar();
+
+			UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
+			UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
+
+			if (matchByte == currentByte)
+			{
+				UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
+				if (shortRepPrice < _optimum[1].Price)
+				{
+					_optimum[1].Price = shortRepPrice;
+					_optimum[1].MakeAsShortRep();
+				}
+			}
+
+			UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
+
+			if(lenEnd < 2)
+			{
+				backRes = _optimum[1].BackPrev;
+				return 1;
+			}
+			
+			_optimum[1].PosPrev = 0;
+
+			_optimum[0].Backs0 = reps[0];
+			_optimum[0].Backs1 = reps[1];
+			_optimum[0].Backs2 = reps[2];
+			_optimum[0].Backs3 = reps[3];
+
+			UInt32 len = lenEnd;
+			do
+				_optimum[len--].Price = kIfinityPrice;
+			while (len >= 2);
+
+			for (i = 0; i < Base.kNumRepDistances; i++)
+			{
+				UInt32 repLen = repLens[i];
+				if (repLen < 2)
+					continue;
+				UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
+				do
+				{
+					UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
+					Optimal optimum = _optimum[repLen];
+					if (curAndLenPrice < optimum.Price)
+					{
+						optimum.Price = curAndLenPrice;
+						optimum.PosPrev = 0;
+						optimum.BackPrev = i;
+						optimum.Prev1IsChar = false;
+					}
+				}
+				while (--repLen >= 2);
+			}
+
+			UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
+			
+			len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+			if (len <= lenMain)
+			{
+				UInt32 offs = 0;
+				while (len > _matchDistances[offs])
+					offs += 2;
+				for (; ; len++)
+				{
+					UInt32 distance = _matchDistances[offs + 1];
+					UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
+					Optimal optimum = _optimum[len];
+					if (curAndLenPrice < optimum.Price)
+					{
+						optimum.Price = curAndLenPrice;
+						optimum.PosPrev = 0;
+						optimum.BackPrev = distance + Base.kNumRepDistances;
+						optimum.Prev1IsChar = false;
+					}
+					if (len == _matchDistances[offs])
+					{
+						offs += 2;
+						if (offs == numDistancePairs)
+							break;
+					}
+				}
+			}
+
+			UInt32 cur = 0;
+
+			while (true)
+			{
+				cur++;
+				if (cur == lenEnd)
+					return Backward(out backRes, cur);
+				UInt32 newLen;
+				ReadMatchDistances(out newLen, out numDistancePairs);
+				if (newLen >= _numFastBytes)
+				{
+					_numDistancePairs = numDistancePairs;
+					_longestMatchLength = newLen;
+					_longestMatchWasFound = true;
+					return Backward(out backRes, cur);
+				}
+				position++;
+				UInt32 posPrev = _optimum[cur].PosPrev;
+				Base.State state;
+				if (_optimum[cur].Prev1IsChar)
+				{
+					posPrev--;
+					if (_optimum[cur].Prev2)
+					{
+						state = _optimum[_optimum[cur].PosPrev2].State;
+						if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
+							state.UpdateRep();
+						else
+							state.UpdateMatch();
+					}
+					else
+						state = _optimum[posPrev].State;
+					state.UpdateChar();
+				}
+				else
+					state = _optimum[posPrev].State;
+				if (posPrev == cur - 1)
+				{
+					if (_optimum[cur].IsShortRep())
+						state.UpdateShortRep();
+					else
+						state.UpdateChar();
+				}
+				else
+				{
+					UInt32 pos;
+					if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)
+					{
+						posPrev = _optimum[cur].PosPrev2;
+						pos = _optimum[cur].BackPrev2;
+						state.UpdateRep();
+					}
+					else
+					{
+						pos = _optimum[cur].BackPrev;
+						if (pos < Base.kNumRepDistances)
+							state.UpdateRep();
+						else
+							state.UpdateMatch();
+					}
+					Optimal opt = _optimum[posPrev];
+					if (pos < Base.kNumRepDistances)
+					{
+						if (pos == 0)
+						{
+							reps[0] = opt.Backs0;
+							reps[1] = opt.Backs1;
+							reps[2] = opt.Backs2;
+							reps[3] = opt.Backs3;
+						}
+						else if (pos == 1)
+						{
+							reps[0] = opt.Backs1;
+							reps[1] = opt.Backs0;
+							reps[2] = opt.Backs2;
+							reps[3] = opt.Backs3;
+						}
+						else if (pos == 2)
+						{
+							reps[0] = opt.Backs2;
+							reps[1] = opt.Backs0;
+							reps[2] = opt.Backs1;
+							reps[3] = opt.Backs3;
+						}
+						else
+						{
+							reps[0] = opt.Backs3;
+							reps[1] = opt.Backs0;
+							reps[2] = opt.Backs1;
+							reps[3] = opt.Backs2;
+						}
+					}
+					else
+					{
+						reps[0] = (pos - Base.kNumRepDistances);
+						reps[1] = opt.Backs0;
+						reps[2] = opt.Backs1;
+						reps[3] = opt.Backs2;
+					}
+				}
+				_optimum[cur].State = state;
+				_optimum[cur].Backs0 = reps[0];
+				_optimum[cur].Backs1 = reps[1];
+				_optimum[cur].Backs2 = reps[2];
+				_optimum[cur].Backs3 = reps[3];
+				UInt32 curPrice = _optimum[cur].Price;
+
+				currentByte = _matchFinder.GetIndexByte(0 - 1);
+				matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1));
+
+				posState = (position & _posStateMask);
+
+				UInt32 curAnd1Price = curPrice +
+					_isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
+					_literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).
+					GetPrice(!state.IsCharState(), matchByte, currentByte);
+
+				Optimal nextOptimum = _optimum[cur + 1];
+
+				bool nextIsChar = false;
+				if (curAnd1Price < nextOptimum.Price)
+				{
+					nextOptimum.Price = curAnd1Price;
+					nextOptimum.PosPrev = cur;
+					nextOptimum.MakeAsChar();
+					nextIsChar = true;
+				}
+
+				matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
+				repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
+
+				if (matchByte == currentByte &&
+					!(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
+				{
+					UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
+					if (shortRepPrice <= nextOptimum.Price)
+					{
+						nextOptimum.Price = shortRepPrice;
+						nextOptimum.PosPrev = cur;
+						nextOptimum.MakeAsShortRep();
+						nextIsChar = true;
+					}
+				}
+
+				UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
+				numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull);
+				numAvailableBytes = numAvailableBytesFull;
+
+				if (numAvailableBytes < 2)
+					continue;
+				if (numAvailableBytes > _numFastBytes)
+					numAvailableBytes = _numFastBytes;
+				if (!nextIsChar && matchByte != currentByte)
+				{
+					// try Literal + rep0
+					UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes);
+					UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);
+					if (lenTest2 >= 2)
+					{
+						Base.State state2 = state;
+						state2.UpdateChar();
+						UInt32 posStateNext = (position + 1) & _posStateMask;
+						UInt32 nextRepMatchPrice = curAnd1Price +
+							_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() +
+							_isRep[state2.Index].GetPrice1();
+						{
+							UInt32 offset = cur + 1 + lenTest2;
+							while (lenEnd < offset)
+								_optimum[++lenEnd].Price = kIfinityPrice;
+							UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
+								0, lenTest2, state2, posStateNext);
+							Optimal optimum = _optimum[offset];
+							if (curAndLenPrice < optimum.Price)
+							{
+								optimum.Price = curAndLenPrice;
+								optimum.PosPrev = cur + 1;
+								optimum.BackPrev = 0;
+								optimum.Prev1IsChar = true;
+								optimum.Prev2 = false;
+							}
+						}
+					}
+				}
+
+				UInt32 startLen = 2; // speed optimization 
+
+				for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)
+				{
+					UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
+					if (lenTest < 2)
+						continue;
+					UInt32 lenTestTemp = lenTest;
+					do
+					{
+						while (lenEnd < cur + lenTest)
+							_optimum[++lenEnd].Price = kIfinityPrice;
+						UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
+						Optimal optimum = _optimum[cur + lenTest];
+						if (curAndLenPrice < optimum.Price)
+						{
+							optimum.Price = curAndLenPrice;
+							optimum.PosPrev = cur;
+							optimum.BackPrev = repIndex;
+							optimum.Prev1IsChar = false;
+						}
+					}
+					while(--lenTest >= 2);
+					lenTest = lenTestTemp;
+
+					if (repIndex == 0)
+						startLen = lenTest + 1;
+
+					// if (_maxMode)
+					if (lenTest < numAvailableBytesFull)
+					{
+						UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
+						UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t);
+						if (lenTest2 >= 2)
+						{
+							Base.State state2 = state;
+							state2.UpdateRep();
+							UInt32 posStateNext = (position + lenTest) & _posStateMask;
+							UInt32 curAndLenCharPrice = 
+									repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + 
+									_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
+									_literalEncoder.GetSubCoder(position + lenTest, 
+									_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true,
+									_matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), 
+									_matchFinder.GetIndexByte((Int32)lenTest - 1));
+							state2.UpdateChar();
+							posStateNext = (position + lenTest + 1) & _posStateMask;
+							UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
+							UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+							
+							// for(; lenTest2 >= 2; lenTest2--)
+							{
+								UInt32 offset = lenTest + 1 + lenTest2;
+								while(lenEnd < cur + offset)
+									_optimum[++lenEnd].Price = kIfinityPrice;
+								UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+								Optimal optimum = _optimum[cur + offset];
+								if (curAndLenPrice < optimum.Price) 
+								{
+									optimum.Price = curAndLenPrice;
+									optimum.PosPrev = cur + lenTest + 1;
+									optimum.BackPrev = 0;
+									optimum.Prev1IsChar = true;
+									optimum.Prev2 = true;
+									optimum.PosPrev2 = cur;
+									optimum.BackPrev2 = repIndex;
+								}
+							}
+						}
+					}
+				}
+
+				if (newLen > numAvailableBytes)
+				{
+					newLen = numAvailableBytes;
+					for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ;
+					_matchDistances[numDistancePairs] = newLen;
+					numDistancePairs += 2;
+				}
+				if (newLen >= startLen)
+				{
+					normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
+					while (lenEnd < cur + newLen)
+						_optimum[++lenEnd].Price = kIfinityPrice;
+
+					UInt32 offs = 0;
+					while (startLen > _matchDistances[offs])
+						offs += 2;
+
+					for (UInt32 lenTest = startLen; ; lenTest++)
+					{
+						UInt32 curBack = _matchDistances[offs + 1];
+						UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
+						Optimal optimum = _optimum[cur + lenTest];
+						if (curAndLenPrice < optimum.Price)
+						{
+							optimum.Price = curAndLenPrice;
+							optimum.PosPrev = cur;
+							optimum.BackPrev = curBack + Base.kNumRepDistances;
+							optimum.Prev1IsChar = false;
+						}
+
+						if (lenTest == _matchDistances[offs])
+						{
+							if (lenTest < numAvailableBytesFull)
+							{
+								UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
+								UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t);
+								if (lenTest2 >= 2)
+								{
+									Base.State state2 = state;
+									state2.UpdateMatch();
+									UInt32 posStateNext = (position + lenTest) & _posStateMask;
+									UInt32 curAndLenCharPrice = curAndLenPrice +
+										_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
+										_literalEncoder.GetSubCoder(position + lenTest,
+										_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).
+										GetPrice(true,
+										_matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1),
+										_matchFinder.GetIndexByte((Int32)lenTest - 1));
+									state2.UpdateChar();
+									posStateNext = (position + lenTest + 1) & _posStateMask;
+									UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
+									UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+
+									UInt32 offset = lenTest + 1 + lenTest2;
+									while (lenEnd < cur + offset)
+										_optimum[++lenEnd].Price = kIfinityPrice;
+									curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+									optimum = _optimum[cur + offset];
+									if (curAndLenPrice < optimum.Price)
+									{
+										optimum.Price = curAndLenPrice;
+										optimum.PosPrev = cur + lenTest + 1;
+										optimum.BackPrev = 0;
+										optimum.Prev1IsChar = true;
+										optimum.Prev2 = true;
+										optimum.PosPrev2 = cur;
+										optimum.BackPrev2 = curBack + Base.kNumRepDistances;
+									}
+								}
+							}
+							offs += 2;
+							if (offs == numDistancePairs)
+								break;
+						}
+					}
+				}
+			}
+		}
+
+		bool ChangePair(UInt32 smallDist, UInt32 bigDist)
+		{
+			const int kDif = 7;
+			return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));
+		}
+
+		void WriteEndMarker(UInt32 posState)
+		{
+			if (!_writeEndMark)
+				return;
+
+			_isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1);
+			_isRep[_state.Index].Encode(_rangeEncoder, 0);
+			_state.UpdateMatch();
+			UInt32 len = Base.kMatchMinLen;
+			_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+			UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1;
+			UInt32 lenToPosState = Base.GetLenToPosState(len);
+			_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
+			int footerBits = 30;
+			UInt32 posReduced = (((UInt32)1) << footerBits) - 1;
+			_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
+			_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
+		}
+
+		void Flush(UInt32 nowPos)
+		{
+			ReleaseMFStream();
+			WriteEndMarker(nowPos & _posStateMask);
+			_rangeEncoder.FlushData();
+			_rangeEncoder.FlushStream();
+		}
+
+		public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)
+		{
+			inSize = 0;
+			outSize = 0;
+			finished = true;
+
+			if (_inStream != null)
+			{
+				_matchFinder.SetStream(_inStream);
+				_matchFinder.Init();
+				_needReleaseMFStream = true;
+				_inStream = null;
+				if (_trainSize > 0)
+					_matchFinder.Skip(_trainSize);
+			}
+
+			if (_finished)
+				return;
+			_finished = true;
+
+
+			Int64 progressPosValuePrev = nowPos64;
+			if (nowPos64 == 0)
+			{
+				if (_matchFinder.GetNumAvailableBytes() == 0)
+				{
+					Flush((UInt32)nowPos64);
+					return;
+				}
+				UInt32 len, numDistancePairs; // it's not used
+				ReadMatchDistances(out len, out numDistancePairs);
+				UInt32 posState = (UInt32)(nowPos64) & _posStateMask;
+				_isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0);
+				_state.UpdateChar();
+				Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
+				_literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);
+				_previousByte = curByte;
+				_additionalOffset--;
+				nowPos64++;
+			}
+			if (_matchFinder.GetNumAvailableBytes() == 0)
+			{
+				Flush((UInt32)nowPos64);
+				return;
+			}
+			while (true)
+			{
+				UInt32 pos;
+				UInt32 len = GetOptimum((UInt32)nowPos64, out pos);
+				
+				UInt32 posState = ((UInt32)nowPos64) & _posStateMask;
+				UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState;
+				if (len == 1 && pos == 0xFFFFFFFF)
+				{
+					_isMatch[complexState].Encode(_rangeEncoder, 0);
+					Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
+					LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte);
+					if (!_state.IsCharState())
+					{
+						Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset));
+						subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
+					}
+					else
+						subCoder.Encode(_rangeEncoder, curByte);
+					_previousByte = curByte;
+					_state.UpdateChar();
+				}
+				else
+				{
+					_isMatch[complexState].Encode(_rangeEncoder, 1);
+					if (pos < Base.kNumRepDistances)
+					{
+						_isRep[_state.Index].Encode(_rangeEncoder, 1);
+						if (pos == 0)
+						{
+							_isRepG0[_state.Index].Encode(_rangeEncoder, 0);
+							if (len == 1)
+								_isRep0Long[complexState].Encode(_rangeEncoder, 0);
+							else
+								_isRep0Long[complexState].Encode(_rangeEncoder, 1);
+						}
+						else
+						{
+							_isRepG0[_state.Index].Encode(_rangeEncoder, 1);
+							if (pos == 1)
+								_isRepG1[_state.Index].Encode(_rangeEncoder, 0);
+							else
+							{
+								_isRepG1[_state.Index].Encode(_rangeEncoder, 1);
+								_isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2);
+							}
+						}
+						if (len == 1)
+							_state.UpdateShortRep();
+						else
+						{
+							_repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+							_state.UpdateRep();
+						}
+						UInt32 distance = _repDistances[pos];
+						if (pos != 0)
+						{
+							for (UInt32 i = pos; i >= 1; i--)
+								_repDistances[i] = _repDistances[i - 1];
+							_repDistances[0] = distance;
+						}
+					}
+					else
+					{
+						_isRep[_state.Index].Encode(_rangeEncoder, 0);
+						_state.UpdateMatch();
+						_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+						pos -= Base.kNumRepDistances;
+						UInt32 posSlot = GetPosSlot(pos);
+						UInt32 lenToPosState = Base.GetLenToPosState(len);
+						_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
+
+						if (posSlot >= Base.kStartPosModelIndex)
+						{
+							int footerBits = (int)((posSlot >> 1) - 1);
+							UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);
+							UInt32 posReduced = pos - baseVal;
+
+							if (posSlot < Base.kEndPosModelIndex)
+								RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders,
+										baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
+							else
+							{
+								_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
+								_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
+								_alignPriceCount++;
+							}
+						}
+						UInt32 distance = pos;
+						for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--)
+							_repDistances[i] = _repDistances[i - 1];
+						_repDistances[0] = distance;
+						_matchPriceCount++;
+					}
+					_previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset));
+				}
+				_additionalOffset -= len;
+				nowPos64 += len;
+				if (_additionalOffset == 0)
+				{
+					// if (!_fastMode)
+					if (_matchPriceCount >= (1 << 7))
+						FillDistancesPrices();
+					if (_alignPriceCount >= Base.kAlignTableSize)
+						FillAlignPrices();
+					inSize = nowPos64;
+					outSize = _rangeEncoder.GetProcessedSizeAdd();
+					if (_matchFinder.GetNumAvailableBytes() == 0)
+					{
+						Flush((UInt32)nowPos64);
+						return;
+					}
+
+					if (nowPos64 - progressPosValuePrev >= (1 << 12))
+					{
+						_finished = false;
+						finished = false;
+						return;
+					}
+				}
+			}
+		}
+
+		void ReleaseMFStream()
+		{
+			if (_matchFinder != null && _needReleaseMFStream)
+			{
+				_matchFinder.ReleaseStream();
+				_needReleaseMFStream = false;
+			}
+		}
+
+		void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); }
+		void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); }
+
+		void ReleaseStreams()
+		{
+			ReleaseMFStream();
+			ReleaseOutStream();
+		}
+
+		void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream,
+				Int64 inSize, Int64 outSize)
+		{
+			_inStream = inStream;
+			_finished = false;
+			Create();
+			SetOutStream(outStream);
+			Init();
+
+			// if (!_fastMode)
+			{
+				FillDistancesPrices();
+				FillAlignPrices();
+			}
+
+			_lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
+			_lenEncoder.UpdateTables((UInt32)1 << _posStateBits);
+			_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
+			_repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits);
+
+			nowPos64 = 0;
+		}
+
+
+		public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
+			Int64 inSize, Int64 outSize, ICodeProgress progress)
+		{
+			_needReleaseMFStream = false;
+			try
+			{
+				SetStreams(inStream, outStream, inSize, outSize);
+				while (true)
+				{
+					Int64 processedInSize;
+					Int64 processedOutSize;
+					bool finished;
+					CodeOneBlock(out processedInSize, out processedOutSize, out finished);
+					if (finished)
+						return;
+					if (progress != null)
+					{
+						progress.SetProgress(processedInSize, processedOutSize);
+					}
+				}
+			}
+			finally
+			{
+				ReleaseStreams();
+			}
+		}
+
+		const int kPropSize = 5;
+		Byte[] properties = new Byte[kPropSize];
+
+		public void WriteCoderProperties(System.IO.Stream outStream)
+		{
+			properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
+			for (int i = 0; i < 4; i++)
+				properties[1 + i] = (Byte)(_dictionarySize >> (8 * i));
+			outStream.Write(properties, 0, kPropSize);
+		}
+		
+		UInt32[] tempPrices = new UInt32[Base.kNumFullDistances];
+		UInt32 _matchPriceCount;
+
+		void FillDistancesPrices()
+		{
+			for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)
+			{ 
+				UInt32 posSlot = GetPosSlot(i);
+				int footerBits = (int)((posSlot >> 1) - 1);
+				UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);
+				tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, 
+					baseVal - posSlot - 1, footerBits, i - baseVal);
+			}
+
+			for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)
+			{
+				UInt32 posSlot;
+				RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
+			
+				UInt32 st = (lenToPosState << Base.kNumPosSlotBits);
+				for (posSlot = 0; posSlot < _distTableSize; posSlot++)
+					_posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);
+				for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
+					_posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits);
+
+				UInt32 st2 = lenToPosState * Base.kNumFullDistances;
+				UInt32 i;
+				for (i = 0; i < Base.kStartPosModelIndex; i++)
+					_distancesPrices[st2 + i] = _posSlotPrices[st + i];
+				for (; i < Base.kNumFullDistances; i++)
+					_distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];
+			}
+			_matchPriceCount = 0;
+		}
+
+		void FillAlignPrices()
+		{
+			for (UInt32 i = 0; i < Base.kAlignTableSize; i++)
+				_alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
+			_alignPriceCount = 0;
+		}
+
+
+		static string[] kMatchFinderIDs = 
+		{
+			"BT2",
+			"BT4",
+		};
+
+		static int FindMatchFinder(string s)
+		{
+			for (int m = 0; m < kMatchFinderIDs.Length; m++)
+				if (s == kMatchFinderIDs[m])
+					return m;
+			return -1;
+		}
+	
+		public void SetCoderProperties(CoderPropID[] propIDs, object[] properties)
+		{
+			for (UInt32 i = 0; i < properties.Length; i++)
+			{
+				object prop = properties[i];
+				switch (propIDs[i])
+				{
+					case CoderPropID.NumFastBytes:
+					{
+						if (!(prop is Int32))
+							throw new InvalidParamException();
+						Int32 numFastBytes = (Int32)prop;
+						if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
+							throw new InvalidParamException();
+						_numFastBytes = (UInt32)numFastBytes;
+						break;
+					}
+					case CoderPropID.Algorithm:
+					{
+						/*
+						if (!(prop is Int32))
+							throw new InvalidParamException();
+						Int32 maximize = (Int32)prop;
+						_fastMode = (maximize == 0);
+						_maxMode = (maximize >= 2);
+						*/
+						break;
+					}
+					case CoderPropID.MatchFinder:
+					{
+						if (!(prop is String))
+							throw new InvalidParamException();
+						EMatchFinderType matchFinderIndexPrev = _matchFinderType;
+						int m = FindMatchFinder(((string)prop).ToUpper());
+						if (m < 0)
+							throw new InvalidParamException();
+						_matchFinderType = (EMatchFinderType)m;
+						if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
+							{
+							_dictionarySizePrev = 0xFFFFFFFF;
+							_matchFinder = null;
+							}
+						break;
+					}
+					case CoderPropID.DictionarySize:
+					{
+						const int kDicLogSizeMaxCompress = 30;
+						if (!(prop is Int32))
+							throw new InvalidParamException(); ;
+						Int32 dictionarySize = (Int32)prop;
+						if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) ||
+							dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))
+							throw new InvalidParamException();
+						_dictionarySize = (UInt32)dictionarySize;
+						int dicLogSize;
+						for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
+							if (dictionarySize <= ((UInt32)(1) << dicLogSize))
+								break;
+						_distTableSize = (UInt32)dicLogSize * 2;
+						break;
+					}
+					case CoderPropID.PosStateBits:
+					{
+						if (!(prop is Int32))
+							throw new InvalidParamException();
+						Int32 v = (Int32)prop;
+						if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax)
+							throw new InvalidParamException();
+						_posStateBits = (int)v;
+						_posStateMask = (((UInt32)1) << (int)_posStateBits) - 1;
+						break;
+					}
+					case CoderPropID.LitPosBits:
+					{
+						if (!(prop is Int32))
+							throw new InvalidParamException();
+						Int32 v = (Int32)prop;
+						if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax)
+							throw new InvalidParamException();
+						_numLiteralPosStateBits = (int)v;
+						break;
+					}
+					case CoderPropID.LitContextBits:
+					{
+						if (!(prop is Int32))
+							throw new InvalidParamException();
+						Int32 v = (Int32)prop;
+						if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax)
+							throw new InvalidParamException(); ;
+						_numLiteralContextBits = (int)v;
+						break;
+					}
+					case CoderPropID.EndMarker:
+					{
+						if (!(prop is Boolean))
+							throw new InvalidParamException();
+						SetWriteEndMarkerMode((Boolean)prop);
+						break;
+					}
+					default:
+						throw new InvalidParamException();
+				}
+			}
+		}
+
+		uint _trainSize = 0;
+		public void SetTrainSize(uint trainSize)
+		{
+			_trainSize = trainSize;
+		}
+		
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,364 @@
+using System;
+using System.IO;
+namespace SevenZip
+{
+	using CommandLineParser;
+	
+	public class CDoubleStream: Stream
+	{
+		public System.IO.Stream s1;
+		public System.IO.Stream s2;
+		public int fileIndex;
+		public long skipSize;
+		
+		public override bool CanRead { get { return true; }}
+		public override bool CanWrite { get { return false; }}
+		public override bool CanSeek { get { return false; }}
+		public override long Length { get { return s1.Length + s2.Length - skipSize; } }
+		public override long Position
+		{
+			get { return 0;	}
+			set { }
+		}
+		public override void Flush() { }
+		public override int Read(byte[] buffer, int offset, int count) 
+		{
+			int numTotal = 0;
+			while (count > 0)
+			{
+				if (fileIndex == 0)
+				{
+					int num = s1.Read(buffer, offset, count);
+					offset += num;
+					count -= num;
+					numTotal += num;
+					if (num == 0)
+						fileIndex++;
+				}
+				if (fileIndex == 1)
+				{
+					numTotal += s2.Read(buffer, offset, count);
+					return numTotal;
+				}
+			}
+			return numTotal;
+		}
+		public override void Write(byte[] buffer, int offset, int count)
+		{
+			throw (new Exception("can't Write"));
+		}
+		public override long Seek(long offset, System.IO.SeekOrigin origin)
+		{
+			throw (new Exception("can't Seek"));
+		}
+		public override void SetLength(long value)
+		{
+			throw (new Exception("can't SetLength"));
+		}
+	}
+	
+	class LzmaAlone
+	{
+		enum Key
+		{
+			Help1 = 0,
+			Help2,
+			Mode,
+			Dictionary,
+			FastBytes,
+			LitContext,
+			LitPos,
+			PosBits,
+			MatchFinder,
+			EOS,
+			StdIn,
+			StdOut,
+			Train
+		};
+
+		static void PrintHelp()
+		{
+			System.Console.WriteLine("\nUsage:  LZMA <e|d> [<switches>...] inputFile outputFile\n" +
+				"  e: encode file\n" +
+				"  d: decode file\n" +
+				"  b: Benchmark\n" +
+				"<Switches>\n" +
+				// "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n" +
+				"  -d{N}:  set dictionary - [0, 29], default: 23 (8MB)\n" +
+				"  -fb{N}: set number of fast bytes - [5, 273], default: 128\n" +
+				"  -lc{N}: set number of literal context bits - [0, 8], default: 3\n" +
+				"  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" +
+				"  -pb{N}: set number of pos bits - [0, 4], default: 2\n" +
+				"  -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" +
+				"  -eos:   write End Of Stream marker\n"
+				// + "  -si:    read data from stdin\n"
+				// + "  -so:    write data to stdout\n"
+				);
+		}
+
+		static bool GetNumber(string s, out Int32 v)
+		{
+			v = 0;
+			for (int i = 0; i < s.Length; i++)
+			{
+				char c = s[i];
+				if (c < '0' || c > '9')
+					return false;
+				v *= 10;
+				v += (Int32)(c - '0');
+			}
+			return true;
+		}
+
+		static int IncorrectCommand()
+		{
+			throw (new Exception("Command line error"));
+			// System.Console.WriteLine("\nCommand line error\n");
+			// return 1;
+		}
+		static int Main2(string[] args)
+		{
+			System.Console.WriteLine("\nLZMA# 4.49 Copyright (c) 1999-2007 Igor Pavlov  2006-07-05\n");
+
+			if (args.Length == 0)
+			{
+				PrintHelp();
+				return 0;
+			}
+
+			SwitchForm[] kSwitchForms = new SwitchForm[13];
+			int sw = 0;
+			kSwitchForms[sw++] = new SwitchForm("?", SwitchType.Simple, false);
+			kSwitchForms[sw++] = new SwitchForm("H", SwitchType.Simple, false);
+			kSwitchForms[sw++] = new SwitchForm("A", SwitchType.UnLimitedPostString, false, 1);
+			kSwitchForms[sw++] = new SwitchForm("D", SwitchType.UnLimitedPostString, false, 1);
+			kSwitchForms[sw++] = new SwitchForm("FB", SwitchType.UnLimitedPostString, false, 1);
+			kSwitchForms[sw++] = new SwitchForm("LC", SwitchType.UnLimitedPostString, false, 1);
+			kSwitchForms[sw++] = new SwitchForm("LP", SwitchType.UnLimitedPostString, false, 1);
+			kSwitchForms[sw++] = new SwitchForm("PB", SwitchType.UnLimitedPostString, false, 1);
+			kSwitchForms[sw++] = new SwitchForm("MF", SwitchType.UnLimitedPostString, false, 1);
+			kSwitchForms[sw++] = new SwitchForm("EOS", SwitchType.Simple, false);
+			kSwitchForms[sw++] = new SwitchForm("SI", SwitchType.Simple, false);
+			kSwitchForms[sw++] = new SwitchForm("SO", SwitchType.Simple, false);
+			kSwitchForms[sw++] = new SwitchForm("T", SwitchType.UnLimitedPostString, false, 1);
+
+
+			Parser parser = new Parser(sw);
+			try
+			{
+				parser.ParseStrings(kSwitchForms, args);
+			}
+			catch
+			{
+				return IncorrectCommand();
+			}
+
+			if (parser[(int)Key.Help1].ThereIs || parser[(int)Key.Help2].ThereIs)
+			{
+				PrintHelp();
+				return 0;
+			}
+
+			System.Collections.ArrayList nonSwitchStrings = parser.NonSwitchStrings;
+
+			int paramIndex = 0;
+			if (paramIndex >= nonSwitchStrings.Count)
+				return IncorrectCommand();
+			string command = (string)nonSwitchStrings[paramIndex++];
+			command = command.ToLower();
+
+			bool dictionaryIsDefined = false;
+			Int32 dictionary = 1 << 21;
+			if (parser[(int)Key.Dictionary].ThereIs)
+			{
+				Int32 dicLog;
+				if (!GetNumber((string)parser[(int)Key.Dictionary].PostStrings[0], out dicLog))
+					IncorrectCommand();
+				dictionary = (Int32)1 << dicLog;
+				dictionaryIsDefined = true;
+			}
+			string mf = "bt4";
+			if (parser[(int)Key.MatchFinder].ThereIs)
+				mf = (string)parser[(int)Key.MatchFinder].PostStrings[0];
+			mf = mf.ToLower();
+
+			if (command == "b")
+			{
+				const Int32 kNumDefaultItereations = 10;
+				Int32 numIterations = kNumDefaultItereations;
+				if (paramIndex < nonSwitchStrings.Count)
+					if (!GetNumber((string)nonSwitchStrings[paramIndex++], out numIterations))
+						numIterations = kNumDefaultItereations;
+				return LzmaBench.LzmaBenchmark(numIterations, (UInt32)dictionary);
+			}
+
+			string train = "";
+			if (parser[(int)Key.Train].ThereIs)
+				train = (string)parser[(int)Key.Train].PostStrings[0];
+
+			bool encodeMode = false;
+			if (command == "e")
+				encodeMode = true;
+			else if (command == "d")
+				encodeMode = false;
+			else
+				IncorrectCommand();
+
+			bool stdInMode = parser[(int)Key.StdIn].ThereIs;
+			bool stdOutMode = parser[(int)Key.StdOut].ThereIs;
+
+			Stream inStream = null;
+			if (stdInMode)
+			{
+				throw (new Exception("Not implemeted"));
+			}
+			else
+			{
+				if (paramIndex >= nonSwitchStrings.Count)
+					IncorrectCommand();
+				string inputName = (string)nonSwitchStrings[paramIndex++];
+				inStream = new FileStream(inputName, FileMode.Open, FileAccess.Read);
+			}
+
+			FileStream outStream = null;
+			if (stdOutMode)
+			{
+				throw (new Exception("Not implemeted"));
+			}
+			else
+			{
+				if (paramIndex >= nonSwitchStrings.Count)
+					IncorrectCommand();
+				string outputName = (string)nonSwitchStrings[paramIndex++];
+				outStream = new FileStream(outputName, FileMode.Create, FileAccess.Write);
+			}
+
+			FileStream trainStream = null;
+			if (train.Length != 0)
+				trainStream = new FileStream(train, FileMode.Open, FileAccess.Read);
+
+			if (encodeMode)
+			{
+				if (!dictionaryIsDefined)
+					dictionary = 1 << 23;
+
+				Int32 posStateBits = 2;
+				Int32 litContextBits = 3; // for normal files
+				// UInt32 litContextBits = 0; // for 32-bit data
+				Int32 litPosBits = 0;
+				// UInt32 litPosBits = 2; // for 32-bit data
+				Int32 algorithm = 2;
+				Int32 numFastBytes = 128;
+
+				bool eos = parser[(int)Key.EOS].ThereIs || stdInMode;
+
+				if (parser[(int)Key.Mode].ThereIs)
+					if (!GetNumber((string)parser[(int)Key.Mode].PostStrings[0], out algorithm))
+						IncorrectCommand();
+
+				if (parser[(int)Key.FastBytes].ThereIs)
+					if (!GetNumber((string)parser[(int)Key.FastBytes].PostStrings[0], out numFastBytes))
+						IncorrectCommand();
+				if (parser[(int)Key.LitContext].ThereIs)
+					if (!GetNumber((string)parser[(int)Key.LitContext].PostStrings[0], out litContextBits))
+						IncorrectCommand();
+				if (parser[(int)Key.LitPos].ThereIs)
+					if (!GetNumber((string)parser[(int)Key.LitPos].PostStrings[0], out litPosBits))
+						IncorrectCommand();
+				if (parser[(int)Key.PosBits].ThereIs)
+					if (!GetNumber((string)parser[(int)Key.PosBits].PostStrings[0], out posStateBits))
+						IncorrectCommand();
+
+				CoderPropID[] propIDs = 
+				{
+					CoderPropID.DictionarySize,
+					CoderPropID.PosStateBits,
+					CoderPropID.LitContextBits,
+					CoderPropID.LitPosBits,
+					CoderPropID.Algorithm,
+					CoderPropID.NumFastBytes,
+					CoderPropID.MatchFinder,
+					CoderPropID.EndMarker
+				};
+				object[] properties = 
+				{
+					(Int32)(dictionary),
+					(Int32)(posStateBits),
+					(Int32)(litContextBits),
+					(Int32)(litPosBits),
+					(Int32)(algorithm),
+					(Int32)(numFastBytes),
+					mf,
+					eos
+				};
+
+				Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();
+				encoder.SetCoderProperties(propIDs, properties);
+				encoder.WriteCoderProperties(outStream);
+				Int64 fileSize;
+				if (eos || stdInMode)
+					fileSize = -1;
+				else
+					fileSize = inStream.Length;
+				for (int i = 0; i < 8; i++)
+					outStream.WriteByte((Byte)(fileSize >> (8 * i)));
+				if (trainStream != null)
+				{
+					CDoubleStream doubleStream = new CDoubleStream();
+					doubleStream.s1 = trainStream;
+					doubleStream.s2 = inStream;
+					doubleStream.fileIndex = 0;
+					inStream = doubleStream;
+					long trainFileSize = trainStream.Length;
+					doubleStream.skipSize = 0;
+					if (trainFileSize > dictionary)
+						doubleStream.skipSize = trainFileSize - dictionary;
+					trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin);
+					encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize));
+				}
+				encoder.Code(inStream, outStream, -1, -1, null);
+			}
+			else if (command == "d")
+			{
+				byte[] properties = new byte[5];
+				if (inStream.Read(properties, 0, 5) != 5)
+					throw (new Exception("input .lzma is too short"));
+				Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder();
+				decoder.SetDecoderProperties(properties);
+				if (trainStream != null)
+				{
+					if (!decoder.Train(trainStream))
+						throw (new Exception("can't train"));
+				}
+				long outSize = 0;
+				for (int i = 0; i < 8; i++)
+				{
+					int v = inStream.ReadByte();
+					if (v < 0)
+						throw (new Exception("Can't Read 1"));
+					outSize |= ((long)(byte)v) << (8 * i);
+				}
+				long compressedSize = inStream.Length - inStream.Position;
+				decoder.Code(inStream, outStream, compressedSize, outSize, null);
+			}
+			else
+				throw (new Exception("Command Error"));
+			return 0;
+		}
+
+		[STAThread]
+		static int Main(string[] args)
+		{
+			try
+			{
+				return Main2(args);
+			}
+			catch (Exception e)
+			{
+				Console.WriteLine("{0} Caught exception #1.", e);
+				// throw e;
+				return 1;
+			}
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj
===================================================================
--- trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.csproj	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,90 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>LzmaAlone</RootNamespace>
+    <AssemblyName>Lzma#</AssemblyName>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>.\bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugSymbols>false</DebugSymbols>
+    <Optimize>true</Optimize>
+    <OutputPath>.\bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\..\Common\CommandLineParser.cs">
+      <Link>Common\CommandLineParser.cs</Link>
+    </Compile>
+    <Compile Include="..\..\Common\CRC.cs">
+      <Link>Common\CRC.cs</Link>
+    </Compile>
+    <Compile Include="..\..\ICoder.cs">
+      <Link>ICoder.cs</Link>
+    </Compile>
+    <Compile Include="..\LZ\IMatchFinder.cs">
+      <Link>LZ\IMatchFinder.cs</Link>
+    </Compile>
+    <Compile Include="..\LZ\LzBinTree.cs">
+      <Link>LZ\LzBinTree.cs</Link>
+    </Compile>
+    <Compile Include="..\LZ\LzInWindow.cs">
+      <Link>LZ\LzInWindow.cs</Link>
+    </Compile>
+    <Compile Include="..\LZ\LzOutWindow.cs">
+      <Link>LZ\LzOutWindow.cs</Link>
+    </Compile>
+    <Compile Include="..\LZMA\LzmaBase.cs">
+      <Link>LZMA\LzmaBase.cs</Link>
+    </Compile>
+    <Compile Include="..\LZMA\LzmaDecoder.cs">
+      <Link>LZMA\LzmaDecoder.cs</Link>
+    </Compile>
+    <Compile Include="..\LZMA\LzmaEncoder.cs">
+      <Link>LZMA\LzmaEncoder.cs</Link>
+    </Compile>
+    <Compile Include="..\RangeCoder\RangeCoder.cs">
+      <Link>RangeCoder\RangeCoder.cs</Link>
+    </Compile>
+    <Compile Include="..\RangeCoder\RangeCoderBit.cs">
+      <Link>RangeCoder\RangeCoderBit.cs</Link>
+    </Compile>
+    <Compile Include="..\RangeCoder\RangeCoderBitTree.cs">
+      <Link>RangeCoder\RangeCoderBitTree.cs</Link>
+    </Compile>
+    <Compile Include="LzmaAlone.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="LzmaBench.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Settings.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+    </Compile>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.cs</LastGenOutput>
+    </None>
+    <AppDesigner Include="Properties\" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
+</Project>
\ No newline at end of file

Added: trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln
===================================================================
--- trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaAlone.sln	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C# Express 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LzmaAlone", "LzmaAlone.csproj", "{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CE33DF18-F9C8-4D6F-9057-DBB4DB96E973}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

Added: trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,340 @@
+// LzmaBench.cs
+
+using System;
+using System.IO;
+
+namespace SevenZip
+{
+	/// <summary>
+	/// LZMA Benchmark
+	/// </summary>
+	internal abstract class LzmaBench
+	{
+		const UInt32 kAdditionalSize = (6 << 20);
+		const UInt32 kCompressedAdditionalSize = (1 << 10);
+		const UInt32 kMaxLzmaPropSize = 10;
+
+		class CRandomGenerator
+		{
+			UInt32 A1;
+			UInt32 A2;
+			public CRandomGenerator() { Init(); }
+			public void Init() { A1 = 362436069; A2 = 521288629; }
+			public UInt32 GetRnd()
+			{
+				return
+					((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^
+					((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)));
+			}
+		};
+
+		class CBitRandomGenerator
+		{
+			CRandomGenerator RG = new CRandomGenerator();
+			UInt32 Value;
+			int NumBits;
+			public void Init()
+			{
+				Value = 0;
+				NumBits = 0;
+			}
+			public UInt32 GetRnd(int numBits)
+			{
+				UInt32 result;
+				if (NumBits > numBits)
+				{
+					result = Value & (((UInt32)1 << numBits) - 1);
+					Value >>= numBits;
+					NumBits -= numBits;
+					return result;
+				}
+				numBits -= NumBits;
+				result = (Value << numBits);
+				Value = RG.GetRnd();
+				result |= Value & (((UInt32)1 << numBits) - 1);
+				Value >>= numBits;
+				NumBits = 32 - numBits;
+				return result;
+			}
+		};
+
+		class CBenchRandomGenerator
+		{
+			CBitRandomGenerator RG = new CBitRandomGenerator();
+			UInt32 Pos;
+			UInt32 Rep0;
+			
+			public UInt32 BufferSize;
+			public Byte[] Buffer = null;
+
+			public CBenchRandomGenerator() { }
+
+			public void Set(UInt32 bufferSize)
+			{
+				Buffer = new Byte[bufferSize];
+				Pos = 0;
+				BufferSize = bufferSize;
+			}
+			UInt32 GetRndBit() { return RG.GetRnd(1); }
+			UInt32 GetLogRandBits(int numBits)
+			{
+				UInt32 len = RG.GetRnd(numBits);
+				return RG.GetRnd((int)len);
+			}
+			UInt32 GetOffset()
+			{
+				if (GetRndBit() == 0)
+					return GetLogRandBits(4);
+				return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
+			}
+			UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); }
+			UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); }
+			public void Generate()
+			{
+				RG.Init();
+				Rep0 = 1;
+				while (Pos < BufferSize)
+				{
+					if (GetRndBit() == 0 || Pos < 1)
+						Buffer[Pos++] = (Byte)RG.GetRnd(8);
+					else
+					{
+						UInt32 len;
+						if (RG.GetRnd(3) == 0)
+							len = 1 + GetLen1();
+						else
+						{
+							do
+								Rep0 = GetOffset();
+							while (Rep0 >= Pos);
+							Rep0++;
+							len = 2 + GetLen2();
+						}
+						for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)
+							Buffer[Pos] = Buffer[Pos - Rep0];
+					}
+				}
+			}
+		};
+
+		class CrcOutStream : System.IO.Stream
+		{
+			public CRC CRC = new CRC();
+			public void Init() { CRC.Init(); }
+			public UInt32 GetDigest() { return CRC.GetDigest(); }
+
+			public override bool CanRead { get { return false; } }
+			public override bool CanSeek { get { return false; } }
+			public override bool CanWrite { get { return true; } }
+			public override Int64 Length { get { return 0; } }
+			public override Int64 Position { get { return 0; } set { } }
+			public override void Flush() { }
+			public override long Seek(long offset, SeekOrigin origin) { return 0; }
+			public override void SetLength(long value) { }
+			public override int Read(byte[] buffer, int offset, int count) { return 0; }
+
+			public override void WriteByte(byte b)
+			{
+				CRC.UpdateByte(b);
+			}
+			public override void Write(byte[] buffer, int offset, int count)
+			{
+				CRC.Update(buffer, (uint)offset, (uint)count);
+			}
+		};
+
+		class CProgressInfo : ICodeProgress
+		{
+			public Int64 ApprovedStart;
+			public Int64 InSize;
+			public System.DateTime Time;
+			public void Init() { InSize = 0; }
+			public void SetProgress(Int64 inSize, Int64 outSize)
+			{
+				if (inSize >= ApprovedStart && InSize == 0)
+				{
+					Time = DateTime.UtcNow;
+					InSize = inSize;
+				}
+			}
+		}
+		const int kSubBits = 8;
+
+		static UInt32 GetLogSize(UInt32 size)
+		{
+			for (int i = kSubBits; i < 32; i++)
+				for (UInt32 j = 0; j < (1 << kSubBits); j++)
+					if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
+						return (UInt32)(i << kSubBits) + j;
+			return (32 << kSubBits);
+		}
+
+		static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime)
+		{
+			UInt64 freq = TimeSpan.TicksPerSecond;
+			UInt64 elTime = elapsedTime;
+			while (freq > 1000000)
+			{
+				freq >>= 1;
+				elTime >>= 1;
+			}
+			if (elTime == 0)
+				elTime = 1;
+			return value * freq / elTime;
+		}
+
+		static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size)
+		{
+			UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits);
+			UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits));
+			UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
+			return MyMultDiv64(numCommands, elapsedTime);
+		}
+
+		static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize)
+		{
+			UInt64 numCommands = inSize * 220 + outSize * 20;
+			return MyMultDiv64(numCommands, elapsedTime);
+		}
+
+		static UInt64 GetTotalRating(
+			UInt32 dictionarySize,
+			UInt64 elapsedTimeEn, UInt64 sizeEn,
+			UInt64 elapsedTimeDe,
+			UInt64 inSizeDe, UInt64 outSizeDe)
+		{
+			return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) +
+				GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2;
+		}
+
+		static void PrintValue(UInt64 v)
+		{
+			string s = v.ToString();
+			for (int i = 0; i + s.Length < 6; i++)
+				System.Console.Write(" ");
+			System.Console.Write(s);
+		}
+
+		static void PrintRating(UInt64 rating)
+		{
+			PrintValue(rating / 1000000);
+			System.Console.Write(" MIPS");
+		}
+
+		static void PrintResults(
+			UInt32 dictionarySize,
+			UInt64 elapsedTime,
+			UInt64 size,
+			bool decompressMode, UInt64 secondSize)
+		{
+			UInt64 speed = MyMultDiv64(size, elapsedTime);
+			PrintValue(speed / 1024);
+			System.Console.Write(" KB/s  ");
+			UInt64 rating;
+			if (decompressMode)
+				rating = GetDecompressRating(elapsedTime, size, secondSize);
+			else
+				rating = GetCompressRating(dictionarySize, elapsedTime, size);
+			PrintRating(rating);
+		}
+
+		static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize)
+		{
+			if (numIterations <= 0)
+				return 0;
+			if (dictionarySize < (1 << 18))
+			{
+				System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)");
+				return 1;
+			}
+			System.Console.Write("\n       Compressing                Decompressing\n\n");
+
+			Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();
+			Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder();
+
+
+			CoderPropID[] propIDs = 
+			{ 
+				CoderPropID.DictionarySize,
+			};
+			object[] properties = 
+			{
+				(Int32)(dictionarySize),
+			};
+
+			UInt32 kBufferSize = dictionarySize + kAdditionalSize;
+			UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
+
+			encoder.SetCoderProperties(propIDs, properties);
+			System.IO.MemoryStream propStream = new System.IO.MemoryStream();
+			encoder.WriteCoderProperties(propStream);
+			byte[] propArray = propStream.ToArray();
+
+			CBenchRandomGenerator rg = new CBenchRandomGenerator();
+
+			rg.Set(kBufferSize);
+			rg.Generate();
+			CRC crc = new CRC();
+			crc.Init();
+			crc.Update(rg.Buffer, 0, rg.BufferSize);
+
+			CProgressInfo progressInfo = new CProgressInfo();
+			progressInfo.ApprovedStart = dictionarySize;
+
+			UInt64 totalBenchSize = 0;
+			UInt64 totalEncodeTime = 0;
+			UInt64 totalDecodeTime = 0;
+			UInt64 totalCompressedSize = 0;
+
+			MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize);
+			MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize);
+			CrcOutStream crcOutStream = new CrcOutStream();
+			for (Int32 i = 0; i < numIterations; i++)
+			{
+				progressInfo.Init();
+				inStream.Seek(0, SeekOrigin.Begin);
+				compressedStream.Seek(0, SeekOrigin.Begin);
+				encoder.Code(inStream, compressedStream, -1, -1, progressInfo);
+				TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time;
+				UInt64 encodeTime = (UInt64)sp2.Ticks;
+
+				long compressedSize = compressedStream.Position;
+				if (progressInfo.InSize == 0)
+					throw (new Exception("Internal ERROR 1282"));
+
+				UInt64 decodeTime = 0;
+				for (int j = 0; j < 2; j++)
+				{
+					compressedStream.Seek(0, SeekOrigin.Begin);
+					crcOutStream.Init();
+
+					decoder.SetDecoderProperties(propArray);
+					UInt64 outSize = kBufferSize;
+					System.DateTime startTime = DateTime.UtcNow;
+					decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null);
+					TimeSpan sp = (DateTime.UtcNow - startTime);
+					decodeTime = (ulong)sp.Ticks;
+					if (crcOutStream.GetDigest() != crc.GetDigest())
+						throw (new Exception("CRC Error"));
+				}
+				UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize;
+				PrintResults(dictionarySize, encodeTime, benchSize, false, 0);
+				System.Console.Write("     ");
+				PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize);
+				System.Console.WriteLine();
+
+				totalBenchSize += benchSize;
+				totalEncodeTime += encodeTime;
+				totalDecodeTime += decodeTime;
+				totalCompressedSize += (ulong)compressedSize;
+			}
+			System.Console.WriteLine("---------------------------------------------------");
+			PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0);
+			System.Console.Write("     ");
+			PrintResults(dictionarySize, totalDecodeTime,
+					kBufferSize * (UInt64)numIterations, true, totalCompressedSize);
+			System.Console.WriteLine("    Average");
+			return 0;
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/AssemblyInfo.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,29 @@
+#region Using directives
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+#endregion
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("LZMA#")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Igor Pavlov")]
+[assembly: AssemblyProduct("LZMA# SDK")]
+[assembly: AssemblyCopyright("Copyright @ Igor Pavlov 1999-2004")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("4.12.*")]

Added: trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/Resources.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,70 @@
+//------------------------------------------------------------------------------
+// <autogenerated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.40607.42
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </autogenerated>
+//------------------------------------------------------------------------------
+
+namespace LzmaAlone.Properties
+{
+	using System;
+	using System.IO;
+	using System.Resources;
+
+	/// <summary>
+	///    A strongly-typed resource class, for looking up localized strings, etc.
+	/// </summary>
+	// This class was auto-generated by the Strongly Typed Resource Builder
+	// class via a tool like ResGen or Visual Studio.NET.
+	// To add or remove a member, edit your .ResX file then rerun ResGen
+	// with the /str option, or rebuild your VS project.
+	class Resources
+	{
+
+		private static System.Resources.ResourceManager _resMgr;
+
+		private static System.Globalization.CultureInfo _resCulture;
+
+		/*FamANDAssem*/
+		internal Resources()
+		{
+		}
+
+		/// <summary>
+		///    Returns the cached ResourceManager instance used by this class.
+		/// </summary>
+		[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+		public static System.Resources.ResourceManager ResourceManager
+		{
+			get
+			{
+				if ((_resMgr == null))
+				{
+					System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Resources", typeof(Resources).Assembly);
+					_resMgr = temp;
+				}
+				return _resMgr;
+			}
+		}
+
+		/// <summary>
+		///    Overrides the current thread's CurrentUICulture property for all
+		///    resource lookups using this strongly typed resource class.
+		/// </summary>
+		[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+		public static System.Globalization.CultureInfo Culture
+		{
+			get
+			{
+				return _resCulture;
+			}
+			set
+			{
+				_resCulture = value;
+			}
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/LzmaAlone/Properties/Settings.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,42 @@
+//------------------------------------------------------------------------------
+// <autogenerated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.40607.42
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </autogenerated>
+//------------------------------------------------------------------------------
+
+namespace LzmaAlone.Properties
+{
+	public partial class Settings : System.Configuration.ApplicationSettingsBase
+	{
+		private static Settings m_Value;
+
+		private static object m_SyncObject = new object();
+
+		public static Settings Value
+		{
+			get
+			{
+				if ((Settings.m_Value == null))
+				{
+					System.Threading.Monitor.Enter(Settings.m_SyncObject);
+					if ((Settings.m_Value == null))
+					{
+						try
+						{
+							Settings.m_Value = new Settings();
+						}
+						finally
+						{
+							System.Threading.Monitor.Exit(Settings.m_SyncObject);
+						}
+					}
+				}
+				return Settings.m_Value;
+			}
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoder.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,234 @@
+using System;
+
+namespace SevenZip.Compression.RangeCoder
+{
+	class Encoder
+	{
+		public const uint kTopValue = (1 << 24);
+
+		System.IO.Stream Stream;
+
+		public UInt64 Low;
+		public uint Range;
+		uint _cacheSize;
+		byte _cache;
+
+		long StartPosition;
+
+		public void SetStream(System.IO.Stream stream)
+		{
+			Stream = stream;
+		}
+
+		public void ReleaseStream()
+		{
+			Stream = null;
+		}
+
+		public void Init()
+		{
+			StartPosition = Stream.Position;
+
+			Low = 0;
+			Range = 0xFFFFFFFF;
+			_cacheSize = 1;
+			_cache = 0;
+		}
+
+		public void FlushData()
+		{
+			for (int i = 0; i < 5; i++)
+				ShiftLow();
+		}
+
+		public void FlushStream()
+		{
+			Stream.Flush();
+		}
+
+		public void CloseStream()
+		{
+			Stream.Close();
+		}
+
+		public void Encode(uint start, uint size, uint total)
+		{
+			Low += start * (Range /= total);
+			Range *= size;
+			while (Range < kTopValue)
+			{
+				Range <<= 8;
+				ShiftLow();
+			}
+		}
+
+		public void ShiftLow()
+		{
+			if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
+			{
+				byte temp = _cache;
+				do
+				{
+					Stream.WriteByte((byte)(temp + (Low >> 32)));
+					temp = 0xFF;
+				}
+				while (--_cacheSize != 0);
+				_cache = (byte)(((uint)Low) >> 24);
+			}
+			_cacheSize++;
+			Low = ((uint)Low) << 8;
+		}
+
+		public void EncodeDirectBits(uint v, int numTotalBits)
+		{
+			for (int i = numTotalBits - 1; i >= 0; i--)
+			{
+				Range >>= 1;
+				if (((v >> i) & 1) == 1)
+					Low += Range;
+				if (Range < kTopValue)
+				{
+					Range <<= 8;
+					ShiftLow();
+				}
+			}
+		}
+
+		public void EncodeBit(uint size0, int numTotalBits, uint symbol)
+		{
+			uint newBound = (Range >> numTotalBits) * size0;
+			if (symbol == 0)
+				Range = newBound;
+			else
+			{
+				Low += newBound;
+				Range -= newBound;
+			}
+			while (Range < kTopValue)
+			{
+				Range <<= 8;
+				ShiftLow();
+			}
+		}
+
+		public long GetProcessedSizeAdd()
+		{
+			return _cacheSize +
+				Stream.Position - StartPosition + 4;
+			// (long)Stream.GetProcessedSize();
+		}
+	}
+
+	class Decoder
+	{
+		public const uint kTopValue = (1 << 24);
+		public uint Range;
+		public uint Code;
+		// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
+		public System.IO.Stream Stream;
+
+		public void Init(System.IO.Stream stream)
+		{
+			// Stream.Init(stream);
+			Stream = stream;
+
+			Code = 0;
+			Range = 0xFFFFFFFF;
+			for (int i = 0; i < 5; i++)
+				Code = (Code << 8) | (byte)Stream.ReadByte();
+		}
+
+		public void ReleaseStream()
+		{
+			// Stream.ReleaseStream();
+			Stream = null;
+		}
+
+		public void CloseStream()
+		{
+			Stream.Close();
+		}
+
+		public void Normalize()
+		{
+			while (Range < kTopValue)
+			{
+				Code = (Code << 8) | (byte)Stream.ReadByte();
+				Range <<= 8;
+			}
+		}
+
+		public void Normalize2()
+		{
+			if (Range < kTopValue)
+			{
+				Code = (Code << 8) | (byte)Stream.ReadByte();
+				Range <<= 8;
+			}
+		}
+
+		public uint GetThreshold(uint total)
+		{
+			return Code / (Range /= total);
+		}
+
+		public void Decode(uint start, uint size, uint total)
+		{
+			Code -= start * Range;
+			Range *= size;
+			Normalize();
+		}
+
+		public uint DecodeDirectBits(int numTotalBits)
+		{
+			uint range = Range;
+			uint code = Code;
+			uint result = 0;
+			for (int i = numTotalBits; i > 0; i--)
+			{
+				range >>= 1;
+				/*
+				result <<= 1;
+				if (code >= range)
+				{
+					code -= range;
+					result |= 1;
+				}
+				*/
+				uint t = (code - range) >> 31;
+				code -= range & (t - 1);
+				result = (result << 1) | (1 - t);
+
+				if (range < kTopValue)
+				{
+					code = (code << 8) | (byte)Stream.ReadByte();
+					range <<= 8;
+				}
+			}
+			Range = range;
+			Code = code;
+			return result;
+		}
+
+		public uint DecodeBit(uint size0, int numTotalBits)
+		{
+			uint newBound = (Range >> numTotalBits) * size0;
+			uint symbol;
+			if (Code < newBound)
+			{
+				symbol = 0;
+				Range = newBound;
+			}
+			else
+			{
+				symbol = 1;
+				Code -= newBound;
+				Range -= newBound;
+			}
+			Normalize();
+			return symbol;
+		}
+
+		// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBit.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,117 @@
+using System;
+
+namespace SevenZip.Compression.RangeCoder
+{
+	struct BitEncoder
+	{
+		public const int kNumBitModelTotalBits = 11;
+		public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
+		const int kNumMoveBits = 5;
+		const int kNumMoveReducingBits = 2;
+		public const int kNumBitPriceShiftBits = 6;
+
+		uint Prob;
+
+		public void Init() { Prob = kBitModelTotal >> 1; }
+
+		public void UpdateModel(uint symbol)
+		{
+			if (symbol == 0)
+				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
+			else
+				Prob -= (Prob) >> kNumMoveBits;
+		}
+
+		public void Encode(Encoder encoder, uint symbol)
+		{
+			// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
+			// UpdateModel(symbol);
+			uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
+			if (symbol == 0)
+			{
+				encoder.Range = newBound;
+				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
+			}
+			else
+			{
+				encoder.Low += newBound;
+				encoder.Range -= newBound;
+				Prob -= (Prob) >> kNumMoveBits;
+			}
+			if (encoder.Range < Encoder.kTopValue)
+			{
+				encoder.Range <<= 8;
+				encoder.ShiftLow();
+			}
+		}
+
+		private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
+
+		static BitEncoder()
+		{
+			const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
+			for (int i = kNumBits - 1; i >= 0; i--)
+			{
+				UInt32 start = (UInt32)1 << (kNumBits - i - 1);
+				UInt32 end = (UInt32)1 << (kNumBits - i);
+				for (UInt32 j = start; j < end; j++)
+					ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
+						(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
+			}
+		}
+
+		public uint GetPrice(uint symbol)
+		{
+			return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
+		}
+	  public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
+		public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
+	}
+
+	struct BitDecoder
+	{
+		public const int kNumBitModelTotalBits = 11;
+		public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
+		const int kNumMoveBits = 5;
+
+		uint Prob;
+
+		public void UpdateModel(int numMoveBits, uint symbol)
+		{
+			if (symbol == 0)
+				Prob += (kBitModelTotal - Prob) >> numMoveBits;
+			else
+				Prob -= (Prob) >> numMoveBits;
+		}
+
+		public void Init() { Prob = kBitModelTotal >> 1; }
+
+		public uint Decode(RangeCoder.Decoder rangeDecoder)
+		{
+			uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;
+			if (rangeDecoder.Code < newBound)
+			{
+				rangeDecoder.Range = newBound;
+				Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
+				if (rangeDecoder.Range < Decoder.kTopValue)
+				{
+					rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
+					rangeDecoder.Range <<= 8;
+				}
+				return 0;
+			}
+			else
+			{
+				rangeDecoder.Range -= newBound;
+				rangeDecoder.Code -= newBound;
+				Prob -= (Prob) >> kNumMoveBits;
+				if (rangeDecoder.Range < Decoder.kTopValue)
+				{
+					rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
+					rangeDecoder.Range <<= 8;
+				}
+				return 1;
+			}
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
===================================================================
--- trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/Compress/RangeCoder/RangeCoderBitTree.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,157 @@
+using System;
+
+namespace SevenZip.Compression.RangeCoder
+{
+	struct BitTreeEncoder
+	{
+		BitEncoder[] Models;
+		int NumBitLevels;
+
+		public BitTreeEncoder(int numBitLevels)
+		{
+			NumBitLevels = numBitLevels;
+			Models = new BitEncoder[1 << numBitLevels];
+		}
+
+		public void Init()
+		{
+			for (uint i = 1; i < (1 << NumBitLevels); i++)
+				Models[i].Init();
+		}
+
+		public void Encode(Encoder rangeEncoder, UInt32 symbol)
+		{
+			UInt32 m = 1;
+			for (int bitIndex = NumBitLevels; bitIndex > 0; )
+			{
+				bitIndex--;
+				UInt32 bit = (symbol >> bitIndex) & 1;
+				Models[m].Encode(rangeEncoder, bit);
+				m = (m << 1) | bit;
+			}
+		}
+
+		public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
+		{
+			UInt32 m = 1;
+			for (UInt32 i = 0; i < NumBitLevels; i++)
+			{
+				UInt32 bit = symbol & 1;
+				Models[m].Encode(rangeEncoder, bit);
+				m = (m << 1) | bit;
+				symbol >>= 1;
+			}
+		}
+
+		public UInt32 GetPrice(UInt32 symbol)
+		{
+			UInt32 price = 0;
+			UInt32 m = 1;
+			for (int bitIndex = NumBitLevels; bitIndex > 0; )
+			{
+				bitIndex--;
+				UInt32 bit = (symbol >> bitIndex) & 1;
+				price += Models[m].GetPrice(bit);
+				m = (m << 1) + bit;
+			}
+			return price;
+		}
+
+		public UInt32 ReverseGetPrice(UInt32 symbol)
+		{
+			UInt32 price = 0;
+			UInt32 m = 1;
+			for (int i = NumBitLevels; i > 0; i--)
+			{
+				UInt32 bit = symbol & 1;
+				symbol >>= 1;
+				price += Models[m].GetPrice(bit);
+				m = (m << 1) | bit;
+			}
+			return price;
+		}
+
+		public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
+			int NumBitLevels, UInt32 symbol)
+		{
+			UInt32 price = 0;
+			UInt32 m = 1;
+			for (int i = NumBitLevels; i > 0; i--)
+			{
+				UInt32 bit = symbol & 1;
+				symbol >>= 1;
+				price += Models[startIndex + m].GetPrice(bit);
+				m = (m << 1) | bit;
+			}
+			return price;
+		}
+
+		public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
+			Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
+		{
+			UInt32 m = 1;
+			for (int i = 0; i < NumBitLevels; i++)
+			{
+				UInt32 bit = symbol & 1;
+				Models[startIndex + m].Encode(rangeEncoder, bit);
+				m = (m << 1) | bit;
+				symbol >>= 1;
+			}
+		}
+	}
+
+	struct BitTreeDecoder
+	{
+		BitDecoder[] Models;
+		int NumBitLevels;
+
+		public BitTreeDecoder(int numBitLevels)
+		{
+			NumBitLevels = numBitLevels;
+			Models = new BitDecoder[1 << numBitLevels];
+		}
+
+		public void Init()
+		{
+			for (uint i = 1; i < (1 << NumBitLevels); i++)
+				Models[i].Init();
+		}
+
+		public uint Decode(RangeCoder.Decoder rangeDecoder)
+		{
+			uint m = 1;
+			for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
+				m = (m << 1) + Models[m].Decode(rangeDecoder);
+			return m - ((uint)1 << NumBitLevels);
+		}
+
+		public uint ReverseDecode(RangeCoder.Decoder rangeDecoder)
+		{
+			uint m = 1;
+			uint symbol = 0;
+			for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+			{
+				uint bit = Models[m].Decode(rangeDecoder);
+				m <<= 1;
+				m += bit;
+				symbol |= (bit << bitIndex);
+			}
+			return symbol;
+		}
+
+		public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
+			RangeCoder.Decoder rangeDecoder, int NumBitLevels)
+		{
+			uint m = 1;
+			uint symbol = 0;
+			for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+			{
+				uint bit = Models[startIndex + m].Decode(rangeDecoder);
+				m <<= 1;
+				m += bit;
+				symbol |= (bit << bitIndex);
+			}
+			return symbol;
+		}
+	}
+}

Added: trunk/lzma/CS/7zip/ICoder.cs
===================================================================
--- trunk/lzma/CS/7zip/ICoder.cs	                        (rev 0)
+++ trunk/lzma/CS/7zip/ICoder.cs	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,145 @@
+// ICoder.h
+
+using System;
+
+namespace SevenZip
+{
+	/// <summary>
+	/// The exception that is thrown when an error in input stream occurs during decoding.
+	/// </summary>
+	class DataErrorException : ApplicationException
+	{
+		public DataErrorException(): base("Data Error") { }
+	}
+
+	/// <summary>
+	/// The exception that is thrown when the value of an argument is outside the allowable range.
+	/// </summary>
+	class InvalidParamException : ApplicationException
+	{
+		public InvalidParamException(): base("Invalid Parameter") { }
+	}
+
+	public interface ICodeProgress
+	{
+		/// <summary>
+		/// Callback progress.
+		/// </summary>
+		/// <param name="inSize">
+		/// input size. -1 if unknown.
+		/// </param>
+		/// <param name="outSize">
+		/// output size. -1 if unknown.
+		/// </param>
+		void SetProgress(Int64 inSize, Int64 outSize);
+	};
+
+	public interface ICoder
+	{
+		/// <summary>
+		/// Codes streams.
+		/// </summary>
+		/// <param name="inStream">
+		/// input Stream.
+		/// </param>
+		/// <param name="outStream">
+		/// output Stream.
+		/// </param>
+		/// <param name="inSize">
+		/// input Size. -1 if unknown.
+		/// </param>
+		/// <param name="outSize">
+		/// output Size. -1 if unknown.
+		/// </param>
+		/// <param name="progress">
+		/// callback progress reference.
+		/// </param>
+		/// <exception cref="SevenZip.DataErrorException">
+		/// if input stream is not valid
+		/// </exception>
+		void Code(System.IO.Stream inStream, System.IO.Stream outStream,
+			Int64 inSize, Int64 outSize, ICodeProgress progress);
+	};
+
+	/*
+	public interface ICoder2
+	{
+		 void Code(ISequentialInStream []inStreams,
+				const UInt64 []inSizes, 
+				ISequentialOutStream []outStreams, 
+				UInt64 []outSizes,
+				ICodeProgress progress);
+	};
+  */
+
+	/// <summary>
+	/// Provides the fields that represent properties idenitifiers for compressing.
+	/// </summary>
+	public enum CoderPropID
+	{
+		/// <summary>
+		/// Specifies size of dictionary.
+		/// </summary>
+		DictionarySize = 0x400,
+		/// <summary>
+		/// Specifies size of memory for PPM*.
+		/// </summary>
+		UsedMemorySize,
+		/// <summary>
+		/// Specifies order for PPM methods.
+		/// </summary>
+		Order,
+		/// <summary>
+		/// Specifies number of postion state bits for LZMA (0 <= x <= 4).
+		/// </summary>
+		PosStateBits = 0x440,
+		/// <summary>
+		/// Specifies number of literal context bits for LZMA (0 <= x <= 8).
+		/// </summary>
+		LitContextBits,
+		/// <summary>
+		/// Specifies number of literal position bits for LZMA (0 <= x <= 4).
+		/// </summary>
+		LitPosBits,
+		/// <summary>
+		/// Specifies number of fast bytes for LZ*.
+		/// </summary>
+		NumFastBytes = 0x450,
+		/// <summary>
+		/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
+		/// </summary>
+		MatchFinder,
+		/// <summary>
+		/// Specifies number of passes.
+		/// </summary>
+		NumPasses = 0x460,
+		/// <summary>
+		/// Specifies number of algorithm.
+		/// </summary>
+		Algorithm = 0x470,
+		/// <summary>
+		/// Specifies multithread mode.
+		/// </summary>
+		MultiThread = 0x480,
+		/// <summary>
+		/// Specifies mode with end marker.
+		/// </summary>
+		EndMarker = 0x490
+	};
+
+
+	public interface ISetCoderProperties
+	{
+		void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
+	};
+
+	public interface IWriteCoderProperties
+	{
+		void WriteCoderProperties(System.IO.Stream outStream);
+	}
+
+	public interface ISetDecoderProperties
+	{
+		void SetDecoderProperties(byte[] properties);
+	}
+}

Added: trunk/lzma/Java/SevenZip/CRC.java
===================================================================
--- trunk/lzma/Java/SevenZip/CRC.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/CRC.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,52 @@
+// SevenZip/CRC.java
+
+package SevenZip;
+
+public class CRC
+{
+	static public int[] Table = new int[256];
+	
+	static
+	{
+		for (int i = 0; i < 256; i++)
+		{
+			int r = i;
+			for (int j = 0; j < 8; j++)
+				if ((r & 1) != 0)
+					r = (r >>> 1) ^ 0xEDB88320;
+				else
+					r >>>= 1;
+			Table[i] = r;
+		}
+	}
+	
+	int _value = -1;
+	
+	public void Init()
+	{
+		_value = -1;
+	}
+	
+	public void Update(byte[] data, int offset, int size)
+	{
+		for (int i = 0; i < size; i++)
+			_value = Table[(_value ^ data[offset + i]) & 0xFF] ^ (_value >>> 8);
+	}
+	
+	public void Update(byte[] data)
+	{
+		int size = data.length;
+		for (int i = 0; i < size; i++)
+			_value = Table[(_value ^ data[i]) & 0xFF] ^ (_value >>> 8);
+	}
+	
+	public void UpdateByte(int b)
+	{
+		_value = Table[(_value ^ b) & 0xFF] ^ (_value >>> 8);
+	}
+	
+	public int GetDigest()
+	{
+		return _value ^ (-1);
+	}
+}

Added: trunk/lzma/Java/SevenZip/Compression/LZ/BinTree.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/LZ/BinTree.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/LZ/BinTree.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,382 @@
+// LZ.BinTree
+
+package SevenZip.Compression.LZ;
+import java.io.IOException;
+
+
+public class BinTree extends InWindow
+{
+	int _cyclicBufferPos;
+	int _cyclicBufferSize = 0;
+	int _matchMaxLen;
+	
+	int[] _son;
+	int[] _hash;
+	
+	int _cutValue = 0xFF;
+	int _hashMask;
+	int _hashSizeSum = 0;
+	
+	boolean HASH_ARRAY = true;
+
+	static final int kHash2Size = 1 << 10;
+	static final int kHash3Size = 1 << 16;
+	static final int kBT2HashSize = 1 << 16;
+	static final int kStartMaxLen = 1;
+	static final int kHash3Offset = kHash2Size;
+	static final int kEmptyHashValue = 0;
+	static final int kMaxValForNormalize = (1 << 30) - 1;
+	
+	int kNumHashDirectBytes = 0;
+	int kMinMatchCheck = 4;
+	int kFixHashSize = kHash2Size + kHash3Size;
+
+	public void SetType(int numHashBytes)
+	{
+		HASH_ARRAY = (numHashBytes > 2);
+		if (HASH_ARRAY)
+		{
+			kNumHashDirectBytes = 0;
+			kMinMatchCheck = 4;
+			kFixHashSize = kHash2Size + kHash3Size;
+		}
+		else
+		{
+			kNumHashDirectBytes = 2;
+			kMinMatchCheck = 2 + 1;
+			kFixHashSize = 0;
+		}
+	}
+	
+
+	
+
+	public void Init() throws IOException
+	{
+		super.Init();
+		for (int i = 0; i < _hashSizeSum; i++)
+			_hash[i] = kEmptyHashValue;
+		_cyclicBufferPos = 0;
+		ReduceOffsets(-1);
+	}
+	
+	public void MovePos() throws IOException
+	{
+		if (++_cyclicBufferPos >= _cyclicBufferSize)
+			_cyclicBufferPos = 0;
+		super.MovePos();
+		if (_pos == kMaxValForNormalize)
+			Normalize();
+	}
+	
+
+	
+	
+	
+	
+	
+	
+	public boolean Create(int historySize, int keepAddBufferBefore,
+			int matchMaxLen, int keepAddBufferAfter)
+	{
+		if (historySize > kMaxValForNormalize - 256)
+			return false;
+		_cutValue = 16 + (matchMaxLen >> 1);
+
+		int windowReservSize = (historySize + keepAddBufferBefore +
+				matchMaxLen + keepAddBufferAfter) / 2 + 256;
+		
+		super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
+		
+		_matchMaxLen = matchMaxLen;
+
+		int cyclicBufferSize = historySize + 1;
+		if (_cyclicBufferSize != cyclicBufferSize)
+			_son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2];
+
+		int hs = kBT2HashSize;
+
+		if (HASH_ARRAY)
+		{
+			hs = historySize - 1;
+			hs |= (hs >> 1);
+			hs |= (hs >> 2);
+			hs |= (hs >> 4);
+			hs |= (hs >> 8);
+			hs >>= 1;
+			hs |= 0xFFFF;
+			if (hs > (1 << 24))
+				hs >>= 1;
+			_hashMask = hs;
+			hs++;
+			hs += kFixHashSize;
+		}
+		if (hs != _hashSizeSum)
+			_hash = new int [_hashSizeSum = hs];
+		return true;
+	}
+	public int GetMatches(int[] distances) throws IOException
+	{
+		int lenLimit;
+		if (_pos + _matchMaxLen <= _streamPos)
+			lenLimit = _matchMaxLen;
+		else
+		{
+			lenLimit = _streamPos - _pos;
+			if (lenLimit < kMinMatchCheck)
+			{
+				MovePos();
+				return 0;
+			}
+		}
+
+		int offset = 0;
+		int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+		int cur = _bufferOffset + _pos;
+		int maxLen = kStartMaxLen; // to avoid items for len < hashSize;
+		int hashValue, hash2Value = 0, hash3Value = 0;
+		
+		if (HASH_ARRAY)
+		{
+			int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF);
+			hash2Value = temp & (kHash2Size - 1);
+			temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8);
+			hash3Value = temp & (kHash3Size - 1);
+			hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask;
+		}
+		else
+			hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8));
+
+		int curMatch = _hash[kFixHashSize + hashValue];
+		if (HASH_ARRAY)
+		{
+			int curMatch2 = _hash[hash2Value];
+			int curMatch3 = _hash[kHash3Offset + hash3Value];
+			_hash[hash2Value] = _pos;
+			_hash[kHash3Offset + hash3Value] = _pos;
+			if (curMatch2 > matchMinPos)
+				if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
+				{
+					distances[offset++] = maxLen = 2;
+					distances[offset++] = _pos - curMatch2 - 1;
+				}
+			if (curMatch3 > matchMinPos)
+				if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
+				{
+					if (curMatch3 == curMatch2)
+						offset -= 2;
+					distances[offset++] = maxLen = 3;
+					distances[offset++] = _pos - curMatch3 - 1;
+					curMatch2 = curMatch3;
+				}
+			if (offset != 0 && curMatch2 == curMatch)
+			{
+				offset -= 2;
+				maxLen = kStartMaxLen;
+			}
+		}
+
+		_hash[kFixHashSize + hashValue] = _pos;
+
+		int ptr0 = (_cyclicBufferPos << 1) + 1;
+		int ptr1 = (_cyclicBufferPos << 1);
+
+		int len0, len1;
+		len0 = len1 = kNumHashDirectBytes;
+
+		if (kNumHashDirectBytes != 0)
+		{
+			if (curMatch > matchMinPos)
+			{
+				if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
+						_bufferBase[cur + kNumHashDirectBytes])
+				{
+					distances[offset++] = maxLen = kNumHashDirectBytes;
+					distances[offset++] = _pos - curMatch - 1;
+				}
+			}
+		}
+
+		int count = _cutValue;
+
+		while (true)
+		{
+			if (curMatch <= matchMinPos || count-- == 0)
+			{
+				_son[ptr0] = _son[ptr1] = kEmptyHashValue;
+				break;
+			}
+			int delta = _pos - curMatch;
+			int cyclicPos = ((delta <= _cyclicBufferPos) ?
+				(_cyclicBufferPos - delta) :
+				(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
+
+			int pby1 = _bufferOffset + curMatch;
+			int len = Math.min(len0, len1);
+			if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
+			{
+				while(++len != lenLimit)
+					if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
+						break;
+				if (maxLen < len)
+				{
+					distances[offset++] = maxLen = len;
+					distances[offset++] = delta - 1;
+					if (len == lenLimit)
+					{
+						_son[ptr1] = _son[cyclicPos];
+						_son[ptr0] = _son[cyclicPos + 1];
+						break;
+					}
+				}
+			}
+			if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF))
+			{
+				_son[ptr1] = curMatch;
+				ptr1 = cyclicPos + 1;
+				curMatch = _son[ptr1];
+				len1 = len;
+			}
+			else
+			{
+				_son[ptr0] = curMatch;
+				ptr0 = cyclicPos;
+				curMatch = _son[ptr0];
+				len0 = len;
+			}
+		}
+		MovePos();
+		return offset;
+	}
+
+	public void Skip(int num) throws IOException
+	{
+		do
+		{
+			int lenLimit;
+			if (_pos + _matchMaxLen <= _streamPos)
+			lenLimit = _matchMaxLen;
+			else
+			{
+				lenLimit = _streamPos - _pos;
+				if (lenLimit < kMinMatchCheck)
+				{
+					MovePos();
+					continue;
+				}
+			}
+
+			int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+			int cur = _bufferOffset + _pos;
+			
+			int hashValue;
+
+			if (HASH_ARRAY)
+			{
+				int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF);
+				int hash2Value = temp & (kHash2Size - 1);
+				_hash[hash2Value] = _pos;
+				temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8);
+				int hash3Value = temp & (kHash3Size - 1);
+				_hash[kHash3Offset + hash3Value] = _pos;
+				hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask;
+			}
+			else
+				hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8));
+
+			int curMatch = _hash[kFixHashSize + hashValue];
+			_hash[kFixHashSize + hashValue] = _pos;
+
+			int ptr0 = (_cyclicBufferPos << 1) + 1;
+			int ptr1 = (_cyclicBufferPos << 1);
+
+			int len0, len1;
+			len0 = len1 = kNumHashDirectBytes;
+
+			int count = _cutValue;
+			while (true)
+			{
+				if (curMatch <= matchMinPos || count-- == 0)
+				{
+					_son[ptr0] = _son[ptr1] = kEmptyHashValue;
+					break;
+				}
+
+				int delta = _pos - curMatch;
+				int cyclicPos = ((delta <= _cyclicBufferPos) ?
+					(_cyclicBufferPos - delta) :
+					(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
+
+				int pby1 = _bufferOffset + curMatch;
+				int len = Math.min(len0, len1);
+				if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
+				{
+					while (++len != lenLimit)
+						if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
+							break;
+					if (len == lenLimit)
+					{
+						_son[ptr1] = _son[cyclicPos];
+						_son[ptr0] = _son[cyclicPos + 1];
+						break;
+					}
+				}
+				if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF))
+				{
+					_son[ptr1] = curMatch;
+					ptr1 = cyclicPos + 1;
+					curMatch = _son[ptr1];
+					len1 = len;
+				}
+				else
+				{
+					_son[ptr0] = curMatch;
+					ptr0 = cyclicPos;
+					curMatch = _son[ptr0];
+					len0 = len;
+				}
+			}
+			MovePos();
+		}
+		while (--num != 0);
+	}
+	
+	void NormalizeLinks(int[] items, int numItems, int subValue)
+	{
+		for (int i = 0; i < numItems; i++)
+		{
+			int value = items[i];
+			if (value <= subValue)
+				value = kEmptyHashValue;
+			else
+				value -= subValue;
+			items[i] = value;
+		}
+	}
+	
+	void Normalize()
+	{
+		int subValue = _pos - _cyclicBufferSize;
+		NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
+		NormalizeLinks(_hash, _hashSizeSum, subValue);
+		ReduceOffsets(subValue);
+	}
+	
+	public void SetCutValue(int cutValue) { _cutValue = cutValue; }
+
+	private static final int[] CrcTable = new int[256];
+
+	static
+	{
+		for (int i = 0; i < 256; i++)
+		{
+			int r = i;
+			for (int j = 0; j < 8; j++)
+				if ((r & 1) != 0)
+					r = (r >>> 1) ^ 0xEDB88320;
+				else
+					r >>>= 1;
+			CrcTable[i] = r;
+		}
+	}
+}

Added: trunk/lzma/Java/SevenZip/Compression/LZ/InWindow.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/LZ/InWindow.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/LZ/InWindow.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,131 @@
+// LZ.InWindow
+
+package SevenZip.Compression.LZ;
+
+import java.io.IOException;
+
+public class InWindow
+{
+	public byte[] _bufferBase; // pointer to buffer with data
+	java.io.InputStream _stream;
+	int _posLimit;  // offset (from _buffer) of first byte when new block reading must be done
+	boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream
+	
+	int _pointerToLastSafePosition;
+	
+	public int _bufferOffset;
+	
+	public int _blockSize;  // Size of Allocated memory block
+	public int _pos;             // offset (from _buffer) of curent byte
+	int _keepSizeBefore;  // how many BYTEs must be kept in buffer before _pos
+	int _keepSizeAfter;   // how many BYTEs must be kept buffer after _pos
+	public int _streamPos;   // offset (from _buffer) of first not read byte from Stream
+	
+	public void MoveBlock()
+	{
+		int offset = _bufferOffset + _pos - _keepSizeBefore;
+		// we need one additional byte, since MovePos moves on 1 byte.
+		if (offset > 0)
+			offset--;
+
+		int numBytes = _bufferOffset + _streamPos - offset;
+		
+		// check negative offset ????
+		for (int i = 0; i < numBytes; i++)
+			_bufferBase[i] = _bufferBase[offset + i];
+		_bufferOffset -= offset;
+	}
+	
+	public void ReadBlock() throws IOException
+	{
+		if (_streamEndWasReached)
+			return;
+		while (true)
+		{
+			int size = (0 - _bufferOffset) + _blockSize - _streamPos;
+			if (size == 0)
+				return;
+			int numReadBytes = _stream.read(_bufferBase, _bufferOffset + _streamPos, size);
+			if (numReadBytes == -1)
+			{
+				_posLimit = _streamPos;
+				int pointerToPostion = _bufferOffset + _posLimit;
+				if (pointerToPostion > _pointerToLastSafePosition)
+					_posLimit = _pointerToLastSafePosition - _bufferOffset;
+				
+				_streamEndWasReached = true;
+				return;
+			}
+			_streamPos += numReadBytes;
+			if (_streamPos >= _pos + _keepSizeAfter)
+				_posLimit = _streamPos - _keepSizeAfter;
+		}
+	}
+	
+	void Free() { _bufferBase = null; }
+	
+	public void Create(int keepSizeBefore, int keepSizeAfter, int keepSizeReserv)
+	{
+		_keepSizeBefore = keepSizeBefore;
+		_keepSizeAfter = keepSizeAfter;
+		int blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
+		if (_bufferBase == null || _blockSize != blockSize)
+		{
+			Free();
+			_blockSize = blockSize;
+			_bufferBase = new byte[_blockSize];
+		}
+		_pointerToLastSafePosition = _blockSize - keepSizeAfter;
+	}
+	
+	public void SetStream(java.io.InputStream stream) { _stream = stream; 	}
+	public void ReleaseStream() { _stream = null; }
+
+	public void Init() throws IOException
+	{
+		_bufferOffset = 0;
+		_pos = 0;
+		_streamPos = 0;
+		_streamEndWasReached = false;
+		ReadBlock();
+	}
+	
+	public void MovePos() throws IOException
+	{
+		_pos++;
+		if (_pos > _posLimit)
+		{
+			int pointerToPostion = _bufferOffset + _pos;
+			if (pointerToPostion > _pointerToLastSafePosition)
+				MoveBlock();
+			ReadBlock();
+		}
+	}
+	
+	public byte GetIndexByte(int index)	{ return _bufferBase[_bufferOffset + _pos + index]; }
+	
+	// index + limit have not to exceed _keepSizeAfter;
+	public int GetMatchLen(int index, int distance, int limit)
+	{
+		if (_streamEndWasReached)
+			if ((_pos + index) + limit > _streamPos)
+				limit = _streamPos - (_pos + index);
+		distance++;
+		// Byte *pby = _buffer + (size_t)_pos + index;
+		int pby = _bufferOffset + _pos + index;
+		
+		int i;
+		for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);
+		return i;
+	}
+	
+	public int GetNumAvailableBytes()	{ return _streamPos - _pos; }
+	
+	public void ReduceOffsets(int subValue)
+	{
+		_bufferOffset += subValue;
+		_posLimit -= subValue;
+		_pos -= subValue;
+		_streamPos -= subValue;
+	}
+}

Added: trunk/lzma/Java/SevenZip/Compression/LZ/OutWindow.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/LZ/OutWindow.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/LZ/OutWindow.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,85 @@
+// LZ.OutWindow
+
+package SevenZip.Compression.LZ;
+
+import java.io.IOException;
+
+public class OutWindow
+{
+	byte[] _buffer;
+	int _pos;
+	int _windowSize = 0;
+	int _streamPos;
+	java.io.OutputStream _stream;
+	
+	public void Create(int windowSize)
+	{
+		if (_buffer == null || _windowSize != windowSize)
+			_buffer = new byte[windowSize];
+		_windowSize = windowSize;
+		_pos = 0;
+		_streamPos = 0;
+	}
+	
+	public void SetStream(java.io.OutputStream stream) throws IOException
+	{
+		ReleaseStream();
+		_stream = stream;
+	}
+	
+	public void ReleaseStream() throws IOException
+	{
+		Flush();
+		_stream = null;
+	}
+	
+	public void Init(boolean solid)
+	{
+		if (!solid)
+		{
+			_streamPos = 0;
+			_pos = 0;
+		}
+	}
+	
+	public void Flush() throws IOException
+	{
+		int size = _pos - _streamPos;
+		if (size == 0)
+			return;
+		_stream.write(_buffer, _streamPos, size);
+		if (_pos >= _windowSize)
+			_pos = 0;
+		_streamPos = _pos;
+	}
+	
+	public void CopyBlock(int distance, int len) throws IOException
+	{
+		int pos = _pos - distance - 1;
+		if (pos < 0)
+			pos += _windowSize;
+		for (; len != 0; len--)
+		{
+			if (pos >= _windowSize)
+				pos = 0;
+			_buffer[_pos++] = _buffer[pos++];
+			if (_pos >= _windowSize)
+				Flush();
+		}
+	}
+	
+	public void PutByte(byte b) throws IOException
+	{
+		_buffer[_pos++] = b;
+		if (_pos >= _windowSize)
+			Flush();
+	}
+	
+	public byte GetByte(int distance)
+	{
+		int pos = _pos - distance - 1;
+		if (pos < 0)
+			pos += _windowSize;
+		return _buffer[pos];
+	}
+}

Added: trunk/lzma/Java/SevenZip/Compression/LZMA/Base.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/LZMA/Base.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/LZMA/Base.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,88 @@
+// Base.java
+
+package SevenZip.Compression.LZMA;
+
+public class Base
+{
+	public static final int kNumRepDistances = 4;
+	public static final int kNumStates = 12;
+	
+	public static final int StateInit()
+	{
+		return 0;
+	}
+	
+	public static final int StateUpdateChar(int index)
+	{
+		if (index < 4) 
+			return 0;
+		if (index < 10) 
+			return index - 3;
+		return index - 6;
+	}
+	
+	public static final int StateUpdateMatch(int index)
+	{
+		return (index < 7 ? 7 : 10); 
+	}
+
+	public static final int StateUpdateRep(int index)
+	{ 
+		return (index < 7 ? 8 : 11); 
+	}
+	
+	public static final int StateUpdateShortRep(int index)
+	{ 
+		return (index < 7 ? 9 : 11); 
+	}
+
+	public static final boolean StateIsCharState(int index)
+	{ 
+		return index < 7; 
+	}
+	
+	public static final int kNumPosSlotBits = 6;
+	public static final int kDicLogSizeMin = 0;
+	// public static final int kDicLogSizeMax = 28;
+	// public static final int kDistTableSizeMax = kDicLogSizeMax * 2;
+	
+	public static final int kNumLenToPosStatesBits = 2; // it's for speed optimization
+	public static final int kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
+	
+	public static final int kMatchMinLen = 2;
+	
+	public static final int GetLenToPosState(int len)
+	{
+		len -= kMatchMinLen;
+		if (len < kNumLenToPosStates)
+			return len;
+		return (int)(kNumLenToPosStates - 1);
+	}
+	
+	public static final int kNumAlignBits = 4;
+	public static final int kAlignTableSize = 1 << kNumAlignBits;
+	public static final int kAlignMask = (kAlignTableSize - 1);
+	
+	public static final int kStartPosModelIndex = 4;
+	public static final int kEndPosModelIndex = 14;
+	public static final int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
+	
+	public static final  int kNumFullDistances = 1 << (kEndPosModelIndex / 2);
+	
+	public static final  int kNumLitPosStatesBitsEncodingMax = 4;
+	public static final  int kNumLitContextBitsMax = 8;
+	
+	public static final  int kNumPosStatesBitsMax = 4;
+	public static final  int kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
+	public static final  int kNumPosStatesBitsEncodingMax = 4;
+	public static final  int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
+	
+	public static final  int kNumLowLenBits = 3;
+	public static final  int kNumMidLenBits = 3;
+	public static final  int kNumHighLenBits = 8;
+	public static final  int kNumLowLenSymbols = 1 << kNumLowLenBits;
+	public static final  int kNumMidLenSymbols = 1 << kNumMidLenBits;
+	public static final  int kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
+			(1 << kNumHighLenBits);
+	public static final  int kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
+}

Added: trunk/lzma/Java/SevenZip/Compression/LZMA/Decoder.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/LZMA/Decoder.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/LZMA/Decoder.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,329 @@
+package SevenZip.Compression.LZMA;
+
+import SevenZip.Compression.RangeCoder.BitTreeDecoder;
+import SevenZip.Compression.LZMA.Base;
+import SevenZip.Compression.LZ.OutWindow;
+import java.io.IOException;
+
+public class Decoder
+{
+	class LenDecoder
+	{
+		short[] m_Choice = new short[2];
+		BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
+		BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
+		BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
+		int m_NumPosStates = 0;
+		
+		public void Create(int numPosStates)
+		{
+			for (; m_NumPosStates < numPosStates; m_NumPosStates++)
+			{
+				m_LowCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumLowLenBits);
+				m_MidCoder[m_NumPosStates] = new BitTreeDecoder(Base.kNumMidLenBits);
+			}
+		}
+		
+		public void Init()
+		{
+			SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Choice);
+			for (int posState = 0; posState < m_NumPosStates; posState++)
+			{
+				m_LowCoder[posState].Init();
+				m_MidCoder[posState].Init();
+			}
+			m_HighCoder.Init();
+		}
+		
+		public int Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, int posState) throws IOException
+		{
+			if (rangeDecoder.DecodeBit(m_Choice, 0) == 0)
+				return m_LowCoder[posState].Decode(rangeDecoder);
+			int symbol = Base.kNumLowLenSymbols;
+			if (rangeDecoder.DecodeBit(m_Choice, 1) == 0)
+				symbol += m_MidCoder[posState].Decode(rangeDecoder);
+			else
+				symbol += Base.kNumMidLenSymbols + m_HighCoder.Decode(rangeDecoder);
+			return symbol;
+		}
+	}
+	
+	class LiteralDecoder
+	{
+		class Decoder2
+		{
+			short[] m_Decoders = new short[0x300];
+			
+			public void Init()
+			{
+				SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_Decoders);
+			}
+			
+			public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) throws IOException
+			{
+				int symbol = 1;
+				do
+					symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol);
+				while (symbol < 0x100);
+				return (byte)symbol;
+			}
+			
+			public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) throws IOException
+			{
+				int symbol = 1;
+				do
+				{
+					int matchBit = (matchByte >> 7) & 1;
+					matchByte <<= 1;
+					int bit = rangeDecoder.DecodeBit(m_Decoders, ((1 + matchBit) << 8) + symbol);
+					symbol = (symbol << 1) | bit;
+					if (matchBit != bit)
+					{
+						while (symbol < 0x100)
+							symbol = (symbol << 1) | rangeDecoder.DecodeBit(m_Decoders, symbol);
+						break;
+					}
+				}
+				while (symbol < 0x100);
+				return (byte)symbol;
+			}
+		}
+		
+		Decoder2[] m_Coders;
+		int m_NumPrevBits;
+		int m_NumPosBits;
+		int m_PosMask;
+		
+		public void Create(int numPosBits, int numPrevBits)
+		{
+			if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
+				return;
+			m_NumPosBits = numPosBits;
+			m_PosMask = (1 << numPosBits) - 1;
+			m_NumPrevBits = numPrevBits;
+			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
+			m_Coders = new Decoder2[numStates];
+			for (int i = 0; i < numStates; i++)
+				m_Coders[i] = new Decoder2();
+		}
+		
+		public void Init()
+		{
+			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
+			for (int i = 0; i < numStates; i++)
+				m_Coders[i].Init();
+		}
+		
+		Decoder2 GetDecoder(int pos, byte prevByte)
+		{
+			return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))];
+		}
+	}
+	
+	OutWindow m_OutWindow = new OutWindow();
+	SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder();
+	
+	short[] m_IsMatchDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
+	short[] m_IsRepDecoders = new short[Base.kNumStates];
+	short[] m_IsRepG0Decoders = new short[Base.kNumStates];
+	short[] m_IsRepG1Decoders = new short[Base.kNumStates];
+	short[] m_IsRepG2Decoders = new short[Base.kNumStates];
+	short[] m_IsRep0LongDecoders = new short[Base.kNumStates << Base.kNumPosStatesBitsMax];
+	
+	BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
+	short[] m_PosDecoders = new short[Base.kNumFullDistances - Base.kEndPosModelIndex];
+	
+	BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
+	
+	LenDecoder m_LenDecoder = new LenDecoder();
+	LenDecoder m_RepLenDecoder = new LenDecoder();
+	
+	LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
+	
+	int m_DictionarySize = -1;
+	int m_DictionarySizeCheck =  -1;
+	
+	int m_PosStateMask;
+	
+	public Decoder()
+	{
+		for (int i = 0; i < Base.kNumLenToPosStates; i++)
+			m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
+	}
+	
+	boolean SetDictionarySize(int dictionarySize)
+	{
+		if (dictionarySize < 0)
+			return false;
+		if (m_DictionarySize != dictionarySize)
+		{
+			m_DictionarySize = dictionarySize;
+			m_DictionarySizeCheck = Math.max(m_DictionarySize, 1);
+			m_OutWindow.Create(Math.max(m_DictionarySizeCheck, (1 << 12)));
+		}
+		return true;
+	}
+	
+	boolean SetLcLpPb(int lc, int lp, int pb)
+	{
+		if (lc > Base.kNumLitContextBitsMax || lp > 4 || pb > Base.kNumPosStatesBitsMax)
+			return false;
+		m_LiteralDecoder.Create(lp, lc);
+		int numPosStates = 1 << pb;
+		m_LenDecoder.Create(numPosStates);
+		m_RepLenDecoder.Create(numPosStates);
+		m_PosStateMask = numPosStates - 1;
+		return true;
+	}
+	
+	void Init() throws IOException
+	{
+		m_OutWindow.Init(false);
+		
+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsMatchDecoders);
+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRep0LongDecoders);
+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepDecoders);
+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG0Decoders);
+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG1Decoders);
+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_IsRepG2Decoders);
+		SevenZip.Compression.RangeCoder.Decoder.InitBitModels(m_PosDecoders);
+		
+		m_LiteralDecoder.Init();
+		int i;
+		for (i = 0; i < Base.kNumLenToPosStates; i++)
+			m_PosSlotDecoder[i].Init();
+		m_LenDecoder.Init();
+		m_RepLenDecoder.Init();
+		m_PosAlignDecoder.Init();
+		m_RangeDecoder.Init();
+	}
+	
+	public boolean Code(java.io.InputStream inStream, java.io.OutputStream outStream,
+			long outSize) throws IOException
+	{
+		m_RangeDecoder.SetStream(inStream);
+		m_OutWindow.SetStream(outStream);
+		Init();
+		
+		int state = Base.StateInit();
+		int rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
+		
+		long nowPos64 = 0;
+		byte prevByte = 0;
+		while (outSize < 0 || nowPos64 < outSize)
+		{
+			int posState = (int)nowPos64 & m_PosStateMask;
+			if (m_RangeDecoder.DecodeBit(m_IsMatchDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0)
+			{
+				LiteralDecoder.Decoder2 decoder2 = m_LiteralDecoder.GetDecoder((int)nowPos64, prevByte);
+				if (!Base.StateIsCharState(state))
+					prevByte = decoder2.DecodeWithMatchByte(m_RangeDecoder, m_OutWindow.GetByte(rep0));
+				else
+					prevByte = decoder2.DecodeNormal(m_RangeDecoder);
+				m_OutWindow.PutByte(prevByte);
+				state = Base.StateUpdateChar(state);
+				nowPos64++;
+			}
+			else
+			{
+				int len;
+				if (m_RangeDecoder.DecodeBit(m_IsRepDecoders, state) == 1)
+				{
+					len = 0;
+					if (m_RangeDecoder.DecodeBit(m_IsRepG0Decoders, state) == 0)
+					{
+						if (m_RangeDecoder.DecodeBit(m_IsRep0LongDecoders, (state << Base.kNumPosStatesBitsMax) + posState) == 0)
+						{
+							state = Base.StateUpdateShortRep(state);
+							len = 1;
+						}
+					}
+					else
+					{
+						int distance;
+						if (m_RangeDecoder.DecodeBit(m_IsRepG1Decoders, state) == 0)
+							distance = rep1;
+						else
+						{
+							if (m_RangeDecoder.DecodeBit(m_IsRepG2Decoders, state) == 0)
+								distance = rep2;
+							else
+							{
+								distance = rep3;
+								rep3 = rep2;
+							}
+							rep2 = rep1;
+						}
+						rep1 = rep0;
+						rep0 = distance;
+					}
+					if (len == 0)
+					{
+						len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
+						state = Base.StateUpdateRep(state);
+					}
+				}
+				else
+				{
+					rep3 = rep2;
+					rep2 = rep1;
+					rep1 = rep0;
+					len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
+					state = Base.StateUpdateMatch(state);
+					int posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
+					if (posSlot >= Base.kStartPosModelIndex)
+					{
+						int numDirectBits = (posSlot >> 1) - 1;
+						rep0 = ((2 | (posSlot & 1)) << numDirectBits);
+						if (posSlot < Base.kEndPosModelIndex)
+							rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
+									rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
+						else
+						{
+							rep0 += (m_RangeDecoder.DecodeDirectBits(
+									numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
+							rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
+							if (rep0 < 0)
+							{
+								if (rep0 == -1)
+									break;
+								return false;
+							}
+						}
+					}
+					else
+						rep0 = posSlot;
+				}
+				if (rep0 >= nowPos64 || rep0 >= m_DictionarySizeCheck)
+				{
+					// m_OutWindow.Flush();
+					return false;
+				}
+				m_OutWindow.CopyBlock(rep0, len);
+				nowPos64 += len;
+				prevByte = m_OutWindow.GetByte(0);
+			}
+		}
+		m_OutWindow.Flush();
+		m_OutWindow.ReleaseStream();
+		m_RangeDecoder.ReleaseStream();
+		return true;
+	}
+	
+	public boolean SetDecoderProperties(byte[] properties)
+	{
+		if (properties.length < 5)
+			return false;
+		int val = properties[0] & 0xFF;
+		int lc = val % 9;
+		int remainder = val / 9;
+		int lp = remainder % 5;
+		int pb = remainder / 5;
+		int dictionarySize = 0;
+		for (int i = 0; i < 4; i++)
+			dictionarySize += ((int)(properties[1 + i]) & 0xFF) << (i * 8);
+		if (!SetLcLpPb(lc, lp, pb))
+			return false;
+		return SetDictionarySize(dictionarySize);
+	}
+}

Added: trunk/lzma/Java/SevenZip/Compression/LZMA/Encoder.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/LZMA/Encoder.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/LZMA/Encoder.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,1416 @@
+package SevenZip.Compression.LZMA;
+
+import SevenZip.Compression.RangeCoder.BitTreeEncoder;
+import SevenZip.Compression.LZMA.Base;
+import SevenZip.Compression.LZ.BinTree;
+import SevenZip.ICodeProgress;
+import java.io.IOException;
+
+public class Encoder
+{
+	public static final int EMatchFinderTypeBT2 = 0;
+	public static final int EMatchFinderTypeBT4 = 1;
+
+
+
+
+	static final int kIfinityPrice = 0xFFFFFFF;
+
+	static byte[] g_FastPos = new byte[1 << 11];
+
+	static
+	{
+		int kFastSlots = 22;
+		int c = 2;
+		g_FastPos[0] = 0;
+		g_FastPos[1] = 1;
+		for (int slotFast = 2; slotFast < kFastSlots; slotFast++)
+		{
+			int k = (1 << ((slotFast >> 1) - 1));
+			for (int j = 0; j < k; j++, c++)
+				g_FastPos[c] = (byte)slotFast;
+		}
+	}
+
+	static int GetPosSlot(int pos)
+	{
+		if (pos < (1 << 11))
+			return g_FastPos[pos];
+		if (pos < (1 << 21))
+			return (g_FastPos[pos >> 10] + 20);
+		return (g_FastPos[pos >> 20] + 40);
+	}
+
+	static int GetPosSlot2(int pos)
+	{
+		if (pos < (1 << 17))
+			return (g_FastPos[pos >> 6] + 12);
+		if (pos < (1 << 27))
+			return (g_FastPos[pos >> 16] + 32);
+		return (g_FastPos[pos >> 26] + 52);
+	}
+
+	int _state = Base.StateInit();
+	byte _previousByte;
+	int[] _repDistances = new int[Base.kNumRepDistances];
+
+	void BaseInit()
+	{
+		_state = Base.StateInit();
+		_previousByte = 0;
+		for (int i = 0; i < Base.kNumRepDistances; i++)
+			_repDistances[i] = 0;
+	}
+
+	static final int kDefaultDictionaryLogSize = 22;
+	static final int kNumFastBytesDefault = 0x20;
+
+	class LiteralEncoder
+	{
+		class Encoder2
+		{
+			short[] m_Encoders = new short[0x300];
+
+			public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); }
+
+
+
+			public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException
+			{
+				int context = 1;
+				for (int i = 7; i >= 0; i--)
+				{
+					int bit = ((symbol >> i) & 1);
+					rangeEncoder.Encode(m_Encoders, context, bit);
+					context = (context << 1) | bit;
+				}
+			}
+
+			public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException
+			{
+				int context = 1;
+				boolean same = true;
+				for (int i = 7; i >= 0; i--)
+				{
+					int bit = ((symbol >> i) & 1);
+					int state = context;
+					if (same)
+					{
+						int matchBit = ((matchByte >> i) & 1);
+						state += ((1 + matchBit) << 8);
+						same = (matchBit == bit);
+					}
+					rangeEncoder.Encode(m_Encoders, state, bit);
+					context = (context << 1) | bit;
+				}
+			}
+
+			public int GetPrice(boolean matchMode, byte matchByte, byte symbol)
+			{
+				int price = 0;
+				int context = 1;
+				int i = 7;
+				if (matchMode)
+				{
+					for (; i >= 0; i--)
+					{
+						int matchBit = (matchByte >> i) & 1;
+						int bit = (symbol >> i) & 1;
+						price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit);
+						context = (context << 1) | bit;
+						if (matchBit != bit)
+						{
+							i--;
+							break;
+						}
+					}
+				}
+				for (; i >= 0; i--)
+				{
+					int bit = (symbol >> i) & 1;
+					price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit);
+					context = (context << 1) | bit;
+				}
+				return price;
+			}
+		}
+
+		Encoder2[] m_Coders;
+		int m_NumPrevBits;
+		int m_NumPosBits;
+		int m_PosMask;
+
+		public void Create(int numPosBits, int numPrevBits)
+		{
+			if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
+				return;
+			m_NumPosBits = numPosBits;
+			m_PosMask = (1 << numPosBits) - 1;
+			m_NumPrevBits = numPrevBits;
+			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
+			m_Coders = new Encoder2[numStates];
+			for (int i = 0; i < numStates; i++)
+				m_Coders[i] = new Encoder2();
+		}
+
+		public void Init()
+		{
+			int numStates = 1 << (m_NumPrevBits + m_NumPosBits);
+			for (int i = 0; i < numStates; i++)
+				m_Coders[i].Init();
+		}
+
+		public Encoder2 GetSubCoder(int pos, byte prevByte)
+		{ return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; }
+	}
+
+	class LenEncoder
+	{
+		short[] _choice = new short[2];
+		BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
+		BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax];
+		BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits);
+
+
+		public LenEncoder()
+		{
+			for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)
+			{
+				_lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits);
+				_midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits);
+			}
+		}
+
+		public void Init(int numPosStates)
+		{
+			SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice);
+
+			for (int posState = 0; posState < numPosStates; posState++)
+			{
+				_lowCoder[posState].Init();
+				_midCoder[posState].Init();
+			}
+			_highCoder.Init();
+		}
+
+		public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException
+		{
+			if (symbol < Base.kNumLowLenSymbols)
+			{
+				rangeEncoder.Encode(_choice, 0, 0);
+				_lowCoder[posState].Encode(rangeEncoder, symbol);
+			}
+			else
+			{
+				symbol -= Base.kNumLowLenSymbols;
+				rangeEncoder.Encode(_choice, 0, 1);
+				if (symbol < Base.kNumMidLenSymbols)
+				{
+					rangeEncoder.Encode(_choice, 1, 0);
+					_midCoder[posState].Encode(rangeEncoder, symbol);
+				}
+				else
+				{
+					rangeEncoder.Encode(_choice, 1, 1);
+					_highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
+				}
+			}
+		}
+
+		public void SetPrices(int posState, int numSymbols, int[] prices, int st)
+		{
+			int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]);
+			int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]);
+			int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]);
+			int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]);
+			int i = 0;
+			for (i = 0; i < Base.kNumLowLenSymbols; i++)
+			{
+				if (i >= numSymbols)
+					return;
+				prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
+			}
+			for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)
+			{
+				if (i >= numSymbols)
+					return;
+				prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);
+			}
+			for (; i < numSymbols; i++)
+				prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);
+		}
+	};
+
+	public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
+
+	class LenPriceTableEncoder extends LenEncoder
+	{
+		int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax];
+		int _tableSize;
+		int[] _counters = new int[Base.kNumPosStatesEncodingMax];
+
+		public void SetTableSize(int tableSize) { _tableSize = tableSize; }
+
+		public int GetPrice(int symbol, int posState)
+		{
+			return _prices[posState * Base.kNumLenSymbols + symbol];
+		}
+
+		void UpdateTable(int posState)
+		{
+			SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);
+			_counters[posState] = _tableSize;
+		}
+
+		public void UpdateTables(int numPosStates)
+		{
+			for (int posState = 0; posState < numPosStates; posState++)
+				UpdateTable(posState);
+		}
+
+		public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException
+		{
+			super.Encode(rangeEncoder, symbol, posState);
+			if (--_counters[posState] == 0)
+				UpdateTable(posState);
+		}
+	}
+
+	static final int kNumOpts = 1 << 12;
+	class Optimal
+	{
+		public int State;
+
+		public boolean Prev1IsChar;
+		public boolean Prev2;
+
+		public int PosPrev2;
+		public int BackPrev2;
+
+		public int Price;
+		public int PosPrev;
+		public int BackPrev;
+
+		public int Backs0;
+		public int Backs1;
+		public int Backs2;
+		public int Backs3;
+
+		public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; }
+		public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
+		public boolean IsShortRep() { return (BackPrev == 0); }
+	};
+	Optimal[] _optimum = new Optimal[kNumOpts];
+	SevenZip.Compression.LZ.BinTree _matchFinder = null;
+	SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder();
+
+	short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax];
+	short[] _isRep = new short[Base.kNumStates];
+	short[] _isRepG0 = new short[Base.kNumStates];
+	short[] _isRepG1 = new short[Base.kNumStates];
+	short[] _isRepG2 = new short[Base.kNumStates];
+	short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax];
+
+	BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits
+
+	short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex];
+	BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits);
+
+	LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
+	LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
+
+	LiteralEncoder _literalEncoder = new LiteralEncoder();
+
+	int[] _matchDistances = new int[Base.kMatchMaxLen*2+2];
+
+	int _numFastBytes = kNumFastBytesDefault;
+	int _longestMatchLength;
+	int _numDistancePairs;
+
+	int _additionalOffset;
+
+	int _optimumEndIndex;
+	int _optimumCurrentIndex;
+
+	boolean _longestMatchWasFound;
+
+	int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)];
+	int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits];
+	int[] _alignPrices = new int[Base.kAlignTableSize];
+	int _alignPriceCount;
+
+	int _distTableSize = (kDefaultDictionaryLogSize * 2);
+
+	int _posStateBits = 2;
+	int _posStateMask = (4 - 1);
+	int _numLiteralPosStateBits = 0;
+	int _numLiteralContextBits = 3;
+
+	int _dictionarySize = (1 << kDefaultDictionaryLogSize);
+	int _dictionarySizePrev = -1;
+	int _numFastBytesPrev = -1;
+
+	long nowPos64;
+	boolean _finished;
+	java.io.InputStream _inStream;
+
+	int _matchFinderType = EMatchFinderTypeBT4;
+	boolean _writeEndMark = false;
+
+	boolean _needReleaseMFStream = false;
+
+	void Create()
+	{
+		if (_matchFinder == null)
+		{
+			SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree();
+			int numHashBytes = 4;
+			if (_matchFinderType == EMatchFinderTypeBT2)
+				numHashBytes = 2;
+			bt.SetType(numHashBytes);
+			_matchFinder = bt;
+		}
+		_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
+
+		if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
+			return;
+		_matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);
+		_dictionarySizePrev = _dictionarySize;
+		_numFastBytesPrev = _numFastBytes;
+	}
+
+	public Encoder()
+	{
+		for (int i = 0; i < kNumOpts; i++)
+			_optimum[i] = new Optimal();
+		for (int i = 0; i < Base.kNumLenToPosStates; i++)
+			_posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits);
+	}
+
+	void SetWriteEndMarkerMode(boolean writeEndMarker)
+	{
+		_writeEndMark = writeEndMarker;
+	}
+
+	void Init()
+	{
+		BaseInit();
+		_rangeEncoder.Init();
+
+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch);
+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long);
+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep);
+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0);
+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1);
+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2);
+		SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders);
+
+
+
+
+
+
+
+		_literalEncoder.Init();
+		for (int i = 0; i < Base.kNumLenToPosStates; i++)
+			_posSlotEncoder[i].Init();
+
+
+
+		_lenEncoder.Init(1 << _posStateBits);
+		_repMatchLenEncoder.Init(1 << _posStateBits);
+
+		_posAlignEncoder.Init();
+
+		_longestMatchWasFound = false;
+		_optimumEndIndex = 0;
+		_optimumCurrentIndex = 0;
+		_additionalOffset = 0;
+	}
+
+	int ReadMatchDistances() throws java.io.IOException
+	{
+		int lenRes = 0;
+		_numDistancePairs = _matchFinder.GetMatches(_matchDistances);
+		if (_numDistancePairs > 0)
+		{
+			lenRes = _matchDistances[_numDistancePairs - 2];
+			if (lenRes == _numFastBytes)
+				lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1],
+					Base.kMatchMaxLen - lenRes);
+		}
+		_additionalOffset++;
+		return lenRes;
+	}
+
+	void MovePos(int num) throws java.io.IOException
+	{
+		if (num > 0)
+		{
+			_matchFinder.Skip(num);
+			_additionalOffset += num;
+		}
+	}
+
+	int GetRepLen1Price(int state, int posState)
+	{
+		return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) +
+				SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);
+	}
+
+	int GetPureRepPrice(int repIndex, int state, int posState)
+	{
+		int price;
+		if (repIndex == 0)
+		{
+			price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]);
+			price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]);
+		}
+		else
+		{
+			price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]);
+			if (repIndex == 1)
+				price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]);
+			else
+			{
+				price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]);
+				price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2);
+			}
+		}
+		return price;
+	}
+
+	int GetRepPrice(int repIndex, int len, int state, int posState)
+	{
+		int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
+		return price + GetPureRepPrice(repIndex, state, posState);
+	}
+
+	int GetPosLenPrice(int pos, int len, int posState)
+	{
+		int price;
+		int lenToPosState = Base.GetLenToPosState(len);
+		if (pos < Base.kNumFullDistances)
+			price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos];
+		else
+			price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +
+				_alignPrices[pos & Base.kAlignMask];
+		return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
+	}
+
+	int Backward(int cur)
+	{
+		_optimumEndIndex = cur;
+		int posMem = _optimum[cur].PosPrev;
+		int backMem = _optimum[cur].BackPrev;
+		do
+		{
+			if (_optimum[cur].Prev1IsChar)
+			{
+				_optimum[posMem].MakeAsChar();
+				_optimum[posMem].PosPrev = posMem - 1;
+				if (_optimum[cur].Prev2)
+				{
+					_optimum[posMem - 1].Prev1IsChar = false;
+					_optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
+					_optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
+				}
+			}
+			int posPrev = posMem;
+			int backCur = backMem;
+
+			backMem = _optimum[posPrev].BackPrev;
+			posMem = _optimum[posPrev].PosPrev;
+
+			_optimum[posPrev].BackPrev = backCur;
+			_optimum[posPrev].PosPrev = cur;
+			cur = posPrev;
+		}
+		while (cur > 0);
+		backRes = _optimum[0].BackPrev;
+		_optimumCurrentIndex = _optimum[0].PosPrev;
+		return _optimumCurrentIndex;
+	}
+
+	int[] reps = new int[Base.kNumRepDistances];
+	int[] repLens = new int[Base.kNumRepDistances];
+	int backRes;
+
+	int GetOptimum(int position) throws IOException
+	{
+		if (_optimumEndIndex != _optimumCurrentIndex)
+		{
+			int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
+			backRes = _optimum[_optimumCurrentIndex].BackPrev;
+			_optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
+			return lenRes;
+		}
+		_optimumCurrentIndex = _optimumEndIndex = 0;
+
+		int lenMain, numDistancePairs;
+		if (!_longestMatchWasFound)
+		{
+			lenMain = ReadMatchDistances();
+		}
+		else
+		{
+			lenMain = _longestMatchLength;
+			_longestMatchWasFound = false;
+		}
+		numDistancePairs = _numDistancePairs;
+
+		int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
+		if (numAvailableBytes < 2)
+		{
+			backRes = -1;
+			return 1;
+		}
+		if (numAvailableBytes > Base.kMatchMaxLen)
+			numAvailableBytes = Base.kMatchMaxLen;
+
+		int repMaxIndex = 0;
+		int i;
+		for (i = 0; i < Base.kNumRepDistances; i++)
+		{
+			reps[i] = _repDistances[i];
+			repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
+			if (repLens[i] > repLens[repMaxIndex])
+				repMaxIndex = i;
+		}
+		if (repLens[repMaxIndex] >= _numFastBytes)
+		{
+			backRes = repMaxIndex;
+			int lenRes = repLens[repMaxIndex];
+			MovePos(lenRes - 1);
+			return lenRes;
+		}
+
+		if (lenMain >= _numFastBytes)
+		{
+			backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;
+			MovePos(lenMain - 1);
+			return lenMain;
+		}
+
+		byte currentByte = _matchFinder.GetIndexByte(0 - 1);
+		byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1);
+
+		if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
+		{
+			backRes = -1;
+			return 1;
+		}
+
+		_optimum[0].State = _state;
+
+		int posState = (position & _posStateMask);
+
+		_optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) +
+				_literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte);
+		_optimum[1].MakeAsChar();
+
+		int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]);
+		int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]);
+
+		if (matchByte == currentByte)
+		{
+			int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
+			if (shortRepPrice < _optimum[1].Price)
+			{
+				_optimum[1].Price = shortRepPrice;
+				_optimum[1].MakeAsShortRep();
+			}
+		}
+
+		int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
+
+		if (lenEnd < 2)
+		{
+			backRes = _optimum[1].BackPrev;
+			return 1;
+		}
+
+		_optimum[1].PosPrev = 0;
+
+		_optimum[0].Backs0 = reps[0];
+		_optimum[0].Backs1 = reps[1];
+		_optimum[0].Backs2 = reps[2];
+		_optimum[0].Backs3 = reps[3];
+
+		int len = lenEnd;
+		do
+			_optimum[len--].Price = kIfinityPrice;
+		while (len >= 2);
+
+		for (i = 0; i < Base.kNumRepDistances; i++)
+		{
+			int repLen = repLens[i];
+			if (repLen < 2)
+				continue;
+			int price = repMatchPrice + GetPureRepPrice(i, _state, posState);
+			do
+			{
+				int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
+				Optimal optimum = _optimum[repLen];
+				if (curAndLenPrice < optimum.Price)
+				{
+					optimum.Price = curAndLenPrice;
+					optimum.PosPrev = 0;
+					optimum.BackPrev = i;
+					optimum.Prev1IsChar = false;
+				}
+			}
+			while (--repLen >= 2);
+		}
+
+		int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]);
+
+		len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+		if (len <= lenMain)
+		{
+			int offs = 0;
+			while (len > _matchDistances[offs])
+				offs += 2;
+			for (; ; len++)
+			{
+				int distance = _matchDistances[offs + 1];
+				int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
+				Optimal optimum = _optimum[len];
+				if (curAndLenPrice < optimum.Price)
+				{
+					optimum.Price = curAndLenPrice;
+					optimum.PosPrev = 0;
+					optimum.BackPrev = distance + Base.kNumRepDistances;
+					optimum.Prev1IsChar = false;
+				}
+				if (len == _matchDistances[offs])
+				{
+					offs += 2;
+					if (offs == numDistancePairs)
+						break;
+				}
+			}
+		}
+
+		int cur = 0;
+
+		while (true)
+		{
+			cur++;
+			if (cur == lenEnd)
+				return Backward(cur);
+			int newLen = ReadMatchDistances();
+			numDistancePairs = _numDistancePairs;
+			if (newLen >= _numFastBytes)
+			{
+
+				_longestMatchLength = newLen;
+				_longestMatchWasFound = true;
+				return Backward(cur);
+			}
+			position++;
+			int posPrev = _optimum[cur].PosPrev;
+			int state;
+			if (_optimum[cur].Prev1IsChar)
+			{
+				posPrev--;
+				if (_optimum[cur].Prev2)
+				{
+					state = _optimum[_optimum[cur].PosPrev2].State;
+					if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
+						state = Base.StateUpdateRep(state);
+					else
+						state = Base.StateUpdateMatch(state);
+				}
+				else
+					state = _optimum[posPrev].State;
+				state = Base.StateUpdateChar(state);
+			}
+			else
+				state = _optimum[posPrev].State;
+			if (posPrev == cur - 1)
+			{
+				if (_optimum[cur].IsShortRep())
+					state = Base.StateUpdateShortRep(state);
+				else
+					state = Base.StateUpdateChar(state);
+			}
+			else
+			{
+				int pos;
+				if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)
+				{
+					posPrev = _optimum[cur].PosPrev2;
+					pos = _optimum[cur].BackPrev2;
+					state = Base.StateUpdateRep(state);
+				}
+				else
+				{
+					pos = _optimum[cur].BackPrev;
+					if (pos < Base.kNumRepDistances)
+						state = Base.StateUpdateRep(state);
+					else
+						state = Base.StateUpdateMatch(state);
+				}
+				Optimal opt = _optimum[posPrev];
+				if (pos < Base.kNumRepDistances)
+				{
+					if (pos == 0)
+					{
+						reps[0] = opt.Backs0;
+						reps[1] = opt.Backs1;
+						reps[2] = opt.Backs2;
+						reps[3] = opt.Backs3;
+					}
+					else if (pos == 1)
+					{
+						reps[0] = opt.Backs1;
+						reps[1] = opt.Backs0;
+						reps[2] = opt.Backs2;
+						reps[3] = opt.Backs3;
+					}
+					else if (pos == 2)
+					{
+						reps[0] = opt.Backs2;
+						reps[1] = opt.Backs0;
+						reps[2] = opt.Backs1;
+						reps[3] = opt.Backs3;
+					}
+					else
+					{
+						reps[0] = opt.Backs3;
+						reps[1] = opt.Backs0;
+						reps[2] = opt.Backs1;
+						reps[3] = opt.Backs2;
+					}
+				}
+				else
+				{
+					reps[0] = (pos - Base.kNumRepDistances);
+					reps[1] = opt.Backs0;
+					reps[2] = opt.Backs1;
+					reps[3] = opt.Backs2;
+				}
+			}
+			_optimum[cur].State = state;
+			_optimum[cur].Backs0 = reps[0];
+			_optimum[cur].Backs1 = reps[1];
+			_optimum[cur].Backs2 = reps[2];
+			_optimum[cur].Backs3 = reps[3];
+			int curPrice = _optimum[cur].Price;
+
+			currentByte = _matchFinder.GetIndexByte(0 - 1);
+			matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1);
+
+			posState = (position & _posStateMask);
+
+			int curAnd1Price = curPrice +
+				SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) +
+				_literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).
+				GetPrice(!Base.StateIsCharState(state), matchByte, currentByte);
+
+			Optimal nextOptimum = _optimum[cur + 1];
+
+			boolean nextIsChar = false;
+			if (curAnd1Price < nextOptimum.Price)
+			{
+				nextOptimum.Price = curAnd1Price;
+				nextOptimum.PosPrev = cur;
+				nextOptimum.MakeAsChar();
+				nextIsChar = true;
+			}
+
+			matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]);
+			repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]);
+
+			if (matchByte == currentByte &&
+				!(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
+			{
+				int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
+				if (shortRepPrice <= nextOptimum.Price)
+				{
+					nextOptimum.Price = shortRepPrice;
+					nextOptimum.PosPrev = cur;
+					nextOptimum.MakeAsShortRep();
+					nextIsChar = true;
+				}
+			}
+
+			int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
+			numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull);
+			numAvailableBytes = numAvailableBytesFull;
+
+			if (numAvailableBytes < 2)
+				continue;
+			if (numAvailableBytes > _numFastBytes)
+				numAvailableBytes = _numFastBytes;
+			if (!nextIsChar && matchByte != currentByte)
+			{
+				// try Literal + rep0
+				int t = Math.min(numAvailableBytesFull - 1, _numFastBytes);
+				int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);
+				if (lenTest2 >= 2)
+				{
+					int state2 = Base.StateUpdateChar(state);
+
+					int posStateNext = (position + 1) & _posStateMask;
+					int nextRepMatchPrice = curAnd1Price +
+						SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) +
+						SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]);
+					{
+						int offset = cur + 1 + lenTest2;
+						while (lenEnd < offset)
+							_optimum[++lenEnd].Price = kIfinityPrice;
+						int curAndLenPrice = nextRepMatchPrice + GetRepPrice(
+								0, lenTest2, state2, posStateNext);
+						Optimal optimum = _optimum[offset];
+						if (curAndLenPrice < optimum.Price)
+						{
+							optimum.Price = curAndLenPrice;
+							optimum.PosPrev = cur + 1;
+							optimum.BackPrev = 0;
+							optimum.Prev1IsChar = true;
+							optimum.Prev2 = false;
+						}
+					}
+				}
+			}
+
+			int startLen = 2; // speed optimization 
+
+			for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)
+			{
+				int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
+				if (lenTest < 2)
+					continue;
+				int lenTestTemp = lenTest;
+				do
+				{
+					while (lenEnd < cur + lenTest)
+						_optimum[++lenEnd].Price = kIfinityPrice;
+					int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
+					Optimal optimum = _optimum[cur + lenTest];
+					if (curAndLenPrice < optimum.Price)
+					{
+						optimum.Price = curAndLenPrice;
+						optimum.PosPrev = cur;
+						optimum.BackPrev = repIndex;
+						optimum.Prev1IsChar = false;
+					}
+				}
+				while (--lenTest >= 2);
+				lenTest = lenTestTemp;
+
+				if (repIndex == 0)
+					startLen = lenTest + 1;
+
+				// if (_maxMode)
+				if (lenTest < numAvailableBytesFull)
+				{
+					int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
+					int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t);
+					if (lenTest2 >= 2)
+					{
+						int state2 = Base.StateUpdateRep(state);
+
+						int posStateNext = (position + lenTest) & _posStateMask;
+						int curAndLenCharPrice =
+								repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
+								SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) +
+								_literalEncoder.GetSubCoder(position + lenTest,
+								_matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true,
+								_matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)),
+								_matchFinder.GetIndexByte(lenTest - 1));
+						state2 = Base.StateUpdateChar(state2);
+						posStateNext = (position + lenTest + 1) & _posStateMask;
+						int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]);
+						int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]);
+
+						// for(; lenTest2 >= 2; lenTest2--)
+						{
+							int offset = lenTest + 1 + lenTest2;
+							while (lenEnd < cur + offset)
+								_optimum[++lenEnd].Price = kIfinityPrice;
+							int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+							Optimal optimum = _optimum[cur + offset];
+							if (curAndLenPrice < optimum.Price)
+							{
+								optimum.Price = curAndLenPrice;
+								optimum.PosPrev = cur + lenTest + 1;
+								optimum.BackPrev = 0;
+								optimum.Prev1IsChar = true;
+								optimum.Prev2 = true;
+								optimum.PosPrev2 = cur;
+								optimum.BackPrev2 = repIndex;
+							}
+						}
+					}
+				}
+			}
+
+			if (newLen > numAvailableBytes)
+			{
+				newLen = numAvailableBytes;
+				for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ;
+				_matchDistances[numDistancePairs] = newLen;
+				numDistancePairs += 2;
+			}
+			if (newLen >= startLen)
+			{
+				normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]);
+				while (lenEnd < cur + newLen)
+					_optimum[++lenEnd].Price = kIfinityPrice;
+
+				int offs = 0;
+				while (startLen > _matchDistances[offs])
+					offs += 2;
+
+				for (int lenTest = startLen; ; lenTest++)
+				{
+					int curBack = _matchDistances[offs + 1];
+					int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
+					Optimal optimum = _optimum[cur + lenTest];
+					if (curAndLenPrice < optimum.Price)
+					{
+						optimum.Price = curAndLenPrice;
+						optimum.PosPrev = cur;
+						optimum.BackPrev = curBack + Base.kNumRepDistances;
+						optimum.Prev1IsChar = false;
+					}
+
+					if (lenTest == _matchDistances[offs])
+					{
+						if (lenTest < numAvailableBytesFull)
+						{
+							int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
+							int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t);
+							if (lenTest2 >= 2)
+							{
+								int state2 = Base.StateUpdateMatch(state);
+
+								int posStateNext = (position + lenTest) & _posStateMask;
+								int curAndLenCharPrice = curAndLenPrice +
+									SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) +
+									_literalEncoder.GetSubCoder(position + lenTest,
+									_matchFinder.GetIndexByte(lenTest - 1 - 1)).
+									GetPrice(true,
+									_matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1),
+									_matchFinder.GetIndexByte(lenTest - 1));
+								state2 = Base.StateUpdateChar(state2);
+								posStateNext = (position + lenTest + 1) & _posStateMask;
+								int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]);
+								int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]);
+
+								int offset = lenTest + 1 + lenTest2;
+								while (lenEnd < cur + offset)
+									_optimum[++lenEnd].Price = kIfinityPrice;
+								curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+								optimum = _optimum[cur + offset];
+								if (curAndLenPrice < optimum.Price)
+								{
+									optimum.Price = curAndLenPrice;
+									optimum.PosPrev = cur + lenTest + 1;
+									optimum.BackPrev = 0;
+									optimum.Prev1IsChar = true;
+									optimum.Prev2 = true;
+									optimum.PosPrev2 = cur;
+									optimum.BackPrev2 = curBack + Base.kNumRepDistances;
+								}
+							}
+						}
+						offs += 2;
+						if (offs == numDistancePairs)
+							break;
+					}
+				}
+			}
+		}
+	}
+
+	boolean ChangePair(int smallDist, int bigDist)
+	{
+		int kDif = 7;
+		return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif));
+	}
+
+	void WriteEndMarker(int posState) throws IOException
+	{
+		if (!_writeEndMark)
+			return;
+
+		_rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1);
+		_rangeEncoder.Encode(_isRep, _state, 0);
+		_state = Base.StateUpdateMatch(_state);
+		int len = Base.kMatchMinLen;
+		_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+		int posSlot = (1 << Base.kNumPosSlotBits) - 1;
+		int lenToPosState = Base.GetLenToPosState(len);
+		_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
+		int footerBits = 30;
+		int posReduced = (1 << footerBits) - 1;
+		_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
+		_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
+	}
+
+	void Flush(int nowPos) throws IOException
+	{
+		ReleaseMFStream();
+		WriteEndMarker(nowPos & _posStateMask);
+		_rangeEncoder.FlushData();
+		_rangeEncoder.FlushStream();
+	}
+
+	public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException
+	{
+		inSize[0] = 0;
+		outSize[0] = 0;
+		finished[0] = true;
+
+		if (_inStream != null)
+		{
+			_matchFinder.SetStream(_inStream);
+			_matchFinder.Init();
+			_needReleaseMFStream = true;
+			_inStream = null;
+		}
+
+		if (_finished)
+			return;
+		_finished = true;
+
+
+		long progressPosValuePrev = nowPos64;
+		if (nowPos64 == 0)
+		{
+			if (_matchFinder.GetNumAvailableBytes() == 0)
+			{
+				Flush((int)nowPos64);
+				return;
+			}
+
+			ReadMatchDistances();
+			int posState = (int)(nowPos64) & _posStateMask;
+			_rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0);
+			_state = Base.StateUpdateChar(_state);
+			byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset);
+			_literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);
+			_previousByte = curByte;
+			_additionalOffset--;
+			nowPos64++;
+		}
+		if (_matchFinder.GetNumAvailableBytes() == 0)
+		{
+			Flush((int)nowPos64);
+			return;
+		}
+		while (true)
+		{
+
+			int len = GetOptimum((int)nowPos64);
+			int pos = backRes;
+			int posState = ((int)nowPos64) & _posStateMask;
+			int complexState = (_state << Base.kNumPosStatesBitsMax) + posState;
+			if (len == 1 && pos == -1)
+			{
+				_rangeEncoder.Encode(_isMatch, complexState, 0);
+				byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset));
+				LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte);
+				if (!Base.StateIsCharState(_state))
+				{
+					byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset));
+					subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
+				}
+				else
+					subCoder.Encode(_rangeEncoder, curByte);
+				_previousByte = curByte;
+				_state = Base.StateUpdateChar(_state);
+			}
+			else
+			{
+				_rangeEncoder.Encode(_isMatch, complexState, 1);
+				if (pos < Base.kNumRepDistances)
+				{
+					_rangeEncoder.Encode(_isRep, _state, 1);
+					if (pos == 0)
+					{
+						_rangeEncoder.Encode(_isRepG0, _state, 0);
+						if (len == 1)
+							_rangeEncoder.Encode(_isRep0Long, complexState, 0);
+						else
+							_rangeEncoder.Encode(_isRep0Long, complexState, 1);
+					}
+					else
+					{
+						_rangeEncoder.Encode(_isRepG0, _state, 1);
+						if (pos == 1)
+							_rangeEncoder.Encode(_isRepG1, _state, 0);
+						else
+						{
+							_rangeEncoder.Encode(_isRepG1, _state, 1);
+							_rangeEncoder.Encode(_isRepG2, _state, pos - 2);
+						}
+					}
+					if (len == 1)
+						_state = Base.StateUpdateShortRep(_state);
+					else
+					{
+						_repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+						_state = Base.StateUpdateRep(_state);
+					}
+					int distance = _repDistances[pos];
+					if (pos != 0)
+					{
+						for (int i = pos; i >= 1; i--)
+							_repDistances[i] = _repDistances[i - 1];
+						_repDistances[0] = distance;
+					}
+				}
+				else
+				{
+					_rangeEncoder.Encode(_isRep, _state, 0);
+					_state = Base.StateUpdateMatch(_state);
+					_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+					pos -= Base.kNumRepDistances;
+					int posSlot = GetPosSlot(pos);
+					int lenToPosState = Base.GetLenToPosState(len);
+					_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
+
+					if (posSlot >= Base.kStartPosModelIndex)
+					{
+						int footerBits = (int)((posSlot >> 1) - 1);
+						int baseVal = ((2 | (posSlot & 1)) << footerBits);
+						int posReduced = pos - baseVal;
+
+						if (posSlot < Base.kEndPosModelIndex)
+							BitTreeEncoder.ReverseEncode(_posEncoders,
+									baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
+						else
+						{
+							_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
+							_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
+							_alignPriceCount++;
+						}
+					}
+					int distance = pos;
+					for (int i = Base.kNumRepDistances - 1; i >= 1; i--)
+						_repDistances[i] = _repDistances[i - 1];
+					_repDistances[0] = distance;
+					_matchPriceCount++;
+				}
+				_previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset);
+			}
+			_additionalOffset -= len;
+			nowPos64 += len;
+			if (_additionalOffset == 0)
+			{
+				// if (!_fastMode)
+				if (_matchPriceCount >= (1 << 7))
+					FillDistancesPrices();
+				if (_alignPriceCount >= Base.kAlignTableSize)
+					FillAlignPrices();
+				inSize[0] = nowPos64;
+				outSize[0] = _rangeEncoder.GetProcessedSizeAdd();
+				if (_matchFinder.GetNumAvailableBytes() == 0)
+				{
+					Flush((int)nowPos64);
+					return;
+				}
+
+				if (nowPos64 - progressPosValuePrev >= (1 << 12))
+				{
+					_finished = false;
+					finished[0] = false;
+					return;
+				}
+			}
+		}
+	}
+
+	void ReleaseMFStream()
+	{
+		if (_matchFinder != null && _needReleaseMFStream)
+		{
+			_matchFinder.ReleaseStream();
+			_needReleaseMFStream = false;
+		}
+	}
+
+	void SetOutStream(java.io.OutputStream outStream)
+	{ _rangeEncoder.SetStream(outStream); }
+	void ReleaseOutStream()
+	{ _rangeEncoder.ReleaseStream(); }
+
+	void ReleaseStreams()
+	{
+		ReleaseMFStream();
+		ReleaseOutStream();
+	}
+
+	void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream,
+			long inSize, long outSize)
+	{
+		_inStream = inStream;
+		_finished = false;
+		Create();
+		SetOutStream(outStream);
+		Init();
+
+		// if (!_fastMode)
+		{
+			FillDistancesPrices();
+			FillAlignPrices();
+		}
+
+		_lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
+		_lenEncoder.UpdateTables(1 << _posStateBits);
+		_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
+		_repMatchLenEncoder.UpdateTables(1 << _posStateBits);
+
+		nowPos64 = 0;
+	}
+
+	long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1];
+	public void Code(java.io.InputStream inStream, java.io.OutputStream outStream,
+			long inSize, long outSize, ICodeProgress progress) throws IOException
+	{
+		_needReleaseMFStream = false;
+		try
+		{
+			SetStreams(inStream, outStream, inSize, outSize);
+			while (true)
+			{
+
+
+
+				CodeOneBlock(processedInSize, processedOutSize, finished);
+				if (finished[0])
+					return;
+				if (progress != null)
+				{
+					progress.SetProgress(processedInSize[0], processedOutSize[0]);
+				}
+			}
+		}
+		finally
+		{
+			ReleaseStreams();
+		}
+	}
+
+	public static final int kPropSize = 5;
+	byte[] properties = new byte[kPropSize];
+
+	public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException
+	{
+		properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
+		for (int i = 0; i < 4; i++)
+			properties[1 + i] = (byte)(_dictionarySize >> (8 * i));
+		outStream.write(properties, 0, kPropSize);
+	}
+
+	int[] tempPrices = new int[Base.kNumFullDistances];
+	int _matchPriceCount;
+
+	void FillDistancesPrices()
+	{
+		for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)
+		{
+			int posSlot = GetPosSlot(i);
+			int footerBits = (int)((posSlot >> 1) - 1);
+			int baseVal = ((2 | (posSlot & 1)) << footerBits);
+			tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders,
+				baseVal - posSlot - 1, footerBits, i - baseVal);
+		}
+
+		for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)
+		{
+			int posSlot;
+			BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
+
+			int st = (lenToPosState << Base.kNumPosSlotBits);
+			for (posSlot = 0; posSlot < _distTableSize; posSlot++)
+				_posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);
+			for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
+				_posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits);
+
+			int st2 = lenToPosState * Base.kNumFullDistances;
+			int i;
+			for (i = 0; i < Base.kStartPosModelIndex; i++)
+				_distancesPrices[st2 + i] = _posSlotPrices[st + i];
+			for (; i < Base.kNumFullDistances; i++)
+				_distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];
+		}
+		_matchPriceCount = 0;
+	}
+
+	void FillAlignPrices()
+	{
+		for (int i = 0; i < Base.kAlignTableSize; i++)
+			_alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
+		_alignPriceCount = 0;
+	}
+
+
+	public boolean SetAlgorithm(int algorithm)
+	{
+		/*
+		_fastMode = (algorithm == 0);
+		_maxMode = (algorithm >= 2);
+		*/
+		return true;
+	}
+
+	public boolean SetDictionarySize(int dictionarySize)
+	{
+		int kDicLogSizeMaxCompress = 29;
+		if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress))
+			return false;
+		_dictionarySize = dictionarySize;
+		int dicLogSize;
+		for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ;
+		_distTableSize = dicLogSize * 2;
+		return true;
+	}
+
+	public boolean SeNumFastBytes(int numFastBytes)
+	{
+		if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
+			return false;
+		_numFastBytes = numFastBytes;
+		return true;
+	}
+
+	public boolean SetMatchFinder(int matchFinderIndex)
+	{
+		if (matchFinderIndex < 0 || matchFinderIndex > 2)
+			return false;
+		int matchFinderIndexPrev = _matchFinderType;
+		_matchFinderType = matchFinderIndex;
+		if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
+		{
+			_dictionarySizePrev = -1;
+			_matchFinder = null;
+		}
+		return true;
+	}
+
+	public boolean SetLcLpPb(int lc, int lp, int pb)
+	{
+		if (
+				lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax ||
+				lc < 0 || lc > Base.kNumLitContextBitsMax ||
+				pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax)
+			return false;
+		_numLiteralPosStateBits = lp;
+		_numLiteralContextBits = lc;
+		_posStateBits = pb;
+		_posStateMask = ((1) << _posStateBits) - 1;
+		return true;
+	}
+
+	public void SetEndMarkerMode(boolean endMarkerMode)
+	{
+		_writeEndMark = endMarkerMode;
+	}
+}
+

Added: trunk/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,55 @@
+package SevenZip.Compression.RangeCoder;
+
+public class BitTreeDecoder
+{
+	short[] Models;
+	int NumBitLevels;
+	
+	public BitTreeDecoder(int numBitLevels)
+	{
+		NumBitLevels = numBitLevels;
+		Models = new short[1 << numBitLevels];
+	}
+	
+	public void Init()
+	{
+		Decoder.InitBitModels(Models);
+	}
+	
+	public int Decode(Decoder rangeDecoder) throws java.io.IOException
+	{
+		int m = 1;
+		for (int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--)
+			m = (m << 1) + rangeDecoder.DecodeBit(Models, m);
+		return m - (1 << NumBitLevels);
+	}
+	
+	public int ReverseDecode(Decoder rangeDecoder) throws java.io.IOException
+	{
+		int m = 1;
+		int symbol = 0;
+		for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+		{
+			int bit = rangeDecoder.DecodeBit(Models, m);
+			m <<= 1;
+			m += bit;
+			symbol |= (bit << bitIndex);
+		}
+		return symbol;
+	}
+	
+	public static int ReverseDecode(short[] Models, int startIndex,
+			Decoder rangeDecoder, int NumBitLevels) throws java.io.IOException
+	{
+		int m = 1;
+		int symbol = 0;
+		for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+		{
+			int bit = rangeDecoder.DecodeBit(Models, startIndex + m);
+			m <<= 1;
+			m += bit;
+			symbol |= (bit << bitIndex);
+		}
+		return symbol;
+	}
+}

Added: trunk/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,99 @@
+package SevenZip.Compression.RangeCoder;
+import java.io.IOException;
+
+public class BitTreeEncoder
+{
+	short[] Models;
+	int NumBitLevels;
+	
+	public BitTreeEncoder(int numBitLevels)
+	{
+		NumBitLevels = numBitLevels;
+		Models = new short[1 << numBitLevels];
+	}
+	
+	public void Init()
+	{
+		Decoder.InitBitModels(Models);
+	}
+	
+	public void Encode(Encoder rangeEncoder, int symbol) throws IOException
+	{
+		int m = 1;
+		for (int bitIndex = NumBitLevels; bitIndex != 0; )
+		{
+			bitIndex--;
+			int bit = (symbol >>> bitIndex) & 1;
+			rangeEncoder.Encode(Models, m, bit);
+			m = (m << 1) | bit;
+		}
+	}
+	
+	public void ReverseEncode(Encoder rangeEncoder, int symbol) throws IOException
+	{
+		int m = 1;
+		for (int  i = 0; i < NumBitLevels; i++)
+		{
+			int bit = symbol & 1;
+			rangeEncoder.Encode(Models, m, bit);
+			m = (m << 1) | bit;
+			symbol >>= 1;
+		}
+	}
+	
+	public int GetPrice(int symbol)
+	{
+		int price = 0;
+		int m = 1;
+		for (int bitIndex = NumBitLevels; bitIndex != 0; )
+		{
+			bitIndex--;
+			int bit = (symbol >>> bitIndex) & 1;
+			price += Encoder.GetPrice(Models[m], bit);
+			m = (m << 1) + bit;
+		}
+		return price;
+	}
+	
+	public int ReverseGetPrice(int symbol)
+	{
+		int price = 0;
+		int m = 1;
+		for (int i = NumBitLevels; i != 0; i--)
+		{
+			int bit = symbol & 1;
+			symbol >>>= 1;
+			price += Encoder.GetPrice(Models[m], bit);
+			m = (m << 1) | bit;
+		}
+		return price;
+	}
+	
+	public static int ReverseGetPrice(short[] Models, int startIndex,
+			int NumBitLevels, int symbol)
+	{
+		int price = 0;
+		int m = 1;
+		for (int i = NumBitLevels; i != 0; i--)
+		{
+			int bit = symbol & 1;
+			symbol >>>= 1;
+			price += Encoder.GetPrice(Models[startIndex + m], bit);
+			m = (m << 1) | bit;
+		}
+		return price;
+	}
+	
+	public static void ReverseEncode(short[] Models, int startIndex,
+			Encoder rangeEncoder, int NumBitLevels, int symbol) throws IOException
+	{
+		int m = 1;
+		for (int i = 0; i < NumBitLevels; i++)
+		{
+			int bit = symbol & 1;
+			rangeEncoder.Encode(Models, startIndex + m, bit);
+			m = (m << 1) | bit;
+			symbol >>= 1;
+		}
+	}
+}

Added: trunk/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/RangeCoder/Decoder.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,88 @@
+package SevenZip.Compression.RangeCoder;
+import java.io.IOException;
+
+public class Decoder
+{
+	static final int kTopMask = ~((1 << 24) - 1);
+	
+	static final int kNumBitModelTotalBits = 11;
+	static final int kBitModelTotal = (1 << kNumBitModelTotalBits);
+	static final int kNumMoveBits = 5;
+	
+	int Range;
+	int Code;
+
+	java.io.InputStream Stream;
+	
+	public final void SetStream(java.io.InputStream stream)
+	{ 
+		Stream = stream; 
+	}
+	
+	public final void ReleaseStream()
+	{ 
+		Stream = null; 
+	}
+	
+	public final void Init() throws IOException
+	{
+		Code = 0;
+		Range = -1;
+		for (int i = 0; i < 5; i++)
+			Code = (Code << 8) | Stream.read();
+	}
+	
+	public final int DecodeDirectBits(int numTotalBits) throws IOException
+	{
+		int result = 0;
+		for (int i = numTotalBits; i != 0; i--)
+		{
+			Range >>>= 1;
+			int t = ((Code - Range) >>> 31);
+			Code -= Range & (t - 1);
+			result = (result << 1) | (1 - t);
+			
+			if ((Range & kTopMask) == 0)
+			{
+				Code = (Code << 8) | Stream.read();
+				Range <<= 8;
+			}
+		}
+		return result;
+	}
+	
+	public int DecodeBit(short []probs, int index) throws IOException
+	{
+		int prob = probs[index];
+		int newBound = (Range >>> kNumBitModelTotalBits) * prob;
+		if ((Code ^ 0x80000000) < (newBound ^ 0x80000000))
+		{
+			Range = newBound;
+			probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits));
+			if ((Range & kTopMask) == 0)
+			{
+				Code = (Code << 8) | Stream.read();
+				Range <<= 8;
+			}
+			return 0;
+		}
+		else
+		{
+			Range -= newBound;
+			Code -= newBound;
+			probs[index] = (short)(prob - ((prob) >>> kNumMoveBits));
+			if ((Range & kTopMask) == 0)
+			{
+				Code = (Code << 8) | Stream.read();
+				Range <<= 8;
+			}
+			return 1;
+		}
+	}
+	
+	public static void InitBitModels(short []probs)
+	{
+		for (int i = 0; i < probs.length; i++)
+			probs[i] = (kBitModelTotal >>> 1);
+	}
+}

Added: trunk/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java
===================================================================
--- trunk/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/Compression/RangeCoder/Encoder.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,151 @@
+package SevenZip.Compression.RangeCoder;
+import java.io.IOException;
+
+public class Encoder
+{
+	static final int kTopMask = ~((1 << 24) - 1);
+	
+	static final int kNumBitModelTotalBits = 11;
+	static final int kBitModelTotal = (1 << kNumBitModelTotalBits);
+	static final int kNumMoveBits = 5;
+	
+	java.io.OutputStream Stream;
+
+	long Low;
+	int Range;
+	int _cacheSize;
+	int _cache;
+	
+	long _position;
+	
+	public void SetStream(java.io.OutputStream stream)
+	{
+		Stream = stream;
+	}
+	
+	public void ReleaseStream()
+	{
+		Stream = null;
+	}
+	
+	public void Init()
+	{
+		_position = 0;
+		Low = 0;
+		Range = -1;
+		_cacheSize = 1;
+		_cache = 0;
+	}
+	
+	public void FlushData() throws IOException
+	{
+		for (int i = 0; i < 5; i++)
+			ShiftLow();
+	}
+	
+	public void FlushStream() throws IOException
+	{
+		Stream.flush();
+	}
+	
+	public void ShiftLow() throws IOException
+	{
+		int LowHi = (int)(Low >>> 32);
+		if (LowHi != 0 || Low < 0xFF000000L)
+		{
+			_position += _cacheSize;
+			int temp = _cache;
+			do
+			{
+				Stream.write(temp + LowHi);
+				temp = 0xFF;
+			}
+			while(--_cacheSize != 0);
+			_cache = (((int)Low) >>> 24);
+		}
+		_cacheSize++;
+		Low = (Low & 0xFFFFFF) << 8;
+	}
+	
+	public void EncodeDirectBits(int v, int numTotalBits) throws IOException
+	{
+		for (int i = numTotalBits - 1; i >= 0; i--)
+		{
+			Range >>>= 1;
+			if (((v >>> i) & 1) == 1)
+				Low += Range;
+			if ((Range & Encoder.kTopMask) == 0)
+			{
+				Range <<= 8;
+				ShiftLow();
+			}
+		}
+	}
+	
+	
+	public long GetProcessedSizeAdd()
+	{
+		return _cacheSize + _position + 4;
+	}
+	
+	
+	
+	static final int kNumMoveReducingBits = 2;
+	public static final int kNumBitPriceShiftBits = 6;
+	
+	public static void InitBitModels(short []probs)
+	{
+		for (int i = 0; i < probs.length; i++)
+			probs[i] = (kBitModelTotal >>> 1);
+	}
+	
+	public void Encode(short []probs, int index, int symbol) throws IOException
+	{
+		int prob = probs[index];
+		int newBound = (Range >>> kNumBitModelTotalBits) * prob;
+		if (symbol == 0)
+		{
+			Range = newBound;
+			probs[index] = (short)(prob + ((kBitModelTotal - prob) >>> kNumMoveBits));
+		}
+		else
+		{
+			Low += (newBound & 0xFFFFFFFFL);
+			Range -= newBound;
+			probs[index] = (short)(prob - ((prob) >>> kNumMoveBits));
+		}
+		if ((Range & kTopMask) == 0)
+		{
+			Range <<= 8;
+			ShiftLow();
+		}
+	}
+	
+	private static int[] ProbPrices = new int[kBitModelTotal >>> kNumMoveReducingBits];
+	
+	static
+	{
+		int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
+		for (int i = kNumBits - 1; i >= 0; i--)
+		{
+			int start = 1 << (kNumBits - i - 1);
+			int end = 1 << (kNumBits - i);
+			for (int j = start; j < end; j++)
+				ProbPrices[j] = (i << kNumBitPriceShiftBits) +
+						(((end - j) << kNumBitPriceShiftBits) >>> (kNumBits - i - 1));
+		}
+	}
+	
+	static public int GetPrice(int Prob, int symbol)
+	{
+		return ProbPrices[(((Prob - symbol) ^ ((-symbol))) & (kBitModelTotal - 1)) >>> kNumMoveReducingBits];
+	}
+	static public int GetPrice0(int Prob)
+	{ 
+		return ProbPrices[Prob >>> kNumMoveReducingBits]; 
+	}
+	static public int GetPrice1(int Prob)
+	{ 
+		return ProbPrices[(kBitModelTotal - Prob) >>> kNumMoveReducingBits]; 
+	}
+}

Added: trunk/lzma/Java/SevenZip/ICodeProgress.java
===================================================================
--- trunk/lzma/Java/SevenZip/ICodeProgress.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/ICodeProgress.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,6 @@
+package SevenZip;
+
+public interface ICodeProgress
+{
+	public void SetProgress(long inSize, long outSize);
+}

Added: trunk/lzma/Java/SevenZip/LzmaAlone.java
===================================================================
--- trunk/lzma/Java/SevenZip/LzmaAlone.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/LzmaAlone.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,253 @@
+package SevenZip;
+
+public class LzmaAlone
+{
+	static public class CommandLine
+	{
+		public static final int kEncode = 0;
+		public static final int kDecode = 1;
+		public static final int kBenchmak = 2;
+		
+		public int Command = -1;
+		public int NumBenchmarkPasses = 10;
+		
+		public int DictionarySize = 1 << 23;
+		public boolean DictionarySizeIsDefined = false;
+		
+		public int Lc = 3;
+		public int Lp = 0;
+		public int Pb = 2;
+		
+		public int Fb = 128;
+		public boolean FbIsDefined = false;
+		
+		public boolean Eos = false;
+		
+		public int Algorithm = 2;
+		public int MatchFinder = 1;
+		
+		public String InFile;
+		public String OutFile;
+		
+		boolean ParseSwitch(String s)
+		{
+			if (s.startsWith("d"))
+			{
+				DictionarySize = 1 << Integer.parseInt(s.substring(1));
+				DictionarySizeIsDefined = true;
+			}
+			else if (s.startsWith("fb"))
+			{
+				Fb = Integer.parseInt(s.substring(2));
+				FbIsDefined = true;
+			}
+			else if (s.startsWith("a"))
+				Algorithm = Integer.parseInt(s.substring(1));
+			else if (s.startsWith("lc"))
+				Lc = Integer.parseInt(s.substring(2));
+			else if (s.startsWith("lp"))
+				Lp = Integer.parseInt(s.substring(2));
+			else if (s.startsWith("pb"))
+				Pb = Integer.parseInt(s.substring(2));
+			else if (s.startsWith("eos"))
+				Eos = true;
+			else if (s.startsWith("mf"))
+			{
+				String mfs = s.substring(2);
+				if (mfs.equals("bt2"))
+					MatchFinder = 0;
+				else if (mfs.equals("bt4"))
+					MatchFinder = 1;
+				else if (mfs.equals("bt4b"))
+					MatchFinder = 2;
+				else
+					return false;
+			}
+			else
+				return false;
+			return true;
+		}
+		
+		public boolean Parse(String[] args) throws Exception
+		{
+			int pos = 0;
+			boolean switchMode = true;
+			for (int i = 0; i < args.length; i++)
+			{
+				String s = args[i];
+				if (s.length() == 0)
+					return false;
+				if (switchMode)
+				{
+					if (s.compareTo("--") == 0)
+					{
+						switchMode = false;
+						continue;
+					}
+					if (s.charAt(0) == '-')
+					{
+						String sw = s.substring(1).toLowerCase();
+						if (sw.length() == 0)
+							return false;
+						try
+						{
+							if (!ParseSwitch(sw))
+								return false;
+						}
+						catch (NumberFormatException e)
+						{
+							return false;
+						}
+						continue;
+					}
+				}
+				if (pos == 0)
+				{
+					if (s.equalsIgnoreCase("e"))
+						Command = kEncode;
+					else if (s.equalsIgnoreCase("d"))
+						Command = kDecode;
+					else if (s.equalsIgnoreCase("b"))
+						Command = kBenchmak;
+					else
+						return false;
+				}
+				else if(pos == 1)
+				{
+					if (Command == kBenchmak)
+					{
+						try
+						{
+							NumBenchmarkPasses = Integer.parseInt(s);
+							if (NumBenchmarkPasses < 1)
+								return false;
+						}
+						catch (NumberFormatException e)
+						{
+							return false;
+						}
+					}
+					else
+						InFile = s;
+				}
+				else if(pos == 2)
+					OutFile = s;
+				else
+					return false;
+				pos++;
+				continue;
+			}
+			return true;
+		}
+	}
+	
+	
+	static void PrintHelp()
+	{
+		System.out.println(
+				"\nUsage:  LZMA <e|d> [<switches>...] inputFile outputFile\n" +
+				"  e: encode file\n" +
+				"  d: decode file\n" +
+				"  b: Benchmark\n" +
+				"<Switches>\n" +
+				// "  -a{N}:  set compression mode - [0, 1], default: 1 (max)\n" +
+				"  -d{N}:  set dictionary - [0,28], default: 23 (8MB)\n" +
+				"  -fb{N}: set number of fast bytes - [5, 273], default: 128\n" +
+				"  -lc{N}: set number of literal context bits - [0, 8], default: 3\n" +
+				"  -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" +
+				"  -pb{N}: set number of pos bits - [0, 4], default: 2\n" +
+				"  -mf{MF_ID}: set Match Finder: [bt2, bt4], default: bt4\n" +
+				"  -eos:   write End Of Stream marker\n"
+				);
+	}
+	
+	public static void main(String[] args) throws Exception
+	{
+		System.out.println("\nLZMA (Java) 4.42 Copyright (c) 1999-2006 Igor Pavlov  2006-05-15\n");
+		
+		if (args.length < 1)
+		{
+			PrintHelp();
+			return;
+		}
+		
+		CommandLine params = new CommandLine();
+		if (!params.Parse(args))
+		{
+			System.out.println("\nIncorrect command");
+			return;
+		}
+		
+		if (params.Command == CommandLine.kBenchmak)
+		{
+			int dictionary = (1 << 21);
+			if (params.DictionarySizeIsDefined)
+				dictionary = params.DictionarySize;
+			if (params.MatchFinder > 1)
+				throw new Exception("Unsupported match finder");
+			SevenZip.LzmaBench.LzmaBenchmark(params.NumBenchmarkPasses, dictionary);
+		}
+		else if (params.Command == CommandLine.kEncode || params.Command == CommandLine.kDecode)
+		{
+			java.io.File inFile = new java.io.File(params.InFile);
+			java.io.File outFile = new java.io.File(params.OutFile);
+			
+			java.io.BufferedInputStream inStream  = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile));
+			java.io.BufferedOutputStream outStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile));
+			
+			boolean eos = false;
+			if (params.Eos)
+				eos = true;
+			if (params.Command == CommandLine.kEncode)
+			{
+				SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
+				if (!encoder.SetAlgorithm(params.Algorithm))
+					throw new Exception("Incorrect compression mode");
+				if (!encoder.SetDictionarySize(params.DictionarySize))
+					throw new Exception("Incorrect dictionary size");
+				if (!encoder.SeNumFastBytes(params.Fb))
+					throw new Exception("Incorrect -fb value");
+				if (!encoder.SetMatchFinder(params.MatchFinder))
+					throw new Exception("Incorrect -mf value");
+				if (!encoder.SetLcLpPb(params.Lc, params.Lp, params.Pb))
+					throw new Exception("Incorrect -lc or -lp or -pb value");
+				encoder.SetEndMarkerMode(eos);
+				encoder.WriteCoderProperties(outStream);
+				long fileSize;
+				if (eos)
+					fileSize = -1;
+				else
+					fileSize = inFile.length();
+				for (int i = 0; i < 8; i++)
+					outStream.write((int)(fileSize >>> (8 * i)) & 0xFF);
+				encoder.Code(inStream, outStream, -1, -1, null);
+			}
+			else
+			{
+				int propertiesSize = 5;
+				byte[] properties = new byte[propertiesSize];
+				if (inStream.read(properties, 0, propertiesSize) != propertiesSize)
+					throw new Exception("input .lzma file is too short");
+				SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
+				if (!decoder.SetDecoderProperties(properties))
+					throw new Exception("Incorrect stream properties");
+				long outSize = 0;
+				for (int i = 0; i < 8; i++)
+				{
+					int v = inStream.read();
+					if (v < 0)
+						throw new Exception("Can't read stream size");
+					outSize |= ((long)v) << (8 * i);
+				}
+				if (!decoder.Code(inStream, outStream, outSize))
+					throw new Exception("Error in data stream");
+			}
+			outStream.flush();
+			outStream.close();
+			inStream.close();
+		}
+		else
+			throw new Exception("Incorrect command");
+		return;
+	}
+}

Added: trunk/lzma/Java/SevenZip/LzmaBench.java
===================================================================
--- trunk/lzma/Java/SevenZip/LzmaBench.java	                        (rev 0)
+++ trunk/lzma/Java/SevenZip/LzmaBench.java	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,392 @@
+package SevenZip;
+
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+public class LzmaBench
+{
+	static final int kAdditionalSize = (1 << 21);
+	static final int kCompressedAdditionalSize = (1 << 10);
+	
+	static class CRandomGenerator
+	{
+		int A1;
+		int A2;
+		public CRandomGenerator() { Init(); }
+		public void Init() { A1 = 362436069; A2 = 521288629; }
+		public int GetRnd()
+		{
+			return
+				((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^
+				((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16)));
+		}
+	};
+	
+	static class CBitRandomGenerator
+	{
+		CRandomGenerator RG = new CRandomGenerator();
+		int Value;
+		int NumBits;
+		public void Init()
+		{
+			Value = 0;
+			NumBits = 0;
+		}
+		public int GetRnd(int numBits)
+		{
+			int result;
+			if (NumBits > numBits)
+			{
+				result = Value & ((1 << numBits) - 1);
+				Value >>>= numBits;
+				NumBits -= numBits;
+				return result;
+			}
+			numBits -= NumBits;
+			result = (Value << numBits);
+			Value = RG.GetRnd();
+			result |= Value & (((int)1 << numBits) - 1);
+			Value >>>= numBits;
+			NumBits = 32 - numBits;
+			return result;
+		}
+	};
+	
+	static class CBenchRandomGenerator
+	{
+		CBitRandomGenerator RG = new CBitRandomGenerator();
+		int Pos;
+		int Rep0;
+
+		public int BufferSize;
+		public byte[] Buffer = null;
+
+		public CBenchRandomGenerator() { }
+		public void Set(int bufferSize)
+		{
+			Buffer = new byte[bufferSize];
+			Pos = 0;
+			BufferSize = bufferSize;
+		}
+		int GetRndBit() { return RG.GetRnd(1); }
+		int GetLogRandBits(int numBits)
+		{
+			int len = RG.GetRnd(numBits);
+			return RG.GetRnd((int)len);
+		}
+		int GetOffset()
+		{
+			if (GetRndBit() == 0)
+				return GetLogRandBits(4);
+			return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
+		}
+		int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); }
+		int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); }
+		public void Generate()
+		{
+			RG.Init();
+			Rep0 = 1;
+			while (Pos < BufferSize)
+			{
+				if (GetRndBit() == 0 || Pos < 1)
+					Buffer[Pos++] = (byte)(RG.GetRnd(8));
+				else
+				{
+					int len;
+					if (RG.GetRnd(3) == 0)
+						len = 1 + GetLen1();
+					else
+					{
+						do
+							Rep0 = GetOffset();
+						while (Rep0 >= Pos);
+						Rep0++;
+						len = 2 + GetLen2();
+					}
+					for (int i = 0; i < len && Pos < BufferSize; i++, Pos++)
+						Buffer[Pos] = Buffer[Pos - Rep0];
+				}
+			}
+		}
+	};
+	
+	static class CrcOutStream extends java.io.OutputStream
+	{
+		public CRC CRC = new CRC();
+		
+		public void Init()
+		{ 
+			CRC.Init(); 
+		}
+		public int GetDigest()
+		{ 
+			return CRC.GetDigest(); 
+		}
+		public void write(byte[] b)
+		{
+			CRC.Update(b);
+		}
+		public void write(byte[] b, int off, int len)
+		{
+			CRC.Update(b, off, len);
+		}
+		public void write(int b)
+		{
+			CRC.UpdateByte(b);
+		}
+	};
+
+	static class MyOutputStream extends java.io.OutputStream
+	{
+		byte[] _buffer;
+		int _size;
+		int _pos;
+		
+		public MyOutputStream(byte[] buffer)
+		{
+			_buffer = buffer;
+			_size = _buffer.length;
+		}
+		
+		public void reset()
+		{ 
+			_pos = 0; 
+		}
+		
+		public void write(int b) throws IOException
+		{
+			if (_pos >= _size)
+				throw new IOException("Error");
+			_buffer[_pos++] = (byte)b;
+		}
+		
+		public int size()
+		{
+			return _pos;
+		}
+	};
+
+	static class MyInputStream extends java.io.InputStream
+	{
+		byte[] _buffer;
+		int _size;
+		int _pos;
+		
+		public MyInputStream(byte[] buffer, int size)
+		{
+			_buffer = buffer;
+			_size = size;
+		}
+		
+		public void reset()
+		{ 
+			_pos = 0; 
+		}
+		
+		public int read()
+		{
+			if (_pos >= _size)
+				return -1;
+			return _buffer[_pos++] & 0xFF;
+		}
+	};
+	
+	static class CProgressInfo implements ICodeProgress
+	{
+		public long ApprovedStart;
+		public long InSize;
+		public long Time;
+		public void Init()
+		{ InSize = 0; }
+		public void SetProgress(long inSize, long outSize)
+		{
+			if (inSize >= ApprovedStart && InSize == 0)
+			{
+				Time = System.currentTimeMillis();
+				InSize = inSize;
+			}
+		}
+	}
+	static final int kSubBits = 8;
+	
+	static int GetLogSize(int size)
+	{
+		for (int i = kSubBits; i < 32; i++)
+			for (int j = 0; j < (1 << kSubBits); j++)
+				if (size <= ((1) << i) + (j << (i - kSubBits)))
+					return (i << kSubBits) + j;
+		return (32 << kSubBits);
+	}
+	
+	static long MyMultDiv64(long value, long elapsedTime)
+	{
+		long freq = 1000; // ms
+		long elTime = elapsedTime;
+		while (freq > 1000000)
+		{
+			freq >>>= 1;
+			elTime >>>= 1;
+		}
+		if (elTime == 0)
+			elTime = 1;
+		return value * freq / elTime;
+	}
+	
+	static long GetCompressRating(int dictionarySize, long elapsedTime, long size)
+	{
+		long t = GetLogSize(dictionarySize) - (18 << kSubBits);
+		long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits));
+		long numCommands = (long)(size) * numCommandsForOne;
+		return MyMultDiv64(numCommands, elapsedTime);
+	}
+	
+	static long GetDecompressRating(long elapsedTime, long outSize, long inSize)
+	{
+		long numCommands = inSize * 220 + outSize * 20;
+		return MyMultDiv64(numCommands, elapsedTime);
+	}
+	
+	static long GetTotalRating(
+			int dictionarySize,
+			long elapsedTimeEn, long sizeEn,
+			long elapsedTimeDe,
+			long inSizeDe, long outSizeDe)
+	{
+		return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) +
+				GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2;
+	}
+	
+	static void PrintValue(long v)
+	{
+		String s = "";
+		s += v;
+		for (int i = 0; i + s.length() < 6; i++)
+			System.out.print(" ");
+		System.out.print(s);
+	}
+	
+	static void PrintRating(long rating)
+	{
+		PrintValue(rating / 1000000);
+		System.out.print(" MIPS");
+	}
+	
+	static void PrintResults(
+			int dictionarySize,
+			long elapsedTime,
+			long size,
+			boolean decompressMode, long secondSize)
+	{
+		long speed = MyMultDiv64(size, elapsedTime);
+		PrintValue(speed / 1024);
+		System.out.print(" KB/s  ");
+		long rating;
+		if (decompressMode)
+			rating = GetDecompressRating(elapsedTime, size, secondSize);
+		else
+			rating = GetCompressRating(dictionarySize, elapsedTime, size);
+		PrintRating(rating);
+	}
+	
+	static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception
+	{
+		if (numIterations <= 0)
+			return 0;
+		if (dictionarySize < (1 << 18))
+		{
+			System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)");
+			return 1;
+		}
+		System.out.print("\n       Compressing                Decompressing\n\n");
+		
+		SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
+		SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
+		
+		if (!encoder.SetDictionarySize(dictionarySize))
+			throw new Exception("Incorrect dictionary size");
+		
+		int kBufferSize = dictionarySize + kAdditionalSize;
+		int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
+		
+		ByteArrayOutputStream propStream = new ByteArrayOutputStream();
+		encoder.WriteCoderProperties(propStream);
+		byte[] propArray = propStream.toByteArray();
+		decoder.SetDecoderProperties(propArray);
+		
+		CBenchRandomGenerator rg = new CBenchRandomGenerator();
+
+		rg.Set(kBufferSize);
+		rg.Generate();
+		CRC crc = new CRC();
+		crc.Init();
+		crc.Update(rg.Buffer, 0, rg.BufferSize);
+		
+		CProgressInfo progressInfo = new CProgressInfo();
+		progressInfo.ApprovedStart = dictionarySize;
+		
+		long totalBenchSize = 0;
+		long totalEncodeTime = 0;
+		long totalDecodeTime = 0;
+		long totalCompressedSize = 0;
+		
+		MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize);
+
+		byte[] compressedBuffer = new byte[kCompressedBufferSize];
+		MyOutputStream compressedStream = new MyOutputStream(compressedBuffer);
+		CrcOutStream crcOutStream = new CrcOutStream();
+		MyInputStream inputCompressedStream = null;
+		int compressedSize = 0;
+		for (int i = 0; i < numIterations; i++)
+		{
+			progressInfo.Init();
+			inStream.reset();
+			compressedStream.reset();
+			encoder.Code(inStream, compressedStream, -1, -1, progressInfo);
+			long encodeTime = System.currentTimeMillis() - progressInfo.Time;
+			
+			if (i == 0)
+			{
+				compressedSize = compressedStream.size();
+				inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize);
+			}
+			else if (compressedSize != compressedStream.size())
+				throw (new Exception("Encoding error"));
+				
+			if (progressInfo.InSize == 0)
+				throw (new Exception("Internal ERROR 1282"));
+
+			long decodeTime = 0;
+			for (int j = 0; j < 2; j++)
+			{
+				inputCompressedStream.reset();
+				crcOutStream.Init();
+				
+				long outSize = kBufferSize;
+				long startTime = System.currentTimeMillis();
+				if (!decoder.Code(inputCompressedStream, crcOutStream, outSize))
+					throw (new Exception("Decoding Error"));;
+				decodeTime = System.currentTimeMillis() - startTime;
+				if (crcOutStream.GetDigest() != crc.GetDigest())
+					throw (new Exception("CRC Error"));
+			}
+			long benchSize = kBufferSize - (long)progressInfo.InSize;
+			PrintResults(dictionarySize, encodeTime, benchSize, false, 0);
+			System.out.print("     ");
+			PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize);
+			System.out.println();
+			
+			totalBenchSize += benchSize;
+			totalEncodeTime += encodeTime;
+			totalDecodeTime += decodeTime;
+			totalCompressedSize += compressedSize;
+		}
+		System.out.println("---------------------------------------------------");
+		PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0);
+		System.out.print("     ");
+		PrintResults(dictionarySize, totalDecodeTime,
+				kBufferSize * (long)numIterations, true, totalCompressedSize);
+		System.out.println("    Average");
+		return 0;
+	}
+}

Added: trunk/lzma/LGPL.txt
===================================================================
--- trunk/lzma/LGPL.txt	                        (rev 0)
+++ trunk/lzma/LGPL.txt	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,504 @@
+      GNU LESSER GENERAL PUBLIC LICENSE
+           Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+          Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+      GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+          NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+         END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library 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 library 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 library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+

Added: trunk/lzma/Methods.txt
===================================================================
--- trunk/lzma/Methods.txt	                        (rev 0)
+++ trunk/lzma/Methods.txt	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,141 @@
+7-Zip method IDs (4.56)
+-----------------------
+
+Each compression or crypto method in 7z has unique binary value (ID).
+The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes).
+
+If you want to add some new ID, you have two ways:
+1) Write request for allocating IDs to 7-zip developers.
+2) Generate 8-bytes ID:
+
+    7F ZZ ZZ ZZ ZZ ZZ MM MM 
+
+    7F              - Prefix for random IDs (1 byte)
+    ZZ ZZ ZZ ZZ ZZ  - Developer ID (5 bytes). Use real random bytes. 
+                      
+    MM MM           - Method ID (2 bytes)
+
+    You can notify 7-Zip developers about your Developer ID / Method ID.
+
+    Note: Use new ID only if old codec can not decode data encoded with new version.
+
+
+List of defined IDs
+-------------------
+      
+00 - Copy
+01 - Reserved
+02 - Common
+   03 Swap
+      - 2 Swap2
+      - 4 Swap4
+   04 Delta (subject to change)
+
+03 - 7z
+   01 - LZMA
+      01 - Version
+  
+   03 - Branch
+      01 - x86
+         03  - BCJ
+         1B  - BCJ2
+      02 - PPC
+         05 - BC_PPC_B (Big Endian)
+      03 - Alpha
+         01 - BC_Alpha
+      04 - IA64
+         01 - BC_IA64
+      05 - ARM
+         01 - BC_ARM
+      06 - M68
+         05 - BC_M68_B (Big Endian)
+      07 - ARM Thumb
+         01 - BC_ARMThumb
+      08 - SPARC
+         05 - BC_SPARC
+
+   04 - PPMD
+      01 - Version
+
+   7F -
+      01 - experimental methods.
+
+   80 - reserved for independent developers
+
+   E0 - Random IDs
+
+04 - Misc
+   00 - Reserved
+   01 - Zip
+      00 - Copy (not used). Use {00} instead
+      01 - Shrink
+      06 - Implode
+      08 - Deflate
+      09 - Deflate64
+      12 - BZip2 (not used). Use {04 02 02} instead
+   02 - BZip
+      02 - BZip2
+   03 - Rar
+      01 - Rar15
+      02 - Rar20
+      03 - Rar29
+   04 - Arj
+      01 - Arj (1,2,3)
+      02 - Arj 4
+   05 - Z
+   06 - Lzh
+   07 - Reserved for 7z
+   08 - Cab
+   09 - NSIS
+      01 - DeflateNSIS
+      02 - BZip2NSIS
+
+
+06 - Crypto 
+   00 - 
+   01 - AES
+      0x - AES-128
+      4x - AES-192
+      8x - AES-256
+      Cx - AES
+
+      x0 - ECB
+      x1 - CBC
+      x2 - CFB
+      x3 - OFB
+
+   07 - Reserved
+   0F - Reserved
+
+   F0 - Misc Ciphers (Real Ciphers without hashing algo)
+
+   F1 - Misc Ciphers (Combine)
+      01 - Zip
+         01 - Main Zip crypto algo
+      03 - RAR
+         02 - 
+         03 - Rar29 AES-128 + (modified SHA-1)
+      07 - 7z
+         01 - AES-256 + SHA-256
+
+07 - Hash (subject to change)
+   00 - 
+   01 - CRC
+   02 - SHA-1
+   03 - SHA-256
+   04 - SHA-384
+   05 - SHA-512
+
+   F0 - Misc Hash
+
+   F1 - Misc
+      03 - RAR
+         03 - Rar29 Password Hashing (modified SHA1)
+      07 - 7z 
+         01 - SHA-256 Password Hashing
+    
+   
+
+
+---
+End of document

Added: trunk/lzma/history.txt
===================================================================
--- trunk/lzma/history.txt	                        (rev 0)
+++ trunk/lzma/history.txt	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,198 @@
+HISTORY of the LZMA SDK
+-----------------------
+
+  4.57           2007-12-12
+  -------------------------
+    - Speed optimizations in Ñ++ LZMA Decoder. 
+    - Small changes for more compatibility with some C/C++ compilers.
+
+  
+  4.49 beta      2007-07-05
+  -------------------------
+    - .7z ANSI-C Decoder:
+         - now it supports BCJ and BCJ2 filters
+         - now it supports files larger than 4 GB.
+         - now it supports "Last Write Time" field for files.
+    - C++ code for .7z archives compressing/decompressing from 7-zip 
+      was included to LZMA SDK.
+      
+
+  4.43           2006-06-04
+  -------------------------
+    - Small changes for more compatibility with some C/C++ compilers.
+      
+
+  4.42           2006-05-15
+  -------------------------
+    - Small changes in .h files in ANSI-C version.
+      
+
+  4.39 beta      2006-04-14
+  -------------------------
+    - Bug in versions 4.33b:4.38b was fixed:
+      C++ version of LZMA encoder could not correctly compress 
+      files larger than 2 GB with HC4 match finder (-mfhc4).
+      
+
+  4.37 beta      2005-04-06
+  -------------------------
+    - Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. 
+
+  
+  4.35 beta      2005-03-02
+  -------------------------
+    - Bug was fixed in C++ version of LZMA Decoder:
+       If encoded stream was corrupted, decoder could access memory 
+       outside of allocated range.
+
+  
+  4.34 beta      2006-02-27
+  -------------------------
+    - Compressing speed and memory requirements for compressing were increased
+    - LZMA now can use only these match finders: HC4, BT2, BT3, BT4
+
+  
+  4.32           2005-12-09
+  -------------------------
+    - Java version of LZMA SDK was included
+
+
+  4.30           2005-11-20
+  -------------------------
+    - Compression ratio was improved in -a2 mode
+    - Speed optimizations for compressing in -a2 mode
+    - -fb switch now supports values up to 273
+    - Bug in 7z_C (7zIn.c) was fixed:
+      It used Alloc/Free functions from different memory pools.
+      So if program used two memory pools, it worked incorrectly.
+    - 7z_C: .7z format supporting was improved
+    - LZMA# SDK (C#.NET version) was included
+
+
+  4.27 (Updated) 2005-09-21
+  -------------------------
+   - Some GUIDs/interfaces in C++ were changed.
+     IStream.h:
+       ISequentialInStream::Read now works as old ReadPart
+       ISequentialOutStream::Write now works as old WritePart
+
+  
+  4.27           2005-08-07
+  -------------------------
+    - Bug in LzmaDecodeSize.c was fixed:
+       if _LZMA_IN_CB and _LZMA_OUT_READ were defined,
+       decompressing worked incorrectly.
+
+
+  4.26           2005-08-05
+  -------------------------
+    - Fixes in 7z_C code and LzmaTest.c:
+      previous versions could work incorrectly,
+      if malloc(0) returns 0
+
+
+  4.23           2005-06-29
+  -------------------------
+    - Small fixes in C++ code
+
+
+  4.22           2005-06-10
+  -------------------------
+    - Small fixes
+
+
+  4.21           2005-06-08
+  -------------------------
+    - Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed
+    - New additional version of ANSI-C LZMA Decoder with zlib-like interface:
+        - LzmaStateDecode.h
+        - LzmaStateDecode.c
+        - LzmaStateTest.c
+    - ANSI-C LZMA Decoder now can decompress files larger than 4 GB
+
+  
+  4.17           2005-04-18
+  -------------------------
+    - New example for RAM->RAM compressing/decompressing: 
+      LZMA + BCJ (filter for x86 code):
+        - LzmaRam.h
+        - LzmaRam.cpp
+        - LzmaRamDecode.h
+        - LzmaRamDecode.c
+        - -f86 switch for lzma.exe
+
+  
+  4.16           2005-03-29
+  -------------------------
+    - Bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): 
+       If _LZMA_OUT_READ was defined, and if encoded stream was corrupted,
+       decoder could access memory outside of allocated range.
+    - Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster).
+      Old version of LZMA Decoder now is in file LzmaDecodeSize.c. 
+      LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c
+    - Small speed optimization in LZMA C++ code
+    - filter for SPARC's code was added
+    - Simplified version of .7z ANSI-C Decoder was included
+
+
+  4.06           2004-09-05
+  -------------------------
+    - Bug in v4.05 was fixed:
+        LZMA-Encoder didn't release output stream in some cases.
+
+
+  4.05           2004-08-25
+  -------------------------
+    - Source code of filters for x86, IA-64, ARM, ARM-Thumb 
+      and PowerPC code was included to SDK
+    - Some internal minor changes
+
+
+  4.04           2004-07-28
+  -------------------------
+    - More compatibility with some C++ compilers
+
+
+  4.03           2004-06-18
+  -------------------------
+    - "Benchmark" command was added. It measures compressing 
+      and decompressing speed and shows rating values. 
+      Also it checks hardware errors.
+
+
+  4.02           2004-06-10
+  -------------------------
+    - C++ LZMA Encoder/Decoder code now is more portable
+      and it can be compiled by GCC on Linux.
+
+
+  4.01           2004-02-15
+  -------------------------
+    - Some detection of data corruption was enabled.
+        LzmaDecode.c / RangeDecoderReadByte
+        .....
+        {
+          rd->ExtraBytes = 1;
+          return 0xFF;
+        }
+
+
+  4.00           2004-02-13
+  -------------------------
+    - Original version of LZMA SDK
+
+
+
+HISTORY of the LZMA
+-------------------
+  2001-2007:  Improvements to LZMA compressing/decompressing code, 
+              keeping compatibility with original LZMA format
+  1996-2001:  Development of LZMA compression format
+
+  Some milestones:
+
+  2001-08-30: LZMA compression was added to 7-Zip
+  1999-01-02: First version of 7-Zip was released
+  
+
+End of document

Added: trunk/lzma/lzma.exe
===================================================================
(Binary files differ)


Property changes on: trunk/lzma/lzma.exe
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lzma/lzma.txt
===================================================================
--- trunk/lzma/lzma.txt	                        (rev 0)
+++ trunk/lzma/lzma.txt	2008-01-23 03:52:35 UTC (rev 923)
@@ -0,0 +1,663 @@
+LZMA SDK 4.57
+-------------
+
+LZMA SDK   Copyright (C) 1999-2007 Igor Pavlov
+
+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 available under any of the following licenses:
+
+1) GNU Lesser General Public License (GNU LGPL)
+2) Common Public License (CPL)
+3) Simplified license for unmodified code (read SPECIAL EXCEPTION) 
+4) Proprietary license 
+
+It means that you can select one of these four options and follow rules of that license.
+
+
+1,2) GNU LGPL and CPL licenses are pretty similar and both these
+licenses are classified as 
+ - "Free software licenses" at http://www.gnu.org/ 
+ - "OSI-approved" at http://www.opensource.org/
+
+
+3) SPECIAL EXCEPTION
+
+Igor Pavlov, as the author of this code, expressly permits you 
+to statically or dynamically link your code (or bind by name) 
+to the files from LZMA SDK without subjecting your linked 
+code to the terms of the CPL or GNU LGPL. 
+Any modifications or additions to files from LZMA SDK, however, 
+are subject to the GNU LGPL or CPL terms.
+
+SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code, 
+while you keep LZMA SDK code unmodified.
+
+
+SPECIAL EXCEPTION #2: Igor Pavlov, as the author of this code, expressly permits 
+you to use this code under the same terms and conditions contained in the License 
+Agreement you have for any previous version of LZMA SDK developed by Igor Pavlov.
+
+SPECIAL EXCEPTION #2 allows owners of proprietary licenses to use latest version 
+of LZMA SDK as update for previous versions.
+
+
+SPECIAL EXCEPTION #3: Igor Pavlov, as the author of this code, expressly permits 
+you to use code of the following files: 
+BranchTypes.h, LzmaTypes.h, LzmaTest.c, LzmaStateTest.c, LzmaAlone.cpp, 
+LzmaAlone.cs, LzmaAlone.java
+as public domain code. 
+
+
+4) Proprietary license
+
+LZMA SDK also can be available under a proprietary license which 
+can include:
+
+1) Right to modify code without subjecting modified code to the 
+terms of the CPL or GNU LGPL
+2) Technical support for code
+
+To request such proprietary license or any additional consultations,
+send email message from that page:
+http://www.7-zip.org/support.html
+
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+You should have received a copy of the Common Public License
+along with this library.
+
+
+LZMA SDK Contents
+-----------------
+
+LZMA SDK includes:
+
+  - C++ source code of LZMA compressing and decompressing
+  - ANSI-C compatible source code for LZMA decompressing
+  - C# source code for LZMA compressing and decompressing
+  - Java source code for LZMA compressing and decompressing
+  - Compiled file->file LZMA compressing/decompressing program for Windows system
+
+ANSI-C LZMA decompression code was ported from original C++ sources to C.
+Also it was simplified and optimized for code size. 
+But it is fully compatible with LZMA from 7-Zip.
+
+
+UNIX/Linux version 
+------------------
+To compile C++ version of file->file LZMA, go to directory
+C/7zip/Compress/LZMA_Alone 
+and type "make" or "make clean all" to recompile all.
+
+In some UNIX/Linux versions you must compile LZMA with static libraries.
+To compile with static libraries, change string in makefile
+LIB = -lm
+to string  
+LIB = -lm -static
+
+
+Files
+---------------------
+C        - C source code
+CPP      - CPP source code
+CS       - C# source code
+Java     - Java source code
+lzma.txt - LZMA SDK description (this file)
+7zFormat.txt - 7z Format description
+7zC.txt  - 7z ANSI-C Decoder description (this file)
+methods.txt  - Compression method IDs for .7z
+LGPL.txt - GNU Lesser General Public License
+CPL.html - Common Public License
+lzma.exe - Compiled file->file LZMA encoder/decoder for Windows
+history.txt - history of the LZMA SDK
+
+
+Source code structure
+---------------------
+
+C  - C files
+    Compress - files related to compression/decompression
+      Lz     - files related to LZ (Lempel-Ziv) compression algorithm
+      Lzma   - ANSI-C compatible LZMA decompressor
+
+        LzmaDecode.h  - interface for LZMA decoding on ANSI-C
+        LzmaDecode.c      - LZMA decoding on ANSI-C (new fastest version)
+        LzmaDecodeSize.c  - LZMA decoding on ANSI-C (old size-optimized version)
+        LzmaTest.c        - test application that decodes LZMA encoded file
+        LzmaTypes.h       - basic types for LZMA Decoder
+        LzmaStateDecode.h - interface for LZMA decoding (State version)
+        LzmaStateDecode.c - LZMA decoding on ANSI-C (State version)
+        LzmaStateTest.c   - test application (State version)
+
+      Branch       - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
+
+    Archive - files related to archiving
+      7z_C     - 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
+
+      LZ     - files related to LZ (Lempel-Ziv) compression algorithm
+
+      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.
+
+You can find ANSI-C LZMA decompressing code at folder 
+  C/7zip/Compress/Lzma
+7-Zip doesn't use that ANSI-C LZMA code and that code was developed 
+specially for this SDK. And files from C/7zip/Compress/Lzma do not need 
+files from other directories of SDK for compiling.
+
+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 1 MB/s on 1 GHz CPU
+  - Estimated decompressing speed: 
+      - 8-12 MB/s on 1 GHz Intel Pentium 3 or AMD Athlon
+      - 500-1000 KB/s on 100 MHz ARM, MIPS, PowerPC or other simple RISC
+  - Small memory requirements for decompressing (8-32 KB + DictionarySize)
+  - Small code size for decompressing: 2-8 KB (depending from 
+    speed optimizations) 
+
+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 to 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
+
+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 AMD Athlon 64 X2 CPU
+     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. Also you 
+     can change 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 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, ...).
+
+
+Using Filters
+-------------
+You can increase compression ratio for some data types, using
+special filters before compressing. For example, it's possible to 
+increase compression ratio on 5-10% for code for those CPU ISAs: 
+x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.
+
+You can find C/C++ source code of such filters in folder "7zip/Compress/Branch"
+
+You can check 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=bc_arm -m1=lzma        
+
+With filter for big-endian ARM code (using additional Swap4 filter):
+  7z a a3.7z a.bin -m0=swap4 -m1=bc_arm -m2=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. Source code of these CALL filters is pretty simple
+(about 20 lines of C++), so you can convert it from C++ version yourself.
+
+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 for compressed data
+  1     4   Dictionary size (little endian)
+  5     8   Uncompressed size (little endian). -1 means unknown size
+ 13         Compressed data
+
+
+ANSI-C LZMA Decoder
+~~~~~~~~~~~~~~~~~~~
+
+To compile ANSI-C LZMA Decoder you can use one of the following files sets:
+1) LzmaDecode.h + LzmaDecode.c + LzmaTest.c  (fastest version)
+2) LzmaDecode.h + LzmaDecodeSize.c + LzmaTest.c  (old size-optimized version)
+3) LzmaStateDecode.h + LzmaStateDecode.c + LzmaStateTest.c  (zlib-like interface)
+
+
+Memory requirements for LZMA decoding
+-------------------------------------
+
+LZMA decoder doesn't allocate memory itself, so you must 
+allocate memory and send it to LZMA.
+
+Stack usage of LZMA decoding function for local variables is not 
+larger than 200 bytes.
+
+How To decompress data
+----------------------
+
+LZMA Decoder (ANSI-C version) now supports 5 interfaces:
+1) Single-call Decompressing
+2) Single-call Decompressing with input stream callback
+3) Multi-call Decompressing with output buffer
+4) Multi-call Decompressing with input callback and output buffer
+5) Multi-call State Decompressing (zlib-like interface)
+
+Variant-5 is similar to Variant-4, but Variant-5 doesn't use callback functions.
+
+Decompressing steps
+-------------------
+
+1) read LZMA properties (5 bytes):
+   unsigned char properties[LZMA_PROPERTIES_SIZE];
+
+2) read uncompressed size (8 bytes, little-endian)
+
+3) Decode properties:
+
+  CLzmaDecoderState state;  /* it's 24-140 bytes structure, if int is 32-bit */
+
+  if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
+    return PrintError(rs, "Incorrect stream properties");
+
+4) Allocate memory block for internal Structures:
+
+  state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+  if (state.Probs == 0)
+    return PrintError(rs, kCantAllocateMessage);
+
+  LZMA decoder uses array of CProb variables as internal structure.
+  By default, CProb is unsigned_short. But you can define _LZMA_PROB32 to make 
+  it unsigned_int. It can increase speed on some 32-bit CPUs, but memory 
+  usage will be doubled in that case.
+
+
+5) Main Decompressing
+
+You must use one of the following interfaces:
+
+5.1 Single-call Decompressing
+-----------------------------
+When to use: RAM->RAM decompressing
+Compile files: LzmaDecode.h, LzmaDecode.c
+Compile defines: no defines
+Memory Requirements:
+  - Input buffer: compressed size
+  - Output buffer: uncompressed size
+  - LZMA Internal Structures (~16 KB for default settings) 
+
+Interface:
+  int res = LzmaDecode(&state, 
+      inStream, compressedSize, &inProcessed,
+      outStream, outSize, &outProcessed);
+
+
+5.2 Single-call Decompressing with input stream callback
+--------------------------------------------------------
+When to use: File->RAM or Flash->RAM decompressing.
+Compile files: LzmaDecode.h, LzmaDecode.c
+Compile defines: _LZMA_IN_CB
+Memory Requirements:
+  - Buffer for input stream: any size (for example, 16 KB)
+  - Output buffer: uncompressed size
+  - LZMA Internal Structures (~16 KB for default settings) 
+
+Interface:
+  typedef struct _CBuffer
+  {
+    ILzmaInCallback InCallback;
+    FILE *File;
+    unsigned char Buffer[kInBufferSize];
+  } CBuffer;
+
+  int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
+  {
+    CBuffer *bo = (CBuffer *)object;
+    *buffer = bo->Buffer;
+    *size = MyReadFile(bo->File, bo->Buffer, kInBufferSize);
+    return LZMA_RESULT_OK;
+  }
+
+  CBuffer g_InBuffer;
+
+  g_InBuffer.File = inFile;
+  g_InBuffer.InCallback.Read = LzmaReadCompressed;
+  int res = LzmaDecode(&state, 
+      &g_InBuffer.InCallback,
+      outStream, outSize, &outProcessed);
+
+
+5.3 Multi-call decompressing with output buffer
+-----------------------------------------------
+When to use: RAM->File decompressing 
+Compile files: LzmaDecode.h, LzmaDecode.c
+Compile defines: _LZMA_OUT_READ
+Memory Requirements:
+ - Input buffer: compressed size
+ - Buffer for output stream: any size (for example, 16 KB)
+ - LZMA Internal Structures (~16 KB for default settings) 
+ - LZMA dictionary (dictionary size is encoded in stream properties)
+ 
+Interface:
+
+  state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+
+  LzmaDecoderInit(&state);
+  do
+  {
+    LzmaDecode(&state,
+      inBuffer, inAvail, &inProcessed,
+      g_OutBuffer, outAvail, &outProcessed);
+    inAvail -= inProcessed;
+    inBuffer += inProcessed;
+  }
+  while you need more bytes
+
+  see LzmaTest.c for more details.
+
+
+5.4 Multi-call decompressing with input callback and output buffer
+------------------------------------------------------------------
+When to use: File->File decompressing 
+Compile files: LzmaDecode.h, LzmaDecode.c
+Compile defines: _LZMA_IN_CB, _LZMA_OUT_READ
+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 (~16 KB for default settings) 
+ - LZMA dictionary (dictionary size is encoded in stream properties)
+ 
+Interface:
+
+  state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+ 
+  LzmaDecoderInit(&state);
+  do
+  {
+    LzmaDecode(&state,
+      &bo.InCallback,
+      g_OutBuffer, outAvail, &outProcessed);
+  }
+  while you need more bytes
+
+  see LzmaTest.c for more details:
+
+
+5.5 Multi-call State Decompressing (zlib-like interface)
+------------------------------------------------------------------
+When to use: file->file decompressing 
+Compile files: LzmaStateDecode.h, LzmaStateDecode.c
+Compile defines:
+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 (~16 KB for default settings) 
+ - LZMA dictionary (dictionary size is encoded in stream properties)
+ 
+Interface:
+
+  state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
+
+  
+  LzmaDecoderInit(&state);
+  do
+  {
+    res = LzmaDecode(&state,
+      inBuffer, inAvail, &inProcessed,
+      g_OutBuffer, outAvail, &outProcessed,
+      finishDecoding);
+    inAvail -= inProcessed;
+    inBuffer += inProcessed;
+  }
+  while you need more bytes
+
+  see LzmaStateTest.c for more details:
+
+
+6) Free all allocated blocks
+
+
+Note
+----
+LzmaDecodeSize.c is size-optimized version of LzmaDecode.c.
+But compiled code of LzmaDecodeSize.c can be larger than 
+compiled code of LzmaDecode.c. So it's better to use 
+LzmaDecode.c in most cases.
+
+
+EXIT codes
+-----------
+
+LZMA decoder can return one of the following codes:
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+If you use callback function for input data and you return some 
+error code, LZMA Decoder also returns that code.
+
+
+
+LZMA Defines
+------------
+
+_LZMA_IN_CB    - Use callback for input data
+
+_LZMA_OUT_READ - Use read function for output data
+
+_LZMA_LOC_OPT  - Enable local speed optimizations inside code.
+                 _LZMA_LOC_OPT is only for LzmaDecodeSize.c (size-optimized version).
+                 _LZMA_LOC_OPT doesn't affect LzmaDecode.c (speed-optimized version)
+                 and LzmaStateDecode.c
+
+_LZMA_PROB32   - It can increase speed on some 32-bit CPUs, 
+                 but memory usage 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_SYSTEM_SIZE_T  - Define it if you want to use system's size_t.
+                       You can use it to enable 64-bit sizes supporting
+
+
+
+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.
+
+By default, LZMA Encoder contains all Match Finders.
+But for compressing it's enough to have just one of them.
+So for reducing size of compressing code you can define:
+  #define COMPRESS_MF_BT
+  #define COMPRESS_MF_BT4
+and it will use only bt4 match finder.
+
+
+---
+
+http://www.7-zip.org
+http://www.7-zip.org/support.html




More information about the physfs-commits mailing list