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