Example #1
0
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;
}
Example #2
0
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
}