mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 22:07:07 -06:00
4.44 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
804edc5756
commit
d9666cf046
57
CPP/7zip/Common/FilePathAutoRename.cpp
Executable file
57
CPP/7zip/Common/FilePathAutoRename.cpp
Executable file
@@ -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;
|
||||
}
|
||||
10
CPP/7zip/Common/FilePathAutoRename.h
Executable file
10
CPP/7zip/Common/FilePathAutoRename.h
Executable file
@@ -0,0 +1,10 @@
|
||||
// Util/FilePathAutoRename.h
|
||||
|
||||
#ifndef __FILEPATHAUTORENAME_H
|
||||
#define __FILEPATHAUTORENAME_H
|
||||
|
||||
#include "Common/String.h"
|
||||
|
||||
bool AutoRenamePath(UString &fullProcessedPath);
|
||||
|
||||
#endif
|
||||
251
CPP/7zip/Common/FileStreams.cpp
Executable file
251
CPP/7zip/Common/FileStreams.cpp
Executable file
@@ -0,0 +1,251 @@
|
||||
// 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)
|
||||
{
|
||||
// return result ? S_OK: E_FAIL;
|
||||
#ifdef _WIN32
|
||||
return result ? S_OK: (::GetLastError());
|
||||
#else
|
||||
return result ? S_OK: E_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CInFileStream::Open(LPCTSTR fileName)
|
||||
{
|
||||
return File.Open(fileName);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef _UNICODE
|
||||
bool CInFileStream::Open(LPCWSTR fileName)
|
||||
{
|
||||
return File.Open(fileName);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
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 _WIN32
|
||||
|
||||
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
|
||||
|
||||
bool COutFileStream::Create(LPCTSTR fileName, bool createAlways)
|
||||
{
|
||||
return File.Create(fileName, createAlways);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef _UNICODE
|
||||
bool COutFileStream::Create(LPCWSTR fileName, bool createAlways)
|
||||
{
|
||||
return File.Create(fileName, createAlways);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
UInt32 realProcessedSize;
|
||||
bool result = File.WritePart(data, size, 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;
|
||||
return S_OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin,
|
||||
UInt64 *newPosition)
|
||||
{
|
||||
if(seekOrigin >= 3)
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
#ifdef _WIN32
|
||||
|
||||
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 _WIN32
|
||||
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
|
||||
98
CPP/7zip/Common/FileStreams.h
Executable file
98
CPP/7zip/Common/FileStreams.h
Executable file
@@ -0,0 +1,98 @@
|
||||
// FileStreams.h
|
||||
|
||||
#ifndef __FILESTREAMS_H
|
||||
#define __FILESTREAMS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#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 _WIN32
|
||||
NWindows::NFile::NIO::CInFile File;
|
||||
#else
|
||||
NC::NFile::NIO::CInFile File;
|
||||
#endif
|
||||
CInFileStream() {}
|
||||
virtual ~CInFileStream() {}
|
||||
|
||||
bool Open(LPCTSTR fileName);
|
||||
#ifdef _WIN32
|
||||
#ifndef _UNICODE
|
||||
bool Open(LPCWSTR fileName);
|
||||
#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
|
||||
{
|
||||
public:
|
||||
#ifdef _WIN32
|
||||
NWindows::NFile::NIO::COutFile File;
|
||||
#else
|
||||
NC::NFile::NIO::COutFile File;
|
||||
#endif
|
||||
virtual ~COutFileStream() {}
|
||||
bool Create(LPCTSTR fileName, bool createAlways);
|
||||
#ifdef _WIN32
|
||||
#ifndef _UNICODE
|
||||
bool Create(LPCWSTR fileName, bool createAlways);
|
||||
#endif
|
||||
#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
|
||||
80
CPP/7zip/Common/InBuffer.cpp
Executable file
80
CPP/7zip/Common/InBuffer.cpp
Executable file
@@ -0,0 +1,80 @@
|
||||
// InBuffer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "InBuffer.h"
|
||||
|
||||
#include "../../Common/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++;
|
||||
}
|
||||
76
CPP/7zip/Common/InBuffer.h
Executable file
76
CPP/7zip/Common/InBuffer.h
Executable file
@@ -0,0 +1,76 @@
|
||||
// InBuffer.h
|
||||
|
||||
#ifndef __INBUFFER_H
|
||||
#define __INBUFFER_H
|
||||
|
||||
#include "../IStream.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
class CInBufferException
|
||||
{
|
||||
public:
|
||||
HRESULT ErrorCode;
|
||||
CInBufferException(HRESULT errorCode): ErrorCode(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
|
||||
222
CPP/7zip/Common/InMemStream.cpp
Executable file
222
CPP/7zip/Common/InMemStream.cpp
Executable file
@@ -0,0 +1,222 @@
|
||||
// InMemStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Windows/Thread.h"
|
||||
|
||||
#include "InMemStream.h"
|
||||
#include "../../Common/Defs.h"
|
||||
|
||||
void CStreamInfo::Free(IInMemStreamMtCallback *callback)
|
||||
{
|
||||
for (int i = 0; i < Blocks.Size(); i++)
|
||||
{
|
||||
callback->FreeBlock(Blocks[i]);
|
||||
Blocks[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CInMemStreamMt::Create(int numSubStreams, UInt64 subStreamSize)
|
||||
{
|
||||
Free();
|
||||
_subStreamSize = subStreamSize;
|
||||
size_t blockSize = Callback->GetBlockSize();
|
||||
for (int i = 0; i < numSubStreams; i++)
|
||||
{
|
||||
_streams.Add(CStreamInfo());
|
||||
CStreamInfo &blocks = _streams.Back();
|
||||
blocks.Create();
|
||||
for (UInt64 j = 0; (UInt64)j * blockSize < _subStreamSize; j++)
|
||||
blocks.Blocks.Add(0);
|
||||
}
|
||||
if (!_streamIndexAllocator.AllocateList(numSubStreams))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CInMemStreamMt::Free()
|
||||
{
|
||||
while(_streams.Size() > 0)
|
||||
{
|
||||
_streams.Back().Free(Callback);
|
||||
_streams.DeleteBack();
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CInMemStreamMt::Read()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// printf("\n_streamIndexAllocator.AllocateItem\n");
|
||||
int index = _streamIndexAllocator.AllocateItem();
|
||||
/*
|
||||
if (_stopReading)
|
||||
return E_ABORT;
|
||||
*/
|
||||
// printf("\nread Index = %d\n", index);
|
||||
CStreamInfo &blocks = _streams[index];
|
||||
blocks.Init();
|
||||
Callback->AddStreamIndexToQueue(index);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const Byte *p = (const Byte *)blocks.Blocks[blocks.LastBlockIndex];
|
||||
if (p == 0)
|
||||
{
|
||||
void **pp = &blocks.Blocks[blocks.LastBlockIndex];
|
||||
HRESULT res = Callback->AllocateBlock(pp);
|
||||
p = (const Byte *)*pp;
|
||||
RINOK(res);
|
||||
if (p == 0)
|
||||
return E_FAIL;
|
||||
}
|
||||
size_t blockSize = Callback->GetBlockSize();
|
||||
UInt32 curSize = (UInt32)(blockSize - blocks.LastBlockPos);
|
||||
UInt32 realProcessedSize;
|
||||
UInt64 pos64 = (UInt64)blocks.LastBlockIndex * blockSize + blocks.LastBlockPos;
|
||||
if (curSize > _subStreamSize - pos64)
|
||||
curSize = (UInt32)(_subStreamSize - pos64);
|
||||
RINOK(_stream->Read((void *)(p + blocks.LastBlockPos), curSize, &realProcessedSize));
|
||||
|
||||
blocks.Cs->Enter();
|
||||
if (realProcessedSize == 0)
|
||||
{
|
||||
blocks.StreamWasFinished = true;
|
||||
blocks.CanReadEvent->Set();
|
||||
blocks.Cs->Leave();
|
||||
|
||||
Callback->AddStreamIndexToQueue(-1);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
blocks.LastBlockPos += realProcessedSize;
|
||||
if (blocks.LastBlockPos == blockSize)
|
||||
{
|
||||
blocks.LastBlockPos = 0;
|
||||
blocks.LastBlockIndex++;
|
||||
}
|
||||
pos64 += realProcessedSize;
|
||||
if (pos64 >= _subStreamSize)
|
||||
blocks.StreamWasFinished = true;
|
||||
blocks.CanReadEvent->Set();
|
||||
blocks.Cs->Leave();
|
||||
if (pos64 >= _subStreamSize)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI CoderThread(void *threadCoderInfo)
|
||||
{
|
||||
((CInMemStreamMt *)threadCoderInfo)->ReadResult = ((CInMemStreamMt *)threadCoderInfo)->Read();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CInMemStreamMt::StartReadThread()
|
||||
{
|
||||
// _stopReading = false;
|
||||
NWindows::CThread Thread;
|
||||
return Thread.Create(CoderThread, this);
|
||||
}
|
||||
|
||||
void CInMemStreamMt::FreeSubStream(int subStreamIndex)
|
||||
{
|
||||
// printf("\nFreeSubStream\n");
|
||||
_streams[subStreamIndex].Free(Callback);
|
||||
_streamIndexAllocator.FreeItem(subStreamIndex);
|
||||
// printf("\nFreeSubStream end\n");
|
||||
}
|
||||
|
||||
HRESULT CInMemStreamMt::ReadSubStream(int subStreamIndex, void *data, UInt32 size, UInt32 *processedSize, bool keepData)
|
||||
{
|
||||
if (processedSize != NULL)
|
||||
*processedSize = 0;
|
||||
CStreamInfo &blocks = _streams[subStreamIndex];
|
||||
while (size > 0)
|
||||
{
|
||||
if (blocks.CurBlockPos == Callback->GetBlockSize())
|
||||
{
|
||||
blocks.CurBlockPos = 0;
|
||||
blocks.CurBlockIndex++;
|
||||
}
|
||||
UInt32 curSize;
|
||||
UInt32 curPos = blocks.CurBlockPos;
|
||||
|
||||
blocks.Cs->Enter();
|
||||
if (blocks.CurBlockIndex == blocks.LastBlockIndex)
|
||||
{
|
||||
curSize = blocks.LastBlockPos - curPos;
|
||||
if (curSize == 0)
|
||||
{
|
||||
if (blocks.StreamWasFinished)
|
||||
{
|
||||
blocks.Cs->Leave();
|
||||
void *p = blocks.Blocks[blocks.CurBlockIndex];
|
||||
if (p != 0 && !keepData)
|
||||
{
|
||||
Callback->FreeBlock(p);
|
||||
blocks.Blocks[blocks.CurBlockIndex] = 0;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
blocks.CanReadEvent->Reset();
|
||||
blocks.Cs->Leave();
|
||||
// printf("\nBlock Lock\n");
|
||||
blocks.CanReadEvent->Lock();
|
||||
// printf("\nAfter Lock\n");
|
||||
if (blocks.ExitResult != S_OK)
|
||||
return blocks.ExitResult;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
curSize = Callback->GetBlockSize() - curPos;
|
||||
blocks.Cs->Leave();
|
||||
|
||||
if (curSize > size)
|
||||
curSize = size;
|
||||
void *p = blocks.Blocks[blocks.CurBlockIndex];
|
||||
memmove(data, (const Byte *)p + curPos, curSize);
|
||||
data = (void *)((Byte *)data + curSize);
|
||||
size -= curSize;
|
||||
if (processedSize != NULL)
|
||||
*processedSize += curSize;
|
||||
curPos += curSize;
|
||||
|
||||
bool needFree = false;
|
||||
blocks.CurBlockPos = curPos;
|
||||
|
||||
if (curPos == Callback->GetBlockSize())
|
||||
needFree = true;
|
||||
blocks.Cs->Enter();
|
||||
if (blocks.CurBlockIndex == blocks.LastBlockIndex &&
|
||||
blocks.CurBlockPos == blocks.LastBlockPos &&
|
||||
blocks.StreamWasFinished)
|
||||
needFree = true;
|
||||
blocks.Cs->Leave();
|
||||
|
||||
if (needFree && !keepData)
|
||||
{
|
||||
Callback->FreeBlock(p);
|
||||
blocks.Blocks[blocks.CurBlockIndex] = 0;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInMemStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = mtStream->ReadSubStream(Index, data, size, &realProcessedSize, _keepData);
|
||||
if (processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
if (realProcessedSize != 0)
|
||||
{
|
||||
// printf("\ns = %d\n", Index);
|
||||
}
|
||||
_size += realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
282
CPP/7zip/Common/InMemStream.h
Executable file
282
CPP/7zip/Common/InMemStream.h
Executable file
@@ -0,0 +1,282 @@
|
||||
// InMemStream.h
|
||||
|
||||
#ifndef __INMEMSTREAM_H
|
||||
#define __INMEMSTREAM_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "MemBlocks.h"
|
||||
|
||||
class CIntListCheck
|
||||
{
|
||||
protected:
|
||||
int *_data;
|
||||
public:
|
||||
CIntListCheck(): _data(0) {}
|
||||
~CIntListCheck() { FreeList(); }
|
||||
|
||||
bool AllocateList(int numItems)
|
||||
{
|
||||
FreeList();
|
||||
if (numItems == 0)
|
||||
return true;
|
||||
_data = (int *)::MyAlloc(numItems * sizeof(int));
|
||||
return (_data != 0);
|
||||
}
|
||||
|
||||
void FreeList()
|
||||
{
|
||||
::MyFree(_data);
|
||||
_data = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CResourceList : public CIntListCheck
|
||||
{
|
||||
int _headFree;
|
||||
public:
|
||||
CResourceList(): _headFree(-1) {}
|
||||
|
||||
bool AllocateList(int numItems)
|
||||
{
|
||||
FreeList();
|
||||
if (numItems == 0)
|
||||
return true;
|
||||
if (!CIntListCheck::AllocateList(numItems))
|
||||
return false;
|
||||
for (int i = 0; i < numItems; i++)
|
||||
_data[i] = i + 1;
|
||||
_data[numItems - 1] = -1;
|
||||
_headFree = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FreeList()
|
||||
{
|
||||
CIntListCheck::FreeList();
|
||||
_headFree = -1;
|
||||
}
|
||||
|
||||
int AllocateItem()
|
||||
{
|
||||
int res = _headFree;
|
||||
if (res >= 0)
|
||||
_headFree = _data[res];
|
||||
return res;
|
||||
}
|
||||
|
||||
void FreeItem(int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return;
|
||||
_data[index] = _headFree;
|
||||
_headFree = index;
|
||||
}
|
||||
};
|
||||
|
||||
class CResourceListMt: public CResourceList
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSection _criticalSection;
|
||||
public:
|
||||
NWindows::NSynchronization::CSemaphore Semaphore;
|
||||
|
||||
bool AllocateList(int numItems)
|
||||
{
|
||||
if (!CResourceList::AllocateList(numItems))
|
||||
return false;
|
||||
return Semaphore.Create((LONG)numItems, (LONG)numItems);
|
||||
}
|
||||
|
||||
int AllocateItem()
|
||||
{
|
||||
Semaphore.Lock();
|
||||
_criticalSection.Enter();
|
||||
int res = CResourceList::AllocateItem();
|
||||
_criticalSection.Leave();
|
||||
return res;
|
||||
}
|
||||
|
||||
void FreeItem(int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return;
|
||||
_criticalSection.Enter();
|
||||
CResourceList::FreeItem(index);
|
||||
_criticalSection.Leave();
|
||||
Semaphore.Release();
|
||||
}
|
||||
};
|
||||
|
||||
class CIntQueueMt: public CIntListCheck
|
||||
{
|
||||
int _numItems;
|
||||
int _head;
|
||||
int _cur;
|
||||
public:
|
||||
CIntQueueMt(): _numItems(0), _head(0), _cur(0) {}
|
||||
NWindows::NSynchronization::CSemaphore Semaphore;
|
||||
|
||||
bool AllocateList(int numItems)
|
||||
{
|
||||
FreeList();
|
||||
if (numItems == 0)
|
||||
return true;
|
||||
if (!CIntListCheck::AllocateList(numItems))
|
||||
return false;
|
||||
_numItems = numItems;
|
||||
return Semaphore.Create((LONG)0, (LONG)numItems);
|
||||
}
|
||||
|
||||
void FreeList()
|
||||
{
|
||||
CIntListCheck::FreeList();
|
||||
_numItems = 0;
|
||||
_head = 0;
|
||||
_cur = 0;
|
||||
}
|
||||
|
||||
void AddItem(int value)
|
||||
{
|
||||
_data[_head++] = value;
|
||||
if (_head == _numItems)
|
||||
_head = 0;
|
||||
LONG previousCount;
|
||||
Semaphore.Release(1, &previousCount);
|
||||
// printf("\nRelease prev = %d\n", previousCount);
|
||||
|
||||
}
|
||||
|
||||
int GetItem()
|
||||
{
|
||||
// Semaphore.Lock();
|
||||
int res = _data[_cur++];
|
||||
if (_cur == _numItems)
|
||||
_cur = 0;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
struct IInMemStreamMtCallback
|
||||
{
|
||||
// must be same for all calls
|
||||
virtual size_t GetBlockSize() = 0;
|
||||
|
||||
// Out:
|
||||
// result != S_OK stops Reading
|
||||
// if *p = 0, result must be != S_OK;
|
||||
// Locking is allowed
|
||||
virtual HRESULT AllocateBlock(void **p) = 0;
|
||||
|
||||
virtual void FreeBlock(void *p) = 0;
|
||||
|
||||
// It must allow to add at least numSubStreams + 1 ,
|
||||
// where numSubStreams is value from CInMemStreamMt::Create
|
||||
// value -1 means End of stream
|
||||
// Locking is not allowed
|
||||
virtual void AddStreamIndexToQueue(int index) = 0;
|
||||
};
|
||||
|
||||
struct CStreamInfo
|
||||
{
|
||||
CRecordVector<void *> Blocks;
|
||||
|
||||
int LastBlockIndex;
|
||||
size_t LastBlockPos;
|
||||
bool StreamWasFinished;
|
||||
|
||||
int CurBlockIndex;
|
||||
size_t CurBlockPos;
|
||||
|
||||
NWindows::NSynchronization::CCriticalSection *Cs;
|
||||
NWindows::NSynchronization::CManualResetEvent *CanReadEvent;
|
||||
|
||||
HRESULT ExitResult;
|
||||
|
||||
CStreamInfo(): Cs(0), CanReadEvent(0), StreamWasFinished(false) { }
|
||||
~CStreamInfo()
|
||||
{
|
||||
delete Cs;
|
||||
delete CanReadEvent;
|
||||
// Free();
|
||||
}
|
||||
void Create()
|
||||
{
|
||||
Cs = new NWindows::NSynchronization::CCriticalSection;
|
||||
CanReadEvent = new NWindows::NSynchronization::CManualResetEvent;
|
||||
}
|
||||
|
||||
void Free(IInMemStreamMtCallback *callback);
|
||||
void Init()
|
||||
{
|
||||
LastBlockIndex = CurBlockIndex = 0;
|
||||
CurBlockPos = LastBlockPos = 0;
|
||||
StreamWasFinished = false;
|
||||
ExitResult = S_OK;
|
||||
}
|
||||
|
||||
// res must be != S_OK
|
||||
void Exit(HRESULT res)
|
||||
{
|
||||
ExitResult = res;
|
||||
CanReadEvent->Set();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CInMemStreamMt
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
NWindows::NSynchronization::CCriticalSection CS;
|
||||
CObjectVector<CStreamInfo> _streams;
|
||||
int _nextFreeStreamIndex;
|
||||
int _currentStreamIndex;
|
||||
UInt64 _subStreamSize;
|
||||
|
||||
CResourceListMt _streamIndexAllocator;
|
||||
|
||||
// bool _stopReading;
|
||||
|
||||
public:
|
||||
HRESULT Read();
|
||||
HRESULT ReadResult;
|
||||
IInMemStreamMtCallback *Callback;
|
||||
void FreeSubStream(int subStreamIndex);
|
||||
HRESULT ReadSubStream(int subStreamIndex, void *data, UInt32 size, UInt32 *processedSize, bool keepData);
|
||||
|
||||
// numSubStreams: min = 1, good min = numThreads
|
||||
bool Create(int numSubStreams, UInt64 subStreamSize);
|
||||
~CInMemStreamMt() { Free(); }
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
|
||||
// to stop reading you must implement
|
||||
// returning Error in IInMemStreamMtCallback::AllocateBlock
|
||||
// and then you must free at least one substream
|
||||
bool StartReadThread();
|
||||
|
||||
void Free();
|
||||
|
||||
// you must free at least one substream after that function to unlock waiting.
|
||||
// void StopReading() { _stopReading = true; }
|
||||
};
|
||||
|
||||
class CInMemStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _size;
|
||||
bool _keepData;
|
||||
public:
|
||||
int Index;
|
||||
CInMemStreamMt *mtStream;
|
||||
void Init(bool keepData = false)
|
||||
{
|
||||
_size = 0; _keepData = keepData ;
|
||||
}
|
||||
MY_UNKNOWN_IMP
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
|
||||
#endif
|
||||
122
CPP/7zip/Common/InOutTempBuffer.cpp
Executable file
122
CPP/7zip/Common/InOutTempBuffer.cpp
Executable file
@@ -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;
|
||||
}
|
||||
55
CPP/7zip/Common/InOutTempBuffer.h
Executable file
55
CPP/7zip/Common/InOutTempBuffer.h
Executable file
@@ -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
|
||||
27
CPP/7zip/Common/LSBFDecoder.cpp
Executable file
27
CPP/7zip/Common/LSBFDecoder.cpp
Executable file
@@ -0,0 +1,27 @@
|
||||
// Stream/LSBFDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "LSBFDecoder.h"
|
||||
|
||||
namespace NStream {
|
||||
namespace NLSBF {
|
||||
|
||||
Byte kInvertTable[256];
|
||||
|
||||
class CInverterTableInitializer
|
||||
{
|
||||
public:
|
||||
CInverterTableInitializer()
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
int x = ((i & 0x55) << 1) | ((i & 0xAA) >> 1);
|
||||
x = ((x & 0x33) << 2) | ((x & 0xCC) >> 2);
|
||||
kInvertTable[i] = (Byte)(((x & 0x0F) << 4) | ((x & 0xF0) >> 4));
|
||||
}
|
||||
}
|
||||
} g_InverterTableInitializer;
|
||||
|
||||
|
||||
}}
|
||||
127
CPP/7zip/Common/LSBFDecoder.h
Executable file
127
CPP/7zip/Common/LSBFDecoder.h
Executable file
@@ -0,0 +1,127 @@
|
||||
// LSBFDecoder.h
|
||||
|
||||
#ifndef __STREAM_LSBFDECODER_H
|
||||
#define __STREAM_LSBFDECODER_H
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
namespace NStream {
|
||||
namespace NLSBF {
|
||||
|
||||
const int kNumBigValueBits = 8 * 4;
|
||||
|
||||
const int kNumValueBytes = 3;
|
||||
const int kNumValueBits = 8 * kNumValueBytes;
|
||||
|
||||
const UInt32 kMask = (1 << kNumValueBits) - 1;
|
||||
|
||||
extern Byte kInvertTable[256];
|
||||
// the Least Significant Bit of byte is First
|
||||
|
||||
template<class TInByte>
|
||||
class CBaseDecoder
|
||||
{
|
||||
protected:
|
||||
int m_BitPos;
|
||||
UInt32 m_Value;
|
||||
TInByte m_Stream;
|
||||
public:
|
||||
UInt32 NumExtraBytes;
|
||||
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
|
||||
void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream); }
|
||||
void ReleaseStream() { m_Stream.ReleaseStream(); }
|
||||
void Init()
|
||||
{
|
||||
m_Stream.Init();
|
||||
m_BitPos = kNumBigValueBits;
|
||||
m_Value = 0;
|
||||
NumExtraBytes = 0;
|
||||
}
|
||||
UInt64 GetProcessedSize() const
|
||||
{ return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; }
|
||||
UInt64 GetProcessedBitsSize() const
|
||||
{ return (m_Stream.GetProcessedSize() << 3) - (kNumBigValueBits - m_BitPos); }
|
||||
int GetBitPosition() const { return (m_BitPos & 7); }
|
||||
|
||||
void Normalize()
|
||||
{
|
||||
for (;m_BitPos >= 8; m_BitPos -= 8)
|
||||
{
|
||||
Byte b = 0;
|
||||
if (!m_Stream.ReadByte(b))
|
||||
{
|
||||
b = 0xFF; // check it
|
||||
NumExtraBytes++;
|
||||
}
|
||||
m_Value = (b << (kNumBigValueBits - m_BitPos)) | m_Value;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 ReadBits(int numBits)
|
||||
{
|
||||
Normalize();
|
||||
UInt32 res = m_Value & ((1 << numBits) - 1);
|
||||
m_BitPos += numBits;
|
||||
m_Value >>= numBits;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ExtraBitsWereRead() const
|
||||
{
|
||||
if (NumExtraBytes == 0)
|
||||
return false;
|
||||
return ((UInt32)(kNumBigValueBits - m_BitPos) < (NumExtraBytes << 3));
|
||||
}
|
||||
};
|
||||
|
||||
template<class TInByte>
|
||||
class CDecoder: public CBaseDecoder<TInByte>
|
||||
{
|
||||
UInt32 m_NormalValue;
|
||||
|
||||
public:
|
||||
void Init()
|
||||
{
|
||||
CBaseDecoder<TInByte>::Init();
|
||||
m_NormalValue = 0;
|
||||
}
|
||||
|
||||
void Normalize()
|
||||
{
|
||||
for (; this->m_BitPos >= 8; this->m_BitPos -= 8)
|
||||
{
|
||||
Byte b = 0;
|
||||
if (!this->m_Stream.ReadByte(b))
|
||||
{
|
||||
b = 0xFF; // check it
|
||||
this->NumExtraBytes++;
|
||||
}
|
||||
m_NormalValue = (b << (kNumBigValueBits - this->m_BitPos)) | m_NormalValue;
|
||||
this->m_Value = (this->m_Value << 8) | kInvertTable[b];
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 GetValue(int numBits)
|
||||
{
|
||||
Normalize();
|
||||
return ((this->m_Value >> (8 - this->m_BitPos)) & kMask) >> (kNumValueBits - numBits);
|
||||
}
|
||||
|
||||
void MovePos(int numBits)
|
||||
{
|
||||
this->m_BitPos += numBits;
|
||||
m_NormalValue >>= numBits;
|
||||
}
|
||||
|
||||
UInt32 ReadBits(int numBits)
|
||||
{
|
||||
Normalize();
|
||||
UInt32 res = m_NormalValue & ( (1 << numBits) - 1);
|
||||
MovePos(numBits);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
29
CPP/7zip/Common/LSBFEncoder.cpp
Executable file
29
CPP/7zip/Common/LSBFEncoder.cpp
Executable file
@@ -0,0 +1,29 @@
|
||||
// LSBFEncoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "LSBFEncoder.h"
|
||||
#include "Common/Defs.h"
|
||||
|
||||
namespace NStream {
|
||||
namespace NLSBF {
|
||||
|
||||
void CEncoder::WriteBits(UInt32 value, int numBits)
|
||||
{
|
||||
while(numBits > 0)
|
||||
{
|
||||
if (numBits < m_BitPos)
|
||||
{
|
||||
m_CurByte |= (value & ((1 << numBits) - 1)) << (8 - m_BitPos);
|
||||
m_BitPos -= numBits;
|
||||
return;
|
||||
}
|
||||
numBits -= m_BitPos;
|
||||
m_Stream.WriteByte((Byte)(m_CurByte | (value << (8 - m_BitPos))));
|
||||
value >>= m_BitPos;
|
||||
m_BitPos = 8;
|
||||
m_CurByte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
51
CPP/7zip/Common/LSBFEncoder.h
Executable file
51
CPP/7zip/Common/LSBFEncoder.h
Executable file
@@ -0,0 +1,51 @@
|
||||
// Stream/LSBFEncoder.h
|
||||
|
||||
#ifndef __STREAM_LSBFENCODER_H
|
||||
#define __STREAM_LSBFENCODER_H
|
||||
|
||||
#include "../IStream.h"
|
||||
#include "OutBuffer.h"
|
||||
|
||||
namespace NStream {
|
||||
namespace NLSBF {
|
||||
|
||||
class CEncoder
|
||||
{
|
||||
COutBuffer m_Stream;
|
||||
int m_BitPos;
|
||||
Byte m_CurByte;
|
||||
public:
|
||||
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
|
||||
void SetStream(ISequentialOutStream *outStream) { m_Stream.SetStream(outStream); }
|
||||
void ReleaseStream() { m_Stream.ReleaseStream(); }
|
||||
void Init()
|
||||
{
|
||||
m_Stream.Init();
|
||||
m_BitPos = 8;
|
||||
m_CurByte = 0;
|
||||
}
|
||||
HRESULT Flush()
|
||||
{
|
||||
FlushByte();
|
||||
return m_Stream.Flush();
|
||||
}
|
||||
|
||||
void FlushByte()
|
||||
{
|
||||
if(m_BitPos < 8)
|
||||
m_Stream.WriteByte(m_CurByte);
|
||||
m_BitPos = 8;
|
||||
m_CurByte = 0;
|
||||
}
|
||||
|
||||
void WriteBits(UInt32 value, int numBits);
|
||||
UInt32 GetBitPosition() const { return (8 - m_BitPos); }
|
||||
UInt64 GetProcessedSize() const {
|
||||
return m_Stream.GetProcessedSize() + (8 - m_BitPos + 7) /8; }
|
||||
void WriteByte(Byte b) { m_Stream.WriteByte(b);}
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
24
CPP/7zip/Common/LimitedStreams.cpp
Executable file
24
CPP/7zip/Common/LimitedStreams.cpp
Executable file
@@ -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;
|
||||
}
|
||||
|
||||
33
CPP/7zip/Common/LimitedStreams.h
Executable file
33
CPP/7zip/Common/LimitedStreams.h
Executable file
@@ -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
|
||||
23
CPP/7zip/Common/LockedStream.cpp
Executable file
23
CPP/7zip/Common/LockedStream.cpp
Executable file
@@ -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;
|
||||
}
|
||||
38
CPP/7zip/Common/LockedStream.h
Executable file
38
CPP/7zip/Common/LockedStream.h
Executable file
@@ -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
|
||||
69
CPP/7zip/Common/MSBFDecoder.h
Executable file
69
CPP/7zip/Common/MSBFDecoder.h
Executable file
@@ -0,0 +1,69 @@
|
||||
// MSBFDecoder.h
|
||||
// the Most Significant Bit of byte is First
|
||||
|
||||
#ifndef __STREAM_MSBFDECODER_H
|
||||
#define __STREAM_MSBFDECODER_H
|
||||
|
||||
#include "../../Common/Types.h"
|
||||
#include "../IStream.h"
|
||||
|
||||
namespace NStream {
|
||||
namespace NMSBF {
|
||||
|
||||
const int kNumBigValueBits = 8 * 4;
|
||||
const int kNumValueBytes = 3;
|
||||
const int kNumValueBits = 8 * kNumValueBytes;
|
||||
|
||||
const UInt32 kMask = (1 << kNumValueBits) - 1;
|
||||
|
||||
template<class TInByte>
|
||||
class CDecoder
|
||||
{
|
||||
UInt32 m_BitPos;
|
||||
UInt32 m_Value;
|
||||
public:
|
||||
TInByte m_Stream;
|
||||
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
|
||||
void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);}
|
||||
void ReleaseStream() { m_Stream.ReleaseStream();}
|
||||
|
||||
void Init()
|
||||
{
|
||||
m_Stream.Init();
|
||||
m_BitPos = kNumBigValueBits;
|
||||
Normalize();
|
||||
}
|
||||
|
||||
UInt64 GetProcessedSize() const
|
||||
{ return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; }
|
||||
UInt32 GetBitPosition() const { return (m_BitPos & 7); }
|
||||
|
||||
void Normalize()
|
||||
{
|
||||
for (;m_BitPos >= 8; m_BitPos -= 8)
|
||||
m_Value = (m_Value << 8) | m_Stream.ReadByte();
|
||||
}
|
||||
|
||||
UInt32 GetValue(UInt32 numBits) const
|
||||
{
|
||||
// return (m_Value << m_BitPos) >> (kNumBigValueBits - numBits);
|
||||
return ((m_Value >> (8 - m_BitPos)) & kMask) >> (kNumValueBits - numBits);
|
||||
}
|
||||
|
||||
void MovePos(UInt32 numBits)
|
||||
{
|
||||
m_BitPos += numBits;
|
||||
Normalize();
|
||||
}
|
||||
|
||||
UInt32 ReadBits(UInt32 numBits)
|
||||
{
|
||||
UInt32 res = GetValue(numBits);
|
||||
MovePos(numBits);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
59
CPP/7zip/Common/MSBFEncoder.h
Executable file
59
CPP/7zip/Common/MSBFEncoder.h
Executable file
@@ -0,0 +1,59 @@
|
||||
// Stream/MSBFEncoder.h
|
||||
|
||||
#ifndef __STREAM_MSBFENCODER_H
|
||||
#define __STREAM_MSBFENCODER_H
|
||||
|
||||
#include "Common/Defs.h"
|
||||
#include "../IStream.h"
|
||||
#include "OutBuffer.h"
|
||||
|
||||
namespace NStream {
|
||||
namespace NMSBF {
|
||||
|
||||
template<class TOutByte>
|
||||
class CEncoder
|
||||
{
|
||||
TOutByte m_Stream;
|
||||
int m_BitPos;
|
||||
Byte m_CurByte;
|
||||
public:
|
||||
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
|
||||
void SetStream(ISequentialOutStream *outStream) { m_Stream.SetStream(outStream);}
|
||||
void ReleaseStream() { m_Stream.ReleaseStream(); }
|
||||
void Init()
|
||||
{
|
||||
m_Stream.Init();
|
||||
m_BitPos = 8;
|
||||
m_CurByte = 0;
|
||||
}
|
||||
HRESULT Flush()
|
||||
{
|
||||
if(m_BitPos < 8)
|
||||
WriteBits(0, m_BitPos);
|
||||
return m_Stream.Flush();
|
||||
}
|
||||
|
||||
void WriteBits(UInt32 value, int numBits)
|
||||
{
|
||||
while(numBits > 0)
|
||||
{
|
||||
if (numBits < m_BitPos)
|
||||
{
|
||||
m_CurByte |= ((Byte)value << (m_BitPos -= numBits));
|
||||
return;
|
||||
}
|
||||
numBits -= m_BitPos;
|
||||
UInt32 newBits = (value >> numBits);
|
||||
value -= (newBits << numBits);
|
||||
m_Stream.WriteByte((Byte)(m_CurByte | newBits));
|
||||
m_BitPos = 8;
|
||||
m_CurByte = 0;
|
||||
}
|
||||
}
|
||||
UInt64 GetProcessedSize() const {
|
||||
return m_Stream.GetProcessedSize() + (8 - m_BitPos + 7) / 8; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
184
CPP/7zip/Common/MemBlocks.cpp
Executable file
184
CPP/7zip/Common/MemBlocks.cpp
Executable file
@@ -0,0 +1,184 @@
|
||||
// MemBlocks.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
|
||||
#include "StreamUtils.h"
|
||||
#include "MemBlocks.h"
|
||||
|
||||
bool CMemBlockManager::AllocateSpace(size_t numBlocks)
|
||||
{
|
||||
FreeSpace();
|
||||
if (_blockSize < sizeof(void *) || numBlocks < 1)
|
||||
return false;
|
||||
size_t totalSize = numBlocks * _blockSize;
|
||||
if (totalSize / _blockSize != numBlocks)
|
||||
return false;
|
||||
_data = ::MidAlloc(totalSize);
|
||||
if (_data == 0)
|
||||
return false;
|
||||
Byte *p = (Byte *)_data;
|
||||
for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize)
|
||||
*(Byte **)p = (p + _blockSize);
|
||||
*(Byte **)p = 0;
|
||||
_headFree = _data;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMemBlockManager::FreeSpace()
|
||||
{
|
||||
::MidFree(_data);
|
||||
_data = 0;
|
||||
_headFree= 0;
|
||||
}
|
||||
|
||||
void *CMemBlockManager::AllocateBlock()
|
||||
{
|
||||
if (_headFree == 0)
|
||||
return 0;
|
||||
void *p = _headFree;
|
||||
_headFree = *(void **)_headFree;
|
||||
return p;
|
||||
}
|
||||
|
||||
void CMemBlockManager::FreeBlock(void *p)
|
||||
{
|
||||
if (p == 0)
|
||||
return;
|
||||
*(void **)p = _headFree;
|
||||
_headFree = p;
|
||||
}
|
||||
|
||||
|
||||
bool CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)
|
||||
{
|
||||
if (numNoLockBlocks > numBlocks)
|
||||
return false;
|
||||
if (!CMemBlockManager::AllocateSpace(numBlocks))
|
||||
return false;
|
||||
size_t numLockBlocks = numBlocks - numNoLockBlocks;
|
||||
return Semaphore.Create((LONG)numLockBlocks, (LONG)numLockBlocks);
|
||||
}
|
||||
|
||||
bool CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)
|
||||
{
|
||||
if (numNoLockBlocks > desiredNumberOfBlocks)
|
||||
return false;
|
||||
for (;;)
|
||||
{
|
||||
if (AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks))
|
||||
return true;
|
||||
if (desiredNumberOfBlocks == numNoLockBlocks)
|
||||
return false;
|
||||
desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CMemBlockManagerMt::FreeSpace()
|
||||
{
|
||||
Semaphore.Close();
|
||||
CMemBlockManager::FreeSpace();
|
||||
}
|
||||
|
||||
void *CMemBlockManagerMt::AllocateBlock()
|
||||
{
|
||||
// Semaphore.Lock();
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
|
||||
return CMemBlockManager::AllocateBlock();
|
||||
}
|
||||
|
||||
void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode)
|
||||
{
|
||||
if (p == 0)
|
||||
return;
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
|
||||
CMemBlockManager::FreeBlock(p);
|
||||
}
|
||||
if (lockMode)
|
||||
Semaphore.Release();
|
||||
}
|
||||
|
||||
void CMemBlocks::Free(CMemBlockManagerMt *manager)
|
||||
{
|
||||
while(Blocks.Size() > 0)
|
||||
{
|
||||
manager->FreeBlock(Blocks.Back());
|
||||
Blocks.DeleteBack();
|
||||
}
|
||||
TotalSize = 0;
|
||||
}
|
||||
|
||||
void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager)
|
||||
{
|
||||
Free(manager);
|
||||
Blocks.Free(); // to reduce memory usage
|
||||
}
|
||||
|
||||
HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const
|
||||
{
|
||||
UInt64 totalSize = TotalSize;
|
||||
for (int blockIndex = 0; totalSize > 0; blockIndex++)
|
||||
{
|
||||
UInt32 curSize = (UInt32)blockSize;
|
||||
if (totalSize < curSize)
|
||||
curSize = (UInt32)totalSize;
|
||||
UInt32 processedSize;
|
||||
if (blockIndex >= Blocks.Size())
|
||||
return E_FAIL;
|
||||
RINOK(WriteStream(outStream, Blocks[blockIndex], curSize, &processedSize));
|
||||
if (processedSize != curSize)
|
||||
return E_FAIL;
|
||||
totalSize -= processedSize;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager)
|
||||
{
|
||||
memManager->FreeBlock(Blocks[index], LockMode);
|
||||
Blocks[index] = 0;
|
||||
}
|
||||
|
||||
void CMemLockBlocks::Free(CMemBlockManagerMt *memManager)
|
||||
{
|
||||
while (Blocks.Size() > 0)
|
||||
{
|
||||
FreeBlock(Blocks.Size() - 1, memManager);
|
||||
Blocks.DeleteBack();
|
||||
}
|
||||
TotalSize = 0;
|
||||
}
|
||||
|
||||
bool CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager)
|
||||
{
|
||||
if (LockMode)
|
||||
{
|
||||
if (Blocks.Size() > 0)
|
||||
if (!memManager->ReleaseLockedBlocks(Blocks.Size()))
|
||||
return false;
|
||||
LockMode = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager)
|
||||
{
|
||||
blocks.Free(memManager);
|
||||
blocks.LockMode = LockMode;
|
||||
UInt64 totalSize = 0;
|
||||
size_t blockSize = memManager->GetBlockSize();
|
||||
for (int i = 0; i < Blocks.Size(); i++)
|
||||
{
|
||||
if (totalSize < TotalSize)
|
||||
blocks.Blocks.Add(Blocks[i]);
|
||||
else
|
||||
FreeBlock(i, memManager);
|
||||
Blocks[i] = 0;
|
||||
totalSize += blockSize;
|
||||
}
|
||||
blocks.TotalSize = TotalSize;
|
||||
Free(memManager);
|
||||
}
|
||||
73
CPP/7zip/Common/MemBlocks.h
Executable file
73
CPP/7zip/Common/MemBlocks.h
Executable file
@@ -0,0 +1,73 @@
|
||||
// MemBlocks.h
|
||||
|
||||
#ifndef __MEMBLOCKS_H
|
||||
#define __MEMBLOCKS_H
|
||||
|
||||
#include "Common/Alloc.h"
|
||||
#include "Common/Types.h"
|
||||
#include "Common/Vector.h"
|
||||
|
||||
#include "Windows/Synchronization.h"
|
||||
|
||||
#include "../IStream.h"
|
||||
|
||||
class CMemBlockManager
|
||||
{
|
||||
void *_data;
|
||||
size_t _blockSize;
|
||||
void *_headFree;
|
||||
public:
|
||||
CMemBlockManager(size_t blockSize = (1 << 20)): _data(0), _blockSize(blockSize), _headFree(0) {}
|
||||
~CMemBlockManager() { FreeSpace(); }
|
||||
|
||||
bool AllocateSpace(size_t numBlocks);
|
||||
void FreeSpace();
|
||||
size_t GetBlockSize() const { return _blockSize; }
|
||||
void *AllocateBlock();
|
||||
void FreeBlock(void *p);
|
||||
};
|
||||
|
||||
|
||||
class CMemBlockManagerMt: public CMemBlockManager
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSection _criticalSection;
|
||||
public:
|
||||
NWindows::NSynchronization::CSemaphore Semaphore;
|
||||
|
||||
CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {}
|
||||
~CMemBlockManagerMt() { FreeSpace(); }
|
||||
|
||||
bool AllocateSpace(size_t numBlocks, size_t numNoLockBlocks = 0);
|
||||
bool AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0);
|
||||
void FreeSpace();
|
||||
void *AllocateBlock();
|
||||
void FreeBlock(void *p, bool lockMode = true);
|
||||
bool ReleaseLockedBlocks(int number) { return Semaphore.Release(number); }
|
||||
};
|
||||
|
||||
|
||||
class CMemBlocks
|
||||
{
|
||||
void Free(CMemBlockManagerMt *manager);
|
||||
public:
|
||||
CRecordVector<void *> Blocks;
|
||||
UInt64 TotalSize;
|
||||
|
||||
CMemBlocks(): TotalSize(0) {}
|
||||
|
||||
void FreeOpt(CMemBlockManagerMt *manager);
|
||||
HRESULT WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const;
|
||||
};
|
||||
|
||||
struct CMemLockBlocks: public CMemBlocks
|
||||
{
|
||||
bool LockMode;
|
||||
|
||||
CMemLockBlocks(): LockMode(true) {};
|
||||
void Free(CMemBlockManagerMt *memManager);
|
||||
void FreeBlock(int index, CMemBlockManagerMt *memManager);
|
||||
bool SwitchToNoLockMode(CMemBlockManagerMt *memManager);
|
||||
void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager);
|
||||
};
|
||||
|
||||
#endif
|
||||
35
CPP/7zip/Common/OffsetStream.cpp
Executable file
35
CPP/7zip/Common/OffsetStream.cpp
Executable file
@@ -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);
|
||||
}
|
||||
25
CPP/7zip/Common/OffsetStream.h
Executable file
25
CPP/7zip/Common/OffsetStream.h
Executable file
@@ -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
|
||||
116
CPP/7zip/Common/OutBuffer.cpp
Executable file
116
CPP/7zip/Common/OutBuffer.cpp
Executable file
@@ -0,0 +1,116 @@
|
||||
// OutByte.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "OutBuffer.h"
|
||||
|
||||
#include "../../Common/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 = FlushPart();
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
ErrorCode = result;
|
||||
#else
|
||||
if (result != S_OK)
|
||||
throw COutBufferException(result);
|
||||
#endif
|
||||
}
|
||||
64
CPP/7zip/Common/OutBuffer.h
Executable file
64
CPP/7zip/Common/OutBuffer.h
Executable file
@@ -0,0 +1,64 @@
|
||||
// OutBuffer.h
|
||||
|
||||
#ifndef __OUTBUFFER_H
|
||||
#define __OUTBUFFER_H
|
||||
|
||||
#include "../IStream.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
struct COutBufferException
|
||||
{
|
||||
HRESULT ErrorCode;
|
||||
COutBufferException(HRESULT errorCode): ErrorCode(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();
|
||||
void FlushWithCheck();
|
||||
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 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
|
||||
137
CPP/7zip/Common/OutMemStream.cpp
Executable file
137
CPP/7zip/Common/OutMemStream.cpp
Executable file
@@ -0,0 +1,137 @@
|
||||
// OutMemStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "OutMemStream.h"
|
||||
|
||||
void COutMemStream::Free()
|
||||
{
|
||||
Blocks.Free(_memManager);
|
||||
Blocks.LockMode = true;
|
||||
}
|
||||
|
||||
void COutMemStream::Init()
|
||||
{
|
||||
WriteToRealStreamEvent.Reset();
|
||||
_unlockEventWasSent = false;
|
||||
_realStreamMode = false;
|
||||
Free();
|
||||
_curBlockPos = 0;
|
||||
_curBlockIndex = 0;
|
||||
}
|
||||
|
||||
void COutMemStream::DetachData(CMemLockBlocks &blocks)
|
||||
{
|
||||
Blocks.Detach(blocks, _memManager);
|
||||
Free();
|
||||
}
|
||||
|
||||
|
||||
HRESULT COutMemStream::WriteToRealStream()
|
||||
{
|
||||
RINOK(Blocks.WriteToStream(_memManager->GetBlockSize(), OutSeqStream));
|
||||
Blocks.Free(_memManager);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (_realStreamMode)
|
||||
return OutSeqStream->Write(data, size, processedSize);
|
||||
if (processedSize != 0)
|
||||
*processedSize = 0;
|
||||
while(size != 0)
|
||||
{
|
||||
if ((int)_curBlockIndex < Blocks.Blocks.Size())
|
||||
{
|
||||
Byte *p = (Byte *)Blocks.Blocks[(int)_curBlockIndex] + _curBlockPos;
|
||||
size_t curSize = _memManager->GetBlockSize() - _curBlockPos;
|
||||
if (size < curSize)
|
||||
curSize = size;
|
||||
memmove(p, data, curSize);
|
||||
if (processedSize != 0)
|
||||
*processedSize += (UInt32)curSize;
|
||||
data = (const void *)((const Byte *)data + curSize);
|
||||
size -= (UInt32)curSize;
|
||||
_curBlockPos += curSize;
|
||||
|
||||
UInt64 pos64 = GetPos();
|
||||
if (pos64 > Blocks.TotalSize)
|
||||
Blocks.TotalSize = pos64;
|
||||
if (_curBlockPos == _memManager->GetBlockSize())
|
||||
{
|
||||
_curBlockIndex++;
|
||||
_curBlockPos = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
HANDLE events[4] = { StopWritingEvent, WriteToRealStreamEvent, NoLockEvent, _memManager->Semaphore };
|
||||
DWORD waitResult = ::WaitForMultipleObjects((Blocks.LockMode ? 4 : 2), events, FALSE, INFINITE);
|
||||
switch (waitResult)
|
||||
{
|
||||
case (WAIT_OBJECT_0 + 0):
|
||||
return StopWriteResult;
|
||||
case (WAIT_OBJECT_0 + 1):
|
||||
{
|
||||
_realStreamMode = true;
|
||||
RINOK(WriteToRealStream());
|
||||
UInt32 processedSize2;
|
||||
HRESULT res = OutSeqStream->Write(data, size, &processedSize2);
|
||||
if (processedSize != 0)
|
||||
*processedSize += processedSize2;
|
||||
return res;
|
||||
}
|
||||
case (WAIT_OBJECT_0 + 2):
|
||||
{
|
||||
if (!Blocks.SwitchToNoLockMode(_memManager))
|
||||
return E_FAIL;
|
||||
break;
|
||||
}
|
||||
case (WAIT_OBJECT_0 + 3):
|
||||
break;
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
Blocks.Blocks.Add(_memManager->AllocateBlock());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if (_realStreamMode)
|
||||
{
|
||||
if (!OutStream)
|
||||
return E_FAIL;
|
||||
return OutStream->Seek(offset, seekOrigin, newPosition);
|
||||
}
|
||||
if (seekOrigin == STREAM_SEEK_CUR)
|
||||
{
|
||||
if (offset != 0)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
else if (seekOrigin == STREAM_SEEK_SET)
|
||||
{
|
||||
if (offset != 0)
|
||||
return E_NOTIMPL;
|
||||
_curBlockIndex = 0;
|
||||
_curBlockPos = 0;
|
||||
}
|
||||
else
|
||||
return E_NOTIMPL;
|
||||
if (newPosition != 0)
|
||||
*newPosition = GetPos();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMemStream::SetSize(Int64 newSize)
|
||||
{
|
||||
if (_realStreamMode)
|
||||
{
|
||||
if (!OutStream)
|
||||
return E_FAIL;
|
||||
return OutStream->SetSize(newSize);
|
||||
}
|
||||
Blocks.TotalSize = newSize;
|
||||
return S_OK;
|
||||
}
|
||||
88
CPP/7zip/Common/OutMemStream.h
Executable file
88
CPP/7zip/Common/OutMemStream.h
Executable file
@@ -0,0 +1,88 @@
|
||||
// OutMemStream.h
|
||||
|
||||
#ifndef __OUTMEMSTREAM_H
|
||||
#define __OUTMEMSTREAM_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "MemBlocks.h"
|
||||
|
||||
class COutMemStream:
|
||||
public IOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMemBlockManagerMt *_memManager;
|
||||
size_t _curBlockIndex;
|
||||
size_t _curBlockPos;
|
||||
bool _realStreamMode;
|
||||
|
||||
bool _unlockEventWasSent;
|
||||
NWindows::NSynchronization::CAutoResetEvent StopWritingEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent WriteToRealStreamEvent;
|
||||
NWindows::NSynchronization::CAutoResetEvent NoLockEvent;
|
||||
|
||||
HRESULT StopWriteResult;
|
||||
CMemLockBlocks Blocks;
|
||||
|
||||
UInt64 GetPos() const { return (UInt64)_curBlockIndex * _memManager->GetBlockSize() + _curBlockPos; }
|
||||
|
||||
CMyComPtr<ISequentialOutStream> OutSeqStream;
|
||||
CMyComPtr<IOutStream> OutStream;
|
||||
|
||||
public:
|
||||
|
||||
void SetOutStream(IOutStream *outStream)
|
||||
{
|
||||
OutStream = outStream;
|
||||
OutSeqStream = outStream;
|
||||
}
|
||||
|
||||
void SetSeqOutStream(ISequentialOutStream *outStream)
|
||||
{
|
||||
OutStream = NULL;
|
||||
OutSeqStream = outStream;
|
||||
}
|
||||
|
||||
void ReleaseOutStream()
|
||||
{
|
||||
OutStream.Release();
|
||||
OutSeqStream.Release();
|
||||
}
|
||||
|
||||
COutMemStream(CMemBlockManagerMt *memManager): _memManager(memManager) { }
|
||||
|
||||
~COutMemStream() { Free(); }
|
||||
void Free();
|
||||
|
||||
void Init();
|
||||
HRESULT WriteToRealStream();
|
||||
|
||||
void DetachData(CMemLockBlocks &blocks);
|
||||
|
||||
bool WasUnlockEventSent() const { return _unlockEventWasSent; }
|
||||
|
||||
void SetRealStreamMode()
|
||||
{
|
||||
_unlockEventWasSent = true;
|
||||
WriteToRealStreamEvent.Set();
|
||||
}
|
||||
|
||||
void SetNoLockMode()
|
||||
{
|
||||
_unlockEventWasSent = true;
|
||||
NoLockEvent.Set();
|
||||
}
|
||||
|
||||
void StopWriting(HRESULT res)
|
||||
{
|
||||
StopWriteResult = res;
|
||||
StopWritingEvent.Set();
|
||||
}
|
||||
|
||||
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
|
||||
53
CPP/7zip/Common/ProgressMt.cpp
Executable file
53
CPP/7zip/Common/ProgressMt.cpp
Executable file
@@ -0,0 +1,53 @@
|
||||
// ProgressMt.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ProgressMt.h"
|
||||
|
||||
void CMtCompressProgressMixer::Init(int numItems, ICompressProgressInfo *progress)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
InSizes.Clear();
|
||||
OutSizes.Clear();
|
||||
for (int i = 0; i < numItems; i++)
|
||||
{
|
||||
InSizes.Add(0);
|
||||
OutSizes.Add(0);
|
||||
}
|
||||
TotalInSize = 0;
|
||||
TotalOutSize = 0;
|
||||
_progress = progress;
|
||||
}
|
||||
|
||||
void CMtCompressProgressMixer::Reinit(int index)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
InSizes[index] = 0;
|
||||
OutSizes[index] = 0;
|
||||
}
|
||||
|
||||
HRESULT CMtCompressProgressMixer::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
|
||||
if (inSize != 0)
|
||||
{
|
||||
UInt64 diff = *inSize - InSizes[index];
|
||||
InSizes[index] = *inSize;
|
||||
TotalInSize += diff;
|
||||
}
|
||||
if (outSize != 0)
|
||||
{
|
||||
UInt64 diff = *outSize - OutSizes[index];
|
||||
OutSizes[index] = *outSize;
|
||||
TotalOutSize += diff;
|
||||
}
|
||||
if (_progress)
|
||||
return _progress->SetRatioInfo(&TotalInSize, &TotalOutSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CMtCompressProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
return _progress->SetRatioInfo(_index, inSize, outSize);
|
||||
}
|
||||
47
CPP/7zip/Common/ProgressMt.h
Executable file
47
CPP/7zip/Common/ProgressMt.h
Executable file
@@ -0,0 +1,47 @@
|
||||
// ProgressMt.h
|
||||
|
||||
#ifndef __PROGRESSMT_H
|
||||
#define __PROGRESSMT_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IProgress.h"
|
||||
|
||||
#include "Windows/Synchronization.h"
|
||||
#include "../../Common/Vector.h"
|
||||
|
||||
class CMtCompressProgressMixer
|
||||
{
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
CRecordVector<UInt64> InSizes;
|
||||
CRecordVector<UInt64> OutSizes;
|
||||
UInt64 TotalInSize;
|
||||
UInt64 TotalOutSize;
|
||||
public:
|
||||
NWindows::NSynchronization::CCriticalSection CriticalSection;
|
||||
void Init(int numItems, ICompressProgressInfo *progress);
|
||||
void Reinit(int index);
|
||||
HRESULT SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
class CMtCompressProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMtCompressProgressMixer *_progress;
|
||||
int _index;
|
||||
public:
|
||||
void Init(CMtCompressProgressMixer *progress, int index)
|
||||
{
|
||||
_progress = progress;
|
||||
_index = index;
|
||||
}
|
||||
void Reinit() { _progress->Reinit(_index); }
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
55
CPP/7zip/Common/ProgressUtils.cpp
Executable file
55
CPP/7zip/Common/ProgressUtils.cpp
Executable file
@@ -0,0 +1,55 @@
|
||||
// ProgressUtils.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ProgressUtils.h"
|
||||
|
||||
void CLocalCompressProgressInfo::Init(ICompressProgressInfo *progress,
|
||||
const UInt64 *inStartValue, const UInt64 *outStartValue)
|
||||
{
|
||||
_progress = progress;
|
||||
_inStartValueIsAssigned = (inStartValue != NULL);
|
||||
if (_inStartValueIsAssigned)
|
||||
_inStartValue = *inStartValue;
|
||||
_outStartValueIsAssigned = (outStartValue != NULL);
|
||||
if (_outStartValueIsAssigned)
|
||||
_outStartValue = *outStartValue;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLocalCompressProgressInfo::SetRatioInfo(
|
||||
const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
UInt64 inSizeNew, outSizeNew;
|
||||
const UInt64 *inSizeNewPointer;
|
||||
const UInt64 *outSizeNewPointer;
|
||||
if (_inStartValueIsAssigned && inSize != NULL)
|
||||
{
|
||||
inSizeNew = _inStartValue + (*inSize);
|
||||
inSizeNewPointer = &inSizeNew;
|
||||
}
|
||||
else
|
||||
inSizeNewPointer = NULL;
|
||||
|
||||
if (_outStartValueIsAssigned && outSize != NULL)
|
||||
{
|
||||
outSizeNew = _outStartValue + (*outSize);
|
||||
outSizeNewPointer = &outSizeNew;
|
||||
}
|
||||
else
|
||||
outSizeNewPointer = NULL;
|
||||
return _progress->SetRatioInfo(inSizeNewPointer, outSizeNewPointer);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
|
||||
void CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)
|
||||
{
|
||||
_progress = progress;
|
||||
_inSizeIsMain = inSizeIsMain;
|
||||
}
|
||||
|
||||
STDMETHODIMP CLocalProgress::SetRatioInfo(
|
||||
const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
return _progress->SetCompleted(_inSizeIsMain ? inSize : outSize);
|
||||
}
|
||||
43
CPP/7zip/Common/ProgressUtils.h
Executable file
43
CPP/7zip/Common/ProgressUtils.h
Executable file
@@ -0,0 +1,43 @@
|
||||
// ProgressUtils.h
|
||||
|
||||
#ifndef __PROGRESSUTILS_H
|
||||
#define __PROGRESSUTILS_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IProgress.h"
|
||||
|
||||
class CLocalCompressProgressInfo:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ICompressProgressInfo> _progress;
|
||||
bool _inStartValueIsAssigned;
|
||||
bool _outStartValueIsAssigned;
|
||||
UInt64 _inStartValue;
|
||||
UInt64 _outStartValue;
|
||||
public:
|
||||
void Init(ICompressProgressInfo *progress,
|
||||
const UInt64 *inStartValue, const UInt64 *outStartValue);
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
class CLocalProgress:
|
||||
public ICompressProgressInfo,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<IProgress> _progress;
|
||||
bool _inSizeIsMain;
|
||||
public:
|
||||
void Init(IProgress *progress, bool inSizeIsMain);
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
9
CPP/7zip/Common/StdAfx.h
Executable file
9
CPP/7zip/Common/StdAfx.h
Executable file
@@ -0,0 +1,9 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../Common/MyWindows.h"
|
||||
#include "../../Common/NewHandler.h"
|
||||
|
||||
#endif
|
||||
162
CPP/7zip/Common/StreamBinder.cpp
Executable file
162
CPP/7zip/Common/StreamBinder.cpp
Executable file
@@ -0,0 +1,162 @@
|
||||
// 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.
|
||||
|
||||
void CStreamBinder::CreateEvents()
|
||||
{
|
||||
_allBytesAreWritenEvent = new CManualResetEvent(true);
|
||||
_thereAreBytesToReadEvent = new CManualResetEvent(false);
|
||||
_readStreamIsClosedEvent = new CManualResetEvent(false);
|
||||
}
|
||||
|
||||
void CStreamBinder::ReInit()
|
||||
{
|
||||
_thereAreBytesToReadEvent->Reset();
|
||||
_readStreamIsClosedEvent->Reset();
|
||||
ProcessedSize = 0;
|
||||
}
|
||||
|
||||
CStreamBinder::~CStreamBinder()
|
||||
{
|
||||
if (_allBytesAreWritenEvent != NULL)
|
||||
delete _allBytesAreWritenEvent;
|
||||
if (_thereAreBytesToReadEvent != NULL)
|
||||
delete _thereAreBytesToReadEvent;
|
||||
if (_readStreamIsClosedEvent != NULL)
|
||||
delete _readStreamIsClosedEvent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
if(!_thereAreBytesToReadEvent->Lock())
|
||||
return E_FAIL;
|
||||
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 E_FAIL;
|
||||
}
|
||||
// if(!_allBytesAreWritenEvent.Lock())
|
||||
// return E_FAIL;
|
||||
}
|
||||
if (processedSize != NULL)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CStreamBinder::CloseWrite()
|
||||
{
|
||||
// _bufferSize must be = 0
|
||||
_thereAreBytesToReadEvent->Set();
|
||||
}
|
||||
37
CPP/7zip/Common/StreamBinder.h
Executable file
37
CPP/7zip/Common/StreamBinder.h
Executable file
@@ -0,0 +1,37 @@
|
||||
// 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():
|
||||
_allBytesAreWritenEvent(NULL),
|
||||
_thereAreBytesToReadEvent(NULL),
|
||||
_readStreamIsClosedEvent(NULL)
|
||||
{}
|
||||
~CStreamBinder();
|
||||
void 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
|
||||
68
CPP/7zip/Common/StreamObjects.cpp
Executable file
68
CPP/7zip/Common/StreamObjects.cpp
Executable file
@@ -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;
|
||||
}
|
||||
117
CPP/7zip/Common/StreamObjects.h
Executable file
117
CPP/7zip/Common/StreamObjects.h
Executable file
@@ -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
|
||||
44
CPP/7zip/Common/StreamUtils.cpp
Executable file
44
CPP/7zip/Common/StreamUtils.cpp
Executable file
@@ -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)
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
11
CPP/7zip/Common/StreamUtils.h
Executable file
11
CPP/7zip/Common/StreamUtils.h
Executable file
@@ -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
|
||||
Reference in New Issue
Block a user