• 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_blockbuffer.h"
8 
9 #include <algorithm>
10 #include <utility>
11 
12 namespace {
13 
14 const size_t kAllocStep = 1024 * 1024;
15 
16 }  // namespace
17 
CFX_BlockBuffer()18 CFX_BlockBuffer::CFX_BlockBuffer()
19     : m_DataLength(0), m_BufferSize(0), m_StartPosition(0) {}
20 
~CFX_BlockBuffer()21 CFX_BlockBuffer::~CFX_BlockBuffer() {}
22 
GetAllocStep() const23 size_t CFX_BlockBuffer::GetAllocStep() const {
24   return kAllocStep;
25 }
26 
GetAvailableBlock()27 std::pair<wchar_t*, size_t> CFX_BlockBuffer::GetAvailableBlock() {
28   if (m_BlockArray.empty())
29     return {nullptr, 0};
30 
31   size_t realIndex = m_StartPosition + m_DataLength;
32   if (realIndex == m_BufferSize) {
33     m_BlockArray.emplace_back(FX_Alloc(wchar_t, kAllocStep));
34     m_BufferSize += kAllocStep;
35     return {m_BlockArray.back().get(), 0};
36   }
37   return {m_BlockArray[realIndex / kAllocStep].get(), realIndex % kAllocStep};
38 }
39 
InitBuffer()40 bool CFX_BlockBuffer::InitBuffer() {
41   m_BlockArray.clear();
42   m_BlockArray.emplace_back(FX_Alloc(wchar_t, kAllocStep));
43   m_BufferSize = kAllocStep;
44   return true;
45 }
46 
SetTextChar(size_t index,wchar_t ch)47 void CFX_BlockBuffer::SetTextChar(size_t index, wchar_t ch) {
48   size_t realIndex = m_StartPosition + index;
49   size_t blockIndex = realIndex / kAllocStep;
50   if (blockIndex >= m_BlockArray.size()) {
51     size_t newBlocks = blockIndex - m_BlockArray.size() + 1;
52     do {
53       m_BlockArray.emplace_back(FX_Alloc(wchar_t, kAllocStep));
54       m_BufferSize += kAllocStep;
55     } while (--newBlocks);
56   }
57   wchar_t* pTextData = m_BlockArray[blockIndex].get();
58   pTextData[realIndex % kAllocStep] = ch;
59   m_DataLength = std::max(m_DataLength, index + 1);
60 }
61 
DeleteTextChars(size_t count)62 void CFX_BlockBuffer::DeleteTextChars(size_t count) {
63   if (count == 0)
64     return;
65 
66   if (count >= m_DataLength) {
67     Reset(false);
68     return;
69   }
70   m_DataLength -= count;
71 }
72 
GetTextData(size_t start,size_t length) const73 WideString CFX_BlockBuffer::GetTextData(size_t start, size_t length) const {
74   if (m_BufferSize <= m_StartPosition + 1 || length == 0)
75     return WideString();
76 
77   size_t maybeDataLength = m_BufferSize - 1 - m_StartPosition;
78   if (start > maybeDataLength)
79     return WideString();
80   length = std::min(length, maybeDataLength);
81 
82   WideString wsTextData;
83   wchar_t* pBuf = wsTextData.GetBuffer(length);
84   if (!pBuf)
85     return WideString();
86 
87   size_t startBlock = 0;
88   size_t startInner = 0;
89   std::tie(startBlock, startInner) = TextDataIndex2BufIndex(start);
90 
91   size_t endBlock = 0;
92   size_t endInner = 0;
93   std::tie(endBlock, endInner) = TextDataIndex2BufIndex(start + length);
94 
95   size_t pointer = 0;
96   for (size_t i = startBlock; i <= endBlock; ++i) {
97     size_t bufferPointer = 0;
98     size_t copyLength = kAllocStep;
99     if (i == startBlock) {
100       copyLength -= startInner;
101       bufferPointer = startInner;
102     }
103     if (i == endBlock)
104       copyLength -= ((kAllocStep - 1) - endInner);
105 
106     wchar_t* pBlockBuf = m_BlockArray[i].get();
107     memcpy(pBuf + pointer, pBlockBuf + bufferPointer,
108            copyLength * sizeof(wchar_t));
109     pointer += copyLength;
110   }
111   wsTextData.ReleaseBuffer(length);
112   return wsTextData;
113 }
114 
TextDataIndex2BufIndex(const size_t iIndex) const115 std::pair<size_t, size_t> CFX_BlockBuffer::TextDataIndex2BufIndex(
116     const size_t iIndex) const {
117   ASSERT(iIndex >= 0);
118 
119   size_t realIndex = m_StartPosition + iIndex;
120   return {realIndex / kAllocStep, realIndex % kAllocStep};
121 }
122