79efa0e1f0152bde15aacff75728e895d607bee8
[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_safe_types.h"
11
12 class IFXCRT_FileAccess
13 {
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, size_t szBuffer, FX_FILESIZE pos) = 0;
27     virtual FX_BOOL             Flush() = 0;
28     virtual FX_BOOL             Truncate(FX_FILESIZE szFile) = 0;
29 };
30 IFXCRT_FileAccess*      FXCRT_FileAccess_Create();
31 class CFX_CRTFileStream final : public IFX_FileStream
32 {
33 public:
34     CFX_CRTFileStream(IFXCRT_FileAccess* pFA) : m_pFile(pFA), m_dwCount(1), m_bUseRange(FALSE), m_nOffset(0), m_nSize(0) {}
35     ~CFX_CRTFileStream()
36     {
37         if (m_pFile) {
38             m_pFile->Release();
39         }
40     }
41     virtual IFX_FileStream*             Retain() override
42     {
43         m_dwCount ++;
44         return this;
45     }
46     virtual void                                Release() override
47     {
48         FX_DWORD nCount = -- m_dwCount;
49         if (!nCount) {
50             delete this;
51         }
52     }
53     virtual FX_FILESIZE                 GetSize() override
54     {
55         return m_bUseRange ? m_nSize : m_pFile->GetSize();
56     }
57     virtual FX_BOOL                             IsEOF() override
58     {
59         return GetPosition() >= GetSize();
60     }
61     virtual FX_FILESIZE                 GetPosition() override
62     {
63         FX_FILESIZE pos = m_pFile->GetPosition();
64         if (m_bUseRange) {
65             pos -= m_nOffset;
66         }
67         return pos;
68     }
69     virtual FX_BOOL                             SetRange(FX_FILESIZE offset, FX_FILESIZE size) override
70     {
71         if (offset < 0 || size < 0) {
72             return FALSE;
73         }
74      
75         FX_SAFE_FILESIZE pos = size;
76         pos += offset;
77
78         if (!pos.IsValid() || pos.ValueOrDie() > m_pFile->GetSize()) {
79             return FALSE;
80         }
81
82         m_nOffset = offset, m_nSize = size;
83         m_bUseRange = TRUE;
84         m_pFile->SetPosition(m_nOffset);
85         return TRUE;
86     }
87     virtual void                                ClearRange() override
88     {
89         m_bUseRange = FALSE;
90     }
91     virtual FX_BOOL                             ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override
92     {
93         if (m_bUseRange && offset < 0) {
94             return FALSE;
95         }
96         FX_SAFE_FILESIZE pos = offset;
97
98         if (m_bUseRange) {
99             pos += m_nOffset;
100             if (!pos.IsValid() || pos.ValueOrDie() > (size_t)GetSize()) {
101                 return FALSE;
102             }
103         }
104         return (FX_BOOL)m_pFile->ReadPos(buffer, size, pos.ValueOrDie());
105     }
106     virtual size_t                              ReadBlock(void* buffer, size_t size) override
107     {
108         if (m_bUseRange) {
109             FX_FILESIZE availSize = m_nOffset + m_nSize - m_pFile->GetPosition();
110             if ((size_t)availSize < size) {
111                 size -= size - (size_t)availSize;
112             }
113         }
114         return m_pFile->Read(buffer, size);
115     }
116     virtual     FX_BOOL                         WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override
117     {
118         if (m_bUseRange) {
119             offset += m_nOffset;
120         }
121         return (FX_BOOL)m_pFile->WritePos(buffer, size, offset);
122     }
123     virtual FX_BOOL                             Flush()  override
124     {
125         return m_pFile->Flush();
126     }
127     IFXCRT_FileAccess*  m_pFile;
128     FX_DWORD                    m_dwCount;
129     FX_BOOL                             m_bUseRange;
130     FX_FILESIZE                 m_nOffset;
131     FX_FILESIZE                 m_nSize;
132 };
133 #define FX_MEMSTREAM_BlockSize          (64 * 1024)
134 #define FX_MEMSTREAM_Consecutive        0x01
135 #define FX_MEMSTREAM_TakeOver           0x02
136 class CFX_MemoryStream final : public IFX_MemoryStream
137 {
138 public:
139     CFX_MemoryStream(FX_BOOL bConsecutive)
140         : m_dwCount(1)
141         , m_nTotalSize(0)
142         , m_nCurSize(0)
143         , m_nCurPos(0)
144         , m_nGrowSize(FX_MEMSTREAM_BlockSize)
145         , m_bUseRange(FALSE)
146     {
147         m_dwFlags = FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0);
148     }
149     CFX_MemoryStream(uint8_t* pBuffer, size_t nSize, FX_BOOL bTakeOver)
150         : m_dwCount(1)
151         , m_nTotalSize(nSize)
152         , m_nCurSize(nSize)
153         , m_nCurPos(0)
154         , m_nGrowSize(FX_MEMSTREAM_BlockSize)
155         , m_bUseRange(FALSE)
156     {
157         m_Blocks.Add(pBuffer);
158         m_dwFlags = FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
159     }
160     ~CFX_MemoryStream()
161     {
162         if (m_dwFlags & FX_MEMSTREAM_TakeOver) {
163             for (int32_t i = 0; i < m_Blocks.GetSize(); i++) {
164                 FX_Free((uint8_t*)m_Blocks[i]);
165             }
166         }
167         m_Blocks.RemoveAll();
168     }
169     virtual IFX_FileStream*             Retain()  override
170     {
171         m_dwCount ++;
172         return this;
173     }
174     virtual void                                Release()  override
175     {
176         FX_DWORD nCount = -- m_dwCount;
177         if (nCount) {
178             return;
179         }
180         delete this;
181     }
182     virtual FX_FILESIZE                 GetSize()  override
183     {
184         return m_bUseRange ? (FX_FILESIZE) m_nSize : (FX_FILESIZE)m_nCurSize;
185     }
186     virtual FX_BOOL                             IsEOF()  override
187     {
188         return m_nCurPos >= (size_t)GetSize();
189     }
190     virtual FX_FILESIZE                 GetPosition()  override
191     {
192         FX_FILESIZE pos = (FX_FILESIZE)m_nCurPos;
193         if (m_bUseRange) {
194             pos -= (FX_FILESIZE)m_nOffset;
195         }
196         return pos;
197     }
198     virtual FX_BOOL                             SetRange(FX_FILESIZE offset, FX_FILESIZE size)  override
199     {
200         if (offset < 0 || size < 0) {
201             return FALSE;
202         }
203         FX_SAFE_FILESIZE range = size;
204         range += offset;
205         if (!range.IsValid() || range.ValueOrDie() > m_nCurSize) {
206             return FALSE;
207         }
208         
209         m_nOffset = (size_t)offset, m_nSize = (size_t)size;
210         m_bUseRange = TRUE;
211         m_nCurPos = m_nOffset;
212         return TRUE;
213     }
214     virtual void                                ClearRange()  override
215     {
216         m_bUseRange = FALSE;
217     }
218     virtual FX_BOOL                             ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)  override
219     {
220         if (!buffer || !size) {
221             return FALSE;
222         }
223
224         FX_SAFE_FILESIZE safeOffset = offset;
225         if (m_bUseRange) {
226             safeOffset += m_nOffset;
227         }
228          
229         if (!safeOffset.IsValid()) {
230             return FALSE;
231         }
232
233         offset = safeOffset.ValueOrDie();
234
235         FX_SAFE_SIZE_T newPos = size;
236         newPos += offset;
237         if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 || newPos.ValueOrDie() > m_nCurSize) {
238             return FALSE;
239         }
240
241         m_nCurPos = newPos.ValueOrDie();
242         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
243             FXSYS_memcpy(buffer, (uint8_t*)m_Blocks[0] + (size_t)offset, size);
244             return TRUE;
245         }
246         size_t nStartBlock = (size_t)offset / m_nGrowSize;
247         offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
248         while (size) {
249             size_t nRead = m_nGrowSize - (size_t)offset;
250             if (nRead > size) {
251                 nRead = size;
252             }
253             FXSYS_memcpy(buffer, (uint8_t*)m_Blocks[(int)nStartBlock] + (size_t)offset, nRead);
254             buffer = ((uint8_t*)buffer) + nRead;
255             size -= nRead;
256             nStartBlock ++;
257             offset = 0;
258         }
259         return TRUE;
260     }
261     virtual size_t                              ReadBlock(void* buffer, size_t size)  override
262     {
263         if (m_nCurPos >= m_nCurSize) {
264             return 0;
265         }
266         if (m_bUseRange) {
267             size_t availSize = m_nOffset + m_nSize - m_nCurPos;
268             if (availSize < size) {
269                 size -= size - (size_t)availSize;
270             }
271         }
272         size_t nRead = FX_MIN(size, m_nCurSize - m_nCurPos);
273         if (!ReadBlock(buffer, (int32_t)m_nCurPos, nRead)) {
274             return 0;
275         }
276         return nRead;
277     }
278     virtual     FX_BOOL                         WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size)  override
279     {
280         if (!buffer || !size) {
281             return FALSE;
282         }
283         if (m_bUseRange) {
284             offset += (FX_FILESIZE)m_nOffset;
285         }
286         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
287             FX_SAFE_SIZE_T newPos = size; 
288             newPos += offset;
289             if (!newPos.IsValid())
290                 return FALSE;
291
292             m_nCurPos = newPos.ValueOrDie();
293             if (m_nCurPos > m_nTotalSize) {
294                 m_nTotalSize = (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
295                 if (m_Blocks.GetSize() < 1) {
296                     void* block = FX_Alloc(uint8_t, m_nTotalSize);
297                     m_Blocks.Add(block);
298                 } else {
299                     m_Blocks[0] = FX_Realloc(uint8_t, m_Blocks[0], m_nTotalSize);
300                 }
301                 if (!m_Blocks[0]) {
302                     m_Blocks.RemoveAll();
303                     return FALSE;
304                 }
305             }
306             FXSYS_memcpy((uint8_t*)m_Blocks[0] + (size_t)offset, buffer, size);
307             if (m_nCurSize < m_nCurPos) {
308                 m_nCurSize = m_nCurPos;
309             }
310             return TRUE;
311         }
312
313         FX_SAFE_SIZE_T newPos = size;
314         newPos += offset;
315         if (!newPos.IsValid()) {
316             return FALSE;
317         }
318
319         if (!ExpandBlocks(newPos.ValueOrDie())) {
320             return FALSE;
321         }
322         m_nCurPos = newPos.ValueOrDie();
323         size_t nStartBlock = (size_t)offset / m_nGrowSize;
324         offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
325         while (size) {
326             size_t nWrite = m_nGrowSize - (size_t)offset;
327             if (nWrite > size) {
328                 nWrite = size;
329             }
330             FXSYS_memcpy((uint8_t*)m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite);
331             buffer = ((uint8_t*)buffer) + nWrite;
332             size -= nWrite;
333             nStartBlock ++;
334             offset = 0;
335         }
336         return TRUE;
337     }
338     virtual FX_BOOL                             Flush()  override
339     {
340         return TRUE;
341     }
342     virtual FX_BOOL                             IsConsecutive() const  override
343     {
344         return m_dwFlags & FX_MEMSTREAM_Consecutive;
345     }
346     virtual void                                EstimateSize(size_t nInitSize, size_t nGrowSize)  override
347     {
348         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
349             if (m_Blocks.GetSize() < 1) {
350                 uint8_t* pBlock = FX_Alloc(uint8_t, FX_MAX(nInitSize, 4096));
351                 m_Blocks.Add(pBlock);
352             }
353             m_nGrowSize = FX_MAX(nGrowSize, 4096);
354         } else if (m_Blocks.GetSize() < 1) {
355             m_nGrowSize = FX_MAX(nGrowSize, 4096);
356         }
357     }
358     virtual uint8_t*                    GetBuffer() const  override
359     {
360         return m_Blocks.GetSize() ? (uint8_t*)m_Blocks[0] : NULL;
361     }
362     virtual void                                AttachBuffer(uint8_t* pBuffer, size_t nSize, FX_BOOL bTakeOver = FALSE)  override
363     {
364         if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
365             return;
366         }
367         m_Blocks.RemoveAll();
368         m_Blocks.Add(pBuffer);
369         m_nTotalSize = m_nCurSize = nSize;
370         m_nCurPos = 0;
371         m_dwFlags = FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
372         ClearRange();
373     }
374     virtual void                                DetachBuffer()  override
375     {
376         if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
377             return;
378         }
379         m_Blocks.RemoveAll();
380         m_nTotalSize = m_nCurSize = m_nCurPos = 0;
381         m_dwFlags = FX_MEMSTREAM_TakeOver;
382         ClearRange();
383     }
384 protected:
385     CFX_PtrArray        m_Blocks;
386     FX_DWORD            m_dwCount;
387     size_t                      m_nTotalSize;
388     size_t                      m_nCurSize;
389     size_t                      m_nCurPos;
390     size_t                      m_nGrowSize;
391     FX_DWORD            m_dwFlags;
392     FX_BOOL                     m_bUseRange;
393     size_t                      m_nOffset;
394     size_t                      m_nSize;
395     FX_BOOL     ExpandBlocks(size_t size)
396     {
397         if (m_nCurSize < size) {
398             m_nCurSize = size;
399         }
400         if (size <= m_nTotalSize) {
401             return TRUE;
402         }
403         int32_t iCount = m_Blocks.GetSize();
404         size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize;
405         m_Blocks.SetSize(m_Blocks.GetSize() + (int32_t)size);
406         while (size --) {
407             uint8_t* pBlock = FX_Alloc(uint8_t, m_nGrowSize);
408             m_Blocks.SetAt(iCount ++, pBlock);
409             m_nTotalSize += m_nGrowSize;
410         }
411         return TRUE;
412     }
413 };
414 #ifdef __cplusplus
415 extern "C" {
416 #endif
417 #define MT_N                    848
418 #define MT_M                    456
419 #define MT_Matrix_A             0x9908b0df
420 #define MT_Upper_Mask   0x80000000
421 #define MT_Lower_Mask   0x7fffffff
422 typedef struct _FX_MTRANDOMCONTEXT {
423     _FX_MTRANDOMCONTEXT()
424     {
425         mti = MT_N + 1;
426         bHaveSeed = FALSE;
427     }
428     FX_DWORD mti;
429     FX_BOOL      bHaveSeed;
430     FX_DWORD mt[MT_N];
431 } FX_MTRANDOMCONTEXT, * FX_LPMTRANDOMCONTEXT;
432 typedef FX_MTRANDOMCONTEXT const * FX_LPCMTRANDOMCONTEXT;
433 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
434 FX_BOOL FX_GenerateCryptoRandom(FX_DWORD* pBuffer, int32_t iCount);
435 #endif
436 #ifdef __cplusplus
437 }
438 #endif
439
440 #endif  // CORE_SRC_FXCRT_EXTENSION_H_