| // Copyright 2017 The PDFium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "testing/fake_file_access.h" | 
 |  | 
 | #include <utility> | 
 |  | 
 | #include "core/fxcrt/check.h" | 
 | #include "core/fxcrt/fx_system.h" | 
 |  | 
 | class FileAccessWrapper final : public FPDF_FILEACCESS { | 
 |  public: | 
 |   explicit FileAccessWrapper(FakeFileAccess* simulator) | 
 |       : simulator_(simulator) { | 
 |     m_FileLen = simulator_->GetFileSize(); | 
 |     m_GetBlock = &GetBlockImpl; | 
 |     m_Param = this; | 
 |   } | 
 |  | 
 |   static int GetBlockImpl(void* param, | 
 |                           unsigned long position, | 
 |                           unsigned char* pBuf, | 
 |                           unsigned long size) { | 
 |     return static_cast<FileAccessWrapper*>(param)->simulator_->GetBlock( | 
 |         position, pBuf, size); | 
 |   } | 
 |  | 
 |  private: | 
 |   UnownedPtr<FakeFileAccess> simulator_; | 
 | }; | 
 |  | 
 | class FileAvailImpl final : public FX_FILEAVAIL { | 
 |  public: | 
 |   explicit FileAvailImpl(FakeFileAccess* simulator) : simulator_(simulator) { | 
 |     version = 1; | 
 |     IsDataAvail = &IsDataAvailImpl; | 
 |   } | 
 |  | 
 |   static FPDF_BOOL IsDataAvailImpl(FX_FILEAVAIL* pThis, | 
 |                                    size_t offset, | 
 |                                    size_t size) { | 
 |     return static_cast<FileAvailImpl*>(pThis)->simulator_->IsDataAvail(offset, | 
 |                                                                        size); | 
 |   } | 
 |  | 
 |  private: | 
 |   UnownedPtr<FakeFileAccess> simulator_; | 
 | }; | 
 |  | 
 | class DownloadHintsImpl final : public FX_DOWNLOADHINTS { | 
 |  public: | 
 |   explicit DownloadHintsImpl(FakeFileAccess* simulator) | 
 |       : simulator_(simulator) { | 
 |     version = 1; | 
 |     AddSegment = &AddSegmentImpl; | 
 |   } | 
 |  | 
 |   static void AddSegmentImpl(FX_DOWNLOADHINTS* pThis, | 
 |                              size_t offset, | 
 |                              size_t size) { | 
 |     return static_cast<DownloadHintsImpl*>(pThis)->simulator_->AddSegment( | 
 |         offset, size); | 
 |   } | 
 |  | 
 |  private: | 
 |   UnownedPtr<FakeFileAccess> simulator_; | 
 | }; | 
 |  | 
 | FakeFileAccess::FakeFileAccess(FPDF_FILEACCESS* file_access) | 
 |     : file_access_(file_access), | 
 |       file_access_wrapper_(std::make_unique<FileAccessWrapper>(this)), | 
 |       file_avail_(std::make_unique<FileAvailImpl>(this)), | 
 |       download_hints_(std::make_unique<DownloadHintsImpl>(this)) { | 
 |   DCHECK(file_access_); | 
 | } | 
 |  | 
 | FakeFileAccess::~FakeFileAccess() = default; | 
 |  | 
 | FPDF_FILEACCESS* FakeFileAccess::GetFileAccess() const { | 
 |   return file_access_wrapper_.get(); | 
 | } | 
 |  | 
 | FX_FILEAVAIL* FakeFileAccess::GetFileAvail() const { | 
 |   return file_avail_.get(); | 
 | } | 
 |  | 
 | FX_DOWNLOADHINTS* FakeFileAccess::GetDownloadHints() const { | 
 |   return download_hints_.get(); | 
 | } | 
 |  | 
 | FPDF_BOOL FakeFileAccess::IsDataAvail(size_t offset, size_t size) const { | 
 |   return available_data_.Contains(RangeSet::Range(offset, offset + size)); | 
 | } | 
 |  | 
 | void FakeFileAccess::AddSegment(size_t offset, size_t size) { | 
 |   requested_data_.Union(RangeSet::Range(offset, offset + size)); | 
 | } | 
 |  | 
 | unsigned long FakeFileAccess::GetFileSize() { | 
 |   return file_access_->m_FileLen; | 
 | } | 
 |  | 
 | int FakeFileAccess::GetBlock(unsigned long position, | 
 |                              unsigned char* pBuf, | 
 |                              unsigned long size) { | 
 |   if (!pBuf || !size) | 
 |     return false; | 
 |  | 
 |   if (!IsDataAvail(static_cast<size_t>(position), static_cast<size_t>(size))) | 
 |     return false; | 
 |  | 
 |   return file_access_->m_GetBlock(file_access_->m_Param, position, pBuf, size); | 
 | } | 
 |  | 
 | void FakeFileAccess::SetRequestedDataAvailable() { | 
 |   available_data_.Union(requested_data_); | 
 |   requested_data_.Clear(); | 
 | } | 
 |  | 
 | void FakeFileAccess::SetWholeFileAvailable() { | 
 |   available_data_.Union(RangeSet::Range(0, static_cast<size_t>(GetFileSize()))); | 
 |   requested_data_.Clear(); | 
 | } |