bool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) { unsigned sizeLog = blockSizeLog + numBlocksLog; if (sizeLog >= sizeof(size_t) * 8) return false; size_t dataSize = (size_t)1 << sizeLog; if (_data == 0 || dataSize != _dataSize) { MidFree(_data); _data = (Byte *)MidAlloc(dataSize); if (_data == 0) return false; _dataSize = dataSize; } if (_tags == 0 || numBlocksLog != _numBlocksLog) { MyFree(_tags); _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog); if (_tags == 0) return false; _numBlocksLog = numBlocksLog; } _blockSizeLog = blockSizeLog; return true; }
STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) { #ifdef USE_WIN_FILE #ifdef SUPPORT_DEVICE_FILE if (processedSize) *processedSize = 0; if (size == 0) return S_OK; if (File.IsDeviceFile) { if (File.SizeDefined) { if (VirtPos >= File.Size) return VirtPos == File.Size ? S_OK : E_FAIL; UInt64 rem = File.Size - VirtPos; if (size > rem) size = (UInt32)rem; } for (;;) { const UInt32 mask = kClusterSize - 1; const UInt64 mask2 = ~(UInt64)mask; UInt64 alignedPos = VirtPos & mask2; if (BufSize > 0 && BufStartPos == alignedPos) { UInt32 pos = (UInt32)VirtPos & mask; if (pos >= BufSize) return S_OK; UInt32 rem = MyMin(BufSize - pos, size); memcpy(data, Buf + pos, rem); VirtPos += rem; if (processedSize) *processedSize += rem; return S_OK; } bool useBuf = false; if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 ) useBuf = true; else { UInt64 end = VirtPos + size; if ((end & mask) != 0) { end &= mask2; if (end <= VirtPos) useBuf = true; else size = (UInt32)(end - VirtPos); } } if (!useBuf) break; if (alignedPos != PhyPos) { UInt64 realNewPosition; bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition); if (!result) return ConvertBoolToHRESULT(result); PhyPos = realNewPosition; } BufStartPos = alignedPos; UInt32 readSize = kClusterSize; if (File.SizeDefined) readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize); if (!Buf) { Buf = (Byte *)MidAlloc(kClusterSize); if (!Buf) return E_OUTOFMEMORY; } bool result = File.Read1(Buf, readSize, BufSize); if (!result) return ConvertBoolToHRESULT(result); if (BufSize == 0) return S_OK; PhyPos += BufSize; } if (VirtPos != PhyPos) { UInt64 realNewPosition; bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition); if (!result) return ConvertBoolToHRESULT(result); PhyPos = VirtPos = realNewPosition; } } #endif UInt32 realProcessedSize; bool result = File.ReadPart(data, size, realProcessedSize); if (processedSize) *processedSize = realProcessedSize; #ifdef SUPPORT_DEVICE_FILE VirtPos += realProcessedSize; PhyPos += realProcessedSize; #endif if (result) return S_OK; { 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 }