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