From 0c88b8e318ff3160888bdae29b1eb513e079f3a6 Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sat, 23 Jul 2011 09:41:17 +0100 Subject: [PATCH] Bug 672055 - Use nsCharSeparatedTokenizer to parse number-optional-number attributes. r=dholbert sr=jonas --- .../content/src/SVGMotionSMILPathUtils.cpp | 2 +- content/svg/content/src/nsSVGFeatures.cpp | 3 +- content/svg/content/src/nsSVGIntegerPair.cpp | 63 +++++++++---------- content/svg/content/src/nsSVGNumberPair.cpp | 62 +++++++++--------- content/svg/content/src/nsSVGViewBox.cpp | 12 ++-- xpcom/ds/nsCharSeparatedTokenizer.h | 21 ++++++- 6 files changed, 90 insertions(+), 73 deletions(-) diff --git a/content/svg/content/src/SVGMotionSMILPathUtils.cpp b/content/svg/content/src/SVGMotionSMILPathUtils.cpp index c7c2789006e3..8fd2ecc47014 100644 --- a/content/svg/content/src/SVGMotionSMILPathUtils.cpp +++ b/content/svg/content/src/SVGMotionSMILPathUtils.cpp @@ -122,7 +122,7 @@ SVGMotionSMILPathUtils::PathGenerator:: ParseCoordinatePair(const nsAString& aCoordPairStr, float& aXVal, float& aYVal) { - nsCharSeparatedTokenizer + nsCharSeparatedTokenizerTemplate tokenizer(aCoordPairStr, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); diff --git a/content/svg/content/src/nsSVGFeatures.cpp b/content/svg/content/src/nsSVGFeatures.cpp index 4896646eafbb..8a865b5f0cd1 100644 --- a/content/svg/content/src/nsSVGFeatures.cpp +++ b/content/svg/content/src/nsSVGFeatures.cpp @@ -122,7 +122,8 @@ nsSVGFeatures::MatchesLanguagePreferences(const nsSubstring& aAttribute, { const nsDefaultStringComparator defaultComparator; - nsCharSeparatedTokenizer attributeTokenizer(aAttribute, ','); + nsCharSeparatedTokenizerTemplate + attributeTokenizer(aAttribute, ','); while (attributeTokenizer.hasMoreTokens()) { const nsSubstring &attributeToken = attributeTokenizer.nextToken(); diff --git a/content/svg/content/src/nsSVGIntegerPair.cpp b/content/svg/content/src/nsSVGIntegerPair.cpp index 8ebff9f6926f..acdecd7e8362 100644 --- a/content/svg/content/src/nsSVGIntegerPair.cpp +++ b/content/svg/content/src/nsSVGIntegerPair.cpp @@ -36,8 +36,8 @@ #include "nsSVGIntegerPair.h" #include "nsSVGUtils.h" -#include "nsTextFormatter.h" -#include "prdtoa.h" +#include "nsCharSeparatedTokenizer.h" +#include "nsDOMError.h" #ifdef MOZ_SMIL #include "nsSMILValue.h" #include "SVGIntegerPairSMILType.h" @@ -64,38 +64,37 @@ static nsresult ParseIntegerOptionalInteger(const nsAString& aValue, PRInt32 aValues[2]) { - NS_ConvertUTF16toUTF8 value(aValue); - const char *str = value.get(); - - if (IsSVGWhitespace(*str)) - return NS_ERROR_FAILURE; - - char* rest; - PRInt32 x = strtol(str, &rest, 10); - PRInt32 y = x; - - if (str == rest) { - // first value was illformed - return NS_ERROR_FAILURE; - } - - if (*rest != '\0') { - while (IsSVGWhitespace(*rest)) { - ++rest; - } - if (*rest == ',') { - ++rest; - } - - y = strtol(rest, &rest, 10); - if (*rest != '\0') { - // second value was illformed or there was trailing content - return NS_ERROR_FAILURE; - } + nsCharSeparatedTokenizerTemplate + tokenizer(aValue, ',', + nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); + if (tokenizer.firstTokenBeganWithWhitespace()) { + return NS_ERROR_DOM_SYNTAX_ERR; } - aValues[0] = x; - aValues[1] = y; + PRUint32 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_FloatIsFinite(aValues[i])) { + return NS_ERROR_DOM_SYNTAX_ERR; // parse error + } + } + if (i == 1) { + aValues[1] = aValues[0]; + } + + if (i == 0 || // Too few values. + tokenizer.hasMoreTokens() || // Too many values. + tokenizer.lastTokenEndedWithWhitespace() || // Trailing whitespace. + tokenizer.lastTokenEndedWithSeparator()) { // Trailing comma. + return NS_ERROR_DOM_SYNTAX_ERR; + } return NS_OK; } diff --git a/content/svg/content/src/nsSVGNumberPair.cpp b/content/svg/content/src/nsSVGNumberPair.cpp index 8be54fb0fd0b..f6f412698904 100644 --- a/content/svg/content/src/nsSVGNumberPair.cpp +++ b/content/svg/content/src/nsSVGNumberPair.cpp @@ -36,8 +36,9 @@ #include "nsSVGNumberPair.h" #include "nsSVGUtils.h" -#include "nsTextFormatter.h" +#include "nsCharSeparatedTokenizer.h" #include "prdtoa.h" +#include "nsDOMError.h" #ifdef MOZ_SMIL #include "nsSMILValue.h" #include "SVGNumberPairSMILType.h" @@ -64,38 +65,37 @@ static nsresult ParseNumberOptionalNumber(const nsAString& aValue, float aValues[2]) { - NS_ConvertUTF16toUTF8 value(aValue); - const char *str = value.get(); - - if (IsSVGWhitespace(*str)) - return NS_ERROR_FAILURE; - - char* rest; - float x = float(PR_strtod(str, &rest)); - float y = x; - - if (str == rest || !NS_FloatIsFinite(x)) { - // first value was illformed - return NS_ERROR_FAILURE; - } - - if (*rest != '\0') { - while (IsSVGWhitespace(*rest)) { - ++rest; - } - if (*rest == ',') { - ++rest; - } - - y = float(PR_strtod(rest, &rest)); - if (*rest != '\0' || !NS_FloatIsFinite(y)) { - // second value was illformed or there was trailing content - return NS_ERROR_FAILURE; - } + nsCharSeparatedTokenizerTemplate + tokenizer(aValue, ',', + nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); + if (tokenizer.firstTokenBeganWithWhitespace()) { + return NS_ERROR_DOM_SYNTAX_ERR; } - aValues[0] = x; - aValues[1] = y; + PRUint32 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_FloatIsFinite(aValues[i])) { + return NS_ERROR_DOM_SYNTAX_ERR; // parse error + } + } + if (i == 1) { + aValues[1] = aValues[0]; + } + + if (i == 0 || // Too few values. + tokenizer.hasMoreTokens() || // Too many values. + tokenizer.lastTokenEndedWithWhitespace() || // Trailing whitespace. + tokenizer.lastTokenEndedWithSeparator()) { // Trailing comma. + return NS_ERROR_DOM_SYNTAX_ERR; + } return NS_OK; } diff --git a/content/svg/content/src/nsSVGViewBox.cpp b/content/svg/content/src/nsSVGViewBox.cpp index aeef51c17979..180bb88d3517 100644 --- a/content/svg/content/src/nsSVGViewBox.cpp +++ b/content/svg/content/src/nsSVGViewBox.cpp @@ -142,7 +142,7 @@ nsSVGViewBox::SetBaseValue(float aX, float aY, float aWidth, float aHeight, static nsresult ToSVGViewBoxRect(const nsAString& aStr, nsSVGViewBoxRect *aViewBox) { - nsCharSeparatedTokenizer + nsCharSeparatedTokenizerTemplate tokenizer(aStr, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); float vals[NUM_VIEWBOX_COMPONENTS]; @@ -165,13 +165,13 @@ ToSVGViewBoxRect(const nsAString& aStr, nsSVGViewBoxRect *aViewBox) tokenizer.hasMoreTokens() || // Too many values. tokenizer.lastTokenEndedWithSeparator()) { // Trailing comma. return NS_ERROR_DOM_SYNTAX_ERR; - } else { - aViewBox->x = vals[0]; - aViewBox->y = vals[1]; - aViewBox->width = vals[2]; - aViewBox->height = vals[3]; } + aViewBox->x = vals[0]; + aViewBox->y = vals[1]; + aViewBox->width = vals[2]; + aViewBox->height = vals[3]; + return NS_OK; } diff --git a/xpcom/ds/nsCharSeparatedTokenizer.h b/xpcom/ds/nsCharSeparatedTokenizer.h index 6fa87357c6c1..c1e598223894 100644 --- a/xpcom/ds/nsCharSeparatedTokenizer.h +++ b/xpcom/ds/nsCharSeparatedTokenizer.h @@ -73,7 +73,9 @@ public: nsCharSeparatedTokenizerTemplate(const nsSubstring& aSource, PRUnichar aSeparatorChar, PRUint32 aFlags = 0) - : mLastTokenEndedWithSeparator(PR_FALSE), + : mFirstTokenBeganWithWhitespace(PR_FALSE), + mLastTokenEndedWithWhitespace(PR_FALSE), + mLastTokenEndedWithSeparator(PR_FALSE), mSeparatorChar(aSeparatorChar), mFlags(aFlags) { @@ -82,6 +84,7 @@ public: // Skip initial whitespace while (mIter != mEnd && IsWhitespace(*mIter)) { + mFirstTokenBeganWithWhitespace = PR_TRUE; ++mIter; } } @@ -97,11 +100,21 @@ public: return mIter != mEnd; } - PRBool lastTokenEndedWithSeparator() + PRBool firstTokenBeganWithWhitespace() const + { + return mFirstTokenBeganWithWhitespace; + } + + PRBool lastTokenEndedWithSeparator() const { return mLastTokenEndedWithSeparator; } + PRBool lastTokenEndedWithWhitespace() const + { + return mLastTokenEndedWithWhitespace; + } + /** * Returns the next token. */ @@ -123,7 +136,9 @@ public: end = mIter; // Skip whitespace after current word. + mLastTokenEndedWithWhitespace = PR_FALSE; while (mIter != mEnd && IsWhitespace(*mIter)) { + mLastTokenEndedWithWhitespace = PR_TRUE; ++mIter; } if (mFlags & SEPARATOR_OPTIONAL) { @@ -155,6 +170,8 @@ public: private: nsSubstring::const_char_iterator mIter, mEnd; + PRPackedBool mFirstTokenBeganWithWhitespace; + PRPackedBool mLastTokenEndedWithWhitespace; PRPackedBool mLastTokenEndedWithSeparator; PRUnichar mSeparatorChar; PRUint32 mFlags;