Home | History | Annotate | Download | only in fxcrt
      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