Home | History | Annotate | Download | only in crt
      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:
     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 
     42   uint32_t GetAccessModes() const { return m_dwAccess; }
     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();
     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;
     89   void Flush() override {}
     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();
    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;
    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;
    114   int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override {
    115     return 0;
    116   }
    117   int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override {
    118     return 0;
    119   }
    120   void Flush() override {}
    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;
    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;
    145   int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) override {
    146     return 0;
    147   }
    148   int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) override {
    149     return 0;
    150   }
    151   void Flush() override {}
    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();
    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;
    171   int32_t GetPosition() override { return m_iPosition; }
    172   bool IsEOF() const override;
    173   int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) override { return 0; }
    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;
    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 
    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 
    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
    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
    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
    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 
    370 IFGAS_StreamImp::IFGAS_StreamImp() : m_dwAccess(0) {}
    371 
    372 CFGAS_FileStreamImp::CFGAS_FileStreamImp() : m_hFile(nullptr), m_iLength(0) {}
    373 
    374 CFGAS_FileStreamImp::~CFGAS_FileStreamImp() {
    375   if (m_hFile)
    376     FXSYS_fclose(m_hFile);
    377 }
    378 
    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 }
    457 int32_t CFGAS_FileStreamImp::GetLength() const {
    458   ASSERT(m_hFile);
    459   return m_iLength;
    460 }
    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 }
    466 int32_t CFGAS_FileStreamImp::GetPosition() {
    467   ASSERT(m_hFile);
    468   return FXSYS_ftell(m_hFile);
    469 }
    470 bool CFGAS_FileStreamImp::IsEOF() const {
    471   ASSERT(m_hFile);
    472   return FXSYS_ftell(m_hFile) >= m_iLength;
    473 }
    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 }
    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 }
    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 }
    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 }
    530 void CFGAS_FileStreamImp::Flush() {
    531   ASSERT(m_hFile && (GetAccessModes() & FX_STREAMACCESS_Write) != 0);
    532   FXSYS_fflush(m_hFile);
    533 }
    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 
    541 CFGAS_FileReadStreamImp::CFGAS_FileReadStreamImp()
    542     : m_pFileRead(nullptr), m_iPosition(0), m_iLength(0) {}
    543 
    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 
    556 int32_t CFGAS_FileReadStreamImp::GetLength() const {
    557   return m_iLength;
    558 }
    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 }
    578 bool CFGAS_FileReadStreamImp::IsEOF() const {
    579   return m_iPosition >= m_iLength;
    580 }
    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 }
    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 
    611 CFGAS_BufferReadStreamImp::CFGAS_BufferReadStreamImp()
    612     : m_iPosition(0), m_iBufferSize(0) {}
    613 
    614 CFGAS_BufferReadStreamImp::~CFGAS_BufferReadStreamImp() {}
    615 
    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 }
    639 int32_t CFGAS_BufferReadStreamImp::GetLength() const {
    640   return m_iBufferSize;
    641 }
    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 }
    662 bool CFGAS_BufferReadStreamImp::IsEOF() const {
    663   return m_pBufferRead ? m_pBufferRead->IsEOF() : true;
    664 }
    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 }
    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 }
    735 CFGAS_FileWriteStreamImp::CFGAS_FileWriteStreamImp()
    736     : m_pFileWrite(nullptr), m_iPosition(0) {}
    737 
    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 
    752 int32_t CFGAS_FileWriteStreamImp::GetLength() const {
    753   if (!m_pFileWrite)
    754     return 0;
    755 
    756   return (int32_t)m_pFileWrite->GetSize();
    757 }
    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 }
    778 bool CFGAS_FileWriteStreamImp::IsEOF() const {
    779   return m_iPosition >= GetLength();
    780 }
    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 }
    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 }
    795 void CFGAS_FileWriteStreamImp::Flush() {
    796   if (m_pFileWrite) {
    797     m_pFileWrite->Flush();
    798   }
    799 }
    800 CFGAS_BufferStreamImp::CFGAS_BufferStreamImp()
    801     : m_pData(nullptr), m_iTotalSize(0), m_iPosition(0), m_iLength(0) {}
    802 
    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 }
    814 int32_t CFGAS_BufferStreamImp::GetLength() const {
    815   ASSERT(m_pData);
    816   return m_iLength;
    817 }
    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 }
    835 int32_t CFGAS_BufferStreamImp::GetPosition() {
    836   ASSERT(m_pData);
    837   return m_iPosition;
    838 }
    839 bool CFGAS_BufferStreamImp::IsEOF() const {
    840   ASSERT(m_pData);
    841   return m_iPosition >= m_iLength;
    842 }
    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 }
    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 }
    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 }
    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
    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 
    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 
    922 CFGAS_TextStream::~CFGAS_TextStream() {
    923   if (m_pBuf)
    924     FX_Free(m_pBuf);
    925 }
    926 
    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 
    973 uint32_t CFGAS_TextStream::GetAccessModes() const {
    974   return m_pStreamImp->GetAccessModes() | FX_STREAMACCESS_Text;
    975 }
    976 
    977 int32_t CFGAS_TextStream::GetLength() const {
    978   return m_pStreamImp->GetLength();
    979 }
    980 
    981 int32_t CFGAS_TextStream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
    982   return m_pStreamImp->Seek(eSeek, iOffset);
    983 }
    984 
    985 int32_t CFGAS_TextStream::GetPosition() {
    986   return m_pStreamImp->GetPosition();
    987 }
    988 
    989 bool CFGAS_TextStream::IsEOF() const {
    990   return m_pStreamImp->IsEOF();
    991 }
    992 
    993 int32_t CFGAS_TextStream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
    994   return m_pStreamImp->ReadData(pBuffer, iBufferSize);
    995 }
    996 
    997 int32_t CFGAS_TextStream::WriteData(const uint8_t* pBuffer,
    998                                     int32_t iBufferSize) {
    999   return m_pStreamImp->WriteData(pBuffer, iBufferSize);
   1000 }
   1001 
   1002 void CFGAS_TextStream::Flush() {
   1003   m_pStreamImp->Flush();
   1004 }
   1005 
   1006 bool CFGAS_TextStream::SetLength(int32_t iLength) {
   1007   return m_pStreamImp->SetLength(iLength);
   1008 }
   1009 
   1010 uint16_t CFGAS_TextStream::GetCodePage() const {
   1011   return m_wCodePage;
   1012 }
   1013 
   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 
   1029 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 
   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 
   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 
   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 
   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 
   1127 CFGAS_Stream::~CFGAS_Stream() {
   1128   if (m_eStreamType != FX_STREAMTYPE_Stream)
   1129     delete m_pStreamImp;
   1130 }
   1131 
   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 
   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 
   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 
   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 
   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 
   1231 uint32_t CFGAS_Stream::GetAccessModes() const {
   1232   return m_dwAccess;
   1233 }
   1234 
   1235 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 }
   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 }
   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 }
   1280 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 }
   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 }
   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 
   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 }
   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 }
   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 }
   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 }
   1400 int32_t CFGAS_Stream::GetBOM(uint8_t bom[4]) const {
   1401   if (!m_pStreamImp) {
   1402     return -1;
   1403   }
   1404   return 0;
   1405 }
   1406 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 }
   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 
   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 
   1459 CFX_RetainPtr<IFX_SeekableReadStream> IFGAS_Stream::MakeSeekableReadStream() {
   1460   return CFGAS_FileRead::Create(CFX_RetainPtr<IFGAS_Stream>(this));
   1461 }
   1462 
   1463 CFX_RetainPtr<CFGAS_FileRead> CFGAS_FileRead::Create(
   1464     const CFX_RetainPtr<IFGAS_Stream>& pStream) {
   1465   return pdfium::MakeRetain<CFGAS_FileRead>(pStream);
   1466 }
   1467 
   1468 CFGAS_FileRead::CFGAS_FileRead(const CFX_RetainPtr<IFGAS_Stream>& pStream)
   1469     : m_pStream(pStream) {
   1470   ASSERT(m_pStream);
   1471 }
   1472 
   1473 CFGAS_FileRead::~CFGAS_FileRead() {}
   1474 
   1475 FX_FILESIZE CFGAS_FileRead::GetSize() {
   1476   return (FX_FILESIZE)m_pStream->GetLength();
   1477 }
   1478 
   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