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 18 CFX_BlockBuffer::CFX_BlockBuffer() 19 : m_DataLength(0), m_BufferSize(0), m_StartPosition(0) {} 20 21 CFX_BlockBuffer::~CFX_BlockBuffer() {} 22 23 size_t CFX_BlockBuffer::GetAllocStep() const { 24 return kAllocStep; 25 } 26 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 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 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 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 73 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 115 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