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