4.44 beta

This commit is contained in:
Igor Pavlov
2007-01-20 00:00:00 +00:00
committed by Kornel Lesiński
parent 804edc5756
commit d9666cf046
1331 changed files with 10535 additions and 13791 deletions

View 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;
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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;
}

View 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
View 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
View 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
View 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
View 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

View 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;
}

View 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

View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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
View 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
View 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
View 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

View 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
View 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
View 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
View 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