private void LZMA_Compress(SharedSettings s) { long s_WrittenSize = s.Dst.Length; var props = LZMA.CLzmaEncProps.LzmaEncProps_Init(); props.mLevel = s.ActualLevel; props.mDictSize = (uint)s.ActualDictSize; props.mLC = s.ActualLC; props.mLP = s.ActualLP; props.mPB = s.ActualPB; props.mAlgo = s.ActualAlgo; props.mFB = s.ActualFB; props.mBtMode = s.ActualBTMode; props.mNumHashBytes = s.ActualNumHashBytes; props.mMC = s.ActualMC; props.mWriteEndMark = s.ActualWriteEndMark; props.mNumThreads = s.ActualNumThreads; var enc = LZMA.LzmaEnc_Create(LZMA.ISzAlloc.BigAlloc); var res = enc.LzmaEnc_SetProps(props); if (res != LZMA.SZ_OK) { throw new Exception("SetProps failed: " + res); } res = enc.LzmaEnc_MemEncode(P.From(s.Dst), ref s_WrittenSize, P.From(s.Src), s.Src.Length, s.ActualWriteEndMark != 0, null, LZMA.ISzAlloc.SmallAlloc, LZMA.ISzAlloc.BigAlloc); if (res != LZMA.SZ_OK) { throw new Exception("MemEncode failed: " + res); } s.Enc = new PZ(new byte[LZMA.LZMA_PROPS_SIZE]); long s_Enc_Length = s.Enc.Length; res = enc.LzmaEnc_WriteProperties(P.From(s.Enc), ref s_Enc_Length); if (res != LZMA.SZ_OK) { throw new Exception("WriteProperties failed: " + res); } if (s.Enc.Length != s.Enc.Buffer.Length) { throw new NotSupportedException(); } enc.LzmaEnc_Destroy(LZMA.ISzAlloc.SmallAlloc, LZMA.ISzAlloc.BigAlloc); s.WrittenSize = (int)s_WrittenSize; s.Enc.Length = (int)s_Enc_Length; }
internal PackedStream Compress(Stream inputStream, SevenZipProgressProvider progressProvider) { // Compression method if (!Method.HasValue || !SevenZipMethods.Lookup.ContainsKey(Method.Value)) { throw new SevenZipException("Undefined compression method."); } var MethodID = SevenZipMethods.Lookup[Method.Value]; // create compressed stream information structure var ps = new PackedStream() { NumStreams = 1, Sizes = new UInt64[1] { 0 }, CRCs = new UInt32?[1] { null }, Folder = new SevenZipHeader.Folder() { NumCoders = 1, CodersInfo = new SevenZipHeader.CoderInfo[1] { new SevenZipHeader.CoderInfo() { Attributes = (Byte)MethodID.Raw.Length, CodecId = MethodID.Raw.ToArray(), NumInStreams = 1, NumOutStreams = 1 } }, NumInStreamsTotal = 1, NumOutStreamsTotal = 1, PackedIndices = new UInt64[1] { 0 }, UnPackSizes = new UInt64[1] { 0 }, UnPackCRC = 0 } }; // remember current offsets long outStreamStartOffset = this.stream.Position; long inStreamStartOffset = inputStream.Position; // encode while calculating CRCs using (var inCRCStream = new CRCStream(inputStream)) using (var outCRCStream = new CRCStream(stream)) { LZMA.CLzmaEnc encoder = LZMA.LzmaEnc_Create(LZMA.ISzAlloc.SmallAlloc); LZMA.CLzmaEncProps encoderProps = LZMA.CLzmaEncProps.LzmaEncProps_Init(); LZMA.CSeqOutStream outputHelper; LZMA.CSeqInStream inputHelper; LZMA.SRes res = LZMA.SZ_OK; // prepare encoder settings res = encoder.LzmaEnc_SetProps(encoderProps); if (res != LZMA.SZ_OK) { throw new SevenZipException("Error setting LZMA encoder properties."); } byte[] properties = new byte[LZMA.LZMA_PROPS_SIZE]; long binarySettingsSize = LZMA.LZMA_PROPS_SIZE; res = encoder.LzmaEnc_WriteProperties(properties, ref binarySettingsSize); if (res != LZMA.SZ_OK) { throw new SevenZipException("Error writing LZMA encoder properties."); } if (binarySettingsSize != LZMA.LZMA_PROPS_SIZE) { throw new NotSupportedException(); } // read/write helpers outputHelper = new LZMA.CSeqOutStream( (P <byte> buf, long sz) => { outCRCStream.Write(buf.mBuffer, buf.mOffset, checked ((int)sz)); }); inputHelper = new LZMA.CSeqInStream( (P <byte> buf, long sz) => { return(inCRCStream.Read(buf.mBuffer, buf.mOffset, checked ((int)sz))); }); // encode res = encoder.LzmaEnc_Encode(outputHelper, inputHelper, progressProvider, LZMA.ISzAlloc.SmallAlloc, LZMA.ISzAlloc.BigAlloc); if (res != LZMA.SZ_OK) { throw new InvalidOperationException(); } // cleanup encoder.LzmaEnc_Destroy(LZMA.ISzAlloc.SmallAlloc, LZMA.ISzAlloc.BigAlloc); // keep settings in header ps.Folder.CodersInfo[0].Attributes |= (Byte)SevenZipHeader.CoderInfo.AttrHasAttributes; ps.Folder.CodersInfo[0].Properties = properties.ToArray(); ps.Folder.CodersInfo[0].PropertiesSize = (UInt64)ps.Folder.CodersInfo[0].Properties.Length; // store sizes and checksums ps.Folder.UnPackSizes[0] = (UInt64)(inputStream.Position - inStreamStartOffset); ps.Folder.UnPackCRC = inCRCStream.Result; ps.Sizes[0] = (UInt64)(this.stream.Position - outStreamStartOffset); ps.CRCs[0] = outCRCStream.Result; // handle progress offsets (in case compressor is called multiple times, with non-solid archives for instance) if (progressProvider != null) { progressProvider.IncreaseOffsetBy((long)ps.Folder.UnPackSizes[0], (long)ps.Sizes[0]); progressProvider.SetProgress(0, 0); } } return(ps); }