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