Home | History | Annotate | Download | only in fxcrt
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #ifndef CORE_SRC_FXCRT_EXTENSION_H_
      8 #define CORE_SRC_FXCRT_EXTENSION_H_
      9 
     10 #include <algorithm>
     11 
     12 #include "core/include/fxcrt/fx_basic.h"
     13 #include "core/include/fxcrt/fx_safe_types.h"
     14 
     15 class IFXCRT_FileAccess {
     16  public:
     17   virtual ~IFXCRT_FileAccess() {}
     18   virtual FX_BOOL Open(const CFX_ByteStringC& fileName, FX_DWORD dwMode) = 0;
     19   virtual FX_BOOL Open(const CFX_WideStringC& fileName, FX_DWORD dwMode) = 0;
     20   virtual void Close() = 0;
     21   virtual void Release() = 0;
     22   virtual FX_FILESIZE GetSize() const = 0;
     23   virtual FX_FILESIZE GetPosition() const = 0;
     24   virtual FX_FILESIZE SetPosition(FX_FILESIZE pos) = 0;
     25   virtual size_t Read(void* pBuffer, size_t szBuffer) = 0;
     26   virtual size_t Write(const void* pBuffer, size_t szBuffer) = 0;
     27   virtual size_t ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0;
     28   virtual size_t WritePos(const void* pBuffer,
     29                           size_t szBuffer,
     30                           FX_FILESIZE pos) = 0;
     31   virtual FX_BOOL Flush() = 0;
     32   virtual FX_BOOL Truncate(FX_FILESIZE szFile) = 0;
     33 };
     34 IFXCRT_FileAccess* FXCRT_FileAccess_Create();
     35 
     36 #ifdef PDF_ENABLE_XFA
     37 class CFX_CRTFileAccess : public IFX_FileAccess {
     38  public:
     39   CFX_CRTFileAccess() : m_RefCount(0) {}
     40 
     41   // IFX_FileAccess
     42   void Release() override {
     43     if (--m_RefCount == 0)
     44       delete this;
     45   }
     46 
     47   IFX_FileAccess* Retain() override {
     48     m_RefCount++;
     49     return (IFX_FileAccess*)this;
     50   }
     51 
     52   void GetPath(CFX_WideString& wsPath) override { wsPath = m_path; }
     53 
     54   IFX_FileStream* CreateFileStream(FX_DWORD dwModes) override {
     55     return FX_CreateFileStream(m_path, dwModes);
     56   }
     57 
     58   FX_BOOL Init(const CFX_WideStringC& wsPath) {
     59     m_path = wsPath;
     60     m_RefCount = 1;
     61     return TRUE;
     62   }
     63 
     64  protected:
     65   CFX_WideString m_path;
     66   FX_DWORD m_RefCount;
     67 };
     68 #endif  // PDF_ENABLE_XFA
     69 
     70 class CFX_CRTFileStream final : public IFX_FileStream {
     71  public:
     72   explicit CFX_CRTFileStream(IFXCRT_FileAccess* pFA);
     73   ~CFX_CRTFileStream() override;
     74 
     75   // IFX_FileStream:
     76   IFX_FileStream* Retain() override;
     77   void Release() override;
     78   FX_FILESIZE GetSize() override;
     79   FX_BOOL IsEOF() override;
     80   FX_FILESIZE GetPosition() override;
     81   FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
     82   size_t ReadBlock(void* buffer, size_t size) override;
     83   FX_BOOL WriteBlock(const void* buffer,
     84                      FX_FILESIZE offset,
     85                      size_t size) override;
     86   FX_BOOL Flush() override;
     87 
     88  protected:
     89   IFXCRT_FileAccess* m_pFile;
     90   FX_DWORD m_dwCount;
     91 };
     92 
     93 #define FX_MEMSTREAM_BlockSize (64 * 1024)
     94 #define FX_MEMSTREAM_Consecutive 0x01
     95 #define FX_MEMSTREAM_TakeOver 0x02
     96 class CFX_MemoryStream final : public IFX_MemoryStream {
     97  public:
     98   explicit CFX_MemoryStream(FX_BOOL bConsecutive)
     99       : m_dwCount(1),
    100         m_nTotalSize(0),
    101         m_nCurSize(0),
    102         m_nCurPos(0),
    103         m_nGrowSize(FX_MEMSTREAM_BlockSize) {
    104     m_dwFlags =
    105         FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0);
    106   }
    107   CFX_MemoryStream(uint8_t* pBuffer, size_t nSize, FX_BOOL bTakeOver)
    108       : m_dwCount(1),
    109         m_nTotalSize(nSize),
    110         m_nCurSize(nSize),
    111         m_nCurPos(0),
    112         m_nGrowSize(FX_MEMSTREAM_BlockSize) {
    113     m_Blocks.Add(pBuffer);
    114     m_dwFlags =
    115         FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
    116   }
    117   ~CFX_MemoryStream() override {
    118     if (m_dwFlags & FX_MEMSTREAM_TakeOver) {
    119       for (int32_t i = 0; i < m_Blocks.GetSize(); i++) {
    120         FX_Free(m_Blocks[i]);
    121       }
    122     }
    123     m_Blocks.RemoveAll();
    124   }
    125 
    126   // IFX_MemoryStream:
    127   IFX_FileStream* Retain() override {
    128     m_dwCount++;
    129     return this;
    130   }
    131   void Release() override {
    132     FX_DWORD nCount = --m_dwCount;
    133     if (nCount) {
    134       return;
    135     }
    136     delete this;
    137   }
    138   FX_FILESIZE GetSize() override { return (FX_FILESIZE)m_nCurSize; }
    139   FX_BOOL IsEOF() override { return m_nCurPos >= (size_t)GetSize(); }
    140   FX_FILESIZE GetPosition() override { return (FX_FILESIZE)m_nCurPos; }
    141   FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
    142     if (!buffer || !size) {
    143       return FALSE;
    144     }
    145 
    146     FX_SAFE_SIZE_T newPos = size;
    147     newPos += offset;
    148     if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 ||
    149         newPos.ValueOrDie() > m_nCurSize) {
    150       return FALSE;
    151     }
    152 
    153     m_nCurPos = newPos.ValueOrDie();
    154     if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
    155       FXSYS_memcpy(buffer, m_Blocks[0] + (size_t)offset, size);
    156       return TRUE;
    157     }
    158     size_t nStartBlock = (size_t)offset / m_nGrowSize;
    159     offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
    160     while (size) {
    161       size_t nRead = m_nGrowSize - (size_t)offset;
    162       if (nRead > size) {
    163         nRead = size;
    164       }
    165       FXSYS_memcpy(buffer, m_Blocks[(int)nStartBlock] + (size_t)offset, nRead);
    166       buffer = ((uint8_t*)buffer) + nRead;
    167       size -= nRead;
    168       nStartBlock++;
    169       offset = 0;
    170     }
    171     return TRUE;
    172   }
    173   size_t ReadBlock(void* buffer, size_t size) override {
    174     if (m_nCurPos >= m_nCurSize) {
    175       return 0;
    176     }
    177     size_t nRead = std::min(size, m_nCurSize - m_nCurPos);
    178     if (!ReadBlock(buffer, (int32_t)m_nCurPos, nRead)) {
    179       return 0;
    180     }
    181     return nRead;
    182   }
    183   FX_BOOL WriteBlock(const void* buffer,
    184                      FX_FILESIZE offset,
    185                      size_t size) override {
    186     if (!buffer || !size) {
    187       return FALSE;
    188     }
    189     if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
    190       FX_SAFE_SIZE_T newPos = size;
    191       newPos += offset;
    192       if (!newPos.IsValid())
    193         return FALSE;
    194 
    195       m_nCurPos = newPos.ValueOrDie();
    196       if (m_nCurPos > m_nTotalSize) {
    197         m_nTotalSize =
    198             (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
    199         if (m_Blocks.GetSize() < 1) {
    200           uint8_t* block = FX_Alloc(uint8_t, m_nTotalSize);
    201           m_Blocks.Add(block);
    202         } else {
    203           m_Blocks[0] = FX_Realloc(uint8_t, m_Blocks[0], m_nTotalSize);
    204         }
    205         if (!m_Blocks[0]) {
    206           m_Blocks.RemoveAll();
    207           return FALSE;
    208         }
    209       }
    210       FXSYS_memcpy(m_Blocks[0] + (size_t)offset, buffer, size);
    211       if (m_nCurSize < m_nCurPos) {
    212         m_nCurSize = m_nCurPos;
    213       }
    214       return TRUE;
    215     }
    216 
    217     FX_SAFE_SIZE_T newPos = size;
    218     newPos += offset;
    219     if (!newPos.IsValid()) {
    220       return FALSE;
    221     }
    222 
    223     if (!ExpandBlocks(newPos.ValueOrDie())) {
    224       return FALSE;
    225     }
    226     m_nCurPos = newPos.ValueOrDie();
    227     size_t nStartBlock = (size_t)offset / m_nGrowSize;
    228     offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
    229     while (size) {
    230       size_t nWrite = m_nGrowSize - (size_t)offset;
    231       if (nWrite > size) {
    232         nWrite = size;
    233       }
    234       FXSYS_memcpy(m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite);
    235       buffer = ((uint8_t*)buffer) + nWrite;
    236       size -= nWrite;
    237       nStartBlock++;
    238       offset = 0;
    239     }
    240     return TRUE;
    241   }
    242   FX_BOOL Flush() override { return TRUE; }
    243   FX_BOOL IsConsecutive() const override {
    244     return m_dwFlags & FX_MEMSTREAM_Consecutive;
    245   }
    246   void EstimateSize(size_t nInitSize, size_t nGrowSize) override {
    247     if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
    248       if (m_Blocks.GetSize() < 1) {
    249         uint8_t* pBlock =
    250             FX_Alloc(uint8_t, std::max(nInitSize, static_cast<size_t>(4096)));
    251         m_Blocks.Add(pBlock);
    252       }
    253       m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
    254     } else if (m_Blocks.GetSize() < 1) {
    255       m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
    256     }
    257   }
    258   uint8_t* GetBuffer() const override {
    259     return m_Blocks.GetSize() ? m_Blocks[0] : nullptr;
    260   }
    261   void AttachBuffer(uint8_t* pBuffer,
    262                     size_t nSize,
    263                     FX_BOOL bTakeOver = FALSE) override {
    264     if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
    265       return;
    266     }
    267     m_Blocks.RemoveAll();
    268     m_Blocks.Add(pBuffer);
    269     m_nTotalSize = m_nCurSize = nSize;
    270     m_nCurPos = 0;
    271     m_dwFlags =
    272         FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
    273   }
    274   void DetachBuffer() override {
    275     if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
    276       return;
    277     }
    278     m_Blocks.RemoveAll();
    279     m_nTotalSize = m_nCurSize = m_nCurPos = 0;
    280     m_dwFlags = FX_MEMSTREAM_TakeOver;
    281   }
    282 
    283  protected:
    284   CFX_ArrayTemplate<uint8_t*> m_Blocks;
    285   FX_DWORD m_dwCount;
    286   size_t m_nTotalSize;
    287   size_t m_nCurSize;
    288   size_t m_nCurPos;
    289   size_t m_nGrowSize;
    290   FX_DWORD m_dwFlags;
    291   FX_BOOL ExpandBlocks(size_t size) {
    292     if (m_nCurSize < size) {
    293       m_nCurSize = size;
    294     }
    295     if (size <= m_nTotalSize) {
    296       return TRUE;
    297     }
    298     int32_t iCount = m_Blocks.GetSize();
    299     size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize;
    300     m_Blocks.SetSize(m_Blocks.GetSize() + (int32_t)size);
    301     while (size--) {
    302       uint8_t* pBlock = FX_Alloc(uint8_t, m_nGrowSize);
    303       m_Blocks.SetAt(iCount++, pBlock);
    304       m_nTotalSize += m_nGrowSize;
    305     }
    306     return TRUE;
    307   }
    308 };
    309 
    310 #ifdef __cplusplus
    311 extern "C" {
    312 #endif
    313 #define MT_N 848
    314 #define MT_M 456
    315 #define MT_Matrix_A 0x9908b0df
    316 #define MT_Upper_Mask 0x80000000
    317 #define MT_Lower_Mask 0x7fffffff
    318 typedef struct _FX_MTRANDOMCONTEXT {
    319   _FX_MTRANDOMCONTEXT() {
    320     mti = MT_N + 1;
    321     bHaveSeed = FALSE;
    322   }
    323   FX_DWORD mti;
    324   FX_BOOL bHaveSeed;
    325   FX_DWORD mt[MT_N];
    326 } FX_MTRANDOMCONTEXT, *FX_LPMTRANDOMCONTEXT;
    327 typedef FX_MTRANDOMCONTEXT const* FX_LPCMTRANDOMCONTEXT;
    328 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    329 FX_BOOL FX_GenerateCryptoRandom(FX_DWORD* pBuffer, int32_t iCount);
    330 #endif
    331 #ifdef __cplusplus
    332 }
    333 #endif
    334 
    335 #endif  // CORE_SRC_FXCRT_EXTENSION_H_
    336