blob: c9efb96ea1a5fe0c5821b665e2a4802ac5e28b0d [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/parser/css_parser_idioms.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer_input_stream.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/parser/input_stream_preprocessor.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
void ConsumeSingleWhitespaceIfNext(CSSTokenizerInputStream& input) {
// We check for \r\n and HTML spaces since we don't do preprocessing
UChar next = input.PeekWithoutReplacement(0);
if (next == '\r' && input.PeekWithoutReplacement(1) == '\n')
input.Advance(2);
else if (IsHTMLSpace(next))
input.Advance();
}
// https://drafts.csswg.org/css-syntax/#consume-an-escaped-code-point
UChar32 ConsumeEscape(CSSTokenizerInputStream& input) {
UChar cc = input.NextInputChar();
input.Advance();
DCHECK(!IsCSSNewLine(cc));
if (IsASCIIHexDigit(cc)) {
unsigned consumed_hex_digits = 1;
StringBuilder hex_chars;
hex_chars.Append(cc);
while (consumed_hex_digits < 6 &&
IsASCIIHexDigit(input.PeekWithoutReplacement(0))) {
cc = input.NextInputChar();
input.Advance();
hex_chars.Append(cc);
consumed_hex_digits++;
};
ConsumeSingleWhitespaceIfNext(input);
bool ok = false;
UChar32 code_point = hex_chars.ToString().HexToUIntStrict(&ok);
DCHECK(ok);
if (code_point == 0 || (0xD800 <= code_point && code_point <= 0xDFFF) ||
code_point > 0x10FFFF)
return kReplacementCharacter;
return code_point;
}
if (cc == kEndOfFileMarker)
return kReplacementCharacter;
return cc;
}
// http://www.w3.org/TR/css3-syntax/#consume-a-name
String ConsumeName(CSSTokenizerInputStream& input) {
StringBuilder result;
while (true) {
UChar cc = input.NextInputChar();
input.Advance();
if (IsNameCodePoint(cc)) {
result.Append(cc);
continue;
}
if (TwoCharsAreValidEscape(cc, input.PeekWithoutReplacement(0))) {
result.Append(ConsumeEscape(input));
continue;
}
input.PushBack(cc);
return result.ToString();
}
}
// https://drafts.csswg.org/css-syntax/#would-start-an-identifier
bool NextCharsAreIdentifier(UChar first, const CSSTokenizerInputStream& input) {
UChar second = input.PeekWithoutReplacement(0);
if (IsNameStartCodePoint(first) || TwoCharsAreValidEscape(first, second))
return true;
if (first == '-') {
return IsNameStartCodePoint(second) || second == '-' ||
TwoCharsAreValidEscape(second, input.PeekWithoutReplacement(1));
}
return false;
}
} // namespace blink