• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "xfa/fgas/crt/fgas_stream.h"
8 
9 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
10     _FX_OS_ == _FX_WIN64_
11 #include <io.h>
12 #endif
13 
14 #include <algorithm>
15 #include <memory>
16 
17 #include "third_party/base/ptr_util.h"
18 #include "xfa/fgas/crt/fgas_codepage.h"
19 
20 namespace {
21 
22 class IFGAS_StreamImp {
23  public:
~IFGAS_StreamImp()24   virtual ~IFGAS_StreamImp() {}
25 
26   virtual int32_t GetLength() const = 0;
27   virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) = 0;
28   virtual int32_t GetPosition() = 0;
29   virtual bool IsEOF() const = 0;
30   virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) = 0;
31   virtual int32_t ReadString(FX_WCHAR* pStr,
32                              int32_t iMaxLength,
33                              bool& bEOS) = 0;
34   virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) = 0;
35   virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) = 0;
36   virtual void Flush() = 0;
37   virtual bool SetLength(int32_t iLength) = 0;
38 
39  protected:
40   IFGAS_StreamImp();
41 
GetAccessModes() const42   uint32_t GetAccessModes() const { return m_dwAccess; }
SetAccessModes(uint32_t modes)43   void SetAccessModes(uint32_t modes) { m_dwAccess = modes; }
44 
45  private:
46   uint32_t m_dwAccess;
47 };
48 
49 class CFGAS_FileStreamImp : public IFGAS_StreamImp {
50  public:
51   CFGAS_FileStreamImp();
52   ~CFGAS_FileStreamImp() override;
53 
54   bool LoadFile(const FX_WCHAR* pszSrcFileName, uint32_t dwAccess);
55 
56   // IFGAS_StreamImp:
57   int32_t GetLength() const override;
58   int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override;
59   int32_t GetPosition() override;
60   bool IsEOF() const override;
61   int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override;
62   int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override;
63   int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override;
64   int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override;
65   void Flush() override;
66   bool SetLength(int32_t iLength) override;
67 
68  protected:
69   FXSYS_FILE* m_hFile;
70   int32_t m_iLength;
71 };
72 
73 class CFGAS_BufferStreamImp : public IFGAS_StreamImp {
74  public:
75   CFGAS_BufferStreamImp();
~CFGAS_BufferStreamImp()76   ~CFGAS_BufferStreamImp() override {}
77 
78   bool LoadBuffer(uint8_t* pData, int32_t iTotalSize, uint32_t dwAccess);
79 
80   // IFGAS_StreamImp:
81   int32_t GetLength() const override;
82   int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override;
83   int32_t GetPosition() override;
84   bool IsEOF() const override;
85   int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override;
86   int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override;
87   int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override;
88   int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override;
Flush()89   void Flush() override {}
SetLength(int32_t iLength)90   bool SetLength(int32_t iLength) override { return false; }
91 
92  protected:
93   uint8_t* m_pData;
94   int32_t m_iTotalSize;
95   int32_t m_iPosition;
96   int32_t m_iLength;
97 };
98 
99 class CFGAS_FileReadStreamImp : public IFGAS_StreamImp {
100  public:
101   CFGAS_FileReadStreamImp();
~CFGAS_FileReadStreamImp()102   ~CFGAS_FileReadStreamImp() override {}
103 
104   bool LoadFileRead(const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead,
105                     uint32_t dwAccess);
106 
107   // IFGAS_StreamImp:
108   int32_t GetLength() const override;
109   int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override;
GetPosition()110   int32_t GetPosition() override { return m_iPosition; }
111   bool IsEOF() const override;
112   int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override;
113   int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override;
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)114   int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override {
115     return 0;
116   }
WriteString(const FX_WCHAR * pStr,int32_t iLength)117   int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override {
118     return 0;
119   }
Flush()120   void Flush() override {}
SetLength(int32_t iLength)121   bool SetLength(int32_t iLength) override { return false; }
122 
123  protected:
124   CFX_RetainPtr<IFX_SeekableReadStream> m_pFileRead;
125   int32_t m_iPosition;
126   int32_t m_iLength;
127 };
128 
129 class CFGAS_BufferReadStreamImp : public IFGAS_StreamImp {
130  public:
131   CFGAS_BufferReadStreamImp();
132   ~CFGAS_BufferReadStreamImp() override;
133 
134   bool LoadBufferRead(const CFX_RetainPtr<IFX_BufferedReadStream>& pBufferRead,
135                       int32_t iFileSize,
136                       uint32_t dwAccess);
137 
138   // IFGAS_StreamImp:
139   int32_t GetLength() const override;
140   int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override;
GetPosition()141   int32_t GetPosition() override { return m_iPosition; }
142   bool IsEOF() const override;
143   int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override;
144   int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override;
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)145   int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override {
146     return 0;
147   }
WriteString(const FX_WCHAR * pStr,int32_t iLength)148   int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override {
149     return 0;
150   }
Flush()151   void Flush() override {}
SetLength(int32_t iLength)152   bool SetLength(int32_t iLength) override { return false; }
153 
154  private:
155   CFX_RetainPtr<IFX_BufferedReadStream> m_pBufferRead;
156   int32_t m_iPosition;
157   int32_t m_iBufferSize;
158 };
159 
160 class CFGAS_FileWriteStreamImp : public IFGAS_StreamImp {
161  public:
162   CFGAS_FileWriteStreamImp();
~CFGAS_FileWriteStreamImp()163   ~CFGAS_FileWriteStreamImp() override {}
164 
165   bool LoadFileWrite(const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite,
166                      uint32_t dwAccess);
167 
168   // IFGAS_StreamImp:
169   int32_t GetLength() const override;
170   int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override;
GetPosition()171   int32_t GetPosition() override { return m_iPosition; }
172   bool IsEOF() const override;
ReadData(uint8_t * pBuffer,int32_t iBufferSize)173   int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override { return 0; }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,bool & bEOS)174   int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override {
175     return 0;
176   }
177   int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override;
178   int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override;
179   void Flush() override;
SetLength(int32_t iLength)180   bool SetLength(int32_t iLength) override { return false; }
181 
182  protected:
183   CFX_RetainPtr<IFX_SeekableWriteStream> m_pFileWrite;
184   int32_t m_iPosition;
185 };
186 
187 enum FX_STREAMTYPE {
188   FX_SREAMTYPE_Unknown = 0,
189   FX_STREAMTYPE_File,
190   FX_STREAMTYPE_Buffer,
191   FX_STREAMTYPE_Stream,
192   FX_STREAMTYPE_BufferRead,
193 };
194 
195 class CFGAS_Stream : public IFGAS_Stream {
196  public:
197   template <typename T, typename... Args>
198   friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
199 
200   bool LoadFile(const FX_WCHAR* pszSrcFileName, uint32_t dwAccess);
201   bool LoadBuffer(uint8_t* pData, int32_t iTotalSize, uint32_t dwAccess);
202   bool LoadFileRead(const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead,
203                     uint32_t dwAccess);
204   bool LoadFileWrite(const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite,
205                      uint32_t dwAccess);
206   bool LoadBufferRead(const CFX_RetainPtr<IFX_BufferedReadStream>& pBufferRead,
207                       int32_t iFileSize,
208                       uint32_t dwAccess);
209 
210   // IFGAS_Stream
211   uint32_t GetAccessModes() const override;
212   int32_t GetLength() const override;
213   int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override;
214   int32_t GetPosition() override;
215   bool IsEOF() const override;
216   int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override;
217   int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override;
218   int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override;
219   int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override;
220   void Flush() override;
221   bool SetLength(int32_t iLength) override;
222   int32_t GetBOM(uint8_t bom[4]) const override;
223   uint16_t GetCodePage() const override;
224   uint16_t SetCodePage(uint16_t wCodePage) override;
225   CFX_RetainPtr<IFGAS_Stream> CreateSharedStream(uint32_t dwAccess,
226                                                  int32_t iOffset,
227                                                  int32_t iLength) override;
228 
229  protected:
230   CFGAS_Stream();
231   ~CFGAS_Stream() override;
232 
233   FX_STREAMTYPE m_eStreamType;
234   IFGAS_StreamImp* m_pStreamImp;
235   uint32_t m_dwAccess;
236   int32_t m_iTotalSize;
237   int32_t m_iPosition;
238   int32_t m_iStart;
239   int32_t m_iLength;
240   int32_t m_iRefCount;
241 };
242 
243 class CFGAS_TextStream : public IFGAS_Stream {
244  public:
245   template <typename T, typename... Args>
246   friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
247 
248   // IFGAS_Stream
249   uint32_t GetAccessModes() const override;
250   int32_t GetLength() const override;
251   int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) override;
252   int32_t GetPosition() override;
253   bool IsEOF() const override;
254   int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override;
255   int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, bool& bEOS) override;
256   int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override;
257   int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override;
258   void Flush() override;
259   bool SetLength(int32_t iLength) override;
260   int32_t GetBOM(uint8_t bom[4]) const override;
261   uint16_t GetCodePage() const override;
262   uint16_t SetCodePage(uint16_t wCodePage) override;
263   CFX_RetainPtr<IFGAS_Stream> CreateSharedStream(uint32_t dwAccess,
264                                                  int32_t iOffset,
265                                                  int32_t iLength) override;
266 
267  protected:
268   explicit CFGAS_TextStream(const CFX_RetainPtr<IFGAS_Stream>& pStream);
269   ~CFGAS_TextStream() override;
270 
271   void InitStream();
272 
273   uint16_t m_wCodePage;
274   int32_t m_wBOMLength;
275   uint32_t m_dwBOM;
276   uint8_t* m_pBuf;
277   int32_t m_iBufSize;
278   CFX_RetainPtr<IFGAS_Stream> m_pStreamImp;
279 };
280 
281 class CFGAS_FileRead : public IFX_SeekableReadStream {
282  public:
283   static CFX_RetainPtr<CFGAS_FileRead> Create(
284       const CFX_RetainPtr<IFGAS_Stream>& pStream);
285 
286   explicit CFGAS_FileRead(const CFX_RetainPtr<IFGAS_Stream>& pStream);
287   ~CFGAS_FileRead() override;
288 
289   // IFX_SeekableReadStream
290   FX_FILESIZE GetSize() override;
291   bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
292 
293  protected:
294   CFX_RetainPtr<IFGAS_Stream> m_pStream;
295 };
296 
FileLength(FXSYS_FILE * file)297 int32_t FileLength(FXSYS_FILE* file) {
298   ASSERT(file);
299 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_
300   return _filelength(_fileno(file));
301 #else
302   int32_t iPos = FXSYS_ftell(file);
303   FXSYS_fseek(file, 0, FXSYS_SEEK_END);
304   int32_t iLen = FXSYS_ftell(file);
305   FXSYS_fseek(file, iPos, FXSYS_SEEK_SET);
306   return iLen;
307 #endif
308 }
309 
FileSetSize(FXSYS_FILE * file,int32_t size)310 bool FileSetSize(FXSYS_FILE* file, int32_t size) {
311   ASSERT(file);
312 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_
313   return _chsize(_fileno(file), size) == 0;
314 #elif _FX_OS_ == _FX_WIN32_MOBILE_
315   HANDLE hFile = _fileno(file);
316   uint32_t dwPos = ::SetFilePointer(hFile, 0, 0, FILE_CURRENT);
317   ::SetFilePointer(hFile, size, 0, FILE_BEGIN);
318   bool bRet = ::SetEndOfFile(hFile);
319   ::SetFilePointer(hFile, (int32_t)dwPos, 0, FILE_BEGIN);
320   return bRet;
321 #else
322   return false;
323 #endif
324 }
325 
326 }  // namespace
327 
328 // static
CreateStream(const CFX_RetainPtr<IFX_SeekableReadStream> & pFileRead,uint32_t dwAccess)329 CFX_RetainPtr<IFGAS_Stream> IFGAS_Stream::CreateStream(
330     const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead,
331     uint32_t dwAccess) {
332   auto pSR = pdfium::MakeRetain<CFGAS_Stream>();
333   if (!pSR->LoadFileRead(pFileRead, dwAccess))
334     return nullptr;
335 
336   if (dwAccess & FX_STREAMACCESS_Text)
337     return pdfium::MakeRetain<CFGAS_TextStream>(pSR);
338 
339   return pSR;
340 }
341 
342 // static
CreateStream(const CFX_RetainPtr<IFX_SeekableWriteStream> & pFileWrite,uint32_t dwAccess)343 CFX_RetainPtr<IFGAS_Stream> IFGAS_Stream::CreateStream(
344     const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite,
345     uint32_t dwAccess) {
346   auto pSR = pdfium::MakeRetain<CFGAS_Stream>();
347   if (!pSR->LoadFileWrite(pFileWrite, dwAccess))
348     return nullptr;
349 
350   if (dwAccess & FX_STREAMACCESS_Text)
351     return pdfium::MakeRetain<CFGAS_TextStream>(pSR);
352 
353   return pSR;
354 }
355 
356 // static
CreateStream(uint8_t * pData,int32_t length,uint32_t dwAccess)357 CFX_RetainPtr<IFGAS_Stream> IFGAS_Stream::CreateStream(uint8_t* pData,
358                                                        int32_t length,
359                                                        uint32_t dwAccess) {
360   auto pSR = pdfium::MakeRetain<CFGAS_Stream>();
361   if (!pSR->LoadBuffer(pData, length, dwAccess))
362     return nullptr;
363 
364   if (dwAccess & FX_STREAMACCESS_Text)
365     return pdfium::MakeRetain<CFGAS_TextStream>(pSR);
366 
367   return pSR;
368 }
369 
IFGAS_StreamImp()370 IFGAS_StreamImp::IFGAS_StreamImp() : m_dwAccess(0) {}
371 
CFGAS_FileStreamImp()372 CFGAS_FileStreamImp::CFGAS_FileStreamImp() : m_hFile(nullptr), m_iLength(0) {}
373 
~CFGAS_FileStreamImp()374 CFGAS_FileStreamImp::~CFGAS_FileStreamImp() {
375   if (m_hFile)
376     FXSYS_fclose(m_hFile);
377 }
378 
LoadFile(const FX_WCHAR * pszSrcFileName,uint32_t dwAccess)379 bool CFGAS_FileStreamImp::LoadFile(const FX_WCHAR* pszSrcFileName,
380                                    uint32_t dwAccess) {
381   ASSERT(!m_hFile);
382   ASSERT(pszSrcFileName && FXSYS_wcslen(pszSrcFileName) > 0);
383 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
384     _FX_OS_ == _FX_WIN64_
385   const FX_WCHAR* wsMode;
386   if (dwAccess & FX_STREAMACCESS_Write) {
387     if (dwAccess & FX_STREAMACCESS_Append) {
388       wsMode = L"a+b";
389     } else if (dwAccess & FX_STREAMACCESS_Truncate) {
390       wsMode = L"w+b";
391     } else {
392       wsMode = L"r+b";
393     }
394   } else {
395     wsMode = L"rb";
396   }
397   m_hFile = FXSYS_wfopen(pszSrcFileName, wsMode);
398 
399   if (!m_hFile) {
400     if (dwAccess & FX_STREAMACCESS_Write) {
401       if (dwAccess & FX_STREAMACCESS_Create)
402         m_hFile = FXSYS_wfopen(pszSrcFileName, L"w+b");
403 
404       if (!m_hFile) {
405         m_hFile = FXSYS_wfopen(pszSrcFileName, L"r+b");
406         if (!m_hFile)
407           return false;
408 
409         if (dwAccess & FX_STREAMACCESS_Truncate)
410           FileSetSize(m_hFile, 0);
411       }
412     } else {
413       return false;
414     }
415   }
416 #else
417   const FX_CHAR* wsMode = "rb";
418   if (dwAccess & FX_STREAMACCESS_Write) {
419     if (dwAccess & FX_STREAMACCESS_Append) {
420       wsMode = "a+b";
421     } else if (dwAccess & FX_STREAMACCESS_Truncate) {
422       wsMode = "w+b";
423     } else {
424       wsMode = "r+b";
425     }
426   }
427   CFX_ByteString szFileName = CFX_ByteString::FromUnicode(pszSrcFileName);
428   m_hFile = FXSYS_fopen(szFileName.c_str(), wsMode);
429   if (!m_hFile) {
430     if (dwAccess & FX_STREAMACCESS_Write) {
431       if (dwAccess & FX_STREAMACCESS_Create) {
432         m_hFile = FXSYS_fopen(szFileName.c_str(), "w+b");
433       }
434       if (!m_hFile) {
435         m_hFile = FXSYS_fopen(szFileName.c_str(), "r+b");
436         if (!m_hFile) {
437           return false;
438         }
439         if (dwAccess & FX_STREAMACCESS_Truncate) {
440           FileSetSize(m_hFile, 0);
441         }
442       }
443     } else {
444       return false;
445     }
446   }
447 #endif
448   SetAccessModes(dwAccess);
449   if ((dwAccess & (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) ==
450       (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) {
451     m_iLength = 0;
452   } else {
453     m_iLength = FileLength(m_hFile);
454   }
455   return true;
456 }
GetLength() const457 int32_t CFGAS_FileStreamImp::GetLength() const {
458   ASSERT(m_hFile);
459   return m_iLength;
460 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)461 int32_t CFGAS_FileStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
462   ASSERT(m_hFile);
463   FXSYS_fseek(m_hFile, iOffset, eSeek);
464   return FXSYS_ftell(m_hFile);
465 }
GetPosition()466 int32_t CFGAS_FileStreamImp::GetPosition() {
467   ASSERT(m_hFile);
468   return FXSYS_ftell(m_hFile);
469 }
IsEOF() const470 bool CFGAS_FileStreamImp::IsEOF() const {
471   ASSERT(m_hFile);
472   return FXSYS_ftell(m_hFile) >= m_iLength;
473 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)474 int32_t CFGAS_FileStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
475   ASSERT(m_hFile);
476   ASSERT(pBuffer && iBufferSize > 0);
477   return FXSYS_fread(pBuffer, 1, iBufferSize, m_hFile);
478 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,bool & bEOS)479 int32_t CFGAS_FileStreamImp::ReadString(FX_WCHAR* pStr,
480                                         int32_t iMaxLength,
481                                         bool& bEOS) {
482   ASSERT(m_hFile);
483   ASSERT(pStr && iMaxLength > 0);
484   if (m_iLength <= 0) {
485     return 0;
486   }
487   int32_t iPosition = FXSYS_ftell(m_hFile);
488   int32_t iLen = std::min((m_iLength - iPosition) / 2, iMaxLength);
489   if (iLen <= 0) {
490     return 0;
491   }
492   iLen = FXSYS_fread(pStr, 2, iLen, m_hFile);
493   int32_t iCount = 0;
494   while (*pStr != L'\0' && iCount < iLen) {
495     pStr++, iCount++;
496   }
497   iPosition += iCount * 2;
498   if (FXSYS_ftell(m_hFile) != iPosition) {
499     FXSYS_fseek(m_hFile, iPosition, 0);
500   }
501   bEOS = (iPosition >= m_iLength);
502   return iCount;
503 }
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)504 int32_t CFGAS_FileStreamImp::WriteData(const uint8_t* pBuffer,
505                                        int32_t iBufferSize) {
506   ASSERT(m_hFile && (GetAccessModes() & FX_STREAMACCESS_Write) != 0);
507   ASSERT(pBuffer && iBufferSize > 0);
508   int32_t iRet = FXSYS_fwrite(pBuffer, 1, iBufferSize, m_hFile);
509   if (iRet != 0) {
510     int32_t iPos = FXSYS_ftell(m_hFile);
511     if (iPos > m_iLength) {
512       m_iLength = iPos;
513     }
514   }
515   return iRet;
516 }
WriteString(const FX_WCHAR * pStr,int32_t iLength)517 int32_t CFGAS_FileStreamImp::WriteString(const FX_WCHAR* pStr,
518                                          int32_t iLength) {
519   ASSERT(m_hFile && (GetAccessModes() & FX_STREAMACCESS_Write) != 0);
520   ASSERT(pStr && iLength > 0);
521   int32_t iRet = FXSYS_fwrite(pStr, 2, iLength, m_hFile);
522   if (iRet != 0) {
523     int32_t iPos = FXSYS_ftell(m_hFile);
524     if (iPos > m_iLength) {
525       m_iLength = iPos;
526     }
527   }
528   return iRet;
529 }
Flush()530 void CFGAS_FileStreamImp::Flush() {
531   ASSERT(m_hFile && (GetAccessModes() & FX_STREAMACCESS_Write) != 0);
532   FXSYS_fflush(m_hFile);
533 }
SetLength(int32_t iLength)534 bool CFGAS_FileStreamImp::SetLength(int32_t iLength) {
535   ASSERT(m_hFile && (GetAccessModes() & FX_STREAMACCESS_Write) != 0);
536   bool bRet = FileSetSize(m_hFile, iLength);
537   m_iLength = FileLength(m_hFile);
538   return bRet;
539 }
540 
CFGAS_FileReadStreamImp()541 CFGAS_FileReadStreamImp::CFGAS_FileReadStreamImp()
542     : m_pFileRead(nullptr), m_iPosition(0), m_iLength(0) {}
543 
LoadFileRead(const CFX_RetainPtr<IFX_SeekableReadStream> & pFileRead,uint32_t dwAccess)544 bool CFGAS_FileReadStreamImp::LoadFileRead(
545     const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead,
546     uint32_t dwAccess) {
547   ASSERT(!m_pFileRead && pFileRead);
548   if (dwAccess & FX_STREAMACCESS_Write)
549     return false;
550 
551   m_pFileRead = pFileRead;
552   m_iLength = m_pFileRead->GetSize();
553   return true;
554 }
555 
GetLength() const556 int32_t CFGAS_FileReadStreamImp::GetLength() const {
557   return m_iLength;
558 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)559 int32_t CFGAS_FileReadStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
560   switch (eSeek) {
561     case FX_STREAMSEEK_Begin:
562       m_iPosition = iOffset;
563       break;
564     case FX_STREAMSEEK_Current:
565       m_iPosition += iOffset;
566       break;
567     case FX_STREAMSEEK_End:
568       m_iPosition = m_iLength + iOffset;
569       break;
570   }
571   if (m_iPosition < 0) {
572     m_iPosition = 0;
573   } else if (m_iPosition >= m_iLength) {
574     m_iPosition = m_iLength;
575   }
576   return m_iPosition;
577 }
IsEOF() const578 bool CFGAS_FileReadStreamImp::IsEOF() const {
579   return m_iPosition >= m_iLength;
580 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)581 int32_t CFGAS_FileReadStreamImp::ReadData(uint8_t* pBuffer,
582                                           int32_t iBufferSize) {
583   ASSERT(m_pFileRead);
584   ASSERT(pBuffer && iBufferSize > 0);
585   if (iBufferSize > m_iLength - m_iPosition) {
586     iBufferSize = m_iLength - m_iPosition;
587   }
588   if (m_pFileRead->ReadBlock(pBuffer, m_iPosition, iBufferSize)) {
589     m_iPosition += iBufferSize;
590     return iBufferSize;
591   }
592   return 0;
593 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,bool & bEOS)594 int32_t CFGAS_FileReadStreamImp::ReadString(FX_WCHAR* pStr,
595                                             int32_t iMaxLength,
596                                             bool& bEOS) {
597   ASSERT(m_pFileRead);
598   ASSERT(pStr && iMaxLength > 0);
599   iMaxLength = ReadData((uint8_t*)pStr, iMaxLength * 2) / 2;
600   if (iMaxLength <= 0) {
601     return 0;
602   }
603   int32_t i = 0;
604   while (i < iMaxLength && pStr[i] != L'\0') {
605     ++i;
606   }
607   bEOS = (m_iPosition >= m_iLength) || pStr[i] == L'\0';
608   return i;
609 }
610 
CFGAS_BufferReadStreamImp()611 CFGAS_BufferReadStreamImp::CFGAS_BufferReadStreamImp()
612     : m_iPosition(0), m_iBufferSize(0) {}
613 
~CFGAS_BufferReadStreamImp()614 CFGAS_BufferReadStreamImp::~CFGAS_BufferReadStreamImp() {}
615 
LoadBufferRead(const CFX_RetainPtr<IFX_BufferedReadStream> & pBufferRead,int32_t iFileSize,uint32_t dwAccess)616 bool CFGAS_BufferReadStreamImp::LoadBufferRead(
617     const CFX_RetainPtr<IFX_BufferedReadStream>& pBufferRead,
618     int32_t iFileSize,
619     uint32_t dwAccess) {
620   ASSERT(!m_pBufferRead && pBufferRead);
621   if (dwAccess & FX_STREAMACCESS_Write)
622     return false;
623 
624   m_pBufferRead = pBufferRead;
625   m_iBufferSize = iFileSize;
626   if (m_iBufferSize >= 0)
627     return true;
628 
629   if (!m_pBufferRead->ReadNextBlock(true))
630     return false;
631 
632   m_iBufferSize = m_pBufferRead->GetBlockSize();
633   while (!m_pBufferRead->IsEOF()) {
634     m_pBufferRead->ReadNextBlock(false);
635     m_iBufferSize += m_pBufferRead->GetBlockSize();
636   }
637   return true;
638 }
GetLength() const639 int32_t CFGAS_BufferReadStreamImp::GetLength() const {
640   return m_iBufferSize;
641 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)642 int32_t CFGAS_BufferReadStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
643   int32_t iLength = GetLength();
644   switch (eSeek) {
645     case FX_STREAMSEEK_Begin:
646       m_iPosition = iOffset;
647       break;
648     case FX_STREAMSEEK_Current:
649       m_iPosition += iOffset;
650       break;
651     case FX_STREAMSEEK_End:
652       m_iPosition = iLength + iOffset;
653       break;
654   }
655   if (m_iPosition < 0) {
656     m_iPosition = 0;
657   } else if (m_iPosition >= iLength) {
658     m_iPosition = iLength;
659   }
660   return m_iPosition;
661 }
IsEOF() const662 bool CFGAS_BufferReadStreamImp::IsEOF() const {
663   return m_pBufferRead ? m_pBufferRead->IsEOF() : true;
664 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)665 int32_t CFGAS_BufferReadStreamImp::ReadData(uint8_t* pBuffer,
666                                             int32_t iBufferSize) {
667   ASSERT(m_pBufferRead);
668   ASSERT(pBuffer && iBufferSize > 0);
669   int32_t iLength = GetLength();
670   if (m_iPosition >= iLength) {
671     return 0;
672   }
673   if (iBufferSize > iLength - m_iPosition) {
674     iBufferSize = iLength - m_iPosition;
675   }
676   uint32_t dwBlockOffset = m_pBufferRead->GetBlockOffset();
677   uint32_t dwBlockSize = m_pBufferRead->GetBlockSize();
678   if (m_iPosition < (int32_t)dwBlockOffset) {
679     if (!m_pBufferRead->ReadNextBlock(true)) {
680       return 0;
681     }
682     dwBlockOffset = m_pBufferRead->GetBlockOffset();
683     dwBlockSize = m_pBufferRead->GetBlockSize();
684   }
685   while (m_iPosition < (int32_t)dwBlockOffset ||
686          m_iPosition >= (int32_t)(dwBlockOffset + dwBlockSize)) {
687     if (m_pBufferRead->IsEOF() || !m_pBufferRead->ReadNextBlock(false)) {
688       break;
689     }
690     dwBlockOffset = m_pBufferRead->GetBlockOffset();
691     dwBlockSize = m_pBufferRead->GetBlockSize();
692   }
693   if (m_iPosition < (int32_t)dwBlockOffset ||
694       m_iPosition >= (int32_t)(dwBlockOffset + dwBlockSize)) {
695     return 0;
696   }
697   const uint8_t* pBufferTmp = m_pBufferRead->GetBlockBuffer();
698   uint32_t dwOffsetTmp = m_iPosition - dwBlockOffset;
699   uint32_t dwCopySize =
700       std::min(iBufferSize, (int32_t)(dwBlockSize - dwOffsetTmp));
701   FXSYS_memcpy(pBuffer, pBufferTmp + dwOffsetTmp, dwCopySize);
702   dwOffsetTmp = dwCopySize;
703   iBufferSize -= dwCopySize;
704   while (iBufferSize > 0) {
705     if (!m_pBufferRead->ReadNextBlock(false)) {
706       break;
707     }
708     dwBlockOffset = m_pBufferRead->GetBlockOffset();
709     dwBlockSize = m_pBufferRead->GetBlockSize();
710     pBufferTmp = m_pBufferRead->GetBlockBuffer();
711     dwCopySize = std::min((uint32_t)iBufferSize, dwBlockSize);
712     FXSYS_memcpy(pBuffer + dwOffsetTmp, pBufferTmp, dwCopySize);
713     dwOffsetTmp += dwCopySize;
714     iBufferSize -= dwCopySize;
715   }
716   m_iPosition += dwOffsetTmp;
717   return dwOffsetTmp;
718 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,bool & bEOS)719 int32_t CFGAS_BufferReadStreamImp::ReadString(FX_WCHAR* pStr,
720                                               int32_t iMaxLength,
721                                               bool& bEOS) {
722   ASSERT(m_pBufferRead);
723   ASSERT(pStr && iMaxLength > 0);
724   iMaxLength = ReadData((uint8_t*)pStr, iMaxLength * 2) / 2;
725   if (iMaxLength <= 0) {
726     return 0;
727   }
728   int32_t i = 0;
729   while (i < iMaxLength && pStr[i] != L'\0') {
730     ++i;
731   }
732   bEOS = (m_iPosition >= GetLength()) || pStr[i] == L'\0';
733   return i;
734 }
CFGAS_FileWriteStreamImp()735 CFGAS_FileWriteStreamImp::CFGAS_FileWriteStreamImp()
736     : m_pFileWrite(nullptr), m_iPosition(0) {}
737 
LoadFileWrite(const CFX_RetainPtr<IFX_SeekableWriteStream> & pFileWrite,uint32_t dwAccess)738 bool CFGAS_FileWriteStreamImp::LoadFileWrite(
739     const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite,
740     uint32_t dwAccess) {
741   ASSERT(!m_pFileWrite && pFileWrite);
742   if (dwAccess & FX_STREAMACCESS_Read)
743     return false;
744 
745   if (dwAccess & FX_STREAMACCESS_Append)
746     m_iPosition = pFileWrite->GetSize();
747 
748   m_pFileWrite = pFileWrite;
749   return true;
750 }
751 
GetLength() const752 int32_t CFGAS_FileWriteStreamImp::GetLength() const {
753   if (!m_pFileWrite)
754     return 0;
755 
756   return (int32_t)m_pFileWrite->GetSize();
757 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)758 int32_t CFGAS_FileWriteStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
759   int32_t iLength = GetLength();
760   switch (eSeek) {
761     case FX_STREAMSEEK_Begin:
762       m_iPosition = iOffset;
763       break;
764     case FX_STREAMSEEK_Current:
765       m_iPosition += iOffset;
766       break;
767     case FX_STREAMSEEK_End:
768       m_iPosition = iLength + iOffset;
769       break;
770   }
771   if (m_iPosition < 0) {
772     m_iPosition = 0;
773   } else if (m_iPosition >= iLength) {
774     m_iPosition = iLength;
775   }
776   return m_iPosition;
777 }
IsEOF() const778 bool CFGAS_FileWriteStreamImp::IsEOF() const {
779   return m_iPosition >= GetLength();
780 }
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)781 int32_t CFGAS_FileWriteStreamImp::WriteData(const uint8_t* pBuffer,
782                                             int32_t iBufferSize) {
783   if (!m_pFileWrite) {
784     return 0;
785   }
786   if (m_pFileWrite->WriteBlock(pBuffer, m_iPosition, iBufferSize)) {
787     m_iPosition += iBufferSize;
788   }
789   return iBufferSize;
790 }
WriteString(const FX_WCHAR * pStr,int32_t iLength)791 int32_t CFGAS_FileWriteStreamImp::WriteString(const FX_WCHAR* pStr,
792                                               int32_t iLength) {
793   return WriteData((const uint8_t*)pStr, iLength * sizeof(FX_WCHAR));
794 }
Flush()795 void CFGAS_FileWriteStreamImp::Flush() {
796   if (m_pFileWrite) {
797     m_pFileWrite->Flush();
798   }
799 }
CFGAS_BufferStreamImp()800 CFGAS_BufferStreamImp::CFGAS_BufferStreamImp()
801     : m_pData(nullptr), m_iTotalSize(0), m_iPosition(0), m_iLength(0) {}
802 
LoadBuffer(uint8_t * pData,int32_t iTotalSize,uint32_t dwAccess)803 bool CFGAS_BufferStreamImp::LoadBuffer(uint8_t* pData,
804                                        int32_t iTotalSize,
805                                        uint32_t dwAccess) {
806   ASSERT(!m_pData && pData && iTotalSize > 0);
807   SetAccessModes(dwAccess);
808   m_pData = pData;
809   m_iTotalSize = iTotalSize;
810   m_iPosition = 0;
811   m_iLength = (dwAccess & FX_STREAMACCESS_Write) != 0 ? 0 : iTotalSize;
812   return true;
813 }
GetLength() const814 int32_t CFGAS_BufferStreamImp::GetLength() const {
815   ASSERT(m_pData);
816   return m_iLength;
817 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)818 int32_t CFGAS_BufferStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
819   ASSERT(m_pData);
820   if (eSeek == FX_STREAMSEEK_Begin) {
821     m_iPosition = iOffset;
822   } else if (eSeek == FX_STREAMSEEK_Current) {
823     m_iPosition += iOffset;
824   } else if (eSeek == FX_STREAMSEEK_End) {
825     m_iPosition = m_iLength + iOffset;
826   }
827   if (m_iPosition > m_iLength) {
828     m_iPosition = m_iLength;
829   }
830   if (m_iPosition < 0) {
831     m_iPosition = 0;
832   }
833   return m_iPosition;
834 }
GetPosition()835 int32_t CFGAS_BufferStreamImp::GetPosition() {
836   ASSERT(m_pData);
837   return m_iPosition;
838 }
IsEOF() const839 bool CFGAS_BufferStreamImp::IsEOF() const {
840   ASSERT(m_pData);
841   return m_iPosition >= m_iLength;
842 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)843 int32_t CFGAS_BufferStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
844   ASSERT(m_pData);
845   ASSERT(pBuffer && iBufferSize > 0);
846   int32_t iLen = std::min(m_iLength - m_iPosition, iBufferSize);
847   if (iLen <= 0) {
848     return 0;
849   }
850   FXSYS_memcpy(pBuffer, m_pData + m_iPosition, iLen);
851   m_iPosition += iLen;
852   return iLen;
853 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,bool & bEOS)854 int32_t CFGAS_BufferStreamImp::ReadString(FX_WCHAR* pStr,
855                                           int32_t iMaxLength,
856                                           bool& bEOS) {
857   ASSERT(m_pData);
858   ASSERT(pStr && iMaxLength > 0);
859   int32_t iLen = std::min((m_iLength - m_iPosition) / 2, iMaxLength);
860   if (iLen <= 0) {
861     return 0;
862   }
863   const FX_WCHAR* pSrc = (const FX_WCHAR*)(FX_CHAR*)(m_pData + m_iPosition);
864   int32_t iCount = 0;
865   while (*pSrc && iCount < iLen) {
866     *pStr++ = *pSrc++;
867     iCount++;
868   }
869   m_iPosition += iCount * 2;
870   bEOS = (*pSrc == L'\0') || (m_iPosition >= m_iLength);
871   return iCount;
872 }
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)873 int32_t CFGAS_BufferStreamImp::WriteData(const uint8_t* pBuffer,
874                                          int32_t iBufferSize) {
875   ASSERT(m_pData && (GetAccessModes() & FX_STREAMACCESS_Write) != 0);
876   ASSERT(pBuffer && iBufferSize > 0);
877   int32_t iLen = std::min(m_iTotalSize - m_iPosition, iBufferSize);
878   if (iLen <= 0) {
879     return 0;
880   }
881   FXSYS_memcpy(m_pData + m_iPosition, pBuffer, iLen);
882   m_iPosition += iLen;
883   if (m_iPosition > m_iLength) {
884     m_iLength = m_iPosition;
885   }
886   return iLen;
887 }
WriteString(const FX_WCHAR * pStr,int32_t iLength)888 int32_t CFGAS_BufferStreamImp::WriteString(const FX_WCHAR* pStr,
889                                            int32_t iLength) {
890   ASSERT(m_pData && (GetAccessModes() & FX_STREAMACCESS_Write) != 0);
891   ASSERT(pStr && iLength > 0);
892   int32_t iLen = std::min((m_iTotalSize - m_iPosition) / 2, iLength);
893   if (iLen <= 0) {
894     return 0;
895   }
896   FXSYS_memcpy(m_pData + m_iPosition, pStr, iLen * 2);
897   m_iPosition += iLen * 2;
898   if (m_iPosition > m_iLength) {
899     m_iLength = m_iPosition;
900   }
901   return iLen;
902 }
903 
904 // static
CreateTextStream(const CFX_RetainPtr<IFGAS_Stream> & pBaseStream)905 CFX_RetainPtr<IFGAS_Stream> IFGAS_Stream::CreateTextStream(
906     const CFX_RetainPtr<IFGAS_Stream>& pBaseStream) {
907   ASSERT(pBaseStream);
908   return pdfium::MakeRetain<CFGAS_TextStream>(pBaseStream);
909 }
910 
CFGAS_TextStream(const CFX_RetainPtr<IFGAS_Stream> & pStream)911 CFGAS_TextStream::CFGAS_TextStream(const CFX_RetainPtr<IFGAS_Stream>& pStream)
912     : m_wCodePage(FX_CODEPAGE_DefANSI),
913       m_wBOMLength(0),
914       m_dwBOM(0),
915       m_pBuf(nullptr),
916       m_iBufSize(0),
917       m_pStreamImp(pStream) {
918   ASSERT(m_pStreamImp);
919   InitStream();
920 }
921 
~CFGAS_TextStream()922 CFGAS_TextStream::~CFGAS_TextStream() {
923   if (m_pBuf)
924     FX_Free(m_pBuf);
925 }
926 
InitStream()927 void CFGAS_TextStream::InitStream() {
928   int32_t iPosition = m_pStreamImp->GetPosition();
929   m_pStreamImp->Seek(FX_STREAMSEEK_Begin, 0);
930   m_pStreamImp->ReadData((uint8_t*)&m_dwBOM, 3);
931 #if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
932   m_dwBOM &= 0x00FFFFFF;
933   if (m_dwBOM == 0x00BFBBEF) {
934     m_wBOMLength = 3;
935     m_wCodePage = FX_CODEPAGE_UTF8;
936   } else {
937     m_dwBOM &= 0x0000FFFF;
938     if (m_dwBOM == 0x0000FFFE) {
939       m_wBOMLength = 2;
940       m_wCodePage = FX_CODEPAGE_UTF16BE;
941     } else if (m_dwBOM == 0x0000FEFF) {
942       m_wBOMLength = 2;
943       m_wCodePage = FX_CODEPAGE_UTF16LE;
944     } else {
945       m_wBOMLength = 0;
946       m_dwBOM = 0;
947       m_wCodePage = FXSYS_GetACP();
948     }
949   }
950 #else
951   m_dwBOM &= 0xFFFFFF00;
952   if (m_dwBOM == 0xEFBBBF00) {
953     m_wBOMLength = 3;
954     m_wCodePage = FX_CODEPAGE_UTF8;
955   } else {
956     m_dwBOM &= 0xFFFF0000;
957     if (m_dwBOM == 0xFEFF0000) {
958       m_wBOMLength = 2;
959       m_wCodePage = FX_CODEPAGE_UTF16BE;
960     } else if (m_dwBOM == 0xFFFE0000) {
961       m_wBOMLength = 2;
962       m_wCodePage = FX_CODEPAGE_UTF16LE;
963     } else {
964       m_wBOMLength = 0;
965       m_dwBOM = 0;
966       m_wCodePage = FXSYS_GetACP();
967     }
968   }
969 #endif
970   m_pStreamImp->Seek(FX_STREAMSEEK_Begin, std::max(m_wBOMLength, iPosition));
971 }
972 
GetAccessModes() const973 uint32_t CFGAS_TextStream::GetAccessModes() const {
974   return m_pStreamImp->GetAccessModes() | FX_STREAMACCESS_Text;
975 }
976 
GetLength() const977 int32_t CFGAS_TextStream::GetLength() const {
978   return m_pStreamImp->GetLength();
979 }
980 
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)981 int32_t CFGAS_TextStream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
982   return m_pStreamImp->Seek(eSeek, iOffset);
983 }
984 
GetPosition()985 int32_t CFGAS_TextStream::GetPosition() {
986   return m_pStreamImp->GetPosition();
987 }
988 
IsEOF() const989 bool CFGAS_TextStream::IsEOF() const {
990   return m_pStreamImp->IsEOF();
991 }
992 
ReadData(uint8_t * pBuffer,int32_t iBufferSize)993 int32_t CFGAS_TextStream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
994   return m_pStreamImp->ReadData(pBuffer, iBufferSize);
995 }
996 
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)997 int32_t CFGAS_TextStream::WriteData(const uint8_t* pBuffer,
998                                     int32_t iBufferSize) {
999   return m_pStreamImp->WriteData(pBuffer, iBufferSize);
1000 }
1001 
Flush()1002 void CFGAS_TextStream::Flush() {
1003   m_pStreamImp->Flush();
1004 }
1005 
SetLength(int32_t iLength)1006 bool CFGAS_TextStream::SetLength(int32_t iLength) {
1007   return m_pStreamImp->SetLength(iLength);
1008 }
1009 
GetCodePage() const1010 uint16_t CFGAS_TextStream::GetCodePage() const {
1011   return m_wCodePage;
1012 }
1013 
CreateSharedStream(uint32_t dwAccess,int32_t iOffset,int32_t iLength)1014 CFX_RetainPtr<IFGAS_Stream> CFGAS_TextStream::CreateSharedStream(
1015     uint32_t dwAccess,
1016     int32_t iOffset,
1017     int32_t iLength) {
1018   CFX_RetainPtr<IFGAS_Stream> pSR =
1019       m_pStreamImp->CreateSharedStream(dwAccess, iOffset, iLength);
1020   if (!pSR)
1021     return nullptr;
1022 
1023   if (dwAccess & FX_STREAMACCESS_Text)
1024     return pdfium::MakeRetain<CFGAS_TextStream>(pSR);
1025 
1026   return pSR;
1027 }
1028 
GetBOM(uint8_t bom[4]) const1029 int32_t CFGAS_TextStream::GetBOM(uint8_t bom[4]) const {
1030   if (m_wBOMLength < 1)
1031     return 0;
1032 
1033   *(uint32_t*)bom = m_dwBOM;
1034   return m_wBOMLength;
1035 }
1036 
SetCodePage(uint16_t wCodePage)1037 uint16_t CFGAS_TextStream::SetCodePage(uint16_t wCodePage) {
1038   if (m_wBOMLength > 0)
1039     return m_wCodePage;
1040 
1041   uint16_t v = m_wCodePage;
1042   m_wCodePage = wCodePage;
1043   return v;
1044 }
1045 
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,bool & bEOS)1046 int32_t CFGAS_TextStream::ReadString(FX_WCHAR* pStr,
1047                                      int32_t iMaxLength,
1048                                      bool& bEOS) {
1049   ASSERT(pStr && iMaxLength > 0);
1050   if (!m_pStreamImp) {
1051     return -1;
1052   }
1053   int32_t iLen;
1054   if (m_wCodePage == FX_CODEPAGE_UTF16LE ||
1055       m_wCodePage == FX_CODEPAGE_UTF16BE) {
1056     int32_t iBytes = iMaxLength * 2;
1057     iLen = m_pStreamImp->ReadData((uint8_t*)pStr, iBytes);
1058     iMaxLength = iLen / 2;
1059     if (sizeof(FX_WCHAR) > 2) {
1060       FX_UTF16ToWChar(pStr, iMaxLength);
1061     }
1062 #if _FX_ENDIAN_ == _FX_BIG_ENDIAN_
1063     if (m_wCodePage == FX_CODEPAGE_UTF16LE) {
1064       FX_SwapByteOrder(pStr, iMaxLength);
1065     }
1066 #else
1067     if (m_wCodePage == FX_CODEPAGE_UTF16BE) {
1068       FX_SwapByteOrder(pStr, iMaxLength);
1069     }
1070 #endif
1071   } else {
1072     int32_t pos = m_pStreamImp->GetPosition();
1073     int32_t iBytes = iMaxLength;
1074     iBytes = std::min(iBytes, m_pStreamImp->GetLength() - pos);
1075     if (iBytes > 0) {
1076       if (!m_pBuf) {
1077         m_pBuf = FX_Alloc(uint8_t, iBytes);
1078         m_iBufSize = iBytes;
1079       } else if (iBytes > m_iBufSize) {
1080         m_pBuf = FX_Realloc(uint8_t, m_pBuf, iBytes);
1081         m_iBufSize = iBytes;
1082       }
1083       iLen = m_pStreamImp->ReadData(m_pBuf, iBytes);
1084       int32_t iSrc = iLen;
1085       int32_t iDecode = FX_DecodeString(m_wCodePage, (const FX_CHAR*)m_pBuf,
1086                                         &iSrc, pStr, &iMaxLength, true);
1087       m_pStreamImp->Seek(FX_STREAMSEEK_Current, iSrc - iLen);
1088       if (iDecode < 1) {
1089         return -1;
1090       }
1091     } else {
1092       iMaxLength = 0;
1093     }
1094   }
1095   bEOS = m_pStreamImp->IsEOF();
1096   return iMaxLength;
1097 }
1098 
WriteString(const FX_WCHAR * pStr,int32_t iLength)1099 int32_t CFGAS_TextStream::WriteString(const FX_WCHAR* pStr, int32_t iLength) {
1100   ASSERT(pStr && iLength > 0);
1101   if ((m_pStreamImp->GetAccessModes() & FX_STREAMACCESS_Write) == 0)
1102     return -1;
1103 
1104   if (m_wCodePage == FX_CODEPAGE_UTF8) {
1105     int32_t len = iLength;
1106     CFX_UTF8Encoder encoder;
1107     while (len-- > 0) {
1108       encoder.Input(*pStr++);
1109     }
1110     CFX_ByteStringC bsResult = encoder.GetResult();
1111     m_pStreamImp->WriteData((const uint8_t*)bsResult.c_str(),
1112                             bsResult.GetLength());
1113   }
1114   return iLength;
1115 }
1116 
CFGAS_Stream()1117 CFGAS_Stream::CFGAS_Stream()
1118     : m_eStreamType(FX_SREAMTYPE_Unknown),
1119       m_pStreamImp(nullptr),
1120       m_dwAccess(0),
1121       m_iTotalSize(0),
1122       m_iPosition(0),
1123       m_iStart(0),
1124       m_iLength(0),
1125       m_iRefCount(1) {}
1126 
~CFGAS_Stream()1127 CFGAS_Stream::~CFGAS_Stream() {
1128   if (m_eStreamType != FX_STREAMTYPE_Stream)
1129     delete m_pStreamImp;
1130 }
1131 
LoadFile(const FX_WCHAR * pszSrcFileName,uint32_t dwAccess)1132 bool CFGAS_Stream::LoadFile(const FX_WCHAR* pszSrcFileName, uint32_t dwAccess) {
1133   if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp)
1134     return false;
1135 
1136   if (!pszSrcFileName || FXSYS_wcslen(pszSrcFileName) < 1)
1137     return false;
1138 
1139   std::unique_ptr<CFGAS_FileStreamImp> pImp(new CFGAS_FileStreamImp());
1140   if (!pImp->LoadFile(pszSrcFileName, dwAccess))
1141     return false;
1142 
1143   m_pStreamImp = pImp.release();
1144   m_eStreamType = FX_STREAMTYPE_File;
1145   m_dwAccess = dwAccess;
1146   m_iLength = m_pStreamImp->GetLength();
1147   return true;
1148 }
1149 
LoadFileRead(const CFX_RetainPtr<IFX_SeekableReadStream> & pFileRead,uint32_t dwAccess)1150 bool CFGAS_Stream::LoadFileRead(
1151     const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead,
1152     uint32_t dwAccess) {
1153   if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp)
1154     return false;
1155 
1156   if (!pFileRead)
1157     return false;
1158 
1159   std::unique_ptr<CFGAS_FileReadStreamImp> pImp(new CFGAS_FileReadStreamImp());
1160   if (!pImp->LoadFileRead(pFileRead, dwAccess))
1161     return false;
1162 
1163   m_pStreamImp = pImp.release();
1164   m_eStreamType = FX_STREAMTYPE_File;
1165   m_dwAccess = dwAccess;
1166   m_iLength = m_pStreamImp->GetLength();
1167   return true;
1168 }
1169 
LoadFileWrite(const CFX_RetainPtr<IFX_SeekableWriteStream> & pFileWrite,uint32_t dwAccess)1170 bool CFGAS_Stream::LoadFileWrite(
1171     const CFX_RetainPtr<IFX_SeekableWriteStream>& pFileWrite,
1172     uint32_t dwAccess) {
1173   if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp)
1174     return false;
1175 
1176   if (!pFileWrite)
1177     return false;
1178 
1179   auto pImp = pdfium::MakeUnique<CFGAS_FileWriteStreamImp>();
1180   if (!pImp->LoadFileWrite(pFileWrite, dwAccess))
1181     return false;
1182 
1183   m_pStreamImp = pImp.release();
1184   m_eStreamType = FX_STREAMTYPE_File;
1185   m_dwAccess = dwAccess;
1186   m_iLength = m_pStreamImp->GetLength();
1187   return true;
1188 }
1189 
LoadBuffer(uint8_t * pData,int32_t iTotalSize,uint32_t dwAccess)1190 bool CFGAS_Stream::LoadBuffer(uint8_t* pData,
1191                               int32_t iTotalSize,
1192                               uint32_t dwAccess) {
1193   if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp)
1194     return false;
1195 
1196   if (!pData || iTotalSize < 1)
1197     return false;
1198 
1199   std::unique_ptr<CFGAS_BufferStreamImp> pImp(new CFGAS_BufferStreamImp());
1200   if (!pImp->LoadBuffer(pData, iTotalSize, dwAccess))
1201     return false;
1202 
1203   m_pStreamImp = pImp.release();
1204   m_eStreamType = FX_STREAMTYPE_Buffer;
1205   m_dwAccess = dwAccess;
1206   m_iLength = m_pStreamImp->GetLength();
1207   return true;
1208 }
1209 
LoadBufferRead(const CFX_RetainPtr<IFX_BufferedReadStream> & pBufferRead,int32_t iFileSize,uint32_t dwAccess)1210 bool CFGAS_Stream::LoadBufferRead(
1211     const CFX_RetainPtr<IFX_BufferedReadStream>& pBufferRead,
1212     int32_t iFileSize,
1213     uint32_t dwAccess) {
1214   if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp)
1215     return false;
1216 
1217   if (!pBufferRead)
1218     return false;
1219 
1220   auto pImp = pdfium::MakeUnique<CFGAS_BufferReadStreamImp>();
1221   if (!pImp->LoadBufferRead(pBufferRead, iFileSize, dwAccess))
1222     return false;
1223 
1224   m_pStreamImp = pImp.release();
1225   m_eStreamType = FX_STREAMTYPE_BufferRead;
1226   m_dwAccess = dwAccess;
1227   m_iLength = m_pStreamImp->GetLength();
1228   return true;
1229 }
1230 
GetAccessModes() const1231 uint32_t CFGAS_Stream::GetAccessModes() const {
1232   return m_dwAccess;
1233 }
1234 
GetLength() const1235 int32_t CFGAS_Stream::GetLength() const {
1236   if (!m_pStreamImp) {
1237     return -1;
1238   }
1239   if (m_eStreamType == FX_STREAMTYPE_File ||
1240       m_eStreamType == FX_STREAMTYPE_Buffer) {
1241     return m_pStreamImp->GetLength();
1242   }
1243   return m_iLength;
1244 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)1245 int32_t CFGAS_Stream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
1246   if (!m_pStreamImp) {
1247     return -1;
1248   }
1249   if (m_eStreamType == FX_STREAMTYPE_File ||
1250       m_eStreamType == FX_STREAMTYPE_Buffer) {
1251     return m_iPosition = m_pStreamImp->Seek(eSeek, iOffset);
1252   }
1253   int32_t iEnd = m_iStart + m_iLength;
1254   int32_t iPosition = m_iStart + iOffset;
1255   if (eSeek == FX_STREAMSEEK_Begin) {
1256     m_iPosition = iPosition;
1257   } else if (eSeek == FX_STREAMSEEK_Current) {
1258     m_iPosition += iOffset;
1259   } else if (eSeek == FX_STREAMSEEK_End) {
1260     m_iPosition = iEnd + iOffset;
1261   }
1262   if (m_iPosition > iEnd) {
1263     m_iPosition = iEnd;
1264   }
1265   if (m_iPosition < m_iStart) {
1266     m_iPosition = m_iStart;
1267   }
1268   return m_iPosition - m_iStart;
1269 }
GetPosition()1270 int32_t CFGAS_Stream::GetPosition() {
1271   if (!m_pStreamImp) {
1272     return -1;
1273   }
1274   if (m_eStreamType == FX_STREAMTYPE_File ||
1275       m_eStreamType == FX_STREAMTYPE_Buffer) {
1276     return m_iPosition = m_pStreamImp->GetPosition();
1277   }
1278   return m_iPosition - m_iStart;
1279 }
IsEOF() const1280 bool CFGAS_Stream::IsEOF() const {
1281   if (!m_pStreamImp) {
1282     return true;
1283   }
1284   if (m_eStreamType == FX_STREAMTYPE_File ||
1285       m_eStreamType == FX_STREAMTYPE_Buffer) {
1286     return m_pStreamImp->IsEOF();
1287   }
1288   return m_iPosition >= m_iStart + m_iLength;
1289 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)1290 int32_t CFGAS_Stream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
1291   ASSERT(pBuffer && iBufferSize > 0);
1292   if (!m_pStreamImp) {
1293     return -1;
1294   }
1295   int32_t iLen = std::min(m_iStart + m_iLength - m_iPosition, iBufferSize);
1296   if (iLen <= 0) {
1297     return 0;
1298   }
1299   if (m_pStreamImp->GetPosition() != m_iPosition) {
1300     m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
1301   }
1302   iLen = m_pStreamImp->ReadData(pBuffer, iLen);
1303   m_iPosition = m_pStreamImp->GetPosition();
1304   return iLen;
1305 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,bool & bEOS)1306 int32_t CFGAS_Stream::ReadString(FX_WCHAR* pStr,
1307                                  int32_t iMaxLength,
1308                                  bool& bEOS) {
1309   ASSERT(pStr && iMaxLength > 0);
1310   if (!m_pStreamImp) {
1311     return -1;
1312   }
1313   int32_t iEnd = m_iStart + m_iLength;
1314   int32_t iLen = iEnd - m_iPosition;
1315   iLen = std::min(iEnd / 2, iMaxLength);
1316   if (iLen <= 0) {
1317     return 0;
1318   }
1319   if (m_pStreamImp->GetPosition() != m_iPosition) {
1320     m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
1321   }
1322   iLen = m_pStreamImp->ReadString(pStr, iLen, bEOS);
1323   m_iPosition = m_pStreamImp->GetPosition();
1324   if (iLen > 0 && m_iPosition >= iEnd) {
1325     bEOS = true;
1326   }
1327   return iLen;
1328 }
1329 
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)1330 int32_t CFGAS_Stream::WriteData(const uint8_t* pBuffer, int32_t iBufferSize) {
1331   ASSERT(pBuffer && iBufferSize > 0);
1332   if (!m_pStreamImp) {
1333     return -1;
1334   }
1335   if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
1336     return -1;
1337   }
1338   int32_t iLen = iBufferSize;
1339   if (m_eStreamType == FX_STREAMTYPE_Stream) {
1340     iLen = std::min(m_iStart + m_iTotalSize - m_iPosition, iBufferSize);
1341     if (iLen <= 0) {
1342       return 0;
1343     }
1344   }
1345   int32_t iEnd = m_iStart + m_iLength;
1346   if (m_pStreamImp->GetPosition() != m_iPosition) {
1347     m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
1348   }
1349   iLen = m_pStreamImp->WriteData(pBuffer, iLen);
1350   m_iPosition = m_pStreamImp->GetPosition();
1351   if (m_iPosition > iEnd) {
1352     m_iLength = m_iPosition - m_iStart;
1353   }
1354   return iLen;
1355 }
WriteString(const FX_WCHAR * pStr,int32_t iLength)1356 int32_t CFGAS_Stream::WriteString(const FX_WCHAR* pStr, int32_t iLength) {
1357   ASSERT(pStr && iLength > 0);
1358   if (!m_pStreamImp) {
1359     return -1;
1360   }
1361   if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
1362     return -1;
1363   }
1364   int32_t iLen = iLength;
1365   if (m_eStreamType == FX_STREAMTYPE_Stream) {
1366     iLen = std::min((m_iStart + m_iTotalSize - m_iPosition) / 2, iLength);
1367     if (iLen <= 0) {
1368       return 0;
1369     }
1370   }
1371   int32_t iEnd = m_iStart + m_iLength;
1372   if (m_pStreamImp->GetPosition() != m_iPosition) {
1373     m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
1374   }
1375   iLen = m_pStreamImp->WriteString(pStr, iLen);
1376   m_iPosition = m_pStreamImp->GetPosition();
1377   if (m_iPosition > iEnd) {
1378     m_iLength = m_iPosition - m_iStart;
1379   }
1380   return iLen;
1381 }
Flush()1382 void CFGAS_Stream::Flush() {
1383   if (!m_pStreamImp) {
1384     return;
1385   }
1386   if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
1387     return;
1388   }
1389   m_pStreamImp->Flush();
1390 }
SetLength(int32_t iLength)1391 bool CFGAS_Stream::SetLength(int32_t iLength) {
1392   if (!m_pStreamImp) {
1393     return false;
1394   }
1395   if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
1396     return false;
1397   }
1398   return m_pStreamImp->SetLength(iLength);
1399 }
GetBOM(uint8_t bom[4]) const1400 int32_t CFGAS_Stream::GetBOM(uint8_t bom[4]) const {
1401   if (!m_pStreamImp) {
1402     return -1;
1403   }
1404   return 0;
1405 }
GetCodePage() const1406 uint16_t CFGAS_Stream::GetCodePage() const {
1407 #if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
1408   return FX_CODEPAGE_UTF16LE;
1409 #else
1410   return FX_CODEPAGE_UTF16BE;
1411 #endif
1412 }
SetCodePage(uint16_t wCodePage)1413 uint16_t CFGAS_Stream::SetCodePage(uint16_t wCodePage) {
1414 #if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
1415   return FX_CODEPAGE_UTF16LE;
1416 #else
1417   return FX_CODEPAGE_UTF16BE;
1418 #endif
1419 }
1420 
CreateSharedStream(uint32_t dwAccess,int32_t iOffset,int32_t iLength)1421 CFX_RetainPtr<IFGAS_Stream> CFGAS_Stream::CreateSharedStream(uint32_t dwAccess,
1422                                                              int32_t iOffset,
1423                                                              int32_t iLength) {
1424   ASSERT(iLength > 0);
1425   if (!m_pStreamImp)
1426     return nullptr;
1427 
1428   if ((m_dwAccess & FX_STREAMACCESS_Text) != 0 &&
1429       (dwAccess & FX_STREAMACCESS_Text) == 0) {
1430     return nullptr;
1431   }
1432   if ((m_dwAccess & FX_STREAMACCESS_Write) == 0 &&
1433       (dwAccess & FX_STREAMACCESS_Write) != 0) {
1434     return nullptr;
1435   }
1436   int32_t iStart = m_iStart + iOffset;
1437   int32_t iTotal = m_iStart + m_iLength;
1438   if (iStart < m_iStart || iStart >= iTotal)
1439     return nullptr;
1440 
1441   int32_t iEnd = iStart + iLength;
1442   if (iEnd < iStart || iEnd > iTotal)
1443     return nullptr;
1444 
1445   auto pShared = pdfium::MakeRetain<CFGAS_Stream>();
1446   pShared->m_eStreamType = FX_STREAMTYPE_Stream;
1447   pShared->m_pStreamImp = m_pStreamImp;
1448   pShared->m_dwAccess = dwAccess;
1449   pShared->m_iTotalSize = iLength;
1450   pShared->m_iPosition = iStart;
1451   pShared->m_iStart = iStart;
1452   pShared->m_iLength = (dwAccess & FX_STREAMACCESS_Write) != 0 ? 0 : iLength;
1453   if (dwAccess & FX_STREAMACCESS_Text)
1454     return IFGAS_Stream::CreateTextStream(pShared);
1455 
1456   return pShared;
1457 }
1458 
MakeSeekableReadStream()1459 CFX_RetainPtr<IFX_SeekableReadStream> IFGAS_Stream::MakeSeekableReadStream() {
1460   return CFGAS_FileRead::Create(CFX_RetainPtr<IFGAS_Stream>(this));
1461 }
1462 
Create(const CFX_RetainPtr<IFGAS_Stream> & pStream)1463 CFX_RetainPtr<CFGAS_FileRead> CFGAS_FileRead::Create(
1464     const CFX_RetainPtr<IFGAS_Stream>& pStream) {
1465   return pdfium::MakeRetain<CFGAS_FileRead>(pStream);
1466 }
1467 
CFGAS_FileRead(const CFX_RetainPtr<IFGAS_Stream> & pStream)1468 CFGAS_FileRead::CFGAS_FileRead(const CFX_RetainPtr<IFGAS_Stream>& pStream)
1469     : m_pStream(pStream) {
1470   ASSERT(m_pStream);
1471 }
1472 
~CFGAS_FileRead()1473 CFGAS_FileRead::~CFGAS_FileRead() {}
1474 
GetSize()1475 FX_FILESIZE CFGAS_FileRead::GetSize() {
1476   return (FX_FILESIZE)m_pStream->GetLength();
1477 }
1478 
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)1479 bool CFGAS_FileRead::ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) {
1480   m_pStream->Seek(FX_STREAMSEEK_Begin, (int32_t)offset);
1481   int32_t iLen = m_pStream->ReadData((uint8_t*)buffer, (int32_t)size);
1482   return iLen == (int32_t)size;
1483 }
1484