1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2014 PDFium Authors. All rights reserved.
2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file.
4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifndef CORE_SRC_FXCRT_EXTENSION_H_
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define CORE_SRC_FXCRT_EXTENSION_H_
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include <algorithm>
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "core/include/fxcrt/fx_basic.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "core/include/fxcrt/fx_safe_types.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass IFXCRT_FileAccess {
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual ~IFXCRT_FileAccess() {}
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual FX_BOOL Open(const CFX_ByteStringC& fileName, FX_DWORD dwMode) = 0;
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual FX_BOOL Open(const CFX_WideStringC& fileName, FX_DWORD dwMode) = 0;
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual void Close() = 0;
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual void Release() = 0;
22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual FX_FILESIZE GetSize() const = 0;
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual FX_FILESIZE GetPosition() const = 0;
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual FX_FILESIZE SetPosition(FX_FILESIZE pos) = 0;
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual size_t Read(void* pBuffer, size_t szBuffer) = 0;
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual size_t Write(const void* pBuffer, size_t szBuffer) = 0;
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual size_t ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0;
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual size_t WritePos(const void* pBuffer,
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          size_t szBuffer,
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                          FX_FILESIZE pos) = 0;
31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual FX_BOOL Flush() = 0;
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual FX_BOOL Truncate(FX_FILESIZE szFile) = 0;
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochIFXCRT_FileAccess* FXCRT_FileAccess_Create();
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef PDF_ENABLE_XFA
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass CFX_CRTFileAccess : public IFX_FileAccess {
38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CFX_CRTFileAccess() : m_RefCount(0) {}
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // IFX_FileAccess
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Release() override {
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (--m_RefCount == 0)
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      delete this;
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  IFX_FileAccess* Retain() override {
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_RefCount++;
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return (IFX_FileAccess*)this;
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void GetPath(CFX_WideString& wsPath) override { wsPath = m_path; }
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  IFX_FileStream* CreateFileStream(FX_DWORD dwModes) override {
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return FX_CreateFileStream(m_path, dwModes);
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL Init(const CFX_WideStringC& wsPath) {
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_path = wsPath;
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_RefCount = 1;
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return TRUE;
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch protected:
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CFX_WideString m_path;
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_DWORD m_RefCount;
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // PDF_ENABLE_XFA
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass CFX_CRTFileStream final : public IFX_FileStream {
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit CFX_CRTFileStream(IFXCRT_FileAccess* pFA);
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~CFX_CRTFileStream() override;
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // IFX_FileStream:
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  IFX_FileStream* Retain() override;
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Release() override;
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_FILESIZE GetSize() override;
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL IsEOF() override;
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_FILESIZE GetPosition() override;
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t ReadBlock(void* buffer, size_t size) override;
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL WriteBlock(const void* buffer,
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     FX_FILESIZE offset,
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     size_t size) override;
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL Flush() override;
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch protected:
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  IFXCRT_FileAccess* m_pFile;
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_DWORD m_dwCount;
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define FX_MEMSTREAM_BlockSize (64 * 1024)
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define FX_MEMSTREAM_Consecutive 0x01
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define FX_MEMSTREAM_TakeOver 0x02
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass CFX_MemoryStream final : public IFX_MemoryStream {
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit CFX_MemoryStream(FX_BOOL bConsecutive)
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : m_dwCount(1),
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nTotalSize(0),
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nCurSize(0),
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nCurPos(0),
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nGrowSize(FX_MEMSTREAM_BlockSize) {
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_dwFlags =
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0);
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CFX_MemoryStream(uint8_t* pBuffer, size_t nSize, FX_BOOL bTakeOver)
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : m_dwCount(1),
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nTotalSize(nSize),
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nCurSize(nSize),
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nCurPos(0),
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nGrowSize(FX_MEMSTREAM_BlockSize) {
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_Blocks.Add(pBuffer);
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_dwFlags =
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~CFX_MemoryStream() override {
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (m_dwFlags & FX_MEMSTREAM_TakeOver) {
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (int32_t i = 0; i < m_Blocks.GetSize(); i++) {
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        FX_Free(m_Blocks[i]);
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_Blocks.RemoveAll();
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // IFX_MemoryStream:
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  IFX_FileStream* Retain() override {
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_dwCount++;
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return this;
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Release() override {
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FX_DWORD nCount = --m_dwCount;
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (nCount) {
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return;
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    delete this;
137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_FILESIZE GetSize() override { return (FX_FILESIZE)m_nCurSize; }
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL IsEOF() override { return m_nCurPos >= (size_t)GetSize(); }
140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_FILESIZE GetPosition() override { return (FX_FILESIZE)m_nCurPos; }
141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!buffer || !size) {
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return FALSE;
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FX_SAFE_SIZE_T newPos = size;
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    newPos += offset;
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 ||
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        newPos.ValueOrDie() > m_nCurSize) {
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return FALSE;
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_nCurPos = newPos.ValueOrDie();
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FXSYS_memcpy(buffer, m_Blocks[0] + (size_t)offset, size);
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return TRUE;
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t nStartBlock = (size_t)offset / m_nGrowSize;
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    while (size) {
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      size_t nRead = m_nGrowSize - (size_t)offset;
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (nRead > size) {
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        nRead = size;
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FXSYS_memcpy(buffer, m_Blocks[(int)nStartBlock] + (size_t)offset, nRead);
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      buffer = ((uint8_t*)buffer) + nRead;
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      size -= nRead;
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      nStartBlock++;
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = 0;
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return TRUE;
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t ReadBlock(void* buffer, size_t size) override {
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (m_nCurPos >= m_nCurSize) {
175342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch      return 0;
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
177342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch    size_t nRead = std::min(size, m_nCurSize - m_nCurPos);
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!ReadBlock(buffer, (int32_t)m_nCurPos, nRead)) {
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return 0;
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return nRead;
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL WriteBlock(const void* buffer,
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     FX_FILESIZE offset,
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     size_t size) override {
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!buffer || !size) {
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return FALSE;
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FX_SAFE_SIZE_T newPos = size;
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      newPos += offset;
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!newPos.IsValid())
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return FALSE;
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      m_nCurPos = newPos.ValueOrDie();
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (m_nCurPos > m_nTotalSize) {
197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nTotalSize =
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (m_Blocks.GetSize() < 1) {
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          uint8_t* block = FX_Alloc(uint8_t, m_nTotalSize);
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          m_Blocks.Add(block);
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          m_Blocks[0] = FX_Realloc(uint8_t, m_Blocks[0], m_nTotalSize);
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (!m_Blocks[0]) {
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          m_Blocks.RemoveAll();
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          return FALSE;
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FXSYS_memcpy(m_Blocks[0] + (size_t)offset, buffer, size);
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (m_nCurSize < m_nCurPos) {
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_nCurSize = m_nCurPos;
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return TRUE;
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FX_SAFE_SIZE_T newPos = size;
218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    newPos += offset;
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!newPos.IsValid()) {
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return FALSE;
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!ExpandBlocks(newPos.ValueOrDie())) {
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return FALSE;
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_nCurPos = newPos.ValueOrDie();
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_t nStartBlock = (size_t)offset / m_nGrowSize;
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    while (size) {
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      size_t nWrite = m_nGrowSize - (size_t)offset;
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (nWrite > size) {
232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        nWrite = size;
233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      FXSYS_memcpy(m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite);
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      buffer = ((uint8_t*)buffer) + nWrite;
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      size -= nWrite;
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      nStartBlock++;
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      offset = 0;
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return TRUE;
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL Flush() override { return TRUE; }
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL IsConsecutive() const override {
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return m_dwFlags & FX_MEMSTREAM_Consecutive;
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EstimateSize(size_t nInitSize, size_t nGrowSize) override {
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (m_Blocks.GetSize() < 1) {
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        uint8_t* pBlock =
250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            FX_Alloc(uint8_t, std::max(nInitSize, static_cast<size_t>(4096)));
251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        m_Blocks.Add(pBlock);
252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else if (m_Blocks.GetSize() < 1) {
255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint8_t* GetBuffer() const override {
259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return m_Blocks.GetSize() ? m_Blocks[0] : nullptr;
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AttachBuffer(uint8_t* pBuffer,
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    size_t nSize,
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    FX_BOOL bTakeOver = FALSE) override {
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return;
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_Blocks.RemoveAll();
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_Blocks.Add(pBuffer);
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_nTotalSize = m_nCurSize = nSize;
270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_nCurPos = 0;
271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_dwFlags =
272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DetachBuffer() override {
275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return;
277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_Blocks.RemoveAll();
279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_nTotalSize = m_nCurSize = m_nCurPos = 0;
280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_dwFlags = FX_MEMSTREAM_TakeOver;
281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch protected:
284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CFX_ArrayTemplate<uint8_t*> m_Blocks;
285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_DWORD m_dwCount;
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t m_nTotalSize;
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t m_nCurSize;
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t m_nCurPos;
289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t m_nGrowSize;
290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_DWORD m_dwFlags;
291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL ExpandBlocks(size_t size) {
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (m_nCurSize < size) {
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      m_nCurSize = size;
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (size <= m_nTotalSize) {
296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return TRUE;
297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int32_t iCount = m_Blocks.GetSize();
299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize;
300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    m_Blocks.SetSize(m_Blocks.GetSize() + (int32_t)size);
301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    while (size--) {
302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint8_t* pBlock = FX_Alloc(uint8_t, m_nGrowSize);
303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      m_Blocks.SetAt(iCount++, pBlock);
304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      m_nTotalSize += m_nGrowSize;
305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return TRUE;
307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef __cplusplus
311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochextern "C" {
312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define MT_N 848
314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define MT_M 456
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define MT_Matrix_A 0x9908b0df
316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define MT_Upper_Mask 0x80000000
317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define MT_Lower_Mask 0x7fffffff
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef struct _FX_MTRANDOMCONTEXT {
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  _FX_MTRANDOMCONTEXT() {
320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    mti = MT_N + 1;
321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bHaveSeed = FALSE;
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_DWORD mti;
324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_BOOL bHaveSeed;
325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FX_DWORD mt[MT_N];
326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} FX_MTRANDOMCONTEXT, *FX_LPMTRANDOMCONTEXT;
327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef FX_MTRANDOMCONTEXT const* FX_LPCMTRANDOMCONTEXT;
328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochFX_BOOL FX_GenerateCryptoRandom(FX_DWORD* pBuffer, int32_t iCount);
330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef __cplusplus
332014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
335014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // CORE_SRC_FXCRT_EXTENSION_H_
336014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch