1d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Copyright 2017 PDFium Authors. All rights reserved.
2d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Use of this source code is governed by a BSD-style license that can be
3d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// found in the LICENSE file.
4d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
5d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
7d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcrt/cfx_blockbuffer.h"
8d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
9d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <algorithm>
10d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <utility>
11d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
12d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannnamespace {
13d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
14d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannconst size_t kAllocStep = 1024 * 1024;
15d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
16d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}  // namespace
17d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
18d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCFX_BlockBuffer::CFX_BlockBuffer()
19d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    : m_DataLength(0), m_BufferSize(0), m_StartPosition(0) {}
20d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
21d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCFX_BlockBuffer::~CFX_BlockBuffer() {}
22d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
23d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannsize_t CFX_BlockBuffer::GetAllocStep() const {
24d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return kAllocStep;
25d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
26d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
27d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstd::pair<wchar_t*, size_t> CFX_BlockBuffer::GetAvailableBlock() {
28d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (m_BlockArray.empty())
29d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return {nullptr, 0};
30d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
31d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t realIndex = m_StartPosition + m_DataLength;
32d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (realIndex == m_BufferSize) {
33d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_BlockArray.emplace_back(FX_Alloc(wchar_t, kAllocStep));
34d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_BufferSize += kAllocStep;
35d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return {m_BlockArray.back().get(), 0};
36d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
37d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return {m_BlockArray[realIndex / kAllocStep].get(), realIndex % kAllocStep};
38d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
39d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
40d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool CFX_BlockBuffer::InitBuffer() {
41d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_BlockArray.clear();
42d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_BlockArray.emplace_back(FX_Alloc(wchar_t, kAllocStep));
43d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_BufferSize = kAllocStep;
44d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return true;
45d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
46d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
47d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CFX_BlockBuffer::SetTextChar(size_t index, wchar_t ch) {
48d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t realIndex = m_StartPosition + index;
49d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t blockIndex = realIndex / kAllocStep;
50d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (blockIndex >= m_BlockArray.size()) {
51d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    size_t newBlocks = blockIndex - m_BlockArray.size() + 1;
52d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    do {
53d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_BlockArray.emplace_back(FX_Alloc(wchar_t, kAllocStep));
54d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_BufferSize += kAllocStep;
55d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } while (--newBlocks);
56d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
57d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  wchar_t* pTextData = m_BlockArray[blockIndex].get();
58d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pTextData[realIndex % kAllocStep] = ch;
59d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_DataLength = std::max(m_DataLength, index + 1);
60d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
61d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
62d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CFX_BlockBuffer::DeleteTextChars(size_t count) {
63d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (count == 0)
64d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
65d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
66d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (count >= m_DataLength) {
67d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    Reset(false);
68d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
69d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
70d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_DataLength -= count;
71d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
72d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
73d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannWideString CFX_BlockBuffer::GetTextData(size_t start, size_t length) const {
74d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (m_BufferSize <= m_StartPosition + 1 || length == 0)
75d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return WideString();
76d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
77d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t maybeDataLength = m_BufferSize - 1 - m_StartPosition;
78d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (start > maybeDataLength)
79d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return WideString();
80d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  length = std::min(length, maybeDataLength);
81d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
82d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  WideString wsTextData;
83d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  wchar_t* pBuf = wsTextData.GetBuffer(length);
84d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!pBuf)
85d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return WideString();
86d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
87d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t startBlock = 0;
88d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t startInner = 0;
89d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  std::tie(startBlock, startInner) = TextDataIndex2BufIndex(start);
90d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
91d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t endBlock = 0;
92d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t endInner = 0;
93d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  std::tie(endBlock, endInner) = TextDataIndex2BufIndex(start + length);
94d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
95d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t pointer = 0;
96d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  for (size_t i = startBlock; i <= endBlock; ++i) {
97d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    size_t bufferPointer = 0;
98d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    size_t copyLength = kAllocStep;
99d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (i == startBlock) {
100d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      copyLength -= startInner;
101d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      bufferPointer = startInner;
102d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
103d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (i == endBlock)
104d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      copyLength -= ((kAllocStep - 1) - endInner);
105d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
106d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    wchar_t* pBlockBuf = m_BlockArray[i].get();
107d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memcpy(pBuf + pointer, pBlockBuf + bufferPointer,
108d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann           copyLength * sizeof(wchar_t));
109d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pointer += copyLength;
110d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
111d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  wsTextData.ReleaseBuffer(length);
112d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return wsTextData;
113d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
114d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
115d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstd::pair<size_t, size_t> CFX_BlockBuffer::TextDataIndex2BufIndex(
116d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    const size_t iIndex) const {
117d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(iIndex >= 0);
118d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
119d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t realIndex = m_StartPosition + iIndex;
120d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return {realIndex / kAllocStep, realIndex % kAllocStep};
121d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
122