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