static int parseTransformParamList(const UChar*& ptr, const UChar* end, float* values, int required, int optional) { int optionalParams = 0, requiredParams = 0; if (!skipOptionalSVGSpaces(ptr, end) || *ptr != '(') return -1; ptr++; skipOptionalSVGSpaces(ptr, end); while (requiredParams < required) { if (ptr >= end || !parseNumber(ptr, end, values[requiredParams], false)) return -1; requiredParams++; if (requiredParams < required) skipOptionalSVGSpacesOrDelimiter(ptr, end); } if (!skipOptionalSVGSpaces(ptr, end)) return -1; bool delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end); if (ptr >= end) return -1; if (*ptr == ')') { // skip optionals ptr++; if (delimParsed) return -1; } else { while (optionalParams < optional) { if (ptr >= end || !parseNumber(ptr, end, values[requiredParams + optionalParams], false)) return -1; optionalParams++; if (optionalParams < optional) skipOptionalSVGSpacesOrDelimiter(ptr, end); } if (!skipOptionalSVGSpaces(ptr, end)) return -1; delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end); if (ptr >= end || *ptr != ')' || delimParsed) return -1; ptr++; } return requiredParams + optionalParams; }
static Vector<String> genericParseDelimitedString(const CharType*& ptr, const CharType* end, const char seperator) { Vector<String> values; skipOptionalSVGSpaces(ptr, end); while (ptr < end) { // Leading and trailing white space, and white space before and after semicolon separators, will be ignored. const CharType* inputStart = ptr; while (ptr < end && *ptr != seperator) // careful not to ignore whitespace inside inputs ptr++; if (ptr == inputStart) break; // walk backwards from the ; to ignore any whitespace const CharType* inputEnd = ptr - 1; while (inputStart < inputEnd && isSVGSpace(*inputEnd)) inputEnd--; values.append(String(inputStart, inputEnd - inputStart + 1)); skipOptionalSVGSpacesOrDelimiter(ptr, end, seperator); } return values; }
void SVGLengthList::parse(const String& value, SVGLengthMode mode) { clear(); ExceptionCode ec = 0; const UChar* ptr = value.deprecatedCharacters(); const UChar* end = ptr + value.length(); while (ptr < end) { const UChar* start = ptr; while (ptr < end && *ptr != ',' && !isSVGSpace(*ptr)) ptr++; if (ptr == start) break; SVGLength length(mode); String valueString(start, ptr - start); if (valueString.isEmpty()) return; length.setValueAsString(valueString, ec); if (ec) return; append(length); skipOptionalSVGSpacesOrDelimiter(ptr, end); } }
bool parseGlyphName(const String& input, HashSet<String>& values) { // FIXME: Parsing error detection is missing. values.clear(); const UChar* ptr = input.characters(); const UChar* end = ptr + input.length(); skipOptionalSVGSpaces(ptr, end); while (ptr < end) { // Leading and trailing white space, and white space before and after separators, will be ignored. const UChar* inputStart = ptr; while (ptr < end && *ptr != ',') ++ptr; if (ptr == inputStart) break; // walk backwards from the ; to ignore any whitespace const UChar* inputEnd = ptr - 1; while (inputStart < inputEnd && isSVGSpace(*inputEnd)) --inputEnd; values.add(String(inputStart, inputEnd - inputStart + 1)); skipOptionalSVGSpacesOrDelimiter(ptr, end, ','); } return true; }
Vector<String> parseDelimitedString(const String& input, const char seperator) { Vector<String> values; auto upconvertedCharacters = StringView(input).upconvertedCharacters(); const UChar* ptr = upconvertedCharacters; const UChar* end = ptr + input.length(); skipOptionalSVGSpaces(ptr, end); while (ptr < end) { // Leading and trailing white space, and white space before and after semicolon separators, will be ignored. const UChar* inputStart = ptr; while (ptr < end && *ptr != seperator) // careful not to ignore whitespace inside inputs ptr++; if (ptr == inputStart) break; // walk backwards from the ; to ignore any whitespace const UChar* inputEnd = ptr - 1; while (inputStart < inputEnd && isSVGSpace(*inputEnd)) inputEnd--; values.append(String(inputStart, inputEnd - inputStart + 1)); skipOptionalSVGSpacesOrDelimiter(ptr, end, seperator); } return values; }
void SVGStringList::parseInternal(const CharType*& ptr, const CharType* end) { const UChar delimiter = ' '; while (ptr < end) { const CharType* start = ptr; while (ptr < end && *ptr != delimiter && !isHTMLSpace<CharType>(*ptr)) ptr++; if (ptr == start) break; m_values.append(String(start, ptr - start)); skipOptionalSVGSpacesOrDelimiter(ptr, end, delimiter); } }
// only used to parse largeArcFlag and sweepFlag which must be a "0" or "1" // and might not have any whitespace/comma after it bool parseArcFlag(const UChar*& ptr, const UChar* end, bool& flag) { const UChar flagChar = *ptr++; if (flagChar == '0') flag = false; else if (flagChar == '1') flag = true; else return false; skipOptionalSVGSpacesOrDelimiter(ptr, end); return true; }
bool genericParseArcFlag(const CharType*& ptr, const CharType* end, bool& flag) { if (ptr >= end) return false; const CharType flagChar = *ptr++; if (flagChar == '0') flag = false; else if (flagChar == '1') flag = true; else return false; skipOptionalSVGSpacesOrDelimiter(ptr, end); return true; }
void SVGStringList::parse(const String& data, UChar delimiter) { // TODO : more error checking/reporting clear(); const UChar* ptr = data.deprecatedCharacters(); const UChar* end = ptr + data.length(); while (ptr < end) { const UChar* start = ptr; while (ptr < end && *ptr != delimiter && !isSVGSpace(*ptr)) ptr++; if (ptr == start) break; append(String(start, ptr - start)); skipOptionalSVGSpacesOrDelimiter(ptr, end, delimiter); } }
void SVGLengthList::parseInternal(const CharType*& ptr, const CharType* end, ExceptionState& exceptionState) { clear(); while (ptr < end) { const CharType* start = ptr; while (ptr < end && *ptr != ',' && !isHTMLSpace<CharType>(*ptr)) ptr++; if (ptr == start) break; RefPtr<SVGLength> length = SVGLength::create(m_mode); String valueString(start, ptr - start); if (valueString.isEmpty()) return; length->setValueAsString(valueString, exceptionState); if (exceptionState.hadException()) return; append(length); skipOptionalSVGSpacesOrDelimiter(ptr, end); } }
SVGParsingError SVGLengthList::parseInternal(const CharType*& ptr, const CharType* end) { const CharType* listStart = ptr; while (ptr < end) { const CharType* start = ptr; // TODO(shanmuga.m): Enable calc for SVGLengthList while (ptr < end && *ptr != ',' && !isHTMLSpace<CharType>(*ptr)) ptr++; if (ptr == start) break; String valueString(start, ptr - start); if (valueString.isEmpty()) break; SVGLength* length = SVGLength::create(m_mode); SVGParsingError lengthParseStatus = length->setValueAsString(valueString); if (lengthParseStatus != SVGParseStatus::NoError) return lengthParseStatus.offsetWith(start - listStart); append(length); skipOptionalSVGSpacesOrDelimiter(ptr, end); } return SVGParseStatus::NoError; }
static bool parseGlyphName(const CharType*& ptr, const CharType* end, HashSet<String>& values) { skipOptionalSVGSpaces(ptr, end); while (ptr < end) { // Leading and trailing white space, and white space before and after separators, will be ignored. const CharType* inputStart = ptr; while (ptr < end && *ptr != ',') ++ptr; if (ptr == inputStart) break; // walk backwards from the ; to ignore any whitespace const CharType* inputEnd = ptr - 1; while (inputStart < inputEnd && isSVGSpace(*inputEnd)) --inputEnd; values.add(String(inputStart, inputEnd - inputStart + 1)); skipOptionalSVGSpacesOrDelimiter(ptr, end, ','); } return true; }
void SVGLengthListValues::parse(const String& value, SVGLengthMode mode) { clear(); auto upconvertedCharacters = StringView(value).upconvertedCharacters(); const UChar* ptr = upconvertedCharacters; const UChar* end = ptr + value.length(); while (ptr < end) { const UChar* start = ptr; while (ptr < end && *ptr != ',' && !isSVGSpace(*ptr)) ptr++; if (ptr == start) break; SVGLengthValue length(mode); String valueString(start, ptr - start); if (valueString.isEmpty()) return; if (length.setValueAsString(valueString).hasException()) return; append(length); skipOptionalSVGSpacesOrDelimiter(ptr, end); } }
static bool genericParseNumber(const CharType*& cursor, const CharType* end, FloatType& number, WhitespaceMode mode) { FloatType integer, decimal, frac, exponent; int sign, expsign; exponent = 0; integer = 0; frac = 1; decimal = 0; sign = 1; expsign = 1; if (mode & AllowLeadingWhitespace) skipOptionalSVGSpaces(cursor, end); const CharType* ptr = cursor; // read the sign if (ptr < end && *ptr == '+') ptr++; else if (ptr < end && *ptr == '-') { ptr++; sign = -1; } if (ptr == end || ((*ptr < '0' || *ptr > '9') && *ptr != '.')) // The first character of a number must be one of [0-9+-.] return false; // read the integer part, build right-to-left const CharType* digitsStart = ptr; while (ptr < end && *ptr >= '0' && *ptr <= '9') ++ptr; // Advance to first non-digit. if (ptr != digitsStart) { const CharType* ptrScanIntPart = ptr - 1; FloatType multiplier = 1; while (ptrScanIntPart >= digitsStart) { integer += multiplier * static_cast<FloatType>(*(ptrScanIntPart--) - '0'); multiplier *= 10; } // Bail out early if this overflows. if (!isValidRange(integer)) return false; } if (ptr < end && *ptr == '.') { // read the decimals ptr++; // There must be a least one digit following the . if (ptr >= end || *ptr < '0' || *ptr > '9') return false; while (ptr < end && *ptr >= '0' && *ptr <= '9') decimal += (*(ptr++) - '0') * (frac *= static_cast<FloatType>(0.1)); } // When we get here we should have consumed either a digit for the integer // part or a fractional part (with at least one digit after the '.'.) ASSERT(digitsStart != ptr); // read the exponent part if (ptr + 1 < end && (*ptr == 'e' || *ptr == 'E') && (ptr[1] != 'x' && ptr[1] != 'm')) { ptr++; // read the sign of the exponent if (*ptr == '+') ptr++; else if (*ptr == '-') { ptr++; expsign = -1; } // There must be an exponent if (ptr >= end || *ptr < '0' || *ptr > '9') return false; while (ptr < end && *ptr >= '0' && *ptr <= '9') { exponent *= static_cast<FloatType>(10); exponent += *ptr - '0'; ptr++; } // Make sure exponent is valid. if (!isValidRange(exponent) || exponent > std::numeric_limits<FloatType>::max_exponent) return false; } number = integer + decimal; number *= sign; if (exponent) number *= static_cast<FloatType>(pow(10.0, expsign * static_cast<int>(exponent))); // Don't return Infinity() or NaN(). if (!isValidRange(number)) return false; // A valid number has been parsed. Commit cursor. cursor = ptr; if (mode & AllowTrailingWhitespace) skipOptionalSVGSpacesOrDelimiter(cursor, end); return true; }
static bool genericParseNumber(const CharType*& ptr, const CharType* end, FloatType& number, bool skip) { FloatType integer, decimal, frac, exponent; int sign, expsign; const CharType* start = ptr; exponent = 0; integer = 0; frac = 1; decimal = 0; sign = 1; expsign = 1; // read the sign if (ptr < end && *ptr == '+') ptr++; else if (ptr < end && *ptr == '-') { ptr++; sign = -1; } if (ptr == end || ((*ptr < '0' || *ptr > '9') && *ptr != '.')) // The first character of a number must be one of [0-9+-.] return false; // read the integer part, build right-to-left const CharType* ptrStartIntPart = ptr; while (ptr < end && *ptr >= '0' && *ptr <= '9') ++ptr; // Advance to first non-digit. if (ptr != ptrStartIntPart) { const CharType* ptrScanIntPart = ptr - 1; FloatType multiplier = 1; while (ptrScanIntPart >= ptrStartIntPart) { integer += multiplier * static_cast<FloatType>(*(ptrScanIntPart--) - '0'); multiplier *= 10; } // Bail out early if this overflows. if (!isValidRange(integer)) return false; } if (ptr < end && *ptr == '.') { // read the decimals ptr++; // There must be a least one digit following the . if (ptr >= end || *ptr < '0' || *ptr > '9') return false; while (ptr < end && *ptr >= '0' && *ptr <= '9') decimal += (*(ptr++) - '0') * (frac *= static_cast<FloatType>(0.1)); } // read the exponent part if (ptr != start && ptr + 1 < end && (*ptr == 'e' || *ptr == 'E') && (ptr[1] != 'x' && ptr[1] != 'm')) { ptr++; // read the sign of the exponent if (*ptr == '+') ptr++; else if (*ptr == '-') { ptr++; expsign = -1; } // There must be an exponent if (ptr >= end || *ptr < '0' || *ptr > '9') return false; while (ptr < end && *ptr >= '0' && *ptr <= '9') { exponent *= static_cast<FloatType>(10); exponent += *ptr - '0'; ptr++; } // Make sure exponent is valid. if (!isValidRange(exponent) || exponent > std::numeric_limits<FloatType>::max_exponent) return false; } number = integer + decimal; number *= sign; if (exponent) number *= static_cast<FloatType>(pow(10.0, expsign * static_cast<int>(exponent))); // Don't return Infinity() or NaN(). if (!isValidRange(number)) return false; if (start == ptr) return false; if (skip) skipOptionalSVGSpacesOrDelimiter(ptr, end); return true; }