1/*
2 * Copyright (C) 2010-2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#pragma once
26
27#include <unicode/uchar.h>
28#include <wtf/Expected.h>
29#include <wtf/text/StringView.h>
30
31namespace WebCore {
32
33class Decimal;
34class QualifiedName;
35
36// Space characters as defined by the HTML specification.
37template<typename CharacterType> bool isHTMLSpace(CharacterType);
38template<typename CharacterType> bool isNotHTMLSpace(CharacterType);
39template<typename CharacterType> bool isComma(CharacterType);
40template<typename CharacterType> bool isHTMLSpaceOrComma(CharacterType);
41bool isHTMLLineBreak(UChar);
42bool isHTMLSpaceButNotLineBreak(UChar);
43
44// 2147483647 is 2^31 - 1.
45static const unsigned maxHTMLNonNegativeInteger = 2147483647;
46
47// Strip leading and trailing whitespace as defined by the HTML specification.
48WEBCORE_EXPORT String stripLeadingAndTrailingHTMLSpaces(const String&);
49
50// An implementation of the HTML specification's algorithm to convert a number to a string for number and range types.
51String serializeForNumberType(const Decimal&);
52String serializeForNumberType(double);
53
54// Convert the specified string to a decimal/double. If the conversion fails, the return value is fallback value or NaN if not specified.
55// Leading or trailing illegal characters cause failure, as does passing an empty string.
56// The double* parameter may be 0 to check if the string can be parsed without getting the result.
57Decimal parseToDecimalForNumberType(const String&);
58Decimal parseToDecimalForNumberType(const String&, const Decimal& fallbackValue);
59double parseToDoubleForNumberType(const String&);
60double parseToDoubleForNumberType(const String&, double fallbackValue);
61
62// http://www.whatwg.org/specs/web-apps/current-work/#rules-for-parsing-integers
63enum class HTMLIntegerParsingError { NegativeOverflow, PositiveOverflow, Other };
64
65WEBCORE_EXPORT Expected<int, HTMLIntegerParsingError> parseHTMLInteger(StringView);
66
67// http://www.whatwg.org/specs/web-apps/current-work/#rules-for-parsing-non-negative-integers
68WEBCORE_EXPORT Expected<unsigned, HTMLIntegerParsingError> parseHTMLNonNegativeInteger(StringView);
69
70// https://html.spec.whatwg.org/#valid-non-negative-integer
71Optional<int> parseValidHTMLNonNegativeInteger(StringView);
72
73// https://html.spec.whatwg.org/#valid-floating-point-number
74Optional<double> parseValidHTMLFloatingPointNumber(StringView);
75
76// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-floating-point-number-values
77Vector<double> parseHTMLListOfOfFloatingPointNumberValues(StringView);
78
79// https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-refresh
80bool parseMetaHTTPEquivRefresh(const StringView&, double& delay, String& url);
81
82// https://html.spec.whatwg.org/multipage/infrastructure.html#cors-settings-attribute
83String parseCORSSettingsAttribute(const AtomString&);
84
85bool threadSafeMatch(const QualifiedName&, const QualifiedName&);
86
87AtomString parseHTMLHashNameReference(StringView);
88
89// Inline implementations of some of the functions declared above.
90
91template<typename CharacterType> inline bool isHTMLSpace(CharacterType character)
92{
93 // Histogram from Apple's page load test combined with some ad hoc browsing some other test suites.
94 //
95 // 82%: 216330 non-space characters, all > U+0020
96 // 11%: 30017 plain space characters, U+0020
97 // 5%: 12099 newline characters, U+000A
98 // 2%: 5346 tab characters, U+0009
99 //
100 // No other characters seen. No U+000C or U+000D, and no other control characters.
101 // Accordingly, we check for non-spaces first, then space, then newline, then tab, then the other characters.
102
103 return character <= ' ' && (character == ' ' || character == '\n' || character == '\t' || character == '\r' || character == '\f');
104}
105
106template<typename CharacterType> inline bool isNotHTMLSpace(CharacterType character)
107{
108 return !isHTMLSpace(character);
109}
110
111inline bool isHTMLLineBreak(UChar character)
112{
113 return character <= '\r' && (character == '\n' || character == '\r');
114}
115
116template<typename CharacterType> inline bool isComma(CharacterType character)
117{
118 return character == ',';
119}
120
121template<typename CharacterType> inline bool isHTMLSpaceOrComma(CharacterType character)
122{
123 return isComma(character) || isHTMLSpace(character);
124}
125
126inline bool isHTMLSpaceButNotLineBreak(UChar character)
127{
128 return isHTMLSpace(character) && !isHTMLLineBreak(character);
129}
130
131// https://html.spec.whatwg.org/multipage/infrastructure.html#limited-to-only-non-negative-numbers-greater-than-zero
132inline unsigned limitToOnlyHTMLNonNegativeNumbersGreaterThanZero(unsigned value, unsigned defaultValue = 1)
133{
134 return (value > 0 && value <= maxHTMLNonNegativeInteger) ? value : defaultValue;
135}
136
137inline unsigned limitToOnlyHTMLNonNegativeNumbersGreaterThanZero(StringView stringValue, unsigned defaultValue = 1)
138{
139 ASSERT(defaultValue > 0);
140 ASSERT(defaultValue <= maxHTMLNonNegativeInteger);
141 auto optionalValue = parseHTMLNonNegativeInteger(stringValue);
142 unsigned value = optionalValue && optionalValue.value() ? optionalValue.value() : defaultValue;
143 ASSERT(value > 0);
144 ASSERT(value <= maxHTMLNonNegativeInteger);
145 return value;
146}
147
148// https://html.spec.whatwg.org/#reflecting-content-attributes-in-idl-attributes:idl-unsigned-long
149inline unsigned limitToOnlyHTMLNonNegative(unsigned value, unsigned defaultValue = 0)
150{
151 ASSERT(defaultValue <= maxHTMLNonNegativeInteger);
152 return value <= maxHTMLNonNegativeInteger ? value : defaultValue;
153}
154
155inline unsigned limitToOnlyHTMLNonNegative(StringView stringValue, unsigned defaultValue = 0)
156{
157 ASSERT(defaultValue <= maxHTMLNonNegativeInteger);
158 unsigned value = parseHTMLNonNegativeInteger(stringValue).value_or(defaultValue);
159 ASSERT(value <= maxHTMLNonNegativeInteger);
160 return value;
161}
162
163// https://html.spec.whatwg.org/#clamped-to-the-range
164inline unsigned clampHTMLNonNegativeIntegerToRange(StringView stringValue, unsigned min, unsigned max, unsigned defaultValue = 0)
165{
166 ASSERT(defaultValue >= min);
167 ASSERT(defaultValue <= max);
168 auto optionalValue = parseHTMLNonNegativeInteger(stringValue);
169 if (optionalValue)
170 return std::min(std::max(optionalValue.value(), min), max);
171
172 return optionalValue.error() == HTMLIntegerParsingError::PositiveOverflow ? max : defaultValue;
173}
174
175} // namespace WebCore
176