Bug 919319 - Simplify number parsing. r=dholbert

This commit is contained in:
Robert Longson 2013-10-01 08:50:40 +01:00
parent c67563512e
commit 3f45013a54
16 changed files with 352 additions and 283 deletions

View File

@ -9,13 +9,14 @@
// Keep others in (case-insensitive) order:
#include "gfxMatrix.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "mozilla/RangedPtr.h"
#include "nsComputedDOMStyle.h"
#include "nsFontMetrics.h"
#include "nsIFrame.h"
#include "nsIScriptError.h"
#include "nsLayoutUtils.h"
#include "SVGAnimationElement.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "SVGAnimatedPreserveAspectRatio.h"
#include "nsContentUtils.h"
@ -366,3 +367,191 @@ SVGContentUtils::GetViewBoxTransform(float aViewportWidth, float aViewportHeight
return gfxMatrix(a, 0.0f, 0.0f, d, e, f);
}
/**
* True if 'aCh' is a decimal digit.
*/
static inline bool
IsDigit(PRUnichar aCh)
{
return aCh >= '0' && aCh <= '9';
}
/**
* Assuming that 'aCh' is a decimal digit, return its numeric value.
*/
static inline uint32_t
DecimalDigitValue(PRUnichar aCh)
{
MOZ_ASSERT(IsDigit(aCh), "Digit expected");
return aCh - '0';
}
template<class floatType>
bool
SVGContentUtils::ParseNumber(const nsAString& aString,
floatType& aValue,
nsAString& aLeftOver)
{
mozilla::RangedPtr<const PRUnichar> iter(aString.Data(), aString.Length());
const mozilla::RangedPtr<const PRUnichar> end(aString.Data() + aString.Length(),
aString.Data(), aString.Length());
if (iter == end) {
return false;
}
// Sign of the mantissa (-1 or 1).
int32_t sign = *iter == '-' ? -1 : 1;
if (*iter == '-' || *iter == '+') {
++iter;
if (iter == end) {
return false;
}
}
// Absolute value of the integer part of the mantissa.
floatType intPart = floatType(0);
bool gotDot = *iter == '.';
if (!gotDot) {
if (!IsDigit(*iter)) {
return false;
}
do {
intPart = floatType(10) * intPart + DecimalDigitValue(*iter);
++iter;
} while (iter != end && IsDigit(*iter));
if (iter != end) {
gotDot = *iter == '.';
}
}
// Fractional part of the mantissa.
floatType fracPart = floatType(0);
if (gotDot) {
++iter;
if (iter == end || !IsDigit(*iter)) {
return false;
}
// Power of ten by which we need to divide our next digit
floatType divisor = floatType(10);
do {
fracPart += DecimalDigitValue(*iter) / divisor;
divisor *= 10;
++iter;
} while (iter != end && IsDigit(*iter));
}
bool gotE = false;
int32_t exponent = 0;
int32_t expSign;
if (iter != end && (*iter == 'e' || *iter == 'E')) {
mozilla::RangedPtr<const PRUnichar> expIter(iter);
++expIter;
if (expIter != end) {
expSign = *expIter == '-' ? -1 : 1;
if (*expIter == '-' || *expIter == '+') {
++expIter;
if (expIter != end && IsDigit(*expIter)) {
// At this point we're sure this is an exponent
// and not the start of a unit such as em or ex.
gotE = true;
}
}
}
if (gotE) {
iter = expIter;
do {
exponent = 10 * exponent + DecimalDigitValue(*iter);
++iter;
} while (iter != end && IsDigit(*iter));
}
}
// Assemble the number
aValue = sign * (intPart + fracPart);
if (gotE) {
aValue *= pow(floatType(10), floatType(expSign * exponent));
}
aLeftOver = Substring(iter.get(), end.get());
return NS_finite(aValue);
}
template bool
SVGContentUtils::ParseNumber<float>(const nsAString& aString,
float& aValue,
nsAString& aLeftOver);
template bool
SVGContentUtils::ParseNumber<double>(const nsAString& aString,
double& aValue,
nsAString& aLeftOver);
template<class floatType>
bool
SVGContentUtils::ParseNumber(const nsAString& aString,
floatType& aValue)
{
nsAutoString leftOver;
if (!ParseNumber(aString, aValue, leftOver)) {
return false;
}
return leftOver.IsEmpty();
}
template bool
SVGContentUtils::ParseNumber<float>(const nsAString& aString,
float& aValue);
template bool
SVGContentUtils::ParseNumber<double>(const nsAString& aString,
double& aValue);
bool
SVGContentUtils::ParseInteger(const nsAString& aString,
int32_t& aValue)
{
mozilla::RangedPtr<const PRUnichar> iter(aString.Data(), aString.Length());
const mozilla::RangedPtr<const PRUnichar> end(aString.Data() + aString.Length(),
aString.Data(), aString.Length());
if (iter == end) {
return false;
}
int32_t sign = *iter == '-' ? -1 : 1;
if (*iter == '-' || *iter == '+') {
++iter;
if (iter == end) {
return false;
}
}
int64_t value = 0;
do {
if (!IsDigit(*iter)) {
return false;
}
if (value <= std::numeric_limits<int32_t>::max()) {
value = 10 * value + DecimalDigitValue(*iter);
}
++iter;
} while (iter != end);
aValue = int32_t(clamped(sign * value,
int64_t(std::numeric_limits<int32_t>::min()),
int64_t(std::numeric_limits<int32_t>::max())));
return true;
}

View File

@ -132,6 +132,34 @@ public:
float aViewboxWidth, float aViewboxHeight,
const SVGPreserveAspectRatio &aPreserveAspectRatio);
/**
* Parse a number of the form:
* number ::= integer ([Ee] integer)? | [+-]? [0-9]* "." [0-9]+ ([Ee] integer)?
* Parsing fails if the number cannot be represented by a floatType.
* Anything after the number is returned in aLeftOver.
*/
template<class floatType>
static bool
ParseNumber(const nsAString& aString, floatType& aValue,
nsAString& aLeftOver);
/**
* Parse a number of the form:
* number ::= integer ([Ee] integer)? | [+-]? [0-9]* "." [0-9]+ ([Ee] integer)?
* Parsing fails if there is anything left over after the number,
* or the number cannot be represented by a floatType.
*/
template<class floatType>
static bool
ParseNumber(const nsAString& aString, floatType& aValue);
/**
* Parse an integer of the form:
* integer ::= [+-]? [0-9]+
* Parsing fails if the number cannot be represented by an int32_t.
*/
static bool
ParseInteger(const nsAString& aString, int32_t& aValue);
};
#endif

View File

@ -8,10 +8,7 @@
#include "SVGLength.h"
#include "nsSVGElement.h"
#include "mozilla/dom/SVGSVGElement.h"
#include "nsString.h"
#include "nsTextFormatter.h"
#include "prdtoa.h"
#include "nsMathUtils.h"
#include "SVGContentUtils.h"
#include <limits>
#include <algorithm>
@ -37,40 +34,22 @@ SVGLength::GetValueAsString(nsAString &aValue) const
}
bool
SVGLength::SetValueFromString(const nsAString &aValue)
SVGLength::SetValueFromString(const nsAString &aValueAsString)
{
float tmpValue;
uint16_t tmpUnit;
nsAutoString units;
float value;
NS_ConvertUTF16toUTF8 value(aValue);
const char *str = value.get();
if (!SVGContentUtils::ParseNumber(aValueAsString, value, units)) {
return false;
}
while (*str != '\0' && IsSVGWhitespace(*str)) {
++str;
uint16_t unitType = GetUnitTypeForString(units);
if (!IsValidUnitType(unitType)) {
return false;
}
char *unit;
tmpValue = float(PR_strtod(str, &unit));
if (unit != str && NS_finite(tmpValue)) {
char *theRest = unit;
while (*theRest != '\0' && !IsSVGWhitespace(*theRest)) {
++theRest;
}
tmpUnit = GetUnitTypeForString(
Substring(aValue, unit - str, theRest - unit));
if (tmpUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN) {
// SVGContentUtils::ReportToConsole
return false;
}
while (*theRest && IsSVGWhitespace(*theRest)) {
++theRest;
}
if (!*theRest) {
mValue = tmpValue;
mUnit = tmpUnit;
return true;
}
}
return false;
mValue = value;
mUnit = uint8_t(unitType);
return true;
}
inline static bool

View File

@ -49,8 +49,6 @@ SVGLengthList::SetValueFromString(const nsAString& aValue)
nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
nsAutoCString str; // outside loop to minimize memory churn
while (tokenizer.hasMoreTokens()) {
SVGLength length;
if (!length.SetValueFromString(tokenizer.nextToken())) {

View File

@ -7,11 +7,8 @@
#include "SVGNumberList.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsError.h"
#include "nsMathUtils.h"
#include "nsString.h"
#include "nsTextFormatter.h"
#include "prdtoa.h"
#include "SVGContentUtils.h"
namespace mozilla {
@ -55,17 +52,9 @@ SVGNumberList::SetValueFromString(const nsAString& aValue)
nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
nsAutoCString str; // outside loop to minimize memory churn
while (tokenizer.hasMoreTokens()) {
CopyUTF16toUTF8(tokenizer.nextToken(), str); // NS_ConvertUTF16toUTF8
const char *token = str.get();
if (*token == '\0') {
return NS_ERROR_DOM_SYNTAX_ERR; // nothing between commas
}
char *end;
float num = float(PR_strtod(token, &end));
if (*end != '\0' || !NS_finite(num)) {
float num;
if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), num)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (!temp.AppendItem(num)) {

View File

@ -6,12 +6,8 @@
#include "mozilla/Util.h"
#include "SVGPointList.h"
#include "nsError.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsMathUtils.h"
#include "nsString.h"
#include "nsTextFormatter.h"
#include "prdtoa.h"
#include "SVGContentUtils.h"
namespace mozilla {
@ -62,45 +58,30 @@ SVGPointList::SetValueFromString(const nsAString& aValue)
nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
nsAutoCString str1, str2; // outside loop to minimize memory churn
while (tokenizer.hasMoreTokens()) {
CopyUTF16toUTF8(tokenizer.nextToken(), str1);
const char *token1 = str1.get();
if (*token1 == '\0') {
float x;
nsAutoString leftOver;
if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), x, leftOver)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
char *end;
float x = float(PR_strtod(token1, &end));
if (end == token1 || !NS_finite(x)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
const char *token2;
if (*end == '-') {
float y;
if (leftOver.IsEmpty()) {
if (!tokenizer.hasMoreTokens() ||
!SVGContentUtils::ParseNumber(tokenizer.nextToken(), y)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
} else {
// It's possible for the token to be 10-30 which has
// no separator but needs to be parsed as 10, -30
token2 = end;
} else {
if (!tokenizer.hasMoreTokens()) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
CopyUTF16toUTF8(tokenizer.nextToken(), str2);
token2 = str2.get();
if (*token2 == '\0') {
if (leftOver[0] != '-' || !SVGContentUtils::ParseNumber(leftOver, y)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
}
float y = float(PR_strtod(token2, &end));
if (*end != '\0' || !NS_finite(y)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
temp.AppendItem(SVGPoint(x, y));
}
if (tokenizer.separatorAfterCurrentToken()) {

View File

@ -11,7 +11,6 @@
#include "nsSMILValue.h"
#include "nsSVGAttrTearoffTable.h"
#include "nsTextFormatter.h"
#include "prdtoa.h"
#include "SVGAngle.h"
#include "SVGAnimatedAngle.h"
#include "SVGOrientSMILType.h"
@ -94,28 +93,19 @@ GetValueString(nsAString &aValueAsString, float aValue, uint16_t aUnitType)
aValueAsString.Append(unitString);
}
static nsresult
GetValueFromString(const nsAString &aValueAsString,
float *aValue,
uint16_t *aUnitType)
static bool
GetValueFromString(const nsAString& aValueAsString,
float& aValue,
uint16_t* aUnitType)
{
NS_ConvertUTF16toUTF8 value(aValueAsString);
const char *str = value.get();
nsAutoString units;
if (IsSVGWhitespace(*str))
return NS_ERROR_DOM_SYNTAX_ERR;
char *rest;
*aValue = float(PR_strtod(str, &rest));
if (rest != str && NS_finite(*aValue)) {
*aUnitType = GetUnitTypeForString(
Substring(aValueAsString, rest - str));
if (IsValidUnitType(*aUnitType)) {
return NS_OK;
}
if (!SVGContentUtils::ParseNumber(aValueAsString, aValue, units)) {
return false;
}
return NS_ERROR_DOM_SYNTAX_ERR;
*aUnitType = GetUnitTypeForString(units);
return IsValidUnitType(*aUnitType);
}
/* static */ float
@ -258,12 +248,11 @@ nsSVGAngle::SetBaseValueString(const nsAString &aValueAsString,
nsSVGElement *aSVGElement,
bool aDoSetAttr)
{
float value = 0;
uint16_t unitType = 0;
float value;
uint16_t unitType;
nsresult rv = GetValueFromString(aValueAsString, &value, &unitType);
if (NS_FAILED(rv)) {
return rv;
if (!GetValueFromString(aValueAsString, value, &unitType)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (mBaseVal == value && mBaseValUnit == uint8_t(unitType)) {
return NS_OK;
@ -382,9 +371,8 @@ nsSVGAngle::SMILOrient::ValueFromString(const nsAString& aStr,
} else {
float value;
uint16_t unitType;
nsresult rv = GetValueFromString(aStr, &value, &unitType);
if (NS_FAILED(rv)) {
return rv;
if (!GetValueFromString(aStr, value, &unitType)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
val.mU.mOrient.mAngle = value;
val.mU.mOrient.mUnit = unitType;

View File

@ -6,10 +6,10 @@
#include "nsSVGAnimatedTransformList.h"
#include "mozilla/dom/SVGAnimatedTransformList.h"
#include "mozilla/dom/SVGAnimationElement.h"
#include "nsSMILValue.h"
#include "prdtoa.h"
#include "SVGContentUtils.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsSVGTransform.h"
#include "nsSMILValue.h"
#include "SVGContentUtils.h"
#include "SVGTransformListSMILType.h"
namespace mozilla {
@ -235,54 +235,27 @@ nsSVGAnimatedTransformList::SMILAnimatedTransformList::ParseValue(
aResult.Swap(val);
}
namespace
{
inline void
SkipWsp(nsACString::const_iterator& aIter,
const nsACString::const_iterator& aIterEnd)
{
while (aIter != aIterEnd && IsSVGWhitespace(*aIter))
++aIter;
}
} // end anonymous namespace block
int32_t
nsSVGAnimatedTransformList::SMILAnimatedTransformList::ParseParameterList(
const nsAString& aSpec,
float* aVars,
int32_t aNVars)
{
NS_ConvertUTF16toUTF8 spec(aSpec);
nsACString::const_iterator start, end;
spec.BeginReading(start);
spec.EndReading(end);
SkipWsp(start, end);
nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
tokenizer(aSpec, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
int numArgsFound = 0;
while (start != end) {
char const *arg = start.get();
char *argend;
float f = float(PR_strtod(arg, &argend));
if (arg == argend || argend > end.get() || !NS_finite(f))
return -1;
while (tokenizer.hasMoreTokens()) {
float f;
if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), f)) {
return -1;
}
if (numArgsFound < aNVars) {
aVars[numArgsFound] = f;
}
start.advance(argend - arg);
numArgsFound++;
SkipWsp(start, end);
if (*start == ',') {
++start;
SkipWsp(start, end);
}
}
return numArgsFound;
}

View File

@ -24,19 +24,19 @@ SVGAnimatedBooleanTearoffTable()
return sSVGAnimatedBooleanTearoffTable;
}
static nsresult
GetValueFromString(const nsAString &aValueAsString,
bool *aValue)
static bool
GetValueFromString(const nsAString& aValueAsString,
bool& aValue)
{
if (aValueAsString.EqualsLiteral("true")) {
*aValue = true;
return NS_OK;
aValue = true;
return true;
}
if (aValueAsString.EqualsLiteral("false")) {
*aValue = false;
return NS_OK;
aValue = false;
return true;
}
return NS_ERROR_DOM_SYNTAX_ERR;
return false;
}
static nsresult
@ -141,9 +141,8 @@ nsSVGBoolean::SMILBool::ValueFromString(const nsAString& aStr,
bool& aPreventCachingOfSandwich) const
{
bool value;
nsresult rv = GetValueFromString(aStr, &value);
if (NS_FAILED(rv)) {
return rv;
if (!GetValueFromString(aStr, value)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsSMILValue val(SMILBoolType::Singleton());

View File

@ -18,36 +18,14 @@ using namespace mozilla::dom;
static nsSVGAttrTearoffTable<nsSVGInteger, nsSVGInteger::DOMAnimatedInteger>
sSVGAnimatedIntegerTearoffTable;
static nsresult
GetValueFromString(const nsAString &aValueAsString,
int32_t *aValue)
{
NS_ConvertUTF16toUTF8 value(aValueAsString);
const char *str = value.get();
if (IsSVGWhitespace(*str))
return NS_ERROR_DOM_SYNTAX_ERR;
char *rest;
*aValue = strtol(str, &rest, 10);
if (rest == str || *rest != '\0') {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (*rest == '\0') {
return NS_OK;
}
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsresult
nsSVGInteger::SetBaseValueString(const nsAString &aValueAsString,
nsSVGElement *aSVGElement)
{
int32_t value;
nsresult rv = GetValueFromString(aValueAsString, &value);
if (NS_FAILED(rv)) {
return rv;
if (!SVGContentUtils::ParseInteger(aValueAsString, value)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
mIsBaseSet = true;
@ -133,9 +111,8 @@ nsSVGInteger::SMILInteger::ValueFromString(const nsAString& aStr,
{
int32_t val;
nsresult rv = GetValueFromString(aStr, &val);
if (NS_FAILED(rv)) {
return rv;
if (!SVGContentUtils::ParseInteger(aStr, val)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsSMILValue smilVal(SMILIntegerType::Singleton());

View File

@ -35,16 +35,8 @@ ParseIntegerOptionalInteger(const nsAString& aValue,
uint32_t i;
for (i = 0; i < 2 && tokenizer.hasMoreTokens(); ++i) {
NS_ConvertUTF16toUTF8 utf8Token(tokenizer.nextToken());
const char *token = utf8Token.get();
if (*token == '\0') {
return NS_ERROR_DOM_SYNTAX_ERR; // empty string (e.g. two commas in a row)
}
char *end;
aValues[i] = strtol(token, &end, 10);
if (*end != '\0' || !NS_finite(aValues[i])) {
return NS_ERROR_DOM_SYNTAX_ERR; // parse error
if (!SVGContentUtils::ParseInteger(tokenizer.nextToken(), aValues[i])) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
}
if (i == 1) {

View File

@ -15,7 +15,6 @@
#include "nsSVGAttrTearoffTable.h"
#include "nsSVGIntegrationUtils.h"
#include "nsTextFormatter.h"
#include "prdtoa.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -122,28 +121,17 @@ GetValueString(nsAString &aValueAsString, float aValue, uint16_t aUnitType)
aValueAsString.Append(unitString);
}
static nsresult
GetValueFromString(const nsAString &aValueAsString,
float *aValue,
uint16_t *aUnitType)
static bool
GetValueFromString(const nsAString& aValueAsString,
float& aValue,
uint16_t* aUnitType)
{
NS_ConvertUTF16toUTF8 value(aValueAsString);
const char *str = value.get();
if (IsSVGWhitespace(*str))
return NS_ERROR_DOM_SYNTAX_ERR;
char *rest;
*aValue = float(PR_strtod(str, &rest));
if (rest != str && NS_finite(*aValue)) {
*aUnitType = GetUnitTypeForString(
Substring(aValueAsString, rest - str));
if (IsValidUnitType(*aUnitType)) {
return NS_OK;
}
nsAutoString units;
if (!SVGContentUtils::ParseNumber(aValueAsString, aValue, units)) {
return false;
}
return NS_ERROR_DOM_SYNTAX_ERR;
*aUnitType = GetUnitTypeForString(units);
return IsValidUnitType(*aUnitType);
}
static float
@ -399,12 +387,11 @@ nsSVGLength2::SetBaseValueString(const nsAString &aValueAsString,
float value;
uint16_t unitType;
nsresult rv = GetValueFromString(aValueAsString, &value, &unitType);
if (NS_FAILED(rv)) {
return rv;
if (!GetValueFromString(aValueAsString, value, &unitType)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (mIsBaseSet && mBaseVal == value &&
if (mIsBaseSet && mBaseVal == float(value) &&
mSpecifiedUnitType == uint8_t(unitType)) {
return NS_OK;
}
@ -503,9 +490,8 @@ nsSVGLength2::SMILLength::ValueFromString(const nsAString& aStr,
float value;
uint16_t unitType;
nsresult rv = GetValueFromString(aStr, &value, &unitType);
if (NS_FAILED(rv)) {
return rv;
if (!GetValueFromString(aStr, value, &unitType)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsSMILValue val(nsSMILFloatType::Singleton());

View File

@ -6,12 +6,10 @@
#include "nsSVGNumber2.h"
#include "mozilla/Attributes.h"
#include "nsContentUtils.h" // NS_ENSURE_FINITE
#include "nsError.h"
#include "nsIDOMSVGNumber.h"
#include "nsSMILFloatType.h"
#include "nsSMILValue.h"
#include "nsSVGAttrTearoffTable.h"
#include "prdtoa.h"
#include "SVGContentUtils.h"
using namespace mozilla;
@ -50,30 +48,23 @@ NS_INTERFACE_MAP_END
static nsSVGAttrTearoffTable<nsSVGNumber2, nsSVGNumber2::DOMAnimatedNumber>
sSVGAnimatedNumberTearoffTable;
static nsresult
GetValueFromString(const nsAString &aValueAsString,
static bool
GetValueFromString(const nsAString& aValueAsString,
bool aPercentagesAllowed,
float *aValue)
float& aValue)
{
NS_ConvertUTF16toUTF8 value(aValueAsString);
const char *str = value.get();
nsAutoString units;
if (IsSVGWhitespace(*str))
return NS_ERROR_DOM_SYNTAX_ERR;
char *rest;
*aValue = float(PR_strtod(str, &rest));
if (rest == str || !NS_finite(*aValue)) {
return NS_ERROR_DOM_SYNTAX_ERR;
if (!SVGContentUtils::ParseNumber(aValueAsString, aValue, units)) {
return false;
}
if (*rest == '%' && aPercentagesAllowed) {
*aValue /= 100;
++rest;
if (aPercentagesAllowed && units.EqualsLiteral("%")) {
aValue /= 100;
return true;
}
if (*rest == '\0') {
return NS_OK;
}
return NS_ERROR_DOM_SYNTAX_ERR;
return units.IsEmpty();
}
nsresult
@ -82,11 +73,10 @@ nsSVGNumber2::SetBaseValueString(const nsAString &aValueAsString,
{
float val;
nsresult rv = GetValueFromString(
aValueAsString, aSVGElement->NumberAttrAllowsPercentage(mAttrEnum), &val);
if (NS_FAILED(rv)) {
return rv;
if (!GetValueFromString(aValueAsString,
aSVGElement->NumberAttrAllowsPercentage(mAttrEnum),
val)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
mBaseVal = val;
@ -172,11 +162,10 @@ nsSVGNumber2::SMILNumber::ValueFromString(const nsAString& aStr,
{
float value;
nsresult rv = GetValueFromString(
aStr, mSVGElement->NumberAttrAllowsPercentage(mVal->mAttrEnum), &value);
if (NS_FAILED(rv)) {
return rv;
if (!GetValueFromString(aStr,
mSVGElement->NumberAttrAllowsPercentage(mVal->mAttrEnum),
value)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsSMILValue val(nsSMILFloatType::Singleton());

View File

@ -6,9 +6,6 @@
#include "nsSVGNumberPair.h"
#include "nsSVGAttrTearoffTable.h"
#include "nsCharSeparatedTokenizer.h"
#include "prdtoa.h"
#include "nsError.h"
#include "nsMathUtils.h"
#include "nsSMILValue.h"
#include "SVGContentUtils.h"
#include "SVGNumberPairSMILType.h"
@ -34,16 +31,8 @@ ParseNumberOptionalNumber(const nsAString& aValue,
uint32_t i;
for (i = 0; i < 2 && tokenizer.hasMoreTokens(); ++i) {
NS_ConvertUTF16toUTF8 utf8Token(tokenizer.nextToken());
const char *token = utf8Token.get();
if (*token == '\0') {
return NS_ERROR_DOM_SYNTAX_ERR; // empty string (e.g. two commas in a row)
}
char *end;
aValues[i] = float(PR_strtod(token, &end));
if (*end != '\0' || !NS_finite(aValues[i])) {
return NS_ERROR_DOM_SYNTAX_ERR; // parse error
if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), aValues[i])) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
}
if (i == 1) {

View File

@ -4,10 +4,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsSVGViewBox.h"
#include "prdtoa.h"
#include "nsTextFormatter.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsSMILValue.h"
#include "nsTextFormatter.h"
#include "SVGContentUtils.h"
#include "SVGViewBoxSMILType.h"
@ -122,16 +121,8 @@ ToSVGViewBoxRect(const nsAString& aStr, nsSVGViewBoxRect *aViewBox)
float vals[NUM_VIEWBOX_COMPONENTS];
uint32_t i;
for (i = 0; i < NUM_VIEWBOX_COMPONENTS && tokenizer.hasMoreTokens(); ++i) {
NS_ConvertUTF16toUTF8 utf8Token(tokenizer.nextToken());
const char *token = utf8Token.get();
if (*token == '\0') {
return NS_ERROR_DOM_SYNTAX_ERR; // empty string (e.g. two commas in a row)
}
char *end;
vals[i] = float(PR_strtod(token, &end));
if (*end != '\0' || !NS_finite(vals[i])) {
return NS_ERROR_DOM_SYNTAX_ERR; // parse error
if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), vals[i])) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
}

View File

@ -97,10 +97,10 @@ function runTests()
is(blur.getAttribute("stdDeviation"), "8.5", "number-optional-number attribute");
blur.setStdDeviation(24.5, 0.5);
is(blur.stdDeviationX.baseVal, 24.5, "integer-optional-integer first baseVal");
is(blur.stdDeviationX.animVal, 24.5, "integer-optional-integer first animVal");
is(blur.stdDeviationY.baseVal, 0.5, "integer-optional-integer second baseVal");
is(blur.stdDeviationY.animVal, 0.5, "integer-optional-integer second animVal");
is(blur.stdDeviationX.baseVal, 24.5, "number-optional-number first baseVal");
is(blur.stdDeviationX.animVal, 24.5, "number-optional-number first animVal");
is(blur.stdDeviationY.baseVal, 0.5, "number-optional-number second baseVal");
is(blur.stdDeviationY.animVal, 0.5, "number-optional-number second animVal");
blur.setAttribute("stdDeviation", "");
ok(blur.getAttribute("stdDeviation") === "",
@ -144,6 +144,27 @@ function runTests()
is(filter.filterResY.baseVal, 90, "integer-optional-integer second baseVal");
is(filter.filterResY.animVal, 90, "integer-optional-integer second animVal");
// 32 bit integer range
filter.setFilterRes(-2147483648, 2147483647);
is(filter.filterResX.baseVal, -2147483648, "integer-optional-integer first baseVal");
is(filter.filterResX.animVal, -2147483648, "integer-optional-integer first animVal");
is(filter.filterResY.baseVal, 2147483647, "integer-optional-integer second baseVal");
is(filter.filterResY.animVal, 2147483647, "integer-optional-integer second animVal");
// too big, clamp
filter.setAttribute("filterRes", "-2147483649, 2147483648");
is(filter.filterResX.baseVal, -2147483648, "integer-optional-integer first baseVal");
is(filter.filterResX.animVal, -2147483648, "integer-optional-integer first animVal");
is(filter.filterResY.baseVal, 2147483647, "integer-optional-integer second baseVal");
is(filter.filterResY.animVal, 2147483647, "integer-optional-integer second animVal");
// invalid
filter.setAttribute("filterRes", "-00000000000invalid, 214748364720invalid");
is(filter.filterResX.baseVal, 0, "integer-optional-integer first baseVal");
is(filter.filterResX.animVal, 0, "integer-optional-integer first animVal");
is(filter.filterResY.baseVal, 0, "integer-optional-integer second baseVal");
is(filter.filterResY.animVal, 0, "integer-optional-integer second animVal");
filter.setAttribute("filterRes", "");
ok(filter.getAttribute("filterRes") === "",
"empty integer-optional-integer attribute");