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