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