Bug 1700051: part 35) Reduce accessibility of `mSoftText.mDOMMapping` to `private...
[gecko.git] / layout / style / ImportScanner.cpp
blob445cc861ee186e9613fba470993949ab9794cf85
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=78: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ImportScanner.h"
8 #include "nsContentUtils.h"
10 namespace mozilla {
12 static inline bool IsWhitespace(char16_t aChar) {
13 return nsContentUtils::IsHTMLWhitespace(aChar);
16 void ImportScanner::Start() {
17 Stop();
18 mState = State::Idle;
21 void ImportScanner::EmitUrl() {
22 MOZ_ASSERT(mState == State::AfterRuleValue);
23 if (mInImportRule) {
24 // Trim trailing whitespace from an unquoted URL.
25 if (mUrlValueDelimiterClosingChar == ')') {
26 // FIXME: Add a convenience function in nsContentUtils or something?
27 mRuleValue.Trim(" \t\n\r\f", false);
29 mUrlsFound.AppendElement(std::move(mRuleValue));
31 mInImportRule = false;
32 // We try to avoid freeing the buffers here.
33 mRuleName.Truncate(0);
34 mRuleValue.Truncate(0);
35 MOZ_ASSERT(mRuleValue.IsEmpty());
38 nsTArray<nsString> ImportScanner::Stop() {
39 if (mState == State::AfterRuleValue) {
40 EmitUrl();
42 mState = State::OutsideOfStyleElement;
43 mInImportRule = false;
44 mRuleName.Truncate(0);
45 mRuleValue.Truncate(0);
46 return std::move(mUrlsFound);
49 nsTArray<nsString> ImportScanner::Scan(Span<const char16_t> aFragment) {
50 MOZ_ASSERT(ShouldScan());
52 for (char16_t c : aFragment) {
53 mState = Scan(c);
54 if (mState == State::Done) {
55 break;
59 return std::move(mUrlsFound);
62 auto ImportScanner::Scan(char16_t aChar) -> State {
63 switch (mState) {
64 case State::OutsideOfStyleElement:
65 case State::Done:
66 MOZ_ASSERT_UNREACHABLE("How?");
67 return mState;
68 case State::Idle: {
69 // TODO(emilio): Maybe worth caring about html-style comments like:
70 // <style>
71 // <!--
72 // @import url(stuff);
73 // -->
74 // </style>
75 if (IsWhitespace(aChar)) {
76 return mState;
78 if (aChar == '/') {
79 return State::MaybeAtCommentStart;
81 if (aChar == '@') {
82 MOZ_ASSERT(mRuleName.IsEmpty());
83 return State::AtRuleName;
85 return State::Done;
87 case State::MaybeAtCommentStart: {
88 return aChar == '*' ? State::AtComment : State::Done;
90 case State::AtComment: {
91 return aChar == '*' ? State::MaybeAtCommentEnd : mState;
93 case State::MaybeAtCommentEnd: {
94 return aChar == '/' ? State::Idle : State::AtComment;
96 case State::AtRuleName: {
97 if (IsAsciiAlpha(aChar)) {
98 if (mRuleName.Length() > kMaxRuleNameLength - 1) {
99 return State::Done;
101 mRuleName.Append(aChar);
102 return mState;
104 if (IsWhitespace(aChar)) {
105 mInImportRule = mRuleName.LowerCaseEqualsLiteral("import");
106 if (mInImportRule || mRuleName.LowerCaseEqualsLiteral("charset")) {
107 MOZ_ASSERT(mRuleValue.IsEmpty());
108 return State::AtRuleValue;
111 return State::Done;
113 case State::AtRuleValue: {
114 if (mRuleValue.IsEmpty()) {
115 if (IsWhitespace(aChar)) {
116 return mState;
118 if (aChar == '"' || aChar == '\'') {
119 mUrlValueDelimiterClosingChar = aChar;
120 return State::AtRuleValueDelimited;
122 if (!mInImportRule) {
123 return State::Done;
125 if (aChar == 'u' || aChar == 'U') {
126 mRuleValue.Append('u');
127 return mState;
129 return State::Done;
131 if (mRuleValue.Length() == 1) {
132 MOZ_ASSERT(mRuleValue.EqualsLiteral("u"));
133 if (aChar == 'r' || aChar == 'R') {
134 mRuleValue.Append('r');
135 return mState;
137 return State::Done;
139 if (mRuleValue.Length() == 2) {
140 MOZ_ASSERT(mRuleValue.EqualsLiteral("ur"));
141 if (aChar == 'l' || aChar == 'L') {
142 mRuleValue.Append('l');
144 return mState;
146 if (mRuleValue.Length() == 3) {
147 MOZ_ASSERT(mRuleValue.EqualsLiteral("url"));
148 if (aChar == '(') {
149 mUrlValueDelimiterClosingChar = ')';
150 mRuleValue.Truncate(0);
151 return State::AtRuleValueDelimited;
153 return State::Done;
155 MOZ_ASSERT_UNREACHABLE(
156 "How? We should find a paren or a string delimiter");
157 return State::Done;
159 case State::AtRuleValueDelimited: {
160 if (aChar == mUrlValueDelimiterClosingChar) {
161 return State::AfterRuleValue;
163 if (!mInImportRule) {
164 return mState;
166 if (mUrlValueDelimiterClosingChar == ')' && mRuleValue.IsEmpty()) {
167 if (IsWhitespace(aChar)) {
168 return mState;
170 if (aChar == '"' || aChar == '\'') {
171 // Handle url("") and url('').
172 mUrlValueDelimiterClosingChar = aChar;
173 return mState;
176 if (!mRuleValue.Append(aChar, mozilla::fallible)) {
177 mRuleValue.Truncate(0);
178 return State::Done;
180 return mState;
182 case State::AfterRuleValue: {
183 if (aChar == ';') {
184 EmitUrl();
185 return State::Idle;
187 // If there's a selector here and the import was unterminated, just give
188 // up.
189 if (aChar == '{') {
190 return State::Done;
192 return mState; // There can be all sorts of stuff here like media
193 // queries or what not.
196 MOZ_ASSERT_UNREACHABLE("Forgot to handle a state?");
197 return State::Done;
200 } // namespace mozilla