HTMLParserIdioms.cpp [plain text]
#include "config.h"
#include "HTMLParserIdioms.h"
#include "Decimal.h"
#include "QualifiedName.h"
#include "URL.h"
#include <limits>
#include <wtf/MathExtras.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/text/StringBuilder.h>
namespace WebCore {
template <typename CharType>
static String stripLeadingAndTrailingHTMLSpaces(String string, CharType characters, unsigned length)
{
unsigned numLeadingSpaces = 0;
unsigned numTrailingSpaces = 0;
for (; numLeadingSpaces < length; ++numLeadingSpaces) {
if (isNotHTMLSpace(characters[numLeadingSpaces]))
break;
}
if (numLeadingSpaces == length)
return string.isNull() ? string : emptyAtom.string();
for (; numTrailingSpaces < length; ++numTrailingSpaces) {
if (isNotHTMLSpace(characters[length - numTrailingSpaces - 1]))
break;
}
ASSERT(numLeadingSpaces + numTrailingSpaces < length);
if (!(numLeadingSpaces | numTrailingSpaces))
return string;
return string.substring(numLeadingSpaces, length - (numLeadingSpaces + numTrailingSpaces));
}
String stripLeadingAndTrailingHTMLSpaces(const String& string)
{
unsigned length = string.length();
if (!length)
return string.isNull() ? string : emptyAtom.string();
if (string.is8Bit())
return stripLeadingAndTrailingHTMLSpaces(string, string.characters8(), length);
return stripLeadingAndTrailingHTMLSpaces(string, string.characters16(), length);
}
String serializeForNumberType(const Decimal& number)
{
if (number.isZero()) {
return number.isNegative() ? "-0" : "0";
}
return number.toString();
}
String serializeForNumberType(double number)
{
return String::numberToStringECMAScript(number);
}
Decimal parseToDecimalForNumberType(const String& string, const Decimal& fallbackValue)
{
const UChar firstCharacter = string[0];
if (firstCharacter != '-' && firstCharacter != '.' && !isASCIIDigit(firstCharacter))
return fallbackValue;
const Decimal value = Decimal::fromString(string);
if (!value.isFinite())
return fallbackValue;
const Decimal floatMax = Decimal::fromDouble(std::numeric_limits<float>::max());
if (value < -floatMax || value > floatMax)
return fallbackValue;
return value.isZero() ? Decimal(0) : value;
}
Decimal parseToDecimalForNumberType(const String& string)
{
return parseToDecimalForNumberType(string, Decimal::nan());
}
double parseToDoubleForNumberType(const String& string, double fallbackValue)
{
UChar firstCharacter = string[0];
if (firstCharacter != '-' && firstCharacter != '.' && !isASCIIDigit(firstCharacter))
return fallbackValue;
bool valid = false;
double value = string.toDouble(&valid);
if (!valid)
return fallbackValue;
if (!std::isfinite(value))
return fallbackValue;
if (-std::numeric_limits<float>::max() > value || value > std::numeric_limits<float>::max())
return fallbackValue;
return value ? value : 0;
}
double parseToDoubleForNumberType(const String& string)
{
return parseToDoubleForNumberType(string, std::numeric_limits<double>::quiet_NaN());
}
template <typename CharacterType>
static Optional<int> parseHTMLIntegerInternal(const CharacterType* position, const CharacterType* end)
{
while (position < end && isHTMLSpace(*position))
++position;
if (position == end)
return Nullopt;
bool isNegative = false;
if (*position == '-') {
isNegative = true;
++position;
} else if (*position == '+')
++position;
if (position == end || !isASCIIDigit(*position))
return Nullopt;
constexpr int intMax = std::numeric_limits<int>::max();
constexpr int base = 10;
constexpr int maxMultiplier = intMax / base;
unsigned result = 0;
do {
int digitValue = *position - '0';
if (result > maxMultiplier || (result == maxMultiplier && digitValue > (intMax % base) + isNegative))
return Nullopt;
result = base * result + digitValue;
++position;
} while (position < end && isASCIIDigit(*position));
return isNegative ? -result : result;
}
Optional<int> parseHTMLInteger(const String& input)
{
unsigned length = input.length();
if (!length)
return Nullopt;
if (LIKELY(input.is8Bit())) {
auto* start = input.characters8();
return parseHTMLIntegerInternal(start, start + length);
}
auto* start = input.characters16();
return parseHTMLIntegerInternal(start, start + length);
}
Optional<int> parseHTMLNonNegativeInteger(const String& input)
{
Optional<int> signedValue = parseHTMLInteger(input);
if (!signedValue || signedValue.value() < 0)
return Nullopt;
return signedValue;
}
static bool threadSafeEqual(const StringImpl& a, const StringImpl& b)
{
if (&a == &b)
return true;
if (a.hash() != b.hash())
return false;
return equal(a, b);
}
bool threadSafeMatch(const QualifiedName& a, const QualifiedName& b)
{
return threadSafeEqual(*a.localName().impl(), *b.localName().impl());
}
String parseCORSSettingsAttribute(const AtomicString& value)
{
if (value.isNull())
return String();
if (equalIgnoringASCIICase(value, "use-credentials"))
return ASCIILiteral("use-credentials");
return ASCIILiteral("anonymous");
}
}