• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 "core/fxcrt/cfx_memorystream.h"
8 
9 #include <algorithm>
10 #include <utility>
11 
12 #include "core/fxcrt/fx_safe_types.h"
13 
CFX_MemoryStream()14 CFX_MemoryStream::CFX_MemoryStream() : m_nTotalSize(0), m_nCurSize(0) {}
15 
CFX_MemoryStream(std::unique_ptr<uint8_t,FxFreeDeleter> pBuffer,size_t nSize)16 CFX_MemoryStream::CFX_MemoryStream(
17     std::unique_ptr<uint8_t, FxFreeDeleter> pBuffer,
18     size_t nSize)
19     : m_data(std::move(pBuffer)), m_nTotalSize(nSize), m_nCurSize(nSize) {}
20 
21 CFX_MemoryStream::~CFX_MemoryStream() = default;
22 
GetSize()23 FX_FILESIZE CFX_MemoryStream::GetSize() {
24   return static_cast<FX_FILESIZE>(m_nCurSize);
25 }
26 
IsEOF()27 bool CFX_MemoryStream::IsEOF() {
28   return m_nCurPos >= static_cast<size_t>(GetSize());
29 }
30 
GetPosition()31 FX_FILESIZE CFX_MemoryStream::GetPosition() {
32   return static_cast<FX_FILESIZE>(m_nCurPos);
33 }
34 
Flush()35 bool CFX_MemoryStream::Flush() {
36   return true;
37 }
38 
ReadBlockAtOffset(void * buffer,FX_FILESIZE offset,size_t size)39 bool CFX_MemoryStream::ReadBlockAtOffset(void* buffer,
40                                          FX_FILESIZE offset,
41                                          size_t size) {
42   if (!buffer || offset < 0 || !size)
43     return false;
44 
45   FX_SAFE_SIZE_T newPos = size;
46   newPos += offset;
47   if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 ||
48       newPos.ValueOrDie() > m_nCurSize) {
49     return false;
50   }
51 
52   m_nCurPos = newPos.ValueOrDie();
53   memcpy(buffer, &GetBuffer()[offset], size);
54   return true;
55 }
56 
ReadBlock(void * buffer,size_t size)57 size_t CFX_MemoryStream::ReadBlock(void* buffer, size_t size) {
58   if (m_nCurPos >= m_nCurSize)
59     return 0;
60 
61   size_t nRead = std::min(size, m_nCurSize - m_nCurPos);
62   if (!ReadBlockAtOffset(buffer, static_cast<int32_t>(m_nCurPos), nRead))
63     return 0;
64 
65   return nRead;
66 }
67 
WriteBlockAtOffset(const void * buffer,FX_FILESIZE offset,size_t size)68 bool CFX_MemoryStream::WriteBlockAtOffset(const void* buffer,
69                                           FX_FILESIZE offset,
70                                           size_t size) {
71   if (!buffer || offset < 0 || !size)
72     return false;
73 
74   FX_SAFE_SIZE_T safe_new_pos = size;
75   safe_new_pos += offset;
76   if (!safe_new_pos.IsValid())
77     return false;
78 
79   size_t new_pos = safe_new_pos.ValueOrDie();
80   if (new_pos > m_nTotalSize) {
81     static constexpr size_t kBlockSize = 64 * 1024;
82     FX_SAFE_SIZE_T new_size = new_pos;
83     new_size *= 2;
84     new_size += (kBlockSize - 1);
85     new_size /= kBlockSize;
86     new_size *= kBlockSize;
87     if (!new_size.IsValid())
88       return false;
89 
90     m_nTotalSize = new_size.ValueOrDie();
91     if (m_data)
92       m_data.reset(FX_Realloc(uint8_t, m_data.release(), m_nTotalSize));
93     else
94       m_data.reset(FX_Alloc(uint8_t, m_nTotalSize));
95   }
96   m_nCurPos = new_pos;
97 
98   memcpy(&m_data.get()[offset], buffer, size);
99   m_nCurSize = std::max(m_nCurSize, m_nCurPos);
100 
101   return true;
102 }
103