blob: 0ea46e847608dd7010c15b4265d082bf5dd05199 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// Copyright 2014 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 "xfa/fde/css/fde_csssyntax.h"
8
npm23991522016-11-28 12:49:29 -08009#include <algorithm>
10
Dan Sinclair1770c022016-03-14 14:14:16 -040011#include "xfa/fde/css/fde_cssdatatable.h"
12#include "xfa/fgas/crt/fgas_codepage.h"
13
thestigcfb77cc2016-06-10 12:21:53 -070014namespace {
Dan Sinclair1770c022016-03-14 14:14:16 -040015
thestigcfb77cc2016-06-10 12:21:53 -070016bool FDE_IsSelectorStart(FX_WCHAR wch) {
Dan Sinclair1770c022016-03-14 14:14:16 -040017 return wch == '.' || wch == '#' || wch == '*' || (wch >= 'a' && wch <= 'z') ||
18 (wch >= 'A' && wch <= 'Z');
19}
20
thestigcfb77cc2016-06-10 12:21:53 -070021} // namespace
Dan Sinclair1770c022016-03-14 14:14:16 -040022
Dan Sinclair1770c022016-03-14 14:14:16 -040023CFDE_CSSSyntaxParser::CFDE_CSSSyntaxParser()
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050024 : m_iTextDatLen(0),
tsepez736f28a2016-03-25 14:19:51 -070025 m_dwCheck((uint32_t)-1),
Dan Sinclair1770c022016-03-14 14:14:16 -040026 m_eMode(FDE_CSSSYNTAXMODE_RuleSet),
Dan Sinclair96f482c2017-01-11 16:31:27 -050027 m_eStatus(FDE_CSSSyntaxStatus::None),
dsinclair34965452016-07-18 13:14:49 -070028 m_ModeStack(100) {}
29
Dan Sinclair1770c022016-03-14 14:14:16 -040030CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser() {
31 m_TextData.Reset();
32 m_TextPlane.Reset();
33}
dsinclair34965452016-07-18 13:14:49 -070034
tsepezd19e9122016-11-02 15:43:18 -070035bool CFDE_CSSSyntaxParser::Init(const FX_WCHAR* pBuffer,
36 int32_t iBufferSize,
37 int32_t iTextDatSize,
38 bool bOnlyDeclaration) {
thestigcfb77cc2016-06-10 12:21:53 -070039 ASSERT(pBuffer && iBufferSize > 0 && iTextDatSize > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -040040 Reset(bOnlyDeclaration);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050041 if (!m_TextData.EstimateSize(iTextDatSize))
tsepezd19e9122016-11-02 15:43:18 -070042 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040043 return m_TextPlane.AttachBuffer(pBuffer, iBufferSize);
44}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050045
tsepezd19e9122016-11-02 15:43:18 -070046void CFDE_CSSSyntaxParser::Reset(bool bOnlyDeclaration) {
Dan Sinclair1770c022016-03-14 14:14:16 -040047 m_TextPlane.Reset();
48 m_TextData.Reset();
Dan Sinclair1770c022016-03-14 14:14:16 -040049 m_iTextDatLen = 0;
tsepez736f28a2016-03-25 14:19:51 -070050 m_dwCheck = (uint32_t)-1;
Dan Sinclair96f482c2017-01-11 16:31:27 -050051 m_eStatus = FDE_CSSSyntaxStatus::None;
Dan Sinclair1770c022016-03-14 14:14:16 -040052 m_eMode = bOnlyDeclaration ? FDE_CSSSYNTAXMODE_PropertyName
53 : FDE_CSSSYNTAXMODE_RuleSet;
54}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050055
Dan Sinclair96f482c2017-01-11 16:31:27 -050056FDE_CSSSyntaxStatus CFDE_CSSSyntaxParser::DoSyntaxParse() {
57 while (m_eStatus >= FDE_CSSSyntaxStatus::None) {
Dan Sinclair1770c022016-03-14 14:14:16 -040058 if (m_TextPlane.IsEOF()) {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050059 if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue &&
60 m_TextData.GetLength() > 0) {
61 SaveTextData();
62 m_eStatus = FDE_CSSSyntaxStatus::PropertyValue;
Dan Sinclair96f482c2017-01-11 16:31:27 -050063 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -040064 }
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050065 m_eStatus = FDE_CSSSyntaxStatus::EOS;
66 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -040067 }
68 FX_WCHAR wch;
69 while (!m_TextPlane.IsEOF()) {
70 wch = m_TextPlane.GetChar();
71 switch (m_eMode) {
72 case FDE_CSSSYNTAXMODE_RuleSet:
73 switch (wch) {
74 case '@':
75 m_TextPlane.MoveNext();
76 SwitchMode(FDE_CSSSYNTAXMODE_AtRule);
77 break;
78 case '}':
79 m_TextPlane.MoveNext();
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050080 if (RestoreMode())
Dan Sinclair96f482c2017-01-11 16:31:27 -050081 return FDE_CSSSyntaxStatus::DeclClose;
Dan Sinclair9dbc3c42017-01-18 08:58:00 -050082
83 m_eStatus = FDE_CSSSyntaxStatus::Error;
84 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -040085 case '/':
86 if (m_TextPlane.GetNextChar() == '*') {
87 m_ModeStack.Push(m_eMode);
88 SwitchMode(FDE_CSSSYNTAXMODE_Comment);
89 break;
90 }
91 default:
92 if (wch <= ' ') {
93 m_TextPlane.MoveNext();
94 } else if (FDE_IsSelectorStart(wch)) {
95 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
Dan Sinclair96f482c2017-01-11 16:31:27 -050096 return FDE_CSSSyntaxStatus::StyleRule;
Dan Sinclair1770c022016-03-14 14:14:16 -040097 } else {
Dan Sinclair96f482c2017-01-11 16:31:27 -050098 m_eStatus = FDE_CSSSyntaxStatus::Error;
99 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400100 }
101 break;
102 }
103 break;
104 case FDE_CSSSYNTAXMODE_Selector:
105 switch (wch) {
106 case ',':
107 m_TextPlane.MoveNext();
108 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500109 if (m_iTextDatLen > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500110 return FDE_CSSSyntaxStatus::Selector;
Dan Sinclair1770c022016-03-14 14:14:16 -0400111 break;
112 case '{':
113 if (m_TextData.GetLength() > 0) {
114 SaveTextData();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500115 return FDE_CSSSyntaxStatus::Selector;
Dan Sinclair1770c022016-03-14 14:14:16 -0400116 }
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500117 m_TextPlane.MoveNext();
118 m_ModeStack.Push(FDE_CSSSYNTAXMODE_RuleSet);
119 SwitchMode(FDE_CSSSYNTAXMODE_PropertyName);
120 return FDE_CSSSyntaxStatus::DeclOpen;
Dan Sinclair1770c022016-03-14 14:14:16 -0400121 case '/':
122 if (m_TextPlane.GetNextChar() == '*') {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500123 if (SwitchToComment() > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500124 return FDE_CSSSyntaxStatus::Selector;
Dan Sinclair1770c022016-03-14 14:14:16 -0400125 break;
126 }
127 default:
128 AppendChar(wch);
129 break;
130 }
131 break;
132 case FDE_CSSSYNTAXMODE_PropertyName:
133 switch (wch) {
134 case ':':
135 m_TextPlane.MoveNext();
136 SwitchMode(FDE_CSSSYNTAXMODE_PropertyValue);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500137 return FDE_CSSSyntaxStatus::PropertyName;
Dan Sinclair1770c022016-03-14 14:14:16 -0400138 case '}':
139 m_TextPlane.MoveNext();
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500140 if (RestoreMode())
Dan Sinclair96f482c2017-01-11 16:31:27 -0500141 return FDE_CSSSyntaxStatus::DeclClose;
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500142
143 m_eStatus = FDE_CSSSyntaxStatus::Error;
144 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400145 case '/':
146 if (m_TextPlane.GetNextChar() == '*') {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500147 if (SwitchToComment() > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500148 return FDE_CSSSyntaxStatus::PropertyName;
Dan Sinclair1770c022016-03-14 14:14:16 -0400149 break;
150 }
151 default:
152 AppendChar(wch);
153 break;
154 }
155 break;
156 case FDE_CSSSYNTAXMODE_PropertyValue:
157 switch (wch) {
158 case ';':
159 m_TextPlane.MoveNext();
160 case '}':
161 SwitchMode(FDE_CSSSYNTAXMODE_PropertyName);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500162 return FDE_CSSSyntaxStatus::PropertyValue;
Dan Sinclair1770c022016-03-14 14:14:16 -0400163 case '/':
164 if (m_TextPlane.GetNextChar() == '*') {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500165 if (SwitchToComment() > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500166 return FDE_CSSSyntaxStatus::PropertyValue;
Dan Sinclair1770c022016-03-14 14:14:16 -0400167 break;
168 }
169 default:
170 AppendChar(wch);
171 break;
172 }
173 break;
174 case FDE_CSSSYNTAXMODE_Comment:
175 if (wch == '/' && m_TextData.GetLength() > 0 &&
176 m_TextData.GetAt(m_TextData.GetLength() - 1) == '*') {
177 RestoreMode();
178 } else {
179 m_TextData.AppendChar(wch);
180 }
181 m_TextPlane.MoveNext();
182 break;
183 case FDE_CSSSYNTAXMODE_MediaType:
184 switch (wch) {
185 case ',':
186 m_TextPlane.MoveNext();
187 SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500188 if (m_iTextDatLen > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500189 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400190 break;
191 case '{': {
192 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500193 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_MediaRule) {
194 m_eStatus = FDE_CSSSyntaxStatus::Error;
195 return m_eStatus;
196 }
thestigcfb77cc2016-06-10 12:21:53 -0700197
Dan Sinclair1770c022016-03-14 14:14:16 -0400198 if (m_TextData.GetLength() > 0) {
199 SaveTextData();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500200 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400201 }
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500202 m_TextPlane.MoveNext();
203 *pMode = FDE_CSSSYNTAXMODE_RuleSet;
204 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
205 return FDE_CSSSyntaxStatus::DeclOpen;
206 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400207 case ';': {
208 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500209 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_Import) {
210 m_eStatus = FDE_CSSSyntaxStatus::Error;
211 return m_eStatus;
212 }
thestigcfb77cc2016-06-10 12:21:53 -0700213
Dan Sinclair1770c022016-03-14 14:14:16 -0400214 if (m_TextData.GetLength() > 0) {
215 SaveTextData();
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500216 if (IsImportEnabled())
Dan Sinclair96f482c2017-01-11 16:31:27 -0500217 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400218 } else {
tsepezd19e9122016-11-02 15:43:18 -0700219 bool bEnabled = IsImportEnabled();
Dan Sinclair1770c022016-03-14 14:14:16 -0400220 m_TextPlane.MoveNext();
221 m_ModeStack.Pop();
222 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
223 if (bEnabled) {
224 DisableImport();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500225 return FDE_CSSSyntaxStatus::ImportClose;
Dan Sinclair1770c022016-03-14 14:14:16 -0400226 }
227 }
228 } break;
229 case '/':
230 if (m_TextPlane.GetNextChar() == '*') {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500231 if (SwitchToComment() > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500232 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400233 break;
234 }
235 default:
236 AppendChar(wch);
237 break;
238 }
239 break;
240 case FDE_CSSSYNTAXMODE_URI: {
241 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500242 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_Import) {
243 m_eStatus = FDE_CSSSyntaxStatus::Error;
244 return m_eStatus;
245 }
thestigcfb77cc2016-06-10 12:21:53 -0700246
Dan Sinclair1770c022016-03-14 14:14:16 -0400247 if (wch <= ' ' || wch == ';') {
248 int32_t iURIStart, iURILength = m_TextData.GetLength();
npm23991522016-11-28 12:49:29 -0800249 if (iURILength > 0 && FDE_ParseCSSURI(m_TextData.GetBuffer(),
250 &iURIStart, &iURILength)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400251 m_TextData.Subtract(iURIStart, iURILength);
252 SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
npm23991522016-11-28 12:49:29 -0800253 if (IsImportEnabled())
Dan Sinclair96f482c2017-01-11 16:31:27 -0500254 return FDE_CSSSyntaxStatus::URI;
npm23991522016-11-28 12:49:29 -0800255 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400256 }
257 }
258 AppendChar(wch);
259 } break;
260 case FDE_CSSSYNTAXMODE_AtRule:
261 if (wch > ' ') {
262 AppendChar(wch);
263 } else {
264 int32_t iLen = m_TextData.GetLength();
265 const FX_WCHAR* psz = m_TextData.GetBuffer();
266 if (FXSYS_wcsncmp(L"charset", psz, iLen) == 0) {
267 SwitchMode(FDE_CSSSYNTAXMODE_Charset);
268 } else if (FXSYS_wcsncmp(L"import", psz, iLen) == 0) {
269 m_ModeStack.Push(FDE_CSSSYNTAXMODE_Import);
270 SwitchMode(FDE_CSSSYNTAXMODE_URI);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500271 if (IsImportEnabled())
Dan Sinclair96f482c2017-01-11 16:31:27 -0500272 return FDE_CSSSyntaxStatus::ImportRule;
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500273 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400274 } else if (FXSYS_wcsncmp(L"media", psz, iLen) == 0) {
275 m_ModeStack.Push(FDE_CSSSYNTAXMODE_MediaRule);
276 SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500277 return FDE_CSSSyntaxStatus::MediaRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400278 } else if (FXSYS_wcsncmp(L"font-face", psz, iLen) == 0) {
279 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500280 return FDE_CSSSyntaxStatus::FontFaceRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400281 } else if (FXSYS_wcsncmp(L"page", psz, iLen) == 0) {
282 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500283 return FDE_CSSSyntaxStatus::PageRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400284 } else {
285 SwitchMode(FDE_CSSSYNTAXMODE_UnknownRule);
286 }
287 }
288 break;
289 case FDE_CSSSYNTAXMODE_Charset:
290 if (wch == ';') {
291 m_TextPlane.MoveNext();
292 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
293 if (IsCharsetEnabled()) {
294 DisableCharset();
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500295 if (m_iTextDatLen > 0)
Dan Sinclair96f482c2017-01-11 16:31:27 -0500296 return FDE_CSSSyntaxStatus::Charset;
Dan Sinclair1770c022016-03-14 14:14:16 -0400297 }
298 } else {
299 AppendChar(wch);
300 }
301 break;
302 case FDE_CSSSYNTAXMODE_UnknownRule:
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500303 if (wch == ';')
Dan Sinclair1770c022016-03-14 14:14:16 -0400304 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
Dan Sinclair1770c022016-03-14 14:14:16 -0400305 m_TextPlane.MoveNext();
306 break;
307 default:
tsepezd19e9122016-11-02 15:43:18 -0700308 ASSERT(false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400309 break;
310 }
311 }
312 }
313 return m_eStatus;
314}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500315
tsepezd19e9122016-11-02 15:43:18 -0700316bool CFDE_CSSSyntaxParser::IsImportEnabled() const {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500317 if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0)
tsepezd19e9122016-11-02 15:43:18 -0700318 return false;
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500319 if (m_ModeStack.GetSize() > 1)
tsepezd19e9122016-11-02 15:43:18 -0700320 return false;
tsepezd19e9122016-11-02 15:43:18 -0700321 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400322}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500323
tsepezd19e9122016-11-02 15:43:18 -0700324bool CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400325 m_TextPlane.MoveNext();
326 if (m_TextData.GetLength() > 0 || wch > ' ') {
327 m_TextData.AppendChar(wch);
tsepezd19e9122016-11-02 15:43:18 -0700328 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400329 }
tsepezd19e9122016-11-02 15:43:18 -0700330 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400331}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500332
thestigcfb77cc2016-06-10 12:21:53 -0700333int32_t CFDE_CSSSyntaxParser::SaveTextData() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400334 m_iTextDatLen = m_TextData.TrimEnd();
335 m_TextData.Clear();
336 return m_iTextDatLen;
337}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500338
thestigcfb77cc2016-06-10 12:21:53 -0700339void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSYNTAXMODE eMode) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400340 m_eMode = eMode;
341 SaveTextData();
342}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500343
thestigcfb77cc2016-06-10 12:21:53 -0700344int32_t CFDE_CSSSyntaxParser::SwitchToComment() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400345 int32_t iLength = m_TextData.GetLength();
346 m_ModeStack.Push(m_eMode);
347 SwitchMode(FDE_CSSSYNTAXMODE_Comment);
348 return iLength;
349}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500350
tsepezd19e9122016-11-02 15:43:18 -0700351bool CFDE_CSSSyntaxParser::RestoreMode() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400352 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
thestigcfb77cc2016-06-10 12:21:53 -0700353 if (!pMode)
tsepezd19e9122016-11-02 15:43:18 -0700354 return false;
thestigcfb77cc2016-06-10 12:21:53 -0700355
Dan Sinclair1770c022016-03-14 14:14:16 -0400356 SwitchMode(*pMode);
357 m_ModeStack.Pop();
tsepezd19e9122016-11-02 15:43:18 -0700358 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400359}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500360
Dan Sinclair1770c022016-03-14 14:14:16 -0400361const FX_WCHAR* CFDE_CSSSyntaxParser::GetCurrentString(int32_t& iLength) const {
362 iLength = m_iTextDatLen;
363 return m_TextData.GetBuffer();
364}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500365
Dan Sinclair1770c022016-03-14 14:14:16 -0400366CFDE_CSSTextBuf::CFDE_CSSTextBuf()
tsepezd19e9122016-11-02 15:43:18 -0700367 : m_bExtBuf(false),
thestigcfb77cc2016-06-10 12:21:53 -0700368 m_pBuffer(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -0400369 m_iBufLen(0),
370 m_iDatLen(0),
371 m_iDatPos(0) {}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500372
Dan Sinclair1770c022016-03-14 14:14:16 -0400373CFDE_CSSTextBuf::~CFDE_CSSTextBuf() {
374 Reset();
375}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500376
Dan Sinclair1770c022016-03-14 14:14:16 -0400377void CFDE_CSSTextBuf::Reset() {
378 if (!m_bExtBuf) {
379 FX_Free(m_pBuffer);
thestigcfb77cc2016-06-10 12:21:53 -0700380 m_pBuffer = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400381 }
382 m_iDatPos = m_iDatLen = m_iBufLen;
383}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500384
tsepezd19e9122016-11-02 15:43:18 -0700385bool CFDE_CSSTextBuf::AttachBuffer(const FX_WCHAR* pBuffer, int32_t iBufLen) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400386 Reset();
brucedawson2f109ab2016-05-27 16:13:13 -0700387 m_pBuffer = const_cast<FX_WCHAR*>(pBuffer);
Dan Sinclair1770c022016-03-14 14:14:16 -0400388 m_iDatLen = m_iBufLen = iBufLen;
tsepezd19e9122016-11-02 15:43:18 -0700389 return m_bExtBuf = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400390}
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500391
tsepezd19e9122016-11-02 15:43:18 -0700392bool CFDE_CSSTextBuf::EstimateSize(int32_t iAllocSize) {
dsinclair43854a52016-04-27 12:26:00 -0700393 ASSERT(iAllocSize > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400394 Clear();
tsepezd19e9122016-11-02 15:43:18 -0700395 m_bExtBuf = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400396 return ExpandBuf(iAllocSize);
397}
tsepez7cda31a2016-12-07 12:10:20 -0800398
399int32_t CFDE_CSSTextBuf::LoadFromStream(
400 const CFX_RetainPtr<IFGAS_Stream>& pTxtStream,
401 int32_t iStreamOffset,
402 int32_t iMaxChars,
403 bool& bEOS) {
dsinclair43854a52016-04-27 12:26:00 -0700404 ASSERT(iStreamOffset >= 0 && iMaxChars > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400405 Clear();
tsepezd19e9122016-11-02 15:43:18 -0700406 m_bExtBuf = false;
tsepez7cda31a2016-12-07 12:10:20 -0800407 if (!ExpandBuf(iMaxChars))
Dan Sinclair1770c022016-03-14 14:14:16 -0400408 return 0;
tsepez7cda31a2016-12-07 12:10:20 -0800409
410 if (pTxtStream->GetPosition() != iStreamOffset)
Dan Sinclair1770c022016-03-14 14:14:16 -0400411 pTxtStream->Seek(FX_STREAMSEEK_Begin, iStreamOffset);
tsepez7cda31a2016-12-07 12:10:20 -0800412
Dan Sinclair1770c022016-03-14 14:14:16 -0400413 m_iDatLen = pTxtStream->ReadString(m_pBuffer, iMaxChars, bEOS);
414 return m_iDatLen;
415}
tsepez7cda31a2016-12-07 12:10:20 -0800416
tsepezd19e9122016-11-02 15:43:18 -0700417bool CFDE_CSSTextBuf::ExpandBuf(int32_t iDesiredSize) {
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500418 if (m_bExtBuf)
tsepezd19e9122016-11-02 15:43:18 -0700419 return false;
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500420 if (!m_pBuffer)
Dan Sinclair1770c022016-03-14 14:14:16 -0400421 m_pBuffer = FX_Alloc(FX_WCHAR, iDesiredSize);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500422 else if (m_iBufLen != iDesiredSize)
Dan Sinclair1770c022016-03-14 14:14:16 -0400423 m_pBuffer = FX_Realloc(FX_WCHAR, m_pBuffer, iDesiredSize);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500424 else
tsepezd19e9122016-11-02 15:43:18 -0700425 return true;
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500426
Dan Sinclair1770c022016-03-14 14:14:16 -0400427 if (!m_pBuffer) {
428 m_iBufLen = 0;
tsepezd19e9122016-11-02 15:43:18 -0700429 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400430 }
431 m_iBufLen = iDesiredSize;
tsepezd19e9122016-11-02 15:43:18 -0700432 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400433}
npm23991522016-11-28 12:49:29 -0800434
Dan Sinclair1770c022016-03-14 14:14:16 -0400435void CFDE_CSSTextBuf::Subtract(int32_t iStart, int32_t iLength) {
npm23991522016-11-28 12:49:29 -0800436 ASSERT(iStart >= 0 && iLength >= 0);
Dan Sinclair9dbc3c42017-01-18 08:58:00 -0500437
npm23991522016-11-28 12:49:29 -0800438 iLength = std::max(std::min(iLength, m_iDatLen - iStart), 0);
439 FXSYS_memmove(m_pBuffer, m_pBuffer + iStart, iLength * sizeof(FX_WCHAR));
Dan Sinclair1770c022016-03-14 14:14:16 -0400440 m_iDatLen = iLength;
441}