blob: f25eb4b11527dd86e4a47496af61de2951f3b404 [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()
thestigcfb77cc2016-06-10 12:21:53 -070024 : m_pStream(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040025 m_iStreamPos(0),
26 m_iPlaneSize(0),
27 m_iTextDatLen(0),
tsepez736f28a2016-03-25 14:19:51 -070028 m_dwCheck((uint32_t)-1),
Dan Sinclair1770c022016-03-14 14:14:16 -040029 m_eMode(FDE_CSSSYNTAXMODE_RuleSet),
Dan Sinclair96f482c2017-01-11 16:31:27 -050030 m_eStatus(FDE_CSSSyntaxStatus::None),
dsinclair34965452016-07-18 13:14:49 -070031 m_ModeStack(100) {}
32
Dan Sinclair1770c022016-03-14 14:14:16 -040033CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser() {
34 m_TextData.Reset();
35 m_TextPlane.Reset();
36}
dsinclair34965452016-07-18 13:14:49 -070037
tsepez7cda31a2016-12-07 12:10:20 -080038bool CFDE_CSSSyntaxParser::Init(const CFX_RetainPtr<IFGAS_Stream>& pStream,
tsepezd19e9122016-11-02 15:43:18 -070039 int32_t iCSSPlaneSize,
40 int32_t iTextDataSize,
41 bool bOnlyDeclaration) {
thestigcfb77cc2016-06-10 12:21:53 -070042 ASSERT(pStream && iCSSPlaneSize > 0 && iTextDataSize > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -040043 Reset(bOnlyDeclaration);
44 if (!m_TextData.EstimateSize(iTextDataSize)) {
tsepezd19e9122016-11-02 15:43:18 -070045 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040046 }
47 uint8_t bom[4];
48 m_pStream = pStream;
49 m_iStreamPos = m_pStream->GetBOM(bom);
50 m_iPlaneSize = iCSSPlaneSize;
tsepezd19e9122016-11-02 15:43:18 -070051 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -040052}
tsepezd19e9122016-11-02 15:43:18 -070053bool CFDE_CSSSyntaxParser::Init(const FX_WCHAR* pBuffer,
54 int32_t iBufferSize,
55 int32_t iTextDatSize,
56 bool bOnlyDeclaration) {
thestigcfb77cc2016-06-10 12:21:53 -070057 ASSERT(pBuffer && iBufferSize > 0 && iTextDatSize > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -040058 Reset(bOnlyDeclaration);
59 if (!m_TextData.EstimateSize(iTextDatSize)) {
tsepezd19e9122016-11-02 15:43:18 -070060 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -040061 }
62 return m_TextPlane.AttachBuffer(pBuffer, iBufferSize);
63}
tsepezd19e9122016-11-02 15:43:18 -070064void CFDE_CSSSyntaxParser::Reset(bool bOnlyDeclaration) {
Dan Sinclair1770c022016-03-14 14:14:16 -040065 m_TextPlane.Reset();
66 m_TextData.Reset();
thestigcfb77cc2016-06-10 12:21:53 -070067 m_pStream = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -040068 m_iStreamPos = 0;
69 m_iTextDatLen = 0;
tsepez736f28a2016-03-25 14:19:51 -070070 m_dwCheck = (uint32_t)-1;
Dan Sinclair96f482c2017-01-11 16:31:27 -050071 m_eStatus = FDE_CSSSyntaxStatus::None;
Dan Sinclair1770c022016-03-14 14:14:16 -040072 m_eMode = bOnlyDeclaration ? FDE_CSSSYNTAXMODE_PropertyName
73 : FDE_CSSSYNTAXMODE_RuleSet;
74}
Dan Sinclair96f482c2017-01-11 16:31:27 -050075FDE_CSSSyntaxStatus CFDE_CSSSyntaxParser::DoSyntaxParse() {
76 while (m_eStatus >= FDE_CSSSyntaxStatus::None) {
Dan Sinclair1770c022016-03-14 14:14:16 -040077 if (m_TextPlane.IsEOF()) {
thestigcfb77cc2016-06-10 12:21:53 -070078 if (!m_pStream) {
Dan Sinclair1770c022016-03-14 14:14:16 -040079 if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue &&
80 m_TextData.GetLength() > 0) {
81 SaveTextData();
Dan Sinclair96f482c2017-01-11 16:31:27 -050082 m_eStatus = FDE_CSSSyntaxStatus::PropertyValue;
83 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -040084 }
Dan Sinclair96f482c2017-01-11 16:31:27 -050085 m_eStatus = FDE_CSSSyntaxStatus::EOS;
86 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -040087 }
tsepezd19e9122016-11-02 15:43:18 -070088 bool bEOS;
Dan Sinclair1770c022016-03-14 14:14:16 -040089 int32_t iLen = m_TextPlane.LoadFromStream(m_pStream, m_iStreamPos,
90 m_iPlaneSize, bEOS);
91 m_iStreamPos = m_pStream->GetPosition();
92 if (iLen < 1) {
93 if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue &&
94 m_TextData.GetLength() > 0) {
95 SaveTextData();
Dan Sinclair96f482c2017-01-11 16:31:27 -050096 m_eStatus = FDE_CSSSyntaxStatus::PropertyValue;
97 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -040098 }
Dan Sinclair96f482c2017-01-11 16:31:27 -050099 m_eStatus = FDE_CSSSyntaxStatus::EOS;
100 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400101 }
102 }
103 FX_WCHAR wch;
104 while (!m_TextPlane.IsEOF()) {
105 wch = m_TextPlane.GetChar();
106 switch (m_eMode) {
107 case FDE_CSSSYNTAXMODE_RuleSet:
108 switch (wch) {
109 case '@':
110 m_TextPlane.MoveNext();
111 SwitchMode(FDE_CSSSYNTAXMODE_AtRule);
112 break;
113 case '}':
114 m_TextPlane.MoveNext();
115 if (RestoreMode()) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500116 return FDE_CSSSyntaxStatus::DeclClose;
Dan Sinclair1770c022016-03-14 14:14:16 -0400117 } else {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500118 m_eStatus = FDE_CSSSyntaxStatus::Error;
119 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400120 }
121 break;
122 case '/':
123 if (m_TextPlane.GetNextChar() == '*') {
124 m_ModeStack.Push(m_eMode);
125 SwitchMode(FDE_CSSSYNTAXMODE_Comment);
126 break;
127 }
128 default:
129 if (wch <= ' ') {
130 m_TextPlane.MoveNext();
131 } else if (FDE_IsSelectorStart(wch)) {
132 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500133 return FDE_CSSSyntaxStatus::StyleRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400134 } else {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500135 m_eStatus = FDE_CSSSyntaxStatus::Error;
136 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400137 }
138 break;
139 }
140 break;
141 case FDE_CSSSYNTAXMODE_Selector:
142 switch (wch) {
143 case ',':
144 m_TextPlane.MoveNext();
145 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
146 if (m_iTextDatLen > 0) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500147 return FDE_CSSSyntaxStatus::Selector;
Dan Sinclair1770c022016-03-14 14:14:16 -0400148 }
149 break;
150 case '{':
151 if (m_TextData.GetLength() > 0) {
152 SaveTextData();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500153 return FDE_CSSSyntaxStatus::Selector;
Dan Sinclair1770c022016-03-14 14:14:16 -0400154 } else {
155 m_TextPlane.MoveNext();
156 m_ModeStack.Push(FDE_CSSSYNTAXMODE_RuleSet);
157 SwitchMode(FDE_CSSSYNTAXMODE_PropertyName);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500158 return FDE_CSSSyntaxStatus::DeclOpen;
Dan Sinclair1770c022016-03-14 14:14:16 -0400159 }
160 break;
161 case '/':
162 if (m_TextPlane.GetNextChar() == '*') {
163 if (SwitchToComment() > 0) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500164 return FDE_CSSSyntaxStatus::Selector;
Dan Sinclair1770c022016-03-14 14:14:16 -0400165 }
166 break;
167 }
168 default:
169 AppendChar(wch);
170 break;
171 }
172 break;
173 case FDE_CSSSYNTAXMODE_PropertyName:
174 switch (wch) {
175 case ':':
176 m_TextPlane.MoveNext();
177 SwitchMode(FDE_CSSSYNTAXMODE_PropertyValue);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500178 return FDE_CSSSyntaxStatus::PropertyName;
Dan Sinclair1770c022016-03-14 14:14:16 -0400179 case '}':
180 m_TextPlane.MoveNext();
181 if (RestoreMode()) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500182 return FDE_CSSSyntaxStatus::DeclClose;
Dan Sinclair1770c022016-03-14 14:14:16 -0400183 } else {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500184 m_eStatus = FDE_CSSSyntaxStatus::Error;
185 return m_eStatus;
Dan Sinclair1770c022016-03-14 14:14:16 -0400186 }
187 break;
188 case '/':
189 if (m_TextPlane.GetNextChar() == '*') {
190 if (SwitchToComment() > 0) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500191 return FDE_CSSSyntaxStatus::PropertyName;
Dan Sinclair1770c022016-03-14 14:14:16 -0400192 }
193 break;
194 }
195 default:
196 AppendChar(wch);
197 break;
198 }
199 break;
200 case FDE_CSSSYNTAXMODE_PropertyValue:
201 switch (wch) {
202 case ';':
203 m_TextPlane.MoveNext();
204 case '}':
205 SwitchMode(FDE_CSSSYNTAXMODE_PropertyName);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500206 return FDE_CSSSyntaxStatus::PropertyValue;
Dan Sinclair1770c022016-03-14 14:14:16 -0400207 case '/':
208 if (m_TextPlane.GetNextChar() == '*') {
209 if (SwitchToComment() > 0) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500210 return FDE_CSSSyntaxStatus::PropertyValue;
Dan Sinclair1770c022016-03-14 14:14:16 -0400211 }
212 break;
213 }
214 default:
215 AppendChar(wch);
216 break;
217 }
218 break;
219 case FDE_CSSSYNTAXMODE_Comment:
220 if (wch == '/' && m_TextData.GetLength() > 0 &&
221 m_TextData.GetAt(m_TextData.GetLength() - 1) == '*') {
222 RestoreMode();
223 } else {
224 m_TextData.AppendChar(wch);
225 }
226 m_TextPlane.MoveNext();
227 break;
228 case FDE_CSSSYNTAXMODE_MediaType:
229 switch (wch) {
230 case ',':
231 m_TextPlane.MoveNext();
232 SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
233 if (m_iTextDatLen > 0) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500234 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400235 }
236 break;
237 case '{': {
238 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500239 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_MediaRule) {
240 m_eStatus = FDE_CSSSyntaxStatus::Error;
241 return m_eStatus;
242 }
thestigcfb77cc2016-06-10 12:21:53 -0700243
Dan Sinclair1770c022016-03-14 14:14:16 -0400244 if (m_TextData.GetLength() > 0) {
245 SaveTextData();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500246 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400247 } else {
248 m_TextPlane.MoveNext();
249 *pMode = FDE_CSSSYNTAXMODE_RuleSet;
250 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500251 return FDE_CSSSyntaxStatus::DeclOpen;
Dan Sinclair1770c022016-03-14 14:14:16 -0400252 }
253 } break;
254 case ';': {
255 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500256 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_Import) {
257 m_eStatus = FDE_CSSSyntaxStatus::Error;
258 return m_eStatus;
259 }
thestigcfb77cc2016-06-10 12:21:53 -0700260
Dan Sinclair1770c022016-03-14 14:14:16 -0400261 if (m_TextData.GetLength() > 0) {
262 SaveTextData();
263 if (IsImportEnabled()) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500264 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400265 }
266 } else {
tsepezd19e9122016-11-02 15:43:18 -0700267 bool bEnabled = IsImportEnabled();
Dan Sinclair1770c022016-03-14 14:14:16 -0400268 m_TextPlane.MoveNext();
269 m_ModeStack.Pop();
270 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
271 if (bEnabled) {
272 DisableImport();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500273 return FDE_CSSSyntaxStatus::ImportClose;
Dan Sinclair1770c022016-03-14 14:14:16 -0400274 }
275 }
276 } break;
277 case '/':
278 if (m_TextPlane.GetNextChar() == '*') {
279 if (SwitchToComment() > 0) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500280 return FDE_CSSSyntaxStatus::MediaType;
Dan Sinclair1770c022016-03-14 14:14:16 -0400281 }
282 break;
283 }
284 default:
285 AppendChar(wch);
286 break;
287 }
288 break;
289 case FDE_CSSSYNTAXMODE_URI: {
290 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
Dan Sinclair96f482c2017-01-11 16:31:27 -0500291 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_Import) {
292 m_eStatus = FDE_CSSSyntaxStatus::Error;
293 return m_eStatus;
294 }
thestigcfb77cc2016-06-10 12:21:53 -0700295
Dan Sinclair1770c022016-03-14 14:14:16 -0400296 if (wch <= ' ' || wch == ';') {
297 int32_t iURIStart, iURILength = m_TextData.GetLength();
npm23991522016-11-28 12:49:29 -0800298 if (iURILength > 0 && FDE_ParseCSSURI(m_TextData.GetBuffer(),
299 &iURIStart, &iURILength)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400300 m_TextData.Subtract(iURIStart, iURILength);
301 SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
npm23991522016-11-28 12:49:29 -0800302 if (IsImportEnabled())
Dan Sinclair96f482c2017-01-11 16:31:27 -0500303 return FDE_CSSSyntaxStatus::URI;
npm23991522016-11-28 12:49:29 -0800304 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400305 }
306 }
307 AppendChar(wch);
308 } break;
309 case FDE_CSSSYNTAXMODE_AtRule:
310 if (wch > ' ') {
311 AppendChar(wch);
312 } else {
313 int32_t iLen = m_TextData.GetLength();
314 const FX_WCHAR* psz = m_TextData.GetBuffer();
315 if (FXSYS_wcsncmp(L"charset", psz, iLen) == 0) {
316 SwitchMode(FDE_CSSSYNTAXMODE_Charset);
317 } else if (FXSYS_wcsncmp(L"import", psz, iLen) == 0) {
318 m_ModeStack.Push(FDE_CSSSYNTAXMODE_Import);
319 SwitchMode(FDE_CSSSYNTAXMODE_URI);
320 if (IsImportEnabled()) {
Dan Sinclair96f482c2017-01-11 16:31:27 -0500321 return FDE_CSSSyntaxStatus::ImportRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400322 } else {
323 break;
324 }
325 } else if (FXSYS_wcsncmp(L"media", psz, iLen) == 0) {
326 m_ModeStack.Push(FDE_CSSSYNTAXMODE_MediaRule);
327 SwitchMode(FDE_CSSSYNTAXMODE_MediaType);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500328 return FDE_CSSSyntaxStatus::MediaRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400329 } else if (FXSYS_wcsncmp(L"font-face", psz, iLen) == 0) {
330 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500331 return FDE_CSSSyntaxStatus::FontFaceRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400332 } else if (FXSYS_wcsncmp(L"page", psz, iLen) == 0) {
333 SwitchMode(FDE_CSSSYNTAXMODE_Selector);
Dan Sinclair96f482c2017-01-11 16:31:27 -0500334 return FDE_CSSSyntaxStatus::PageRule;
Dan Sinclair1770c022016-03-14 14:14:16 -0400335 } else {
336 SwitchMode(FDE_CSSSYNTAXMODE_UnknownRule);
337 }
338 }
339 break;
340 case FDE_CSSSYNTAXMODE_Charset:
341 if (wch == ';') {
342 m_TextPlane.MoveNext();
343 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
344 if (IsCharsetEnabled()) {
345 DisableCharset();
346 if (m_iTextDatLen > 0) {
thestigcfb77cc2016-06-10 12:21:53 -0700347 if (m_pStream) {
dsinclairfc2cdf82016-05-19 18:07:11 -0700348 uint16_t wCodePage = FX_GetCodePageFromStringW(
Dan Sinclair1770c022016-03-14 14:14:16 -0400349 m_TextData.GetBuffer(), m_iTextDatLen);
350 if (wCodePage < 0xFFFF &&
351 m_pStream->GetCodePage() != wCodePage) {
352 m_pStream->SetCodePage(wCodePage);
353 }
354 }
Dan Sinclair96f482c2017-01-11 16:31:27 -0500355 return FDE_CSSSyntaxStatus::Charset;
Dan Sinclair1770c022016-03-14 14:14:16 -0400356 }
357 }
358 } else {
359 AppendChar(wch);
360 }
361 break;
362 case FDE_CSSSYNTAXMODE_UnknownRule:
363 if (wch == ';') {
364 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet);
365 }
366 m_TextPlane.MoveNext();
367 break;
368 default:
tsepezd19e9122016-11-02 15:43:18 -0700369 ASSERT(false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400370 break;
371 }
372 }
373 }
374 return m_eStatus;
375}
tsepezd19e9122016-11-02 15:43:18 -0700376bool CFDE_CSSSyntaxParser::IsImportEnabled() const {
Dan Sinclair1770c022016-03-14 14:14:16 -0400377 if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0) {
tsepezd19e9122016-11-02 15:43:18 -0700378 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400379 }
380 if (m_ModeStack.GetSize() > 1) {
tsepezd19e9122016-11-02 15:43:18 -0700381 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400382 }
tsepezd19e9122016-11-02 15:43:18 -0700383 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400384}
tsepezd19e9122016-11-02 15:43:18 -0700385bool CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400386 m_TextPlane.MoveNext();
387 if (m_TextData.GetLength() > 0 || wch > ' ') {
388 m_TextData.AppendChar(wch);
tsepezd19e9122016-11-02 15:43:18 -0700389 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400390 }
tsepezd19e9122016-11-02 15:43:18 -0700391 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400392}
thestigcfb77cc2016-06-10 12:21:53 -0700393int32_t CFDE_CSSSyntaxParser::SaveTextData() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400394 m_iTextDatLen = m_TextData.TrimEnd();
395 m_TextData.Clear();
396 return m_iTextDatLen;
397}
thestigcfb77cc2016-06-10 12:21:53 -0700398void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSYNTAXMODE eMode) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400399 m_eMode = eMode;
400 SaveTextData();
401}
thestigcfb77cc2016-06-10 12:21:53 -0700402int32_t CFDE_CSSSyntaxParser::SwitchToComment() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400403 int32_t iLength = m_TextData.GetLength();
404 m_ModeStack.Push(m_eMode);
405 SwitchMode(FDE_CSSSYNTAXMODE_Comment);
406 return iLength;
407}
tsepezd19e9122016-11-02 15:43:18 -0700408bool CFDE_CSSSyntaxParser::RestoreMode() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400409 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement();
thestigcfb77cc2016-06-10 12:21:53 -0700410 if (!pMode)
tsepezd19e9122016-11-02 15:43:18 -0700411 return false;
thestigcfb77cc2016-06-10 12:21:53 -0700412
Dan Sinclair1770c022016-03-14 14:14:16 -0400413 SwitchMode(*pMode);
414 m_ModeStack.Pop();
tsepezd19e9122016-11-02 15:43:18 -0700415 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400416}
417const FX_WCHAR* CFDE_CSSSyntaxParser::GetCurrentString(int32_t& iLength) const {
418 iLength = m_iTextDatLen;
419 return m_TextData.GetBuffer();
420}
421CFDE_CSSTextBuf::CFDE_CSSTextBuf()
tsepezd19e9122016-11-02 15:43:18 -0700422 : m_bExtBuf(false),
thestigcfb77cc2016-06-10 12:21:53 -0700423 m_pBuffer(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -0400424 m_iBufLen(0),
425 m_iDatLen(0),
426 m_iDatPos(0) {}
427CFDE_CSSTextBuf::~CFDE_CSSTextBuf() {
428 Reset();
429}
430void CFDE_CSSTextBuf::Reset() {
431 if (!m_bExtBuf) {
432 FX_Free(m_pBuffer);
thestigcfb77cc2016-06-10 12:21:53 -0700433 m_pBuffer = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400434 }
435 m_iDatPos = m_iDatLen = m_iBufLen;
436}
tsepezd19e9122016-11-02 15:43:18 -0700437bool CFDE_CSSTextBuf::AttachBuffer(const FX_WCHAR* pBuffer, int32_t iBufLen) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400438 Reset();
brucedawson2f109ab2016-05-27 16:13:13 -0700439 m_pBuffer = const_cast<FX_WCHAR*>(pBuffer);
Dan Sinclair1770c022016-03-14 14:14:16 -0400440 m_iDatLen = m_iBufLen = iBufLen;
tsepezd19e9122016-11-02 15:43:18 -0700441 return m_bExtBuf = true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400442}
tsepezd19e9122016-11-02 15:43:18 -0700443bool CFDE_CSSTextBuf::EstimateSize(int32_t iAllocSize) {
dsinclair43854a52016-04-27 12:26:00 -0700444 ASSERT(iAllocSize > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400445 Clear();
tsepezd19e9122016-11-02 15:43:18 -0700446 m_bExtBuf = false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400447 return ExpandBuf(iAllocSize);
448}
tsepez7cda31a2016-12-07 12:10:20 -0800449
450int32_t CFDE_CSSTextBuf::LoadFromStream(
451 const CFX_RetainPtr<IFGAS_Stream>& pTxtStream,
452 int32_t iStreamOffset,
453 int32_t iMaxChars,
454 bool& bEOS) {
dsinclair43854a52016-04-27 12:26:00 -0700455 ASSERT(iStreamOffset >= 0 && iMaxChars > 0);
Dan Sinclair1770c022016-03-14 14:14:16 -0400456 Clear();
tsepezd19e9122016-11-02 15:43:18 -0700457 m_bExtBuf = false;
tsepez7cda31a2016-12-07 12:10:20 -0800458 if (!ExpandBuf(iMaxChars))
Dan Sinclair1770c022016-03-14 14:14:16 -0400459 return 0;
tsepez7cda31a2016-12-07 12:10:20 -0800460
461 if (pTxtStream->GetPosition() != iStreamOffset)
Dan Sinclair1770c022016-03-14 14:14:16 -0400462 pTxtStream->Seek(FX_STREAMSEEK_Begin, iStreamOffset);
tsepez7cda31a2016-12-07 12:10:20 -0800463
Dan Sinclair1770c022016-03-14 14:14:16 -0400464 m_iDatLen = pTxtStream->ReadString(m_pBuffer, iMaxChars, bEOS);
465 return m_iDatLen;
466}
tsepez7cda31a2016-12-07 12:10:20 -0800467
tsepezd19e9122016-11-02 15:43:18 -0700468bool CFDE_CSSTextBuf::ExpandBuf(int32_t iDesiredSize) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400469 if (m_bExtBuf) {
tsepezd19e9122016-11-02 15:43:18 -0700470 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400471 }
472 if (!m_pBuffer) {
473 m_pBuffer = FX_Alloc(FX_WCHAR, iDesiredSize);
474 } else if (m_iBufLen != iDesiredSize) {
475 m_pBuffer = FX_Realloc(FX_WCHAR, m_pBuffer, iDesiredSize);
476 } else {
tsepezd19e9122016-11-02 15:43:18 -0700477 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400478 }
479 if (!m_pBuffer) {
480 m_iBufLen = 0;
tsepezd19e9122016-11-02 15:43:18 -0700481 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400482 }
483 m_iBufLen = iDesiredSize;
tsepezd19e9122016-11-02 15:43:18 -0700484 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400485}
npm23991522016-11-28 12:49:29 -0800486
Dan Sinclair1770c022016-03-14 14:14:16 -0400487void CFDE_CSSTextBuf::Subtract(int32_t iStart, int32_t iLength) {
npm23991522016-11-28 12:49:29 -0800488 ASSERT(iStart >= 0 && iLength >= 0);
489 iLength = std::max(std::min(iLength, m_iDatLen - iStart), 0);
490 FXSYS_memmove(m_pBuffer, m_pBuffer + iStart, iLength * sizeof(FX_WCHAR));
Dan Sinclair1770c022016-03-14 14:14:16 -0400491 m_iDatLen = iLength;
492}