diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2021-07-23 01:00:14 +0300 |
---|---|---|
committer | Kornel <kornel@geekhood.net> | 2021-07-23 01:00:14 +0300 |
commit | 585698650f7257d2cefa6a3a2a49d5bbe84fd9b2 (patch) | |
tree | 8900be42e892a440bbd1063804b0557288c2f97f /CPP/7zip/Common | |
parent | 4a960640a340a848a2d2c27f19b339c2c3d3f734 (diff) |
21.0221.02
Diffstat (limited to 'CPP/7zip/Common')
30 files changed, 800 insertions, 382 deletions
diff --git a/CPP/7zip/Common/CWrappers.cpp b/CPP/7zip/Common/CWrappers.cpp index d6b04206..ee4c36a2 100644 --- a/CPP/7zip/Common/CWrappers.cpp +++ b/CPP/7zip/Common/CWrappers.cpp @@ -1,4 +1,4 @@ -// CWrappers.h +// CWrappers.c #include "StdAfx.h" @@ -158,27 +158,27 @@ void CSeekInStreamWrap::Init(IInStream *stream) throw() void CByteInBufWrap::Free() throw() { ::MidFree(Buf); - Buf = 0; + Buf = NULL; } bool CByteInBufWrap::Alloc(UInt32 size) throw() { - if (Buf == 0 || size != Size) + if (!Buf || size != Size) { Free(); Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size); Size = size; } - return (Buf != 0); + return (Buf != NULL); } Byte CByteInBufWrap::ReadByteFromNewBlock() throw() { - if (Res == S_OK) + if (!Extra && Res == S_OK) { UInt32 avail; - Processed += (Cur - Buf); Res = Stream->Read(Buf, Size, &avail); + Processed += (size_t)(Cur - Buf); Cur = Buf; Lim = Buf + avail; if (avail != 0) @@ -196,41 +196,88 @@ static Byte Wrap_ReadByte(const IByteIn *pp) throw() return p->ReadByteFromNewBlock(); } -CByteInBufWrap::CByteInBufWrap(): Buf(0) +CByteInBufWrap::CByteInBufWrap(): Buf(NULL) { vt.Read = Wrap_ReadByte; } + +/* ---------- CByteOutBufWrap ---------- */ + +/* +void CLookToSequentialWrap::Free() throw() +{ + ::MidFree(BufBase); + BufBase = NULL; +} + +bool CLookToSequentialWrap::Alloc(UInt32 size) throw() +{ + if (!BufBase || size != Size) + { + Free(); + BufBase = (Byte *)::MidAlloc((size_t)size); + Size = size; + } + return (BufBase != NULL); +} +*/ + +/* +EXTERN_C_BEGIN + +void CLookToSequentialWrap_Look(ILookInSeqStream *pp) +{ + CLookToSequentialWrap *p = (CLookToSequentialWrap *)pp->Obj; + + if (p->Extra || p->Res != S_OK) + return; + { + UInt32 avail; + p->Res = p->Stream->Read(p->BufBase, p->Size, &avail); + p->Processed += avail; + pp->Buf = p->BufBase; + pp->Limit = pp->Buf + avail; + if (avail == 0) + p->Extra = true; + } +} + +EXTERN_C_END +*/ + + /* ---------- CByteOutBufWrap ---------- */ void CByteOutBufWrap::Free() throw() { ::MidFree(Buf); - Buf = 0; + Buf = NULL; } bool CByteOutBufWrap::Alloc(size_t size) throw() { - if (Buf == 0 || size != Size) + if (!Buf || size != Size) { Free(); Buf = (Byte *)::MidAlloc(size); Size = size; } - return (Buf != 0); + return (Buf != NULL); } HRESULT CByteOutBufWrap::Flush() throw() { if (Res == S_OK) { - size_t size = (Cur - Buf); + const size_t size = (size_t)(Cur - Buf); Res = WriteStream(Stream, Buf, size); if (Res == S_OK) Processed += size; - Cur = Buf; + // else throw 11; } + Cur = Buf; // reset pointer for later Wrap_WriteByte() return Res; } @@ -244,7 +291,57 @@ static void Wrap_WriteByte(const IByteOut *pp, Byte b) throw() p->Flush(); } -CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(0) +CByteOutBufWrap::CByteOutBufWrap() throw(): Buf(NULL), Size(0) { vt.Write = Wrap_WriteByte; } + + +/* ---------- CLookOutWrap ---------- */ + +/* +void CLookOutWrap::Free() throw() +{ + ::MidFree(Buf); + Buf = NULL; +} + +bool CLookOutWrap::Alloc(size_t size) throw() +{ + if (!Buf || size != Size) + { + Free(); + Buf = (Byte *)::MidAlloc(size); + Size = size; + } + return (Buf != NULL); +} + +static size_t LookOutWrap_GetOutBuf(const ILookOutStream *pp, void **buf) throw() +{ + CLookOutWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt); + *buf = p->Buf; + return p->Size; +} + +static size_t LookOutWrap_Write(const ILookOutStream *pp, size_t size) throw() +{ + CLookOutWrap *p = CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt); + if (p->Res == S_OK && size != 0) + { + p->Res = WriteStream(p->Stream, p->Buf, size); + if (p->Res == S_OK) + { + p->Processed += size; + return size; + } + } + return 0; +} + +CLookOutWrap::CLookOutWrap() throw(): Buf(NULL), Size(0) +{ + vt.GetOutBuf = LookOutWrap_GetOutBuf; + vt.Write = LookOutWrap_Write; +} +*/ diff --git a/CPP/7zip/Common/CWrappers.h b/CPP/7zip/Common/CWrappers.h index e5c890d8..e7196a5c 100644 --- a/CPP/7zip/Common/CWrappers.h +++ b/CPP/7zip/Common/CWrappers.h @@ -74,7 +74,7 @@ struct CByteInBufWrap Extra = false; Res = S_OK; } - UInt64 GetProcessed() const { return Processed + (Cur - Buf); } + UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); } Byte ReadByteFromNewBlock() throw(); Byte ReadByte() { @@ -85,6 +85,45 @@ struct CByteInBufWrap }; +/* +struct CLookToSequentialWrap +{ + Byte *BufBase; + UInt32 Size; + ISequentialInStream *Stream; + UInt64 Processed; + bool Extra; + HRESULT Res; + + CLookToSequentialWrap(): BufBase(NULL) {} + ~CLookToSequentialWrap() { Free(); } + void Free() throw(); + bool Alloc(UInt32 size) throw(); + void Init() + { + // Lim = Cur = Buf; + Processed = 0; + Extra = false; + Res = S_OK; + } + // UInt64 GetProcessed() const { return Processed + (Cur - Buf); } + + Byte ReadByteFromNewBlock() throw(); + Byte ReadByte() + { + if (Cur != Lim) + return *Cur++; + return ReadByteFromNewBlock(); + } +}; + +EXTERN_C_BEGIN +// void CLookToSequentialWrap_Look(ILookInSeqStream *pp); +EXTERN_C_END +*/ + + + struct CByteOutBufWrap { IByteOut vt; @@ -107,7 +146,7 @@ struct CByteOutBufWrap Processed = 0; Res = S_OK; } - UInt64 GetProcessed() const { return Processed + (Cur - Buf); } + UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); } HRESULT Flush() throw(); void WriteByte(Byte b) { @@ -117,4 +156,27 @@ struct CByteOutBufWrap } }; + +/* +struct CLookOutWrap +{ + ILookOutStream vt; + Byte *Buf; + size_t Size; + ISequentialOutStream *Stream; + UInt64 Processed; + HRESULT Res; + + CLookOutWrap() throw(); + ~CLookOutWrap() { Free(); } + void Free() throw(); + bool Alloc(size_t size) throw(); + void Init() + { + Processed = 0; + Res = S_OK; + } +}; +*/ + #endif diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp index bf525dc8..e62bb0b4 100644 --- a/CPP/7zip/Common/CreateCoder.cpp +++ b/CPP/7zip/Common/CreateCoder.cpp @@ -11,19 +11,23 @@ #include "RegisterCodec.h" static const unsigned kNumCodecsMax = 64; +extern +unsigned g_NumCodecs; unsigned g_NumCodecs = 0; +extern +const CCodecInfo *g_Codecs[]; const CCodecInfo *g_Codecs[kNumCodecsMax]; // We use g_ExternalCodecs in other stages. -/* #ifdef EXTERNAL_CODECS +/* extern CExternalCodecs g_ExternalCodecs; #define CHECK_GLOBAL_CODECS \ if (!__externalCodecs || !__externalCodecs->IsSet()) __externalCodecs = &g_ExternalCodecs; -#endif */ - #define CHECK_GLOBAL_CODECS +#endif + void RegisterCodec(const CCodecInfo *codecInfo) throw() { @@ -32,7 +36,11 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw() } static const unsigned kNumHashersMax = 16; +extern +unsigned g_NumHashers; unsigned g_NumHashers = 0; +extern +const CHasherInfo *g_Hashers[]; const CHasherInfo *g_Hashers[kNumHashersMax]; void RegisterHasher(const CHasherInfo *hashInfo) throw() @@ -164,7 +172,7 @@ int FindMethod_Index( { methodId = codec.Id; numStreams = codec.NumStreams; - return i; + return (int)i; } } @@ -181,7 +189,7 @@ int FindMethod_Index( { methodId = codec.Id; numStreams = codec.NumStreams; - return g_NumCodecs + i; + return (int)(g_NumCodecs + i); } } @@ -200,7 +208,7 @@ static int FindMethod_Index( { const CCodecInfo &codec = *g_Codecs[i]; if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder)) - return i; + return (int)i; } #ifdef EXTERNAL_CODECS @@ -212,7 +220,7 @@ static int FindMethod_Index( { const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)) - return g_NumCodecs + i; + return (int)(g_NumCodecs + i); } #endif @@ -441,7 +449,7 @@ HRESULT CreateCoder_Id( int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode); if (index < 0) return S_OK; - return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS index, encode, filter, cod); + return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)index, encode, filter, cod); } diff --git a/CPP/7zip/Common/FilePathAutoRename.cpp b/CPP/7zip/Common/FilePathAutoRename.cpp index 0904e696..1ebfd72b 100644 --- a/CPP/7zip/Common/FilePathAutoRename.cpp +++ b/CPP/7zip/Common/FilePathAutoRename.cpp @@ -26,8 +26,8 @@ bool AutoRenamePath(FString &path) FString extension; if (dotPos > slashPos + 1) { - name.DeleteFrom(dotPos); - extension = path.Ptr(dotPos); + name.DeleteFrom((unsigned)dotPos); + extension = path.Ptr((unsigned)dotPos); } name += '_'; diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index f3a322fc..466f46e9 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp @@ -6,6 +6,7 @@ #include <fcntl.h> #include <unistd.h> #include <errno.h> +#include "../../Windows/FileFind.h" #endif #ifdef SUPPORT_DEVICE_FILE @@ -15,22 +16,26 @@ #include "FileStreams.h" -static inline HRESULT ConvertBoolToHRESULT(bool result) +static inline HRESULT GetLastError_HRESULT() { - #ifdef _WIN32 - if (result) - return S_OK; DWORD lastError = ::GetLastError(); if (lastError == 0) return E_FAIL; return HRESULT_FROM_WIN32(lastError); - #else - return result ? S_OK: E_FAIL; - #endif +} + +static inline HRESULT ConvertBoolToHRESULT(bool result) +{ + if (result) + return S_OK; + return GetLastError_HRESULT(); } +#ifdef SUPPORT_DEVICE_FILE static const UInt32 kClusterSize = 1 << 18; +#endif + CInFileStream::CInFileStream(): #ifdef SUPPORT_DEVICE_FILE VirtPos(0), @@ -111,7 +116,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (alignedPos != PhyPos) { UInt64 realNewPosition; - bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition); + bool result = File.Seek((Int64)alignedPos, FILE_BEGIN, realNewPosition); if (!result) return ConvertBoolToHRESULT(result); PhyPos = realNewPosition; @@ -140,7 +145,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (VirtPos != PhyPos) { UInt64 realNewPosition; - bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition); + bool result = File.Seek((Int64)VirtPos, FILE_BEGIN, realNewPosition); if (!result) return ConvertBoolToHRESULT(result); PhyPos = VirtPos = realNewPosition; @@ -149,7 +154,7 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) #endif UInt32 realProcessedSize; - bool result = File.ReadPart(data, size, realProcessedSize); + const bool result = File.ReadPart(data, size, realProcessedSize); if (processedSize) *processedSize = realProcessedSize; @@ -161,33 +166,27 @@ STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) if (result) return S_OK; + #else // USE_WIN_FILE + + if (processedSize) + *processedSize = 0; + const ssize_t res = File.read_part(data, (size_t)size); + if (res != -1) { - DWORD error = ::GetLastError(); + if (processedSize) + *processedSize = (UInt32)res; + return S_OK; + } + #endif // USE_WIN_FILE + { + const DWORD error = ::GetLastError(); if (Callback) return Callback->InFileStream_On_Error(CallbackRef, error); if (error == 0) return E_FAIL; - return HRESULT_FROM_WIN32(error); } - - #else - - if (processedSize) - *processedSize = 0; - ssize_t res = File.Read(data, (size_t)size); - if (res == -1) - { - if (Callback) - return Callback->InFileStream_On_Error(CallbackRef, E_FAIL); - return E_FAIL; - } - if (processedSize) - *processedSize = (UInt32)res; - return S_OK; - - #endif } #ifdef UNDER_CE @@ -228,7 +227,7 @@ STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSi } while (res < 0 && (errno == EINTR)); if (res == -1) - return E_FAIL; + return GetLastError_HRESULT(); if (processedSize) *processedSize = (UInt32)res; return S_OK; @@ -257,9 +256,9 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - VirtPos = offset; + VirtPos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } #endif @@ -277,9 +276,9 @@ STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos #else - off_t res = File.Seek((off_t)offset, seekOrigin); + off_t res = File.seek((off_t)offset, (int)seekOrigin); if (res == -1) - return E_FAIL; + return GetLastError_HRESULT(); if (newPosition) *newPosition = (UInt64)res; return S_OK; @@ -306,7 +305,7 @@ STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aT if (attrib) *attrib = info.dwFileAttributes; return S_OK; } - return GetLastError(); + return GetLastError_HRESULT(); } STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) @@ -325,7 +324,71 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) props->MTime = info.ftLastWriteTime; return S_OK; } - return GetLastError(); + return GetLastError_HRESULT(); +} + +#elif !defined(_WIN32) + +STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) +{ + struct stat st; + if (File.my_fstat(&st) != 0) + return GetLastError_HRESULT(); + + if (size) *size = (UInt64)st.st_size; + #ifdef __APPLE__ + if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, *cTime); + if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, *aTime); + if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, *mTime); + #else + if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, *cTime); + if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, *aTime); + if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, *mTime); + #endif + if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); + + return S_OK; +} + +// #include <stdio.h> + +STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) +{ + struct stat st; + if (File.my_fstat(&st) != 0) + return GetLastError_HRESULT(); + + props->Size = (UInt64)st.st_size; + /* + dev_t stat::st_dev: + GCC:Linux long unsigned int : __dev_t + Mac: int + */ + props->VolID = (UInt64)(Int64)st.st_dev; + props->FileID_Low = st.st_ino; + props->FileID_High = 0; + props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long) + props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); + + #ifdef __APPLE__ + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, props->CTime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, props->ATime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, props->MTime); + #else + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, props->CTime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, props->ATime); + NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, props->MTime); + #endif + + /* + printf("\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\n" + , (unsigned)(props->NumLinks) + , (unsigned)(st.st_dev) + , (unsigned)(st.st_ino) + ); + */ + + return S_OK; } #endif @@ -343,7 +406,7 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces #ifdef USE_WIN_FILE UInt32 realProcessedSize; - bool result = File.Write(data, size, realProcessedSize); + const bool result = File.Write(data, size, realProcessedSize); ProcessedSize += realProcessedSize; if (processedSize) *processedSize = realProcessedSize; @@ -353,12 +416,13 @@ STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *proces if (processedSize) *processedSize = 0; - ssize_t res = File.Write(data, (size_t)size); - if (res == -1) - return E_FAIL; + size_t realProcessedSize; + const ssize_t res = File.write_full(data, (size_t)size, realProcessedSize); + ProcessedSize += realProcessedSize; if (processedSize) - *processedSize = (UInt32)res; - ProcessedSize += res; + *processedSize = (UInt32)realProcessedSize; + if (res == -1) + return GetLastError_HRESULT(); return S_OK; #endif @@ -379,9 +443,9 @@ STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo #else - off_t res = File.Seek((off_t)offset, seekOrigin); + off_t res = File.seek((off_t)offset, (int)seekOrigin); if (res == -1) - return E_FAIL; + return GetLastError_HRESULT(); if (newPosition) *newPosition = (UInt64)res; return S_OK; @@ -403,8 +467,11 @@ STDMETHODIMP COutFileStream::SetSize(UInt64 newSize) #else - return E_FAIL; - + // SetLength() uses ftruncate() that doesn't change file offset + if (!File.SetLength(newSize)) + return GetLastError_HRESULT(); + return S_OK; + #endif } @@ -462,7 +529,7 @@ STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *pro while (res < 0 && (errno == EINTR)); if (res == -1) - return E_FAIL; + return GetLastError_HRESULT(); _size += (size_t)res; if (processedSize) diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h index ef2986fd..fe9f4c19 100644 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h @@ -7,42 +7,30 @@ #define USE_WIN_FILE #endif +#include "../../Common/MyCom.h" #include "../../Common/MyString.h" -#ifdef USE_WIN_FILE #include "../../Windows/FileIO.h" -#else -#include "../../Common/C_FileIO.h" -#endif - -#include "../../Common/MyCom.h" #include "../IStream.h" -#ifdef _WIN32 -typedef UINT_PTR My_UINT_PTR; -#else -typedef UINT My_UINT_PTR; -#endif - struct IInFileStream_Callback { - virtual HRESULT InFileStream_On_Error(My_UINT_PTR val, DWORD error) = 0; - virtual void InFileStream_On_Destroy(My_UINT_PTR val) = 0; + virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) = 0; + virtual void InFileStream_On_Destroy(UINT_PTR val) = 0; }; class CInFileStream: public IInStream, public IStreamGetSize, - #ifdef USE_WIN_FILE public IStreamGetProps, public IStreamGetProps2, - #endif public CMyUnknownImp { public: - #ifdef USE_WIN_FILE NWindows::NFile::NIO::CInFile File; + + #ifdef USE_WIN_FILE #ifdef SUPPORT_DEVICE_FILE UInt64 VirtPos; @@ -52,14 +40,12 @@ public: UInt32 BufSize; #endif - #else - NC::NFile::NIO::CInFile File; #endif bool SupportHardLinks; IInFileStream_Callback *Callback; - My_UINT_PTR CallbackRef; + UINT_PTR CallbackRef; virtual ~CInFileStream(); @@ -77,10 +63,8 @@ public: MY_QUERYINTERFACE_BEGIN2(IInStream) MY_QUERYINTERFACE_ENTRY(IStreamGetSize) - #ifdef USE_WIN_FILE MY_QUERYINTERFACE_ENTRY(IStreamGetProps) MY_QUERYINTERFACE_ENTRY(IStreamGetProps2) - #endif MY_QUERYINTERFACE_END MY_ADDREF_RELEASE @@ -88,10 +72,8 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(GetSize)(UInt64 *size); - #ifdef USE_WIN_FILE STDMETHOD(GetProps)(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib); STDMETHOD(GetProps2)(CStreamFileProps *props); - #endif }; class CStdInFileStream: @@ -110,11 +92,8 @@ class COutFileStream: public CMyUnknownImp { public: - #ifdef USE_WIN_FILE NWindows::NFile::NIO::COutFile File; - #else - NC::NFile::NIO::COutFile File; - #endif + virtual ~COutFileStream() {} bool Create(CFSTR fileName, bool createAlways) { @@ -131,14 +110,11 @@ public: UInt64 ProcessedSize; - #ifdef USE_WIN_FILE bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) { return File.SetTime(cTime, aTime, mTime); } bool SetMTime(const FILETIME *mTime) { return File.SetMTime(mTime); } - #endif - MY_UNKNOWN_IMP1(IOutStream) @@ -146,6 +122,15 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(UInt64 newSize); + bool SeekToBegin_bool() + { + #ifdef USE_WIN_FILE + return File.SeekToBegin(); + #else + return File.seekToBegin() == 0; + #endif + } + HRESULT GetSize(UInt64 *size); }; diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp index f4c00273..fb99f610 100644 --- a/CPP/7zip/Common/FilterCoder.cpp +++ b/CPP/7zip/Common/FilterCoder.cpp @@ -86,47 +86,47 @@ STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStr { RINOK(Init_and_Alloc()); + UInt64 prev = 0; UInt64 nowPos64 = 0; bool inputFinished = false; UInt32 pos = 0; while (!outSize || nowPos64 < *outSize) { - UInt32 endPos = pos; - if (!inputFinished) { size_t processedSize = _bufSize - pos; RINOK(ReadStream(inStream, _buf + pos, &processedSize)); - endPos = pos + (UInt32)processedSize; - inputFinished = (endPos != _bufSize); + pos += (UInt32)processedSize; + inputFinished = (pos != _bufSize); } - pos = Filter->Filter(_buf, endPos); + if (pos == 0) + return S_OK; + + UInt32 filtered = Filter->Filter(_buf, pos); - if (pos > endPos) + if (filtered > pos) { // AES - if (!inputFinished || pos > _bufSize) + if (!inputFinished || filtered > _bufSize) return E_FAIL; if (!_encodeMode) return S_FALSE; + Byte *buf = _buf; do - _buf[endPos] = 0; - while (++endPos != pos); + buf[pos] = 0; + while (++pos != filtered); - if (pos != Filter->Filter(_buf, pos)) + if (filtered != Filter->Filter(buf, filtered)) return E_FAIL; } - if (endPos == 0) - return S_OK; - - UInt32 size = (pos != 0 ? pos : endPos); + UInt32 size = (filtered != 0 ? filtered : pos); if (outSize) { - UInt64 remSize = *outSize - nowPos64; + const UInt64 remSize = *outSize - nowPos64; if (size > remSize) size = (UInt32)remSize; } @@ -134,16 +134,17 @@ STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStr RINOK(WriteStream(outStream, _buf, size)); nowPos64 += size; - if (pos == 0) + if (filtered == 0) return S_OK; + pos -= filtered; + for (UInt32 i = 0; i < pos; i++) + _buf[i] = _buf[filtered++]; - if (progress) + if (progress && (nowPos64 - prev) >= (1 << 22)) + { + prev = nowPos64; RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64)); - - UInt32 i = 0; - while (pos < endPos) - _buf[i++] = _buf[pos++]; - pos = i; + } } return S_OK; diff --git a/CPP/7zip/Common/InBuffer.cpp b/CPP/7zip/Common/InBuffer.cpp index d1bc9b9a..6f6eecad 100644 --- a/CPP/7zip/Common/InBuffer.cpp +++ b/CPP/7zip/Common/InBuffer.cpp @@ -56,7 +56,7 @@ bool CInBufferBase::ReadBlock() #endif if (_wasFinished) return false; - _processedSize += (_buf - _bufBase); + _processedSize += (size_t)(_buf - _bufBase); _buf = _bufBase; _bufLim = _bufBase; UInt32 processed; @@ -100,7 +100,7 @@ size_t CInBufferBase::ReadBytes(Byte *buf, size_t size) size_t num = 0; for (;;) { - const size_t rem = _bufLim - _buf; + const size_t rem = (size_t)(_bufLim - _buf); if (size <= rem) { if (size != 0) @@ -148,7 +148,7 @@ size_t CInBufferBase::Skip(size_t size) size_t processed = 0; for (;;) { - size_t rem = (_bufLim - _buf); + const size_t rem = (size_t)(_bufLim - _buf); if (rem >= size) { _buf += size; diff --git a/CPP/7zip/Common/InBuffer.h b/CPP/7zip/Common/InBuffer.h index 4b9c2c32..fa063949 100644 --- a/CPP/7zip/Common/InBuffer.h +++ b/CPP/7zip/Common/InBuffer.h @@ -38,8 +38,16 @@ public: CInBufferBase() throw(); - UInt64 GetStreamSize() const { return _processedSize + (_buf - _bufBase); } - UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (_buf - _bufBase); } + // the size of portion of data in real stream that was already read from this object + // it doesn't include unused data in buffer + // it doesn't include virtual Extra bytes after the end of real stream data + UInt64 GetStreamSize() const { return _processedSize + (size_t)(_buf - _bufBase); } + + // the size of virtual data that was read from this object + // it doesn't include unused data in buffers + // it includes any virtual Extra bytes after the end of real data + UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (size_t)(_buf - _bufBase); } + bool WasFinished() const { return _wasFinished; } void SetStream(ISequentialInStream *stream) { _stream = stream; } @@ -68,6 +76,15 @@ public: b = *_buf++; return true; } + + MY_FORCE_INLINE + bool ReadByte_FromBuf(Byte &b) + { + if (_buf >= _bufLim) + return false; + b = *_buf++; + return true; + } MY_FORCE_INLINE Byte ReadByte() diff --git a/CPP/7zip/Common/InOutTempBuffer.cpp b/CPP/7zip/Common/InOutTempBuffer.cpp index 7523f3a3..cae6b803 100644 --- a/CPP/7zip/Common/InOutTempBuffer.cpp +++ b/CPP/7zip/Common/InOutTempBuffer.cpp @@ -2,13 +2,13 @@ #include "StdAfx.h" -#include "../../../C/7zCrc.h" - -#include "../../Common/Defs.h" - #include "InOutTempBuffer.h" #include "StreamUtils.h" +#ifdef USE_InOutTempBuffer_FILE + +#include "../../../C/7zCrc.h" + using namespace NWindows; using namespace NFile; using namespace NDir; @@ -16,50 +16,58 @@ using namespace NDir; static const size_t kTempBufSize = (1 << 20); #define kTempFilePrefixString FTEXT("7zt") +CInOutTempBuffer::~CInOutTempBuffer() +{ + delete []_buf; +} +#endif -CInOutTempBuffer::CInOutTempBuffer(): _buf(NULL) { } +CInOutTempBuffer::CInOutTempBuffer() + #ifdef USE_InOutTempBuffer_FILE + : _buf(NULL) + #endif +{ } void CInOutTempBuffer::Create() { + #ifdef USE_InOutTempBuffer_FILE if (!_buf) _buf = new Byte[kTempBufSize]; -} - -CInOutTempBuffer::~CInOutTempBuffer() -{ - delete []_buf; + #endif } void CInOutTempBuffer::InitWriting() { + #ifdef USE_InOutTempBuffer_FILE _bufPos = 0; + _crc = CRC_INIT_VAL; _tempFileCreated = false; + #endif _size = 0; - _crc = CRC_INIT_VAL; } -bool CInOutTempBuffer::WriteToFile(const void *data, UInt32 size) + +#ifdef USE_InOutTempBuffer_FILE + +static inline HRESULT Get_HRESULT_LastError() { - if (size == 0) - return true; - if (!_tempFileCreated) - { - if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) - return false; - _tempFileCreated = true; - } - UInt32 processed; - if (!_outFile.Write(data, size, processed)) - return false; - _crc = CrcUpdate(_crc, data, processed); - _size += processed; - return (processed == size); + #ifdef _WIN32 + DWORD lastError = ::GetLastError(); + if (lastError != 0) + return HRESULT_FROM_WIN32(lastError); + #endif + return E_FAIL; } -bool CInOutTempBuffer::Write(const void *data, UInt32 size) +#endif + + +HRESULT CInOutTempBuffer::Write_HRESULT(const void *data, UInt32 size) { + #ifdef USE_InOutTempBuffer_FILE + if (size == 0) - return true; + return S_OK; size_t cur = kTempBufSize - _bufPos; if (cur != 0) { @@ -72,11 +80,42 @@ bool CInOutTempBuffer::Write(const void *data, UInt32 size) size -= (UInt32)cur; data = ((const Byte *)data) + cur; } - return WriteToFile(data, size); + + if (size == 0) + return S_OK; + + if (!_tempFileCreated) + { + if (!_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile)) + return Get_HRESULT_LastError(); + _tempFileCreated = true; + } + UInt32 processed; + if (!_outFile.Write(data, size, processed)) + return Get_HRESULT_LastError(); + _crc = CrcUpdate(_crc, data, processed); + _size += processed; + return (processed == size) ? S_OK : E_FAIL; + + #else + + const size_t newSize = _size + size; + if (newSize < _size) + return E_OUTOFMEMORY; + if (!_dynBuffer.EnsureCapacity(newSize)) + return E_OUTOFMEMORY; + memcpy(((Byte *)_dynBuffer) + _size, data, size); + _size = newSize; + return S_OK; + + #endif } + HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) { + #ifdef USE_InOutTempBuffer_FILE + if (!_outFile.Close()) return E_FAIL; @@ -107,8 +146,13 @@ HRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream) size += processed; } } - return (_crc == crc && size == _size) ? S_OK : E_FAIL; + + #else + + return WriteStream(stream, (const Byte *)_dynBuffer, _size); + + #endif } /* diff --git a/CPP/7zip/Common/InOutTempBuffer.h b/CPP/7zip/Common/InOutTempBuffer.h index 204a105f..755935ea 100644 --- a/CPP/7zip/Common/InOutTempBuffer.h +++ b/CPP/7zip/Common/InOutTempBuffer.h @@ -3,30 +3,48 @@ #ifndef __IN_OUT_TEMP_BUFFER_H #define __IN_OUT_TEMP_BUFFER_H -#include "../../Common/MyCom.h" +#ifdef _WIN32 +// #define USE_InOutTempBuffer_FILE +#endif + +#ifdef USE_InOutTempBuffer_FILE #include "../../Windows/FileDir.h" +#else +#include "StreamObjects.h" +#endif #include "../IStream.h" class CInOutTempBuffer { + #ifdef USE_InOutTempBuffer_FILE + NWindows::NFile::NDir::CTempFile _tempFile; NWindows::NFile::NIO::COutFile _outFile; + bool _tempFileCreated; Byte *_buf; size_t _bufPos; UInt64 _size; UInt32 _crc; - bool _tempFileCreated; - bool WriteToFile(const void *data, UInt32 size); + #else + + CByteDynBuffer _dynBuffer; + size_t _size; + + #endif + + CLASS_NO_COPY(CInOutTempBuffer); public: CInOutTempBuffer(); - ~CInOutTempBuffer(); void Create(); - void InitWriting(); - bool Write(const void *data, UInt32 size); + #ifdef USE_InOutTempBuffer_FILE + ~CInOutTempBuffer(); + #endif + void InitWriting(); + HRESULT Write_HRESULT(const void *data, UInt32 size); HRESULT WriteToStream(ISequentialOutStream *stream); UInt64 GetDataSize() const { return _size; } }; diff --git a/CPP/7zip/Common/LimitedStreams.cpp b/CPP/7zip/Common/LimitedStreams.cpp index 8e032561..add6636b 100644 --- a/CPP/7zip/Common/LimitedStreams.cpp +++ b/CPP/7zip/Common/LimitedStreams.cpp @@ -67,7 +67,7 @@ STDMETHODIMP CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *new } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; @@ -115,7 +115,7 @@ STDMETHODIMP CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSi _curRem = blockSize - offsetInBlock; - for (int i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++) + for (unsigned i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++) _curRem += (UInt32)1 << BlockSizeLog; } @@ -143,9 +143,9 @@ STDMETHODIMP CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *new return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; if (_virtPos != (UInt64)offset) _curRem = 0; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -203,7 +203,7 @@ STDMETHODIMP CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; @@ -268,10 +268,10 @@ STDMETHODIMP CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPos } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; - return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL); + return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL); } STDMETHODIMP CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize) @@ -325,7 +325,7 @@ STDMETHODIMP CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt6 } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; return S_OK; @@ -354,10 +354,10 @@ STDMETHODIMP CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPo } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _virtPos = offset; + _virtPos = (UInt64)offset; if (newPosition) *newPosition = _virtPos; - return Stream->Seek(Offset + _virtPos, STREAM_SEEK_SET, NULL); + return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL); } STDMETHODIMP CTailOutStream::SetSize(UInt64 newSize) diff --git a/CPP/7zip/Common/LimitedStreams.h b/CPP/7zip/Common/LimitedStreams.h index fb1ac3cd..ade29937 100644 --- a/CPP/7zip/Common/LimitedStreams.h +++ b/CPP/7zip/Common/LimitedStreams.h @@ -44,7 +44,7 @@ class CLimitedInStream: UInt64 _size; UInt64 _startOffset; - HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + HRESULT SeekToPhys() { return _stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); } public: void SetStream(IInStream *stream) { _stream = stream; } HRESULT InitAndSeek(UInt64 startOffset, UInt64 size) @@ -80,7 +80,7 @@ public: CRecordVector<UInt32> Vector; UInt64 StartOffset; - HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + HRESULT SeekToPhys() { return Stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); } HRESULT InitAndSeek() { @@ -115,7 +115,7 @@ class CExtentsStream: UInt64 _virtPos; bool _needStartSeek; - HRESULT SeekToPhys() { return Stream->Seek(_phyPos, STREAM_SEEK_SET, NULL); } + HRESULT SeekToPhys() { return Stream->Seek((Int64)_phyPos, STREAM_SEEK_SET, NULL); } public: CMyComPtr<IInStream> Stream; @@ -177,7 +177,7 @@ public: STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); - HRESULT SeekToStart() { return Stream->Seek(Offset, STREAM_SEEK_SET, NULL); } + HRESULT SeekToStart() { return Stream->Seek((Int64)Offset, STREAM_SEEK_SET, NULL); } }; class CLimitedCachedInStream: @@ -195,7 +195,7 @@ class CLimitedCachedInStream: size_t _cachePhyPos; - HRESULT SeekToPhys() { return _stream->Seek(_physPos, STREAM_SEEK_SET, NULL); } + HRESULT SeekToPhys() { return _stream->Seek((Int64)_physPos, STREAM_SEEK_SET, NULL); } public: CByteBuffer Buffer; diff --git a/CPP/7zip/Common/MemBlocks.cpp b/CPP/7zip/Common/MemBlocks.cpp index 5aba046b..f351abbd 100644 --- a/CPP/7zip/Common/MemBlocks.cpp +++ b/CPP/7zip/Common/MemBlocks.cpp @@ -7,21 +7,26 @@ #include "MemBlocks.h" #include "StreamUtils.h" -bool CMemBlockManager::AllocateSpace(size_t numBlocks) +bool CMemBlockManager::AllocateSpace_bool(size_t numBlocks) { FreeSpace(); - if (_blockSize < sizeof(void *) || numBlocks < 1) + if (numBlocks == 0) + { + return true; + // return false; + } + if (_blockSize < sizeof(void *)) return false; - size_t totalSize = numBlocks * _blockSize; + const size_t totalSize = numBlocks * _blockSize; if (totalSize / _blockSize != numBlocks) return false; _data = ::MidAlloc(totalSize); - if (_data == 0) + if (!_data) return false; Byte *p = (Byte *)_data; for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize) - *(Byte **)p = (p + _blockSize); - *(Byte **)p = 0; + *(Byte **)(void *)p = (p + _blockSize); + *(Byte **)(void *)p = NULL; _headFree = _data; return true; } @@ -35,41 +40,64 @@ void CMemBlockManager::FreeSpace() void *CMemBlockManager::AllocateBlock() { - if (_headFree == 0) - return 0; void *p = _headFree; - _headFree = *(void **)_headFree; + if (p) + _headFree = *(void **)p; return p; } void CMemBlockManager::FreeBlock(void *p) { - if (p == 0) + if (!p) return; *(void **)p = _headFree; _headFree = p; } +// #include <stdio.h> + HRes CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks) { if (numNoLockBlocks > numBlocks) return E_INVALIDARG; - if (!CMemBlockManager::AllocateSpace(numBlocks)) + const size_t numLockBlocks = numBlocks - numNoLockBlocks; + UInt32 maxCount = (UInt32)numLockBlocks; + if (maxCount != numLockBlocks) + return E_OUTOFMEMORY; + if (!CMemBlockManager::AllocateSpace_bool(numBlocks)) return E_OUTOFMEMORY; - size_t numLockBlocks = numBlocks - numNoLockBlocks; Semaphore.Close(); - return Semaphore.Create((LONG)numLockBlocks, (LONG)numLockBlocks); + // we need (maxCount = 1), if we want to create non-use empty Semaphore + if (maxCount == 0) + maxCount = 1; + + // printf("\n Synchro.Create() \n"); + WRes wres; + #ifndef _WIN32 + wres = Synchro.Create(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); + wres = Semaphore.Create(&Synchro, (UInt32)numLockBlocks, maxCount); + #else + wres = Semaphore.Create((UInt32)numLockBlocks, maxCount); + #endif + + return HRESULT_FROM_WIN32(wres); } + HRes CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks) { + // desiredNumberOfBlocks = 0; // for debug if (numNoLockBlocks > desiredNumberOfBlocks) return E_INVALIDARG; for (;;) { - if (AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks) == 0) - return 0; + // if (desiredNumberOfBlocks == 0) return E_OUTOFMEMORY; + HRes hres = AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks); + if (hres != E_OUTOFMEMORY) + return hres; if (desiredNumberOfBlocks == numNoLockBlocks) return E_OUTOFMEMORY; desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1); @@ -91,7 +119,7 @@ void *CMemBlockManagerMt::AllocateBlock() void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode) { - if (p == 0) + if (!p) return; { NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection); @@ -101,6 +129,8 @@ void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode) Semaphore.Release(); } + + void CMemBlocks::Free(CMemBlockManagerMt *manager) { while (Blocks.Size() > 0) @@ -122,9 +152,9 @@ HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStr UInt64 totalSize = TotalSize; for (unsigned blockIndex = 0; totalSize > 0; blockIndex++) { - UInt32 curSize = (UInt32)blockSize; - if (totalSize < curSize) - curSize = (UInt32)totalSize; + size_t curSize = blockSize; + if (curSize > totalSize) + curSize = (size_t)totalSize; if (blockIndex >= Blocks.Size()) return E_FAIL; RINOK(WriteStream(outStream, Blocks[blockIndex], curSize)); @@ -134,10 +164,10 @@ HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStr } -void CMemLockBlocks::FreeBlock(int index, CMemBlockManagerMt *memManager) +void CMemLockBlocks::FreeBlock(unsigned index, CMemBlockManagerMt *memManager) { memManager->FreeBlock(Blocks[index], LockMode); - Blocks[index] = 0; + Blocks[index] = NULL; } void CMemLockBlocks::Free(CMemBlockManagerMt *memManager) @@ -150,6 +180,7 @@ void CMemLockBlocks::Free(CMemBlockManagerMt *memManager) TotalSize = 0; } +/* HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager) { if (LockMode) @@ -162,13 +193,14 @@ HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager) } return 0; } +*/ void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager) { blocks.Free(memManager); blocks.LockMode = LockMode; UInt64 totalSize = 0; - size_t blockSize = memManager->GetBlockSize(); + const size_t blockSize = memManager->GetBlockSize(); FOR_VECTOR (i, Blocks) { if (totalSize < TotalSize) diff --git a/CPP/7zip/Common/MemBlocks.h b/CPP/7zip/Common/MemBlocks.h index ec56c14d..3c9cefdb 100644 --- a/CPP/7zip/Common/MemBlocks.h +++ b/CPP/7zip/Common/MemBlocks.h @@ -15,10 +15,10 @@ class CMemBlockManager size_t _blockSize; void *_headFree; public: - CMemBlockManager(size_t blockSize = (1 << 20)): _data(0), _blockSize(blockSize), _headFree(0) {} + CMemBlockManager(size_t blockSize = (1 << 20)): _data(NULL), _blockSize(blockSize), _headFree(NULL) {} ~CMemBlockManager() { FreeSpace(); } - bool AllocateSpace(size_t numBlocks); + bool AllocateSpace_bool(size_t numBlocks); void FreeSpace(); size_t GetBlockSize() const { return _blockSize; } void *AllocateBlock(); @@ -30,17 +30,18 @@ class CMemBlockManagerMt: public CMemBlockManager { NWindows::NSynchronization::CCriticalSection _criticalSection; public: - NWindows::NSynchronization::CSemaphore Semaphore; + SYNC_OBJ_DECL(Synchro); + NWindows::NSynchronization::CSemaphore_WFMO Semaphore; CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {} ~CMemBlockManagerMt() { FreeSpace(); } - HRes AllocateSpace(size_t numBlocks, size_t numNoLockBlocks = 0); + HRes AllocateSpace(size_t numBlocks, size_t numNoLockBlocks); HRes AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0); void FreeSpace(); void *AllocateBlock(); void FreeBlock(void *p, bool lockMode = true); - HRes ReleaseLockedBlocks(int number) { return Semaphore.Release(number); } + // WRes ReleaseLockedBlocks_WRes(unsigned number) { return Semaphore.Release(number); } }; @@ -63,8 +64,8 @@ struct CMemLockBlocks: public CMemBlocks CMemLockBlocks(): LockMode(true) {}; void Free(CMemBlockManagerMt *memManager); - void FreeBlock(int index, CMemBlockManagerMt *memManager); - HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager); + void FreeBlock(unsigned index, CMemBlockManagerMt *memManager); + // HRes SwitchToNoLockMode(CMemBlockManagerMt *memManager); void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager); }; diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp index 8a6ebcaf..bea51db3 100644 --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp @@ -184,10 +184,12 @@ class CCoderProps unsigned _numProps; unsigned _numPropsMax; public: - CCoderProps(unsigned numPropsMax) + CCoderProps(unsigned numPropsMax): + _propIDs(NULL), + _props(NULL), + _numProps(0), + _numPropsMax(numPropsMax) { - _numPropsMax = numPropsMax; - _numProps = 0; _propIDs = new PROPID[numPropsMax]; _props = new NCOM::CPropVariant[numPropsMax]; } @@ -214,7 +216,15 @@ void CCoderProps::AddProp(const CProp &prop) HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const { - CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0)); + return SetCoderProps_DSReduce_Aff(scp, dataSizeReduce, NULL); +} + +HRESULT CProps::SetCoderProps_DSReduce_Aff( + ICompressSetCoderProperties *scp, + const UInt64 *dataSizeReduce, + const UInt64 *affinity) const +{ + CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0) + (affinity ? 1 : 0) ); FOR_VECTOR (i, Props) coderProps.AddProp(Props[i]); if (dataSizeReduce) @@ -224,27 +234,34 @@ HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *da prop.Value = *dataSizeReduce; coderProps.AddProp(prop); } + if (affinity) + { + CProp prop; + prop.Id = NCoderPropID::kAffinity; + prop.Value = *affinity; + coderProps.AddProp(prop); + } return coderProps.SetProps(scp); } int CMethodProps::FindProp(PROPID id) const { - for (int i = Props.Size() - 1; i >= 0; i--) - if (Props[i].Id == id) + for (int i = (int)Props.Size() - 1; i >= 0; i--) + if (Props[(unsigned)i].Id == id) return i; return -1; } -int CMethodProps::GetLevel() const +unsigned CMethodProps::GetLevel() const { int i = FindProp(NCoderPropID::kLevel); if (i < 0) return 5; - if (Props[i].Value.vt != VT_UI4) + if (Props[(unsigned)i].Value.vt != VT_UI4) return 9; - UInt32 level = Props[i].Value.ulVal; - return level > 9 ? 9 : (int)level; + UInt32 level = Props[(unsigned)i].Value.ulVal; + return level > 9 ? 9 : (unsigned)level; } struct CNameToPropID @@ -286,7 +303,7 @@ static int FindPropIdExact(const UString &name) { for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++) if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name)) - return i; + return (int)i; return -1; } @@ -346,8 +363,8 @@ static void SplitParam(const UString ¶m, UString &name, UString &value) int eqPos = param.Find(L'='); if (eqPos >= 0) { - name.SetFrom(param, eqPos); - value = param.Ptr(eqPos + 1); + name.SetFrom(param, (unsigned)eqPos); + value = param.Ptr((unsigned)(eqPos + 1)); return; } unsigned i; @@ -382,7 +399,7 @@ HRESULT CMethodProps::SetParam(const UString &name, const UString &value) return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; - prop.Id = index; + prop.Id = (unsigned)index; if (IsLogSizeProp(prop.Id)) { @@ -463,7 +480,7 @@ HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const return E_INVALIDARG; const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index]; CProp prop; - prop.Id = index; + prop.Id = (unsigned)index; if (IsLogSizeProp(prop.Id)) { @@ -485,14 +502,14 @@ HRESULT COneMethodInfo::ParseMethodFromString(const UString &s) { UString temp = s; if (splitPos >= 0) - temp.DeleteFrom(splitPos); + temp.DeleteFrom((unsigned)splitPos); if (!temp.IsAscii()) return E_INVALIDARG; MethodName.SetFromWStr_if_Ascii(temp); } if (splitPos < 0) return S_OK; - PropsString = s.Ptr(splitPos + 1); + PropsString = s.Ptr((unsigned)(splitPos + 1)); return ParseParamsFromString(PropsString); } diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h index 39580881..e0519b16 100644 --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h @@ -53,20 +53,21 @@ struct CProps prop.Value = s; } - HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const; + HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const; + HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce, const UInt64 *affinity) const; }; class CMethodProps: public CProps { HRESULT SetParam(const UString &name, const UString &value); public: - int GetLevel() const; + unsigned GetLevel() const; int Get_NumThreads() const { int i = FindProp(NCoderPropID::kNumThreads); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) - return (int)Props[i].Value.ulVal; + if (Props[(unsigned)i].Value.vt == VT_UI4) + return (int)Props[(unsigned)i].Value.ulVal; return -1; } @@ -75,9 +76,9 @@ public: res = 0; int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) + if (Props[(unsigned)i].Value.vt == VT_UI4) { - res = Props[i].Value.ulVal; + res = Props[(unsigned)i].Value.ulVal; return true; } return false; @@ -89,8 +90,8 @@ public: { int i = FindProp(NCoderPropID::kAlgorithm); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) - return Props[i].Value.ulVal; + if (Props[(unsigned)i].Value.vt == VT_UI4) + return Props[(unsigned)i].Value.ulVal; return GetLevel() >= 5 ? 1 : 0; } @@ -98,10 +99,14 @@ public: { int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) - return Props[i].Value.ulVal; - int level = GetLevel(); - return level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)); + if (Props[(unsigned)i].Value.vt == VT_UI4) + return Props[(unsigned)i].Value.ulVal; + unsigned level = GetLevel(); + return + ( level <= 3 ? (1 << (level * 2 + 16)) : + ( level <= 6 ? (1 << (level + 19)) : + ( level <= 7 ? (1 << 25) : (1 << 26) + ))); } bool Get_Lzma_Eos() const @@ -109,7 +114,7 @@ public: int i = FindProp(NCoderPropID::kEndMarker); if (i >= 0) { - const NWindows::NCOM::CPropVariant &val = Props[i].Value; + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_BOOL) return VARIANT_BOOLToBool(val.boolVal); } @@ -150,7 +155,7 @@ public: int i = FindProp(id); if (i >= 0) { - const NWindows::NCOM::CPropVariant &val = Props[i].Value; + const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) { return val.ulVal; } if (val.vt == VT_UI8) { return val.uhVal.QuadPart; } } @@ -191,8 +196,8 @@ public: fixedNumber = true; if (numThreads < 1) return 1; const unsigned kNumBZip2ThreadsMax = 64; - if (numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax; - return numThreads; + if ((unsigned)numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax; + return (unsigned)numThreads; } return 1; } @@ -201,16 +206,16 @@ public: { int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) + if (Props[(unsigned)i].Value.vt == VT_UI4) { - UInt32 blockSize = Props[i].Value.ulVal; + UInt32 blockSize = Props[(unsigned)i].Value.ulVal; const UInt32 kDicSizeMin = 100000; const UInt32 kDicSizeMax = 900000; if (blockSize < kDicSizeMin) blockSize = kDicSizeMin; if (blockSize > kDicSizeMax) blockSize = kDicSizeMax; return blockSize; } - int level = GetLevel(); + unsigned level = GetLevel(); return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); } @@ -218,10 +223,10 @@ public: { int i = FindProp(NCoderPropID::kUsedMemorySize); if (i >= 0) - if (Props[i].Value.vt == VT_UI4) - return Props[i].Value.ulVal; - int level = GetLevel(); - return level >= 9 ? (192 << 20) : ((UInt32)1 << (level + 19)); + if (Props[(unsigned)i].Value.vt == VT_UI4) + return Props[(unsigned)i].Value.ulVal; + unsigned level = GetLevel(); + return ((UInt32)1 << (level + 19)); } void AddProp_Level(UInt32 level) diff --git a/CPP/7zip/Common/OffsetStream.cpp b/CPP/7zip/Common/OffsetStream.cpp index 368d39b6..b3e710f9 100644 --- a/CPP/7zip/Common/OffsetStream.cpp +++ b/CPP/7zip/Common/OffsetStream.cpp @@ -10,7 +10,7 @@ HRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset) { _offset = offset; _stream = stream; - return _stream->Seek(offset, STREAM_SEEK_SET, NULL); + return _stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL); } STDMETHODIMP COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) diff --git a/CPP/7zip/Common/OutMemStream.cpp b/CPP/7zip/Common/OutMemStream.cpp index 768c2d45..241589d2 100644 --- a/CPP/7zip/Common/OutMemStream.cpp +++ b/CPP/7zip/Common/OutMemStream.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +// #include <stdio.h> + #include "OutMemStream.h" void COutMemStream::Free() @@ -34,11 +36,12 @@ HRESULT COutMemStream::WriteToRealStream() return S_OK; } + STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (_realStreamMode) return OutSeqStream->Write(data, size, processedSize); - if (processedSize != 0) + if (processedSize) *processedSize = 0; while (size != 0) { @@ -49,7 +52,7 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process if (size < curSize) curSize = size; memcpy(p, data, curSize); - if (processedSize != 0) + if (processedSize) *processedSize += (UInt32)curSize; data = (const void *)((const Byte *)data + curSize); size -= (UInt32)curSize; @@ -65,8 +68,14 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process } continue; } - HANDLE events[3] = { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore }; - DWORD waitResult = ::WaitForMultipleObjects((Blocks.LockMode ? 3 : 2), events, FALSE, INFINITE); + + const NWindows::NSynchronization::CHandle_WFMO events[3] = + { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore }; + const DWORD waitResult = NWindows::NSynchronization::WaitForMultiObj_Any_Infinite( + ((Blocks.LockMode /* && _memManager->Semaphore.IsCreated() */) ? 3 : 2), events); + + // printf("\n 1- outMemStream %d\n", waitResult - WAIT_OBJECT_0); + switch (waitResult) { case (WAIT_OBJECT_0 + 0): @@ -77,27 +86,34 @@ STDMETHODIMP COutMemStream::Write(const void *data, UInt32 size, UInt32 *process RINOK(WriteToRealStream()); UInt32 processedSize2; HRESULT res = OutSeqStream->Write(data, size, &processedSize2); - if (processedSize != 0) + if (processedSize) *processedSize += processedSize2; return res; } - /* case (WAIT_OBJECT_0 + 2): { // it has bug: no write. + /* if (!Blocks.SwitchToNoLockMode(_memManager)) return E_FAIL; + */ break; } - */ - case (WAIT_OBJECT_0 + 2): - break; default: + { + if (waitResult == WAIT_FAILED) + { + DWORD res = ::GetLastError(); + if (res != 0) + return HRESULT_FROM_WIN32(res); + } return E_FAIL; + } } - Blocks.Blocks.Add(_memManager->AllocateBlock()); - if (Blocks.Blocks.Back() == 0) + void *p = _memManager->AllocateBlock(); + if (!p) return E_FAIL; + Blocks.Blocks.Add(p); } return S_OK; } diff --git a/CPP/7zip/Common/OutMemStream.h b/CPP/7zip/Common/OutMemStream.h index 0a892c52..873742ed 100644 --- a/CPP/7zip/Common/OutMemStream.h +++ b/CPP/7zip/Common/OutMemStream.h @@ -17,8 +17,8 @@ class COutMemStream: bool _realStreamMode; bool _unlockEventWasSent; - NWindows::NSynchronization::CAutoResetEvent StopWritingEvent; - NWindows::NSynchronization::CAutoResetEvent WriteToRealStreamEvent; + NWindows::NSynchronization::CAutoResetEvent_WFMO StopWritingEvent; + NWindows::NSynchronization::CAutoResetEvent_WFMO WriteToRealStreamEvent; // NWindows::NSynchronization::CAutoResetEvent NoLockEvent; HRESULT StopWriteResult; @@ -31,10 +31,13 @@ class COutMemStream: public: - HRes CreateEvents() + + HRes CreateEvents(SYNC_PARAM_DECL(synchro)) { - RINOK(StopWritingEvent.CreateIfNotCreated()); - return WriteToRealStreamEvent.CreateIfNotCreated(); + WRes wres = StopWritingEvent.CreateIfNotCreated_Reset(SYNC_WFMO(synchro)); + if (wres == 0) + wres = WriteToRealStreamEvent.CreateIfNotCreated_Reset(SYNC_WFMO(synchro)); + return HRESULT_FROM_WIN32(wres); } void SetOutStream(IOutStream *outStream) @@ -55,7 +58,16 @@ public: OutSeqStream.Release(); } - COutMemStream(CMemBlockManagerMt *memManager): _memManager(memManager) { } + COutMemStream(CMemBlockManagerMt *memManager): + _memManager(memManager) + { + /* + #ifndef _WIN32 + StopWritingEvent._sync = + WriteToRealStreamEvent._sync = &memManager->Synchro; + #endif + */ + } ~COutMemStream() { Free(); } void Free(); diff --git a/CPP/7zip/Common/ProgressMt.cpp b/CPP/7zip/Common/ProgressMt.cpp index 319bd241..c2714a27 100644 --- a/CPP/7zip/Common/ProgressMt.cpp +++ b/CPP/7zip/Common/ProgressMt.cpp @@ -4,12 +4,12 @@ #include "ProgressMt.h" -void CMtCompressProgressMixer::Init(int numItems, ICompressProgressInfo *progress) +void CMtCompressProgressMixer::Init(unsigned numItems, ICompressProgressInfo *progress) { NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); InSizes.Clear(); OutSizes.Clear(); - for (int i = 0; i < numItems; i++) + for (unsigned i = 0; i < numItems; i++) { InSizes.Add(0); OutSizes.Add(0); @@ -19,23 +19,23 @@ void CMtCompressProgressMixer::Init(int numItems, ICompressProgressInfo *progres _progress = progress; } -void CMtCompressProgressMixer::Reinit(int index) +void CMtCompressProgressMixer::Reinit(unsigned index) { NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); InSizes[index] = 0; OutSizes[index] = 0; } -HRESULT CMtCompressProgressMixer::SetRatioInfo(int index, const UInt64 *inSize, const UInt64 *outSize) +HRESULT CMtCompressProgressMixer::SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize) { NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); - if (inSize != 0) + if (inSize) { UInt64 diff = *inSize - InSizes[index]; InSizes[index] = *inSize; TotalInSize += diff; } - if (outSize != 0) + if (outSize) { UInt64 diff = *outSize - OutSizes[index]; OutSizes[index] = *outSize; diff --git a/CPP/7zip/Common/ProgressMt.h b/CPP/7zip/Common/ProgressMt.h index 26079d4e..32da976b 100644 --- a/CPP/7zip/Common/ProgressMt.h +++ b/CPP/7zip/Common/ProgressMt.h @@ -19,9 +19,9 @@ class CMtCompressProgressMixer 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); + void Init(unsigned numItems, ICompressProgressInfo *progress); + void Reinit(unsigned index); + HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize); }; class CMtCompressProgress: @@ -29,9 +29,9 @@ class CMtCompressProgress: public CMyUnknownImp { CMtCompressProgressMixer *_progress; - int _index; + unsigned _index; public: - void Init(CMtCompressProgressMixer *progress, int index) + void Init(CMtCompressProgressMixer *progress, unsigned index) { _progress = progress; _index = index; diff --git a/CPP/7zip/Common/RegisterCodec.h b/CPP/7zip/Common/RegisterCodec.h index 7ddb7604..a942da7a 100644 --- a/CPP/7zip/Common/RegisterCodec.h +++ b/CPP/7zip/Common/RegisterCodec.h @@ -26,11 +26,11 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw(); #define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder) #define REGISTER_CODEC_NAME(x) CRegisterCodec ## x -#define REGISTER_CODEC_VAR static const CCodecInfo g_CodecInfo = +#define REGISTER_CODEC_VAR(x) static const CCodecInfo g_CodecInfo_ ## x = #define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \ - REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo); }}; \ - static REGISTER_CODEC_NAME(x) g_RegisterCodec; + REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo_ ## x); }}; \ + static REGISTER_CODEC_NAME(x) g_RegisterCodec_ ## x; #define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x @@ -43,7 +43,7 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw(); #define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \ - REGISTER_CODEC_VAR \ + REGISTER_CODEC_VAR(x) \ { crDec, crEnc, id, name, 1, false }; \ REGISTER_CODEC(x) @@ -67,19 +67,19 @@ void RegisterCodec(const CCodecInfo *codecInfo) throw(); { crDec, crEnc, id, name, 1, true } #define REGISTER_FILTER(x, crDec, crEnc, id, name) \ - REGISTER_CODEC_VAR \ + REGISTER_CODEC_VAR(x) \ REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \ REGISTER_CODEC(x) #ifdef EXTRACT_ONLY #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ - REGISTER_FILTER_CREATE(CreateDec, clsDec) \ - REGISTER_FILTER(x, CreateDec, NULL, id, name) + REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \ + REGISTER_FILTER(x, x ## _CreateDec, NULL, id, name) #else #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \ - REGISTER_FILTER_CREATE(CreateDec, clsDec) \ - REGISTER_FILTER_CREATE(CreateEnc, clsEnc) \ - REGISTER_FILTER(x, CreateDec, CreateEnc, id, name) + REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \ + REGISTER_FILTER_CREATE(x ## _CreateEnc, clsEnc) \ + REGISTER_FILTER(x, x ## _CreateDec, x ## _CreateEnc, id, name) #endif diff --git a/CPP/7zip/Common/StreamBinder.cpp b/CPP/7zip/Common/StreamBinder.cpp index 435440c6..fbf2a0de 100644 --- a/CPP/7zip/Common/StreamBinder.cpp +++ b/CPP/7zip/Common/StreamBinder.cpp @@ -14,7 +14,7 @@ class CBinderInStream: public: MY_UNKNOWN_IMP1(ISequentialInStream) STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); - ~CBinderInStream() { _binder->CloseRead(); } + ~CBinderInStream() { _binder->CloseRead_CallOnce(); } CBinderInStream(CStreamBinder *binder): _binder(binder) {} }; @@ -37,19 +37,24 @@ STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *proc { return _binder->Write(data, size, processedSize); } - -WRes CStreamBinder::CreateEvents() +static HRESULT Event__Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event) { - RINOK(_canWrite_Event.Create()); - RINOK(_canRead_Event.Create()); - return _readingWasClosed_Event.Create(); + WRes wres; + if (event.IsCreated()) + wres = event.Reset(); + else + wres = event.Create(); + return HRESULT_FROM_WIN32(wres); } -void CStreamBinder::ReInit() +HRESULT CStreamBinder::Create_ReInit() { - _canWrite_Event.Reset(); - _canRead_Event.Reset(); - _readingWasClosed_Event.Reset(); + RINOK(Event__Create_or_Reset(_canRead_Event)); + // RINOK(Event__Create_or_Reset(_canWrite_Event)); + + _canWrite_Semaphore.Close(); + // we need at least 3 items of maxCount: 1 for normal unlock in Read(), 2 items for unlock in CloseRead_CallOnce() + _canWrite_Semaphore.Create(0, 3); // _readingWasClosed = false; _readingWasClosed2 = false; @@ -59,27 +64,14 @@ void CStreamBinder::ReInit() _buf = NULL; ProcessedSize = 0; // WritingWasCut = false; + return S_OK; } -void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) +void CStreamBinder::CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream) { - // _readingWasClosed = false; - _readingWasClosed2 = false; - - _waitWrite = true; - _bufSize = 0; - _buf = NULL; - ProcessedSize = 0; - // WritingWasCut = false; - - CBinderInStream *inStreamSpec = new CBinderInStream(this); - CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); - *inStream = inStreamLoc.Detach(); - - CBinderOutStream *outStreamSpec = new CBinderOutStream(this); - CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); - *outStream = outStreamLoc.Detach(); + inStream = new CBinderInStream(this); + outStream = new CBinderOutStream(this); } // (_canRead_Event && _bufSize == 0) means that stream is finished. @@ -92,7 +84,9 @@ HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (_waitWrite) { - RINOK(_canRead_Event.Lock()); + WRes wres = _canRead_Event.Lock(); + if (wres != 0) + return HRESULT_FROM_WIN32(wres); _waitWrite = false; } if (size > _bufSize) @@ -105,17 +99,25 @@ HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) if (processedSize) *processedSize = size; _bufSize -= size; + + /* + if (_bufSize == 0), then we have read whole buffer + we have two ways here: + - if we check (_bufSize == 0) here, we unlock Write only after full data Reading - it reduces the number of syncs + - if we don't check (_bufSize == 0) here, we unlock Write after partial data Reading + */ if (_bufSize == 0) { _waitWrite = true; - _canRead_Event.Reset(); - _canWrite_Event.Set(); + // _canWrite_Event.Set(); + _canWrite_Semaphore.Release(); } } } return S_OK; } + HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) @@ -135,20 +137,20 @@ HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSiz _readingWasClosed2 = true; */ - HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event }; - DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); - if (waitResult >= WAIT_OBJECT_0 + 2) - return E_FAIL; + _canWrite_Semaphore.Lock(); + // _bufSize : is remain size that was not read size -= _bufSize; + + // size : is size of data that was read if (size != 0) { + // if some data was read, then we report that size and return if (processedSize) *processedSize = size; return S_OK; } - // if (waitResult == WAIT_OBJECT_0 + 1) - _readingWasClosed2 = true; + _readingWasClosed2 = true; } // WritingWasCut = true; diff --git a/CPP/7zip/Common/StreamBinder.h b/CPP/7zip/Common/StreamBinder.h index 12088a94..16c872fb 100644 --- a/CPP/7zip/Common/StreamBinder.h +++ b/CPP/7zip/Common/StreamBinder.h @@ -8,45 +8,63 @@ #include "../IStream.h" /* -We don't use probably UNSAFE version: -reader thread: +We can use one from two code versions here: with Event or with Semaphore to unlock Writer thread +The difference for cases where Reading must be closed before Writing closing + +1) Event Version: _canWrite_Event + We call _canWrite_Event.Set() without waiting _canRead_Event in CloseRead() function. + The writer thread can get (_readingWasClosed) status in one from two iterations. + It's ambiguity of processing flow. But probably it's SAFE to use, if Event functions provide memory barriers. + reader thread: _canWrite_Event.Set(); - _readingWasClosed = true + _readingWasClosed = true; _canWrite_Event.Set(); -writer thread: + writer thread: _canWrite_Event.Wait() if (_readingWasClosed) -Can second call of _canWrite_Event.Set() be executed without memory barrier, if event is already set? + +2) Semaphore Version: _canWrite_Semaphore + writer thread always will detect closing of reading in latest iteration after all data processing iterations */ class CStreamBinder { - NWindows::NSynchronization::CAutoResetEvent _canWrite_Event; - NWindows::NSynchronization::CManualResetEvent _canRead_Event; - NWindows::NSynchronization::CManualResetEvent _readingWasClosed_Event; + NWindows::NSynchronization::CAutoResetEvent _canRead_Event; + // NWindows::NSynchronization::CAutoResetEvent _canWrite_Event; + NWindows::NSynchronization::CSemaphore _canWrite_Semaphore; - // bool _readingWasClosed; - bool _readingWasClosed2; + // bool _readingWasClosed; // set it in reader thread and check it in write thread + bool _readingWasClosed2; // use it in writer thread // bool WritingWasCut; - bool _waitWrite; + bool _waitWrite; // use it in reader thread UInt32 _bufSize; const void *_buf; public: - UInt64 ProcessedSize; + UInt64 ProcessedSize; // the size that was read by reader thread - WRes CreateEvents(); - void CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream); + void CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream); - void ReInit(); + HRESULT Create_ReInit(); HRESULT Read(void *data, UInt32 size, UInt32 *processedSize); HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize); - void CloseRead() + void CloseRead_CallOnce() { - _readingWasClosed_Event.Set(); - // _readingWasClosed = true; - // _canWrite_Event.Set(); + // call it only once: for example, in destructor + + /* + _readingWasClosed = true; + _canWrite_Event.Set(); + */ + + /* + We must relase Semaphore only once !!! + we must release at least 2 items of Semaphore: + one item to unlock partial Write(), if Read() have read some items + then additional item to stop writing (_bufSize will be 0) + */ + _canWrite_Semaphore.Release(2); } void CloseWrite() diff --git a/CPP/7zip/Common/StreamObjects.cpp b/CPP/7zip/Common/StreamObjects.cpp index 8136716d..2d941df6 100644 --- a/CPP/7zip/Common/StreamObjects.cpp +++ b/CPP/7zip/Common/StreamObjects.cpp @@ -37,9 +37,9 @@ STDMETHODIMP CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newP } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _pos = offset; + _pos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -72,9 +72,9 @@ STDMETHODIMP CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosi } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _pos = offset; + _pos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } @@ -108,14 +108,10 @@ bool CByteDynBuffer::EnsureCapacity(size_t cap) throw() { if (cap <= _capacity) return true; - size_t delta; - if (_capacity > 64) - delta = _capacity / 4; - else if (_capacity > 8) - delta = 16; - else - delta = 4; - cap = MyMax(_capacity + delta, cap); + size_t delta = _capacity / 4; + size_t cap2 = _capacity + delta; + if (cap < cap2) + cap = cap2; Byte *buf = (Byte *)realloc(_buf, cap); if (!buf) return false; @@ -185,9 +181,9 @@ static const UInt64 kEmptyTag = (UInt64)(Int64)-1; void CCachedInStream::Free() throw() { MyFree(_tags); - _tags = 0; + _tags = NULL; MidFree(_data); - _data = 0; + _data = NULL; } bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw() @@ -196,19 +192,19 @@ bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw( if (sizeLog >= sizeof(size_t) * 8) return false; size_t dataSize = (size_t)1 << sizeLog; - if (_data == 0 || dataSize != _dataSize) + if (!_data || dataSize != _dataSize) { MidFree(_data); _data = (Byte *)MidAlloc(dataSize); - if (_data == 0) + if (!_data) return false; _dataSize = dataSize; } - if (_tags == 0 || numBlocksLog != _numBlocksLog) + if (!_tags || numBlocksLog != _numBlocksLog) { MyFree(_tags); _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog); - if (_tags == 0) + if (!_tags) return false; _numBlocksLog = numBlocksLog; } @@ -242,21 +238,32 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz while (size != 0) { - UInt64 cacheTag = _pos >> _blockSizeLog; - size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1); + const UInt64 cacheTag = _pos >> _blockSizeLog; + const size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1); Byte *p = _data + (cacheIndex << _blockSizeLog); + if (_tags[cacheIndex] != cacheTag) { + _tags[cacheIndex] = kEmptyTag; UInt64 remInBlock = _size - (cacheTag << _blockSizeLog); size_t blockSize = (size_t)1 << _blockSizeLog; if (blockSize > remInBlock) blockSize = (size_t)remInBlock; + RINOK(ReadBlock(cacheTag, p, blockSize)); + _tags[cacheIndex] = cacheTag; } - size_t offset = (size_t)_pos & (((size_t)1 << _blockSizeLog) - 1); - UInt32 cur = (UInt32)MyMin(((size_t)1 << _blockSizeLog) - offset, (size_t)size); + + const size_t kBlockSize = (size_t)1 << _blockSizeLog; + const size_t offset = (size_t)_pos & (kBlockSize - 1); + UInt32 cur = size; + const size_t rem = kBlockSize - offset; + if (cur > rem) + cur = (UInt32)rem; + memcpy(data, p + offset, cur); + if (processedSize) *processedSize += cur; data = (void *)((const Byte *)data + cur); @@ -266,6 +273,7 @@ STDMETHODIMP CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSiz return S_OK; } + STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { @@ -278,8 +286,8 @@ STDMETHODIMP CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newP } if (offset < 0) return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; - _pos = offset; + _pos = (UInt64)offset; if (newPosition) - *newPosition = offset; + *newPosition = (UInt64)offset; return S_OK; } diff --git a/CPP/7zip/Common/StreamObjects.h b/CPP/7zip/Common/StreamObjects.h index e20e9bd8..a8fb229c 100644 --- a/CPP/7zip/Common/StreamObjects.h +++ b/CPP/7zip/Common/StreamObjects.h @@ -24,6 +24,7 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; + struct CReferenceBuf: public IUnknown, public CMyUnknownImp @@ -32,6 +33,7 @@ struct CReferenceBuf: MY_UNKNOWN_IMP }; + class CBufInStream: public IInStream, public CMyUnknownImp @@ -41,7 +43,7 @@ class CBufInStream: size_t _size; CMyComPtr<IUnknown> _ref; public: - void Init(const Byte *data, size_t size, IUnknown *ref = 0) + void Init(const Byte *data, size_t size, IUnknown *ref = NULL) { _data = data; _size = size; @@ -55,17 +57,20 @@ public: STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); }; + void Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream); void Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream); inline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream) { Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); } + class CByteDynBuffer { size_t _capacity; Byte *_buf; + CLASS_NO_COPY(CByteDynBuffer); public: - CByteDynBuffer(): _capacity(0), _buf(0) {}; + CByteDynBuffer(): _capacity(0), _buf(NULL) {}; // there is no copy constructor. So don't copy this object. ~CByteDynBuffer() { Free(); } void Free() throw(); @@ -75,6 +80,7 @@ public: bool EnsureCapacity(size_t capacity) throw(); }; + class CDynBufSeqOutStream: public ISequentialOutStream, public CMyUnknownImp @@ -94,6 +100,7 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; + class CBufPtrSeqOutStream: public ISequentialOutStream, public CMyUnknownImp @@ -114,6 +121,7 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; + class CSequentialOutStreamSizeCount: public ISequentialOutStream, public CMyUnknownImp @@ -129,6 +137,7 @@ public: STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); }; + class CCachedInStream: public IInStream, public CMyUnknownImp @@ -143,7 +152,7 @@ class CCachedInStream: protected: virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0; public: - CCachedInStream(): _tags(0), _data(0) {} + CCachedInStream(): _tags(NULL), _data(NULL) {} virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (release calls it) !!! void Free() throw(); bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw(); diff --git a/CPP/7zip/Common/UniqBlocks.h b/CPP/7zip/Common/UniqBlocks.h index a376024e..d6cd3728 100644 --- a/CPP/7zip/Common/UniqBlocks.h +++ b/CPP/7zip/Common/UniqBlocks.h @@ -19,7 +19,7 @@ struct CUniqBlocks bool IsOnlyEmpty() const { - return (Bufs.Size() == 0 || Bufs.Size() == 1 && Bufs[0].Size() == 0); + return (Bufs.Size() == 0 || (Bufs.Size() == 1 && Bufs[0].Size() == 0)); } }; diff --git a/CPP/7zip/Common/VirtThread.cpp b/CPP/7zip/Common/VirtThread.cpp index 77e3c1ac..bf24bb1c 100644 --- a/CPP/7zip/Common/VirtThread.cpp +++ b/CPP/7zip/Common/VirtThread.cpp @@ -19,20 +19,20 @@ static THREAD_FUNC_DECL CoderThread(void *p) WRes CVirtThread::Create() { - RINOK(StartEvent.CreateIfNotCreated()); - RINOK(FinishedEvent.CreateIfNotCreated()); - StartEvent.Reset(); - FinishedEvent.Reset(); + RINOK_WRes(StartEvent.CreateIfNotCreated_Reset()); + RINOK_WRes(FinishedEvent.CreateIfNotCreated_Reset()); + // StartEvent.Reset(); + // FinishedEvent.Reset(); Exit = false; if (Thread.IsCreated()) return S_OK; return Thread.Create(CoderThread, this); } -void CVirtThread::Start() +WRes CVirtThread::Start() { Exit = false; - StartEvent.Set(); + return StartEvent.Set(); } void CVirtThread::WaitThreadFinish() @@ -42,7 +42,6 @@ void CVirtThread::WaitThreadFinish() StartEvent.Set(); if (Thread.IsCreated()) { - Thread.Wait(); - Thread.Close(); + Thread.Wait_Close(); } } diff --git a/CPP/7zip/Common/VirtThread.h b/CPP/7zip/Common/VirtThread.h index ebee158c..b4d8a5a9 100644 --- a/CPP/7zip/Common/VirtThread.h +++ b/CPP/7zip/Common/VirtThread.h @@ -16,9 +16,9 @@ struct CVirtThread ~CVirtThread() { WaitThreadFinish(); } void WaitThreadFinish(); // call it in destructor of child class ! WRes Create(); - void Start(); + WRes Start(); virtual void Execute() = 0; - void WaitExecuteFinish() { FinishedEvent.Lock(); } + WRes WaitExecuteFinish() { return FinishedEvent.Lock(); } }; #endif |