PRBool nsCSSScanner::ParseAtKeyword(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aToken) { aToken.mIdent.SetLength(0); aToken.mType = eCSSToken_AtKeyword; return GatherIdent(aErrorCode, 0, aToken.mIdent); }
PRBool nsCSSScanner::ParseAtKeyword(PRInt32 aChar, nsCSSToken& aToken) { aToken.mIdent.SetLength(0); aToken.mType = eCSSToken_AtKeyword; return GatherIdent(0, aToken.mIdent); }
PRBool nsCSSScanner::ParseIdent(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aToken) { nsString& ident = aToken.mIdent; ident.SetLength(0); if (!GatherIdent(aErrorCode, aChar, ident)) { return PR_FALSE; } nsCSSTokenType tokenType = eCSSToken_Ident; // look for functions (ie: "ident(") if (PRUnichar('(') == PRUnichar(Peek(aErrorCode))) { // this is a function definition tokenType = eCSSToken_Function; } aToken.mType = tokenType; return PR_TRUE; }
PRBool nsCSSScanner::ParseRef(PRInt32 aChar, nsCSSToken& aToken) { aToken.mIdent.SetLength(0); aToken.mType = eCSSToken_Ref; PRInt32 ch = Read(); if (ch < 0) { return PR_FALSE; } if (IsIdent(ch) || ch == CSS_ESCAPE) { // First char after the '#' is a valid ident char (or an escape), // so it makes sense to keep going if (StartsIdent(ch, Peek())) { aToken.mType = eCSSToken_ID; } return GatherIdent(ch, aToken.mIdent); } // No ident chars after the '#'. Just unread |ch| and get out of here. Pushback(ch); return PR_TRUE; }
PRBool nsCSSScanner::ParseRef(nsresult& aErrorCode, PRInt32 aChar, nsCSSToken& aToken) { aToken.mIdent.SetLength(0); aToken.mType = eCSSToken_Ref; PRInt32 ch = Read(aErrorCode); if (ch < 0) { return PR_FALSE; } if (ch > 255 || (gLexTable[ch] & IS_IDENT) || ch == CSS_ESCAPE) { // First char after the '#' is a valid ident char (or an escape), // so it makes sense to keep going if (StartsIdent(ch, Peek(aErrorCode), gLexTable)) { aToken.mType = eCSSToken_ID; } return GatherIdent(aErrorCode, ch, aToken.mIdent); } // No ident chars after the '#'. Just unread |ch| and get out of here. Unread(); return PR_TRUE; }
PRBool nsCSSScanner::ParseIdent(PRInt32 aChar, nsCSSToken& aToken) { nsString& ident = aToken.mIdent; ident.SetLength(0); if (!GatherIdent(aChar, ident)) { return PR_FALSE; } nsCSSTokenType tokenType = eCSSToken_Ident; // look for functions (ie: "ident(") if (Peek() == PRUnichar('(')) { Read(); tokenType = eCSSToken_Function; if (ident.LowerCaseEqualsLiteral("url")) { NextURL(aToken); // ignore return value, since *we* read something return PR_TRUE; } } aToken.mType = tokenType; return PR_TRUE; }
PRBool nsCSSScanner::ParseNumber(PRInt32 c, nsCSSToken& aToken) { NS_PRECONDITION(c == '.' || c == '+' || c == '-' || IsDigit(c), "Why did we get called?"); aToken.mHasSign = (c == '+' || c == '-'); // Our sign. PRInt32 sign = c == '-' ? -1 : 1; // Absolute value of the integer part of the mantissa. This is a double so // we don't run into overflow issues for consumers that only care about our // floating-point value while still being able to express the full PRInt32 // range for consumers who want integers. double intPart = 0; // Fractional part of the mantissa. This is a double so that when we convert // to float at the end we'll end up rounding to nearest float instead of // truncating down (as we would if fracPart were a float and we just // effectively lost the last several digits). double fracPart = 0; // Absolute value of the power of 10 that we should multiply by (only // relevant for numbers in scientific notation). Has to be a signed integer, // because multiplication of signed by unsigned converts the unsigned to // signed, so if we plan to actually multiply by expSign... PRInt32 exponent = 0; // Sign of the exponent. PRInt32 expSign = 1; if (aToken.mHasSign) { NS_ASSERTION(c != '.', "How did that happen?"); c = Read(); } PRBool gotDot = (c == '.'); if (!gotDot) { // Parse the integer part of the mantisssa NS_ASSERTION(IsDigit(c), "Why did we get called?"); do { intPart = 10*intPart + DecimalDigitValue(c); c = Read(); // The IsDigit check will do the right thing even if Read() returns < 0 } while (IsDigit(c)); gotDot = (c == '.') && IsDigit(Peek()); } if (gotDot) { // Parse the fractional part of the mantissa. c = Read(); NS_ASSERTION(IsDigit(c), "How did we get here?"); // Power of ten by which we need to divide our next digit float divisor = 10; do { fracPart += DecimalDigitValue(c) / divisor; divisor *= 10; c = Read(); // The IsDigit check will do the right thing even if Read() returns < 0 } while (IsDigit(c)); } PRBool gotE = PR_FALSE; if (IsSVGMode() && (c == 'e' || c == 'E')) { PRInt32 nextChar = Peek(); PRInt32 expSignChar = 0; if (nextChar == '-' || nextChar == '+') { expSignChar = Read(); nextChar = Peek(); } if (IsDigit(nextChar)) { gotE = PR_TRUE; if (expSignChar == '-') { expSign = -1; } c = Read(); NS_ASSERTION(IsDigit(c), "Peek() must have lied"); do { exponent = 10*exponent + DecimalDigitValue(c); c = Read(); // The IsDigit check will do the right thing even if Read() returns < 0 } while (IsDigit(c)); } else { if (expSignChar) { Pushback(expSignChar); } } } nsCSSTokenType type = eCSSToken_Number; // Set mIntegerValid for all cases (except %, below) because we need // it for the "2n" in :nth-child(2n). aToken.mIntegerValid = PR_FALSE; // Time to reassemble our number. float value = float(sign * (intPart + fracPart)); if (gotE) { // pow(), not powf(), because at least wince doesn't have the latter. // And explicitly cast everything to doubles to avoid issues with // overloaded pow() on Windows. value *= pow(10.0, double(expSign * exponent)); } else if (!gotDot) { // Clamp values outside of integer range. if (sign > 0) { aToken.mInteger = PRInt32(NS_MIN(intPart, double(PR_INT32_MAX))); } else { aToken.mInteger = PRInt32(NS_MAX(-intPart, double(PR_INT32_MIN))); } aToken.mIntegerValid = PR_TRUE; } nsString& ident = aToken.mIdent; ident.Truncate(); // Look at character that terminated the number if (c >= 0) { if (StartsIdent(c, Peek())) { if (!GatherIdent(c, ident)) { return PR_FALSE; } type = eCSSToken_Dimension; } else if ('%' == c) { type = eCSSToken_Percentage; value = value / 100.0f; aToken.mIntegerValid = PR_FALSE; } else { // Put back character that stopped numeric scan Pushback(c); } } aToken.mNumber = value; aToken.mType = type; return PR_TRUE; }
PRBool nsCSSScanner::ParseNumber(nsresult& aErrorCode, PRInt32 c, nsCSSToken& aToken) { nsString& ident = aToken.mIdent; ident.SetLength(0); PRBool gotDot = (c == '.') ? PR_TRUE : PR_FALSE; if (c != '+') { ident.Append(PRUnichar(c)); } // Gather up characters that make up the number PRUint8* lexTable = gLexTable; for (;;) { c = Read(aErrorCode); if (c < 0) break; if (!gotDot && (c == '.') && CheckLexTable(Peek(aErrorCode), IS_DIGIT, lexTable)) { gotDot = PR_TRUE; } else if ((c > 255) || ((lexTable[c] & IS_DIGIT) == 0)) { break; } ident.Append(PRUnichar(c)); } // Convert number to floating point nsCSSTokenType type = eCSSToken_Number; PRInt32 ec; float value = ident.ToFloat(&ec); // Look at character that terminated the number aToken.mIntegerValid = PR_FALSE; if (c >= 0) { if ((c <= 255) && ((lexTable[c] & START_IDENT) != 0)) { ident.SetLength(0); if (!GatherIdent(aErrorCode, c, ident)) { return PR_FALSE; } type = eCSSToken_Dimension; } else if ('%' == c) { type = eCSSToken_Percentage; value = value / 100.0f; ident.SetLength(0); } else { // Put back character that stopped numeric scan Unread(); if (!gotDot) { aToken.mInteger = ident.ToInteger(&ec); aToken.mIntegerValid = PR_TRUE; } ident.SetLength(0); } } else { // stream ended if (!gotDot) { aToken.mInteger = ident.ToInteger(&ec); aToken.mIntegerValid = PR_TRUE; } ident.SetLength(0); } aToken.mNumber = value; aToken.mType = type; return PR_TRUE; }