mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-14 10:11:38 -06:00
4.20
This commit is contained in:
committed by
Kornel Lesiński
parent
8c1b5c7b7e
commit
3c510ba80b
239
7zip/Compress/LZMA_Alone/LzmaRam.cpp
Executable file
239
7zip/Compress/LZMA_Alone/LzmaRam.cpp
Executable file
@@ -0,0 +1,239 @@
|
||||
// LzmaRam.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "../../../Common/Types.h"
|
||||
#include "../LZMA/LZMADecoder.h"
|
||||
#include "../LZMA/LZMAEncoder.h"
|
||||
#include "LzmaRam.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "../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);
|
||||
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 remain = Size - Pos;
|
||||
if (size > remain)
|
||||
size = remain;
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
{
|
||||
((Byte *)data)[i] = Data[Pos + i];
|
||||
}
|
||||
Pos += size;
|
||||
if(processedSize != NULL)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamRam::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Read(data, size, processedSize);
|
||||
}
|
||||
|
||||
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);
|
||||
STDMETHOD(WritePart)(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;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutStreamRam::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
#define SZE_FAIL (1)
|
||||
#define SZE_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 SZE_OUTOFMEMORY;
|
||||
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
|
||||
CInStreamRam *inStreamSpec = new CInStreamRam;
|
||||
if (inStreamSpec == 0)
|
||||
return SZE_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)
|
||||
{
|
||||
filteredStream = (Byte *)MyAlloc(inSize);
|
||||
if (filteredStream == 0)
|
||||
return SZE_OUTOFMEMORY;
|
||||
memmove(filteredStream, inBuffer, inSize);
|
||||
UInt32 _prevMask;
|
||||
UInt32 _prevPos;
|
||||
x86_Convert_Init(_prevMask, _prevPos);
|
||||
x86_Convert(filteredStream, (UInt32)inSize, 0, &_prevMask, &_prevPos, 1);
|
||||
}
|
||||
|
||||
UInt32 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 = SZE_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 = SZE_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*outSizeProcessed = outStreamSpec->Pos;
|
||||
if (bestIsFiltered)
|
||||
outBuffer[0] = 1;
|
||||
if (useFilter)
|
||||
MyFree(filteredStream);
|
||||
return mainResult;
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
} catch(...) { return SZE_OUTOFMEMORY; }
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user