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