From be3b47d0d504a3409ce66bd77bb8c0acff87c4f5 Mon Sep 17 00:00:00 2001 From: kh1 Date: Thu, 15 Mar 2012 14:53:47 +0100 Subject: Reorganize the tree, have better ifw.pri. Shadow build support. Change-Id: I01fb12537f863ed0744979973c7e4153889cc5cb Reviewed-by: Tim Jenssen --- .../win/CPP/7zip/Archive/Cab/CabBlockInStream.cpp | 189 +++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 src/libs/7zip/win/CPP/7zip/Archive/Cab/CabBlockInStream.cpp (limited to 'src/libs/7zip/win/CPP/7zip/Archive/Cab/CabBlockInStream.cpp') diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Cab/CabBlockInStream.cpp new file mode 100644 index 000000000..12c73eb5f --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Cab/CabBlockInStream.cpp @@ -0,0 +1,189 @@ +// CabBlockInStream.cpp + +#include "StdAfx.h" + +#include "../../../../C/Alloc.h" + +#include "Common/Defs.h" + +#include "../../Common/StreamUtils.h" + +#include "CabBlockInStream.h" + +namespace NArchive { +namespace NCab { + +static const UInt32 kBlockSize = (1 << 16); + +bool CCabBlockInStream::Create() +{ + if (!_buffer) + _buffer = (Byte *)::MyAlloc(kBlockSize); + return (_buffer != 0); +} + +CCabBlockInStream::~CCabBlockInStream() +{ + MyFree(_buffer); +} + +class CCheckSum2 +{ + UInt32 m_Value; + int m_Pos; + Byte m_Hist[4]; +public: + CCheckSum2(): m_Value(0){}; + void Init() { m_Value = 0; m_Pos = 0; } + void Update(const void *data, UInt32 size); + void FinishDataUpdate() + { + for (int i = 0; i < m_Pos; i++) + m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1)); + } + void UpdateUInt32(UInt32 v) { m_Value ^= v; } + UInt32 GetResult() const { return m_Value; } +}; + +void CCheckSum2::Update(const void *data, UInt32 size) +{ + UInt32 checkSum = m_Value; + const Byte *dataPointer = (const Byte *)data; + + while (size != 0 && m_Pos != 0) + { + m_Hist[m_Pos] = *dataPointer++; + m_Pos = (m_Pos + 1) & 3; + size--; + if (m_Pos == 0) + for (int i = 0; i < 4; i++) + checkSum ^= ((UInt32)m_Hist[i]) << (8 * i); + } + + int numWords = size / 4; + + while (numWords-- != 0) + { + UInt32 temp = *dataPointer++; + temp |= ((UInt32)(*dataPointer++)) << 8; + temp |= ((UInt32)(*dataPointer++)) << 16; + temp |= ((UInt32)(*dataPointer++)) << 24; + checkSum ^= temp; + } + m_Value = checkSum; + + size &= 3; + + while (size != 0) + { + m_Hist[m_Pos] = *dataPointer++; + m_Pos = (m_Pos + 1) & 3; + size--; + } +} + +static const UInt32 kDataBlockHeaderSize = 8; + +class CTempCabInBuffer2 +{ +public: + Byte Buffer[kDataBlockHeaderSize]; + UInt32 Pos; + Byte ReadByte() + { + return Buffer[Pos++]; + } + UInt32 ReadUInt32() + { + UInt32 value = 0; + for (int i = 0; i < 4; i++) + value |= (((UInt32)ReadByte()) << (8 * i)); + return value; + } + UInt16 ReadUInt16() + { + UInt16 value = 0; + for (int i = 0; i < 2; i++) + value |= (((UInt16)ReadByte()) << (8 * i)); + return value; + } +}; + +HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize) +{ + CTempCabInBuffer2 inBuffer; + inBuffer.Pos = 0; + RINOK(ReadStream_FALSE(_stream, inBuffer.Buffer, kDataBlockHeaderSize)) + + UInt32 checkSum = inBuffer.ReadUInt32(); + packSize = inBuffer.ReadUInt16(); + unpackSize = inBuffer.ReadUInt16(); + if (ReservedSize != 0) + { + RINOK(ReadStream_FALSE(_stream, _buffer, ReservedSize)); + } + _pos = 0; + CCheckSum2 checkSumCalc; + checkSumCalc.Init(); + UInt32 packSize2 = packSize; + if (MsZip && _size == 0) + { + if (packSize < 2) + return S_FALSE; // bad block; + Byte sig[2]; + RINOK(ReadStream_FALSE(_stream, sig, 2)); + if (sig[0] != 0x43 || sig[1] != 0x4B) + return S_FALSE; + packSize2 -= 2; + checkSumCalc.Update(sig, 2); + } + + if (kBlockSize - _size < packSize2) + return S_FALSE; + + UInt32 curSize = packSize2; + if (curSize != 0) + { + size_t processedSizeLoc = curSize; + RINOK(ReadStream(_stream, _buffer + _size, &processedSizeLoc)); + checkSumCalc.Update(_buffer + _size, (UInt32)processedSizeLoc); + _size += (UInt32)processedSizeLoc; + if (processedSizeLoc != curSize) + return S_FALSE; + } + TotalPackSize = _size; + + checkSumCalc.FinishDataUpdate(); + + bool dataError; + if (checkSum == 0) + dataError = false; + else + { + checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16)); + dataError = (checkSumCalc.GetResult() != checkSum); + } + DataError |= dataError; + return dataError ? S_FALSE : S_OK; +} + +STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + if (size == 0) + return S_OK; + if (_size != 0) + { + size = MyMin(_size, size); + memmove(data, _buffer + _pos, size); + _pos += size; + _size -= size; + if (processedSize != 0) + *processedSize = size; + return S_OK; + } + return S_OK; // no blocks data +} + +}} -- cgit v1.2.3