Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cfx_csssyntaxparser.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
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/css/cfx_csssyntaxparser.h"
8
9#include "core/fxcrt/css/cfx_cssdata.h"
10#include "core/fxcrt/css/cfx_cssdeclaration.h"
11#include "core/fxcrt/fx_codepage.h"
12#include "core/fxcrt/fx_extension.h"
13
14namespace {
15
16bool IsSelectorStart(wchar_t wch) {
17 return wch == '.' || wch == '#' || wch == '*' ||
18 (isascii(wch) && isalpha(wch));
19}
20
21} // namespace
22
24
26
28 m_eMode = Mode::kPropertyName;
29}
30
32 m_Output.Clear();
33 if (m_bHasError)
34 return Status::kError;
35
36 while (!m_Input.IsEOF()) {
37 wchar_t wch = m_Input.GetChar();
38 switch (m_eMode) {
39 case Mode::kRuleSet:
40 switch (wch) {
41 case '}':
42 m_bHasError = true;
43 return Status::kError;
44 case '/':
45 if (m_Input.GetNextChar() == '*') {
46 SaveMode(Mode::kRuleSet);
47 m_eMode = Mode::kComment;
48 break;
49 }
50 [[fallthrough]];
51 default:
52 if (wch <= ' ') {
53 m_Input.MoveNext();
54 } else if (IsSelectorStart(wch)) {
55 m_eMode = Mode::kSelector;
56 return Status::kStyleRule;
57 } else {
58 m_bHasError = true;
59 return Status::kError;
60 }
61 break;
62 }
63 break;
64 case Mode::kSelector:
65 switch (wch) {
66 case ',':
67 m_Input.MoveNext();
68 if (!m_Output.IsEmpty())
69 return Status::kSelector;
70 break;
71 case '{':
72 if (!m_Output.IsEmpty())
73 return Status::kSelector;
74 m_Input.MoveNext();
75 SaveMode(Mode::kRuleSet); // Back to validate ruleset again.
76 m_eMode = Mode::kPropertyName;
77 return Status::kDeclOpen;
78 case '/':
79 if (m_Input.GetNextChar() == '*') {
80 SaveMode(Mode::kSelector);
81 m_eMode = Mode::kComment;
82 if (!m_Output.IsEmpty())
83 return Status::kSelector;
84 break;
85 }
86 [[fallthrough]];
87 default:
88 m_Output.AppendCharIfNotLeadingBlank(wch);
89 m_Input.MoveNext();
90 break;
91 }
92 break;
93 case Mode::kPropertyName:
94 switch (wch) {
95 case ':':
96 m_Input.MoveNext();
97 m_eMode = Mode::kPropertyValue;
99 case '}':
100 m_Input.MoveNext();
101 if (!RestoreMode())
102 return Status::kError;
103
104 return Status::kDeclClose;
105 case '/':
106 if (m_Input.GetNextChar() == '*') {
107 SaveMode(Mode::kPropertyName);
108 m_eMode = Mode::kComment;
109 if (!m_Output.IsEmpty())
111 break;
112 }
113 [[fallthrough]];
114 default:
115 m_Output.AppendCharIfNotLeadingBlank(wch);
116 m_Input.MoveNext();
117 break;
118 }
119 break;
120 case Mode::kPropertyValue:
121 switch (wch) {
122 case ';':
123 m_Input.MoveNext();
124 [[fallthrough]];
125 case '}':
126 m_eMode = Mode::kPropertyName;
128 case '/':
129 if (m_Input.GetNextChar() == '*') {
130 SaveMode(Mode::kPropertyValue);
131 m_eMode = Mode::kComment;
132 if (!m_Output.IsEmpty())
134 break;
135 }
136 [[fallthrough]];
137 default:
138 m_Output.AppendCharIfNotLeadingBlank(wch);
139 m_Input.MoveNext();
140 break;
141 }
142 break;
143 case Mode::kComment:
144 if (wch == '*' && m_Input.GetNextChar() == '/') {
145 if (!RestoreMode())
146 return Status::kError;
147 m_Input.MoveNext();
148 }
149 m_Input.MoveNext();
150 break;
151 }
152 }
153 if (m_eMode == Mode::kPropertyValue && !m_Output.IsEmpty())
155
156 return Status::kEOS;
157}
158
159void CFX_CSSSyntaxParser::SaveMode(Mode mode) {
160 m_ModeStack.push(mode);
161}
162
163bool CFX_CSSSyntaxParser::RestoreMode() {
164 if (m_ModeStack.empty()) {
165 m_bHasError = true;
166 return false;
167 }
168 m_eMode = m_ModeStack.top();
169 m_ModeStack.pop();
170 return true;
171}
172
173WideStringView CFX_CSSSyntaxParser::GetCurrentString() const {
174 return m_Output.GetTrailingBlankTrimmedString();
175}
CFX_CSSSyntaxParser(WideStringView str)
WideStringView GetCurrentString() const