Bug 870022 - Part 1 - Split nsAttrValue::StringToInteger out to nsContentUtils, update usage. r=jst

This commit is contained in:
John Schoenick 2014-04-30 16:07:48 -07:00
Родитель eb0149fd3f
Коммит 02eb0d8e6f
4 изменённых файлов: 122 добавлений и 105 удалений

Просмотреть файл

@ -367,6 +367,19 @@ public:
*/
static bool IsHTMLVoid(nsIAtom* aLocalName);
enum ParseHTMLIntegerResultFlags {
eParseHTMLInteger_NoFlags = 0,
eParseHTMLInteger_IsPercent = 1 << 0,
eParseHTMLInteger_NonStandard = 1 << 1,
eParseHTMLInteger_DidNotConsumeAllInput = 1 << 2,
// Set if one or more error flags were set.
eParseHTMLInteger_Error = 1 << 3,
eParseHTMLInteger_ErrorNoValue = 1 << 4,
eParseHTMLInteger_ErrorOverflow = 1 << 5
};
static int32_t ParseHTMLInteger(const nsAString& aValue,
ParseHTMLIntegerResultFlags *aResult);
/**
* Parse a margin string of format 'top, right, bottom, left' into
* an nsIntMargin.

Просмотреть файл

@ -1443,28 +1443,27 @@ nsAttrValue::ParseSpecialIntValue(const nsAString& aString)
{
ResetIfSet();
nsresult ec;
bool strict;
bool isPercent = false;
nsAutoString tmp(aString);
int32_t originalVal = StringToInteger(aString, &strict, &ec, true, &isPercent);
nsContentUtils::ParseHTMLIntegerResultFlags result;
int32_t originalVal = nsContentUtils::ParseHTMLInteger(aString, &result);
if (NS_FAILED(ec)) {
if (result & nsContentUtils::eParseHTMLInteger_Error) {
return false;
}
bool isPercent = result & nsContentUtils::eParseHTMLInteger_IsPercent;
int32_t val = std::max(originalVal, 0);
bool nonStrict = val != originalVal ||
(result & nsContentUtils::eParseHTMLInteger_NonStandard) ||
(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput);
// % (percent)
if (isPercent || tmp.RFindChar('%') >= 0) {
isPercent = true;
}
strict = strict && (originalVal == val);
SetIntValueAndType(val,
isPercent ? ePercent : eInteger,
strict ? nullptr : &aString);
SetIntValueAndType(val, isPercent ? ePercent : eInteger,
nonStrict ? &aString : nullptr);
return true;
}
@ -1476,17 +1475,20 @@ nsAttrValue::ParseIntWithBounds(const nsAString& aString,
ResetIfSet();
nsresult ec;
bool strict;
int32_t originalVal = StringToInteger(aString, &strict, &ec);
if (NS_FAILED(ec)) {
nsContentUtils::ParseHTMLIntegerResultFlags result;
int32_t originalVal = nsContentUtils::ParseHTMLInteger(aString, &result);
if (result & nsContentUtils::eParseHTMLInteger_Error) {
return false;
}
int32_t val = std::max(originalVal, aMin);
val = std::min(val, aMax);
strict = strict && (originalVal == val);
SetIntValueAndType(val, eInteger, strict ? nullptr : &aString);
bool nonStrict = (val != originalVal) ||
(result & nsContentUtils::eParseHTMLInteger_IsPercent) ||
(result & nsContentUtils::eParseHTMLInteger_NonStandard) ||
(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput);
SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr);
return true;
}
@ -1496,14 +1498,17 @@ nsAttrValue::ParseNonNegativeIntValue(const nsAString& aString)
{
ResetIfSet();
nsresult ec;
bool strict;
int32_t originalVal = StringToInteger(aString, &strict, &ec);
if (NS_FAILED(ec) || originalVal < 0) {
nsContentUtils::ParseHTMLIntegerResultFlags result;
int32_t originalVal = nsContentUtils::ParseHTMLInteger(aString, &result);
if ((result & nsContentUtils::eParseHTMLInteger_Error) || originalVal < 0) {
return false;
}
SetIntValueAndType(originalVal, eInteger, strict ? nullptr : &aString);
bool nonStrict = (result & nsContentUtils::eParseHTMLInteger_IsPercent) ||
(result & nsContentUtils::eParseHTMLInteger_NonStandard) ||
(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput);
SetIntValueAndType(originalVal, eInteger, nonStrict ? &aString : nullptr);
return true;
}
@ -1513,14 +1518,17 @@ nsAttrValue::ParsePositiveIntValue(const nsAString& aString)
{
ResetIfSet();
nsresult ec;
bool strict;
int32_t originalVal = StringToInteger(aString, &strict, &ec);
if (NS_FAILED(ec) || originalVal <= 0) {
nsContentUtils::ParseHTMLIntegerResultFlags result;
int32_t originalVal = nsContentUtils::ParseHTMLInteger(aString, &result);
if ((result & nsContentUtils::eParseHTMLInteger_Error) || originalVal <= 0) {
return false;
}
SetIntValueAndType(originalVal, eInteger, strict ? nullptr : &aString);
bool nonStrict = (result & nsContentUtils::eParseHTMLInteger_IsPercent) ||
(result & nsContentUtils::eParseHTMLInteger_NonStandard) ||
(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput);
SetIntValueAndType(originalVal, eInteger, nonStrict ? &aString : nullptr);
return true;
}
@ -1878,78 +1886,6 @@ nsAttrValue::GetStringBuffer(const nsAString& aValue) const
return buf.forget();
}
int32_t
nsAttrValue::StringToInteger(const nsAString& aValue, bool* aStrict,
nsresult* aErrorCode,
bool aCanBePercent,
bool* aIsPercent) const
{
*aStrict = true;
*aErrorCode = NS_ERROR_ILLEGAL_VALUE;
if (aCanBePercent) {
*aIsPercent = false;
}
nsAString::const_iterator iter, end;
aValue.BeginReading(iter);
aValue.EndReading(end);
while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
*aStrict = false;
++iter;
}
if (iter == end) {
return 0;
}
bool negate = false;
if (*iter == char16_t('-')) {
negate = true;
++iter;
} else if (*iter == char16_t('+')) {
*aStrict = false;
++iter;
}
int32_t value = 0;
int32_t pValue = 0; // Previous value, used to check integer overflow
while (iter != end) {
if (*iter >= char16_t('0') && *iter <= char16_t('9')) {
value = (value * 10) + (*iter - char16_t('0'));
++iter;
// Checking for integer overflow.
if (pValue > value) {
*aStrict = false;
*aErrorCode = NS_ERROR_ILLEGAL_VALUE;
break;
} else {
pValue = value;
*aErrorCode = NS_OK;
}
} else if (aCanBePercent && *iter == char16_t('%')) {
++iter;
*aIsPercent = true;
if (iter != end) {
*aStrict = false;
break;
}
} else {
*aStrict = false;
break;
}
}
if (negate) {
value = -value;
// Checking the special case of -0.
if (!value) {
*aStrict = false;
}
}
return value;
}
size_t
nsAttrValue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{

Просмотреть файл

@ -425,13 +425,6 @@ private:
bool EnsureEmptyAtomArray();
already_AddRefed<nsStringBuffer>
GetStringBuffer(const nsAString& aValue) const;
// aStrict is set true if stringifying the return value equals with
// aValue.
int32_t StringToInteger(const nsAString& aValue,
bool* aStrict,
nsresult* aErrorCode,
bool aCanBePercent = false,
bool* aIsPercent = nullptr) const;
// Given an enum table and a particular entry in that table, return
// the actual integer value we should store.
int32_t EnumTableEntryToValue(const EnumTable* aEnumTable,

Просмотреть файл

@ -878,6 +878,81 @@ nsContentUtils::InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrV
return eAutocompleteAttrState_Invalid;
}
// Parse an integer according to HTML spec
int32_t
nsContentUtils::ParseHTMLInteger(const nsAString& aValue,
ParseHTMLIntegerResultFlags *aResult)
{
int result = eParseHTMLInteger_NoFlags;
nsAString::const_iterator iter, end;
aValue.BeginReading(iter);
aValue.EndReading(end);
while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
result |= eParseHTMLInteger_NonStandard;
++iter;
}
if (iter == end) {
result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
*aResult = (ParseHTMLIntegerResultFlags)result;
return 0;
}
bool negate = false;
if (*iter == char16_t('-')) {
negate = true;
++iter;
} else if (*iter == char16_t('+')) {
result |= eParseHTMLInteger_NonStandard;
++iter;
}
bool foundValue = false;
int32_t value = 0;
int32_t pValue = 0; // Previous value, used to check integer overflow
while (iter != end) {
if (*iter >= char16_t('0') && *iter <= char16_t('9')) {
value = (value * 10) + (*iter - char16_t('0'));
++iter;
// Checking for integer overflow.
if (pValue > value) {
result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
break;
} else {
foundValue = true;
pValue = value;
}
} else if (*iter == char16_t('%')) {
++iter;
result |= eParseHTMLInteger_IsPercent;
break;
} else {
break;
}
}
if (!foundValue) {
result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
}
if (negate) {
value = -value;
// Checking the special case of -0.
if (!value) {
result |= eParseHTMLInteger_NonStandard;
}
}
if (iter != end) {
result |= eParseHTMLInteger_DidNotConsumeAllInput;
}
*aResult = (ParseHTMLIntegerResultFlags)result;
return value;
}
#define SKIP_WHITESPACE(iter, end_iter, end_res) \
while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
++(iter); \