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_seekablestreamproxy.h"
8d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
9d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
10d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <io.h>
11d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#endif  // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
12d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
13d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <algorithm>
14d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <limits>
15d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <memory>
16d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <utility>
17d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <vector>
18d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
19d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcrt/cfx_memorystream.h"
20d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcrt/fx_codepage.h"
21d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcrt/fx_extension.h"
22d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "third_party/base/ptr_util.h"
23d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "third_party/base/stl_util.h"
24d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
25d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannnamespace {
26d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
27d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Returns {src bytes consumed, dst bytes produced}.
28d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstd::pair<size_t, size_t> UTF8Decode(const char* pSrc,
29d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                     size_t srcLen,
30d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                     wchar_t* pDst,
31d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                     size_t dstLen) {
32d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(pDst && dstLen > 0);
33d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
34d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (srcLen < 1)
35d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return {0, 0};
36d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
37d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  uint32_t dwCode = 0;
38d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  int32_t iPending = 0;
39d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t iSrcNum = 0;
40d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t iDstNum = 0;
41d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  size_t iIndex = 0;
42d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  int32_t k = 1;
43d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  while (iIndex < srcLen) {
44d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    uint8_t byte = static_cast<uint8_t>(*(pSrc + iIndex));
45d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (byte < 0x80) {
46d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iPending = 0;
47d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      k = 1;
48d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iDstNum++;
49d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iSrcNum += k;
50d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      *pDst++ = byte;
51d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (iDstNum >= dstLen)
52d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        break;
53d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else if (byte < 0xc0) {
54d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (iPending < 1)
55d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        break;
56d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
57d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iPending--;
58d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      dwCode |= (byte & 0x3f) << (iPending * 6);
59d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (iPending == 0) {
60d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        iDstNum++;
61d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        iSrcNum += k;
62d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        *pDst++ = dwCode;
63d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        if (iDstNum >= dstLen)
64d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          break;
65d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      }
66d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else if (byte < 0xe0) {
67d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iPending = 1;
68d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      k = 2;
69d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      dwCode = (byte & 0x1f) << 6;
70d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else if (byte < 0xf0) {
71d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iPending = 2;
72d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      k = 3;
73d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      dwCode = (byte & 0x0f) << 12;
74d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else if (byte < 0xf8) {
75d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iPending = 3;
76d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      k = 4;
77d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      dwCode = (byte & 0x07) << 18;
78d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else if (byte < 0xfc) {
79d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iPending = 4;
80d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      k = 5;
81d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      dwCode = (byte & 0x03) << 24;
82d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else if (byte < 0xfe) {
83d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iPending = 5;
84d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      k = 6;
85d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      dwCode = (byte & 0x01) << 30;
86d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else {
87d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      break;
88d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
89d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    iIndex++;
90d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
91d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return {iSrcNum, iDstNum};
92d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
93d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
94d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid UTF16ToWChar(void* pBuffer, size_t iLength) {
95d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(pBuffer);
96d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(iLength > 0);
97d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(sizeof(wchar_t) > 2);
98d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
99d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  uint16_t* pSrc = static_cast<uint16_t*>(pBuffer);
100d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  wchar_t* pDst = static_cast<wchar_t*>(pBuffer);
101d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  for (size_t i = 0; i < iLength; i++)
102d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    pDst[i] = static_cast<wchar_t>(pSrc[i]);
103d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
104d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
105d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid SwapByteOrder(wchar_t* pStr, size_t iLength) {
106d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(pStr);
107d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
108d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  uint16_t wch;
109d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (sizeof(wchar_t) > 2) {
110d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    while (iLength-- > 0) {
111d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      wch = static_cast<uint16_t>(*pStr);
112d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      wch = (wch >> 8) | (wch << 8);
113d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      wch &= 0x00FF;
114d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      *pStr = wch;
115d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      ++pStr;
116d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
117d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
118d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
119d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
120d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  while (iLength-- > 0) {
121d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    wch = static_cast<uint16_t>(*pStr);
122d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    wch = (wch >> 8) | (wch << 8);
123d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    *pStr = wch;
124d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    ++pStr;
125d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
126d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
127d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
128d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}  // namespace
129d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
130d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#define BOM_MASK 0x00FFFFFF
131d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#define BOM_UTF8 0x00BFBBEF
132d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#define BOM_UTF16_MASK 0x0000FFFF
133d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#define BOM_UTF16_BE 0x0000FFFE
134d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#define BOM_UTF16_LE 0x0000FEFF
135d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
136d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCFX_SeekableStreamProxy::CFX_SeekableStreamProxy(
137d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    const RetainPtr<IFX_SeekableStream>& stream,
138d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    bool isWriteStream)
139d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    : m_IsWriteStream(isWriteStream),
140d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wCodePage(FX_CODEPAGE_DefANSI),
141d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wBOMLength(0),
142d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_iPosition(0),
143d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_pStream(stream) {
144d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(m_pStream);
145d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
146d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (isWriteStream) {
147d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_iPosition = m_pStream->GetSize();
148d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
149d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
150d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
151d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  Seek(From::Begin, 0);
152d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
153d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  uint32_t bom = 0;
154d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ReadData(reinterpret_cast<uint8_t*>(&bom), 3);
155d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
156d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  bom &= BOM_MASK;
157d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (bom == BOM_UTF8) {
158d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_wBOMLength = 3;
159d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    m_wCodePage = FX_CODEPAGE_UTF8;
160d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  } else {
161d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    bom &= BOM_UTF16_MASK;
162d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (bom == BOM_UTF16_BE) {
163d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wBOMLength = 2;
164d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wCodePage = FX_CODEPAGE_UTF16BE;
165d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else if (bom == BOM_UTF16_LE) {
166d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wBOMLength = 2;
167d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wCodePage = FX_CODEPAGE_UTF16LE;
168d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else {
169d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wBOMLength = 0;
170d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wCodePage = FXSYS_GetACP();
171d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
172d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
173d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
174d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  Seek(From::Begin, static_cast<FX_FILESIZE>(m_wBOMLength));
175d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
176d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
177d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCFX_SeekableStreamProxy::CFX_SeekableStreamProxy(uint8_t* data, size_t size)
178d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    : CFX_SeekableStreamProxy(
179d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          pdfium::MakeRetain<CFX_MemoryStream>(data, size, false),
180d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          false) {}
181d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
182d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCFX_SeekableStreamProxy::~CFX_SeekableStreamProxy() {}
183d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
184d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CFX_SeekableStreamProxy::Seek(From eSeek, FX_FILESIZE iOffset) {
185d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  switch (eSeek) {
186d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    case From::Begin:
187d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_iPosition = iOffset;
188d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      break;
189d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    case From::Current: {
190d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pdfium::base::CheckedNumeric<FX_FILESIZE> new_pos = m_iPosition;
191d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      new_pos += iOffset;
192d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_iPosition =
193d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          new_pos.ValueOrDefault(std::numeric_limits<FX_FILESIZE>::max());
194d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } break;
195d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
196d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_iPosition =
197d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pdfium::clamp(m_iPosition, static_cast<FX_FILESIZE>(0), GetLength());
198d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
199d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
200d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CFX_SeekableStreamProxy::SetCodePage(uint16_t wCodePage) {
201d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (m_wBOMLength > 0)
202d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
203d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_wCodePage = wCodePage;
204d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
205d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
206d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannsize_t CFX_SeekableStreamProxy::ReadData(uint8_t* pBuffer, size_t iBufferSize) {
207d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  ASSERT(pBuffer && iBufferSize > 0);
208d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
209d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (m_IsWriteStream)
210d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return 0;
211d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
212d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  iBufferSize =
213d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      std::min(iBufferSize, static_cast<size_t>(GetLength() - m_iPosition));
214d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (iBufferSize <= 0)
215d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return 0;
216d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
217d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!m_pStream->ReadBlock(pBuffer, m_iPosition, iBufferSize))
218d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return 0;
219d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
220d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pdfium::base::CheckedNumeric<FX_FILESIZE> new_pos = m_iPosition;
221d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  new_pos += iBufferSize;
222d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_iPosition = new_pos.ValueOrDefault(m_iPosition);
223d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return new_pos.IsValid() ? iBufferSize : 0;
224d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
225d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
226d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannsize_t CFX_SeekableStreamProxy::ReadString(wchar_t* pStr,
227d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                           size_t iMaxLength,
228d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                                           bool* bEOS) {
229d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!pStr || iMaxLength == 0)
230d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return 0;
231d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
232d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (m_IsWriteStream)
233d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return 0;
234d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
235d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (m_wCodePage == FX_CODEPAGE_UTF16LE ||
236d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wCodePage == FX_CODEPAGE_UTF16BE) {
237d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    size_t iBytes = iMaxLength * 2;
238d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    size_t iLen = ReadData(reinterpret_cast<uint8_t*>(pStr), iBytes);
239d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    iMaxLength = iLen / 2;
240d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (sizeof(wchar_t) > 2 && iMaxLength > 0)
241d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      UTF16ToWChar(pStr, iMaxLength);
242d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
243d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (m_wCodePage == FX_CODEPAGE_UTF16BE)
244d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      SwapByteOrder(pStr, iMaxLength);
245d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
246d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  } else {
247d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    FX_FILESIZE pos = GetPosition();
248d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    size_t iBytes =
249d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        std::min(iMaxLength, static_cast<size_t>(GetLength() - pos));
250d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
251d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (iBytes > 0) {
252d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      std::vector<uint8_t> buf(iBytes);
253d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
254d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      size_t iLen = ReadData(buf.data(), iBytes);
255d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (m_wCodePage != FX_CODEPAGE_UTF8)
256d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        return 0;
257d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
258d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      size_t iSrc = 0;
259d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      std::tie(iSrc, iMaxLength) = UTF8Decode(
260d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          reinterpret_cast<const char*>(buf.data()), iLen, pStr, iMaxLength);
261d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      Seek(From::Current, iSrc - iLen);
262d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    } else {
263d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      iMaxLength = 0;
264d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    }
265d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
266d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
267d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  *bEOS = IsEOF();
268d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  return iMaxLength;
269d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
270d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
271d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CFX_SeekableStreamProxy::WriteString(const WideStringView& str) {
272d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!m_IsWriteStream || str.GetLength() == 0 ||
273d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      m_wCodePage != FX_CODEPAGE_UTF8) {
274d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
275d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
276d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (!m_pStream->WriteBlock(str.unterminated_c_str(), m_iPosition,
277d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann                             str.GetLength() * sizeof(wchar_t))) {
278d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
279d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  }
280d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann
281d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  pdfium::base::CheckedNumeric<FX_FILESIZE> new_pos = m_iPosition;
282d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  new_pos += str.GetLength() * sizeof(wchar_t);
283d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_iPosition = new_pos.ValueOrDefault(std::numeric_limits<FX_FILESIZE>::max());
284d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  m_iPosition =
285d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      pdfium::clamp(m_iPosition, static_cast<FX_FILESIZE>(0), GetLength());
286d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann}
287