Changeset 263617 in webkit


Ignore:
Timestamp:
Jun 27, 2020 8:29:30 AM (4 years ago)
Author:
weinig@apple.com
Message:

Convert SVG related parsers over to using StringParsingBuffer
https://bugs.webkit.org/show_bug.cgi?id=213635

Reviewed by Darin Adler.

  • Adopt StringParsingBuffer across SVG code.
  • Remove UTF-16 upconversions in SVGAnimationElement, SVGFitToViewBox, SVGLengthList, SVGLengthValue, SVGNumberList, SVGParserUtilities, SVGPointList, SVGPreserveAspectRatioValue, SVGStringList, SVGTransformList, SVGTransformable and SVGViewSpec.
  • Headers.cmake:
  • WebCore.xcodeproj/project.pbxproj:

Export ParsingUtilities.h, which is now included by SVGParserUtilities.h

  • Sources.txt:

Add implementation files for SVGLengthList, SVGNumberList, SVGPointList, SVGStringList
and SVGTransformList to hold large functions are unlikely to benefit from inlining.

  • html/parser/ParsingUtilities.h:

(WebCore::skipCharactersExactly):
Add new skipCharactersExactly, which takes a c-array (NOT null-terminated) of characters
to compare against.

  • svg/SVGAngleValue.cpp:

(WebCore::parseAngleType):
(WebCore::SVGAngleValue::setValueAsString):
Adopt StringParsingBuffer.

  • svg/SVGAnimateTransformElement.cpp:

(WebCore::SVGAnimateTransformElement::parseAttribute):
Adapt to new shared parseTransformType, which now returns an Optional and default to
SVG_TRANSFORM_UNKNOWN on parse failure as the old parseTransformType did.

  • svg/SVGAnimationElement.cpp:

(WebCore::parseKeySplines):
Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters()

  • svg/SVGFitToViewBox.cpp:

(WebCore::SVGFitToViewBox::parseViewBox):
(WebCore::SVGFitToViewBox::parseViewBoxGeneric):

  • svg/SVGFitToViewBox.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters()

  • svg/SVGLengthList.cpp: Added.

(WebCore::SVGLengthList::parse):
(WebCore::SVGLengthList::valueAsString const):

  • svg/SVGLengthList.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters(). Move parse and valueAsString out of line.

  • svg/SVGLengthValue.cpp:

(WebCore::parseLengthType):
(WebCore::SVGLengthValue::construct):
(WebCore::SVGLengthValue::setValueAsString):

  • svg/SVGLengthValue.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters()

  • svg/SVGNumberList.cpp: Added.

(WebCore::SVGNumberList::parse):
(WebCore::SVGNumberList::valueAsString const):

  • svg/SVGNumberList.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters(). Move parse and valueAsString out of line.

  • svg/SVGParserUtilities.cpp:

(WebCore::genericParseNumber):
(WebCore::parseNumber):
(WebCore::genericParseArcFlag):
(WebCore::parseArcFlag):
(WebCore::parseNumberOptionalNumber):
(WebCore::parsePoint):
(WebCore::parseRect):
(WebCore::parseGlyphName):
(WebCore::parseUnicodeRange):
(WebCore::parseKerningUnicodeString):
(WebCore::genericParseFloatPoint):
(WebCore::parseFloatPoint):

  • svg/SVGParserUtilities.h:

(WebCore::isSVGSpaceOrComma):
(WebCore::skipOptionalSVGSpaces):
(WebCore::skipOptionalSVGSpacesOrDelimiter):
(WebCore::skipString): Deleted.
Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters(). Move parse and valueAsString out of line.

  • svg/SVGPathSource.h:

Add missing include, which is now needed do to removing unncessary includes in other files.

  • svg/SVGPathStringSource.cpp:

(WebCore::SVGPathStringSource::SVGPathStringSource):
(WebCore::SVGPathStringSource::hasMoreData const):
(WebCore::SVGPathStringSource::moveToNextToken):
(WebCore::nextCommandHelper):
(WebCore::SVGPathStringSource::nextCommand):
(WebCore::SVGPathStringSource::parse):
(WebCore::SVGPathStringSource::parseSVGSegmentType):
(WebCore::SVGPathStringSource::parseMoveToSegment):
(WebCore::SVGPathStringSource::parseLineToSegment):
(WebCore::SVGPathStringSource::parseLineToHorizontalSegment):
(WebCore::SVGPathStringSource::parseLineToVerticalSegment):
(WebCore::SVGPathStringSource::parseCurveToCubicSegment):
(WebCore::SVGPathStringSource::parseCurveToCubicSmoothSegment):
(WebCore::SVGPathStringSource::parseCurveToQuadraticSegment):
(WebCore::SVGPathStringSource::parseCurveToQuadraticSmoothSegment):
(WebCore::SVGPathStringSource::parseArcToSegment):
(WebCore::parseSVGSegmentTypeHelper): Deleted.

  • svg/SVGPathStringSource.h:

Adopt StringParsingBuffer. Replace existing set of unions with a single
union of StringParsingBuffers.

  • svg/SVGPointList.cpp: Added.

(WebCore::SVGPointList::parse):
(WebCore::SVGPointList::valueAsString const):

  • svg/SVGPointList.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters(). Move parse and valueAsString out of line.

  • svg/SVGPreserveAspectRatioValue.cpp:

(WebCore::SVGPreserveAspectRatioValue::SVGPreserveAspectRatioValue):
(WebCore::SVGPreserveAspectRatioValue::parse):
(WebCore::SVGPreserveAspectRatioValue::parseInternal):
(WebCore::SVGPreserveAspectRatioValue::valueAsString const):

  • svg/SVGPreserveAspectRatioValue.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters().

  • svg/SVGStringList.cpp: Added.

(WebCore::SVGStringList::parse):
(WebCore::SVGStringList::valueAsString const):

  • svg/SVGStringList.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters(). Move parse and valueAsString out of line.

  • svg/SVGTransformList.cpp: Added.

(WebCore::SVGTransformList::consolidate):
(WebCore::SVGTransformList::concatenate const):
(WebCore::SVGTransformList::parseGeneric):
(WebCore::SVGTransformList::parse):
(WebCore::SVGTransformList::valueAsString const):

  • svg/SVGTransformList.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters(). Move parse, valueAsString, consolidate and
concatenate out of line.

  • svg/SVGTransformable.cpp:

(WebCore::parseTransformParamList):
(WebCore::parseTransformValueGeneric):
(WebCore::SVGTransformable::parseTransformValue):
(WebCore::parseTransformTypeGeneric):
(WebCore::SVGTransformable::parseTransformType):
(WebCore::SVGTransformable::parseAndSkipType): Deleted.

  • svg/SVGTransformable.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters(). Unify parseTransformType implementations to all
use a single implementation and return an Optional<SVGTransformType>.

  • svg/SVGViewSpec.cpp:

(WebCore::SVGViewSpec::parseViewSpec):

  • svg/SVGViewSpec.h:

Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
StringView::upconvertedCharacters().

  • svg/SVGZoomAndPan.cpp:

(WebCore::parseZoomAndPanGeneric):
(WebCore::SVGZoomAndPan::parseZoomAndPan):

  • svg/SVGZoomAndPan.h:

Adopt StringParsingBuffer.

Location:
trunk/Source/WebCore
Files:
3 added
30 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r263601 r263617  
     12020-06-27  Sam Weinig  <weinig@apple.com>
     2
     3        Convert SVG related parsers over to using StringParsingBuffer
     4        https://bugs.webkit.org/show_bug.cgi?id=213635
     5
     6        Reviewed by Darin Adler.
     7
     8        - Adopt StringParsingBuffer across SVG code.
     9        - Remove UTF-16 upconversions in SVGAnimationElement, SVGFitToViewBox, SVGLengthList,
     10          SVGLengthValue, SVGNumberList, SVGParserUtilities, SVGPointList, SVGPreserveAspectRatioValue,
     11          SVGStringList, SVGTransformList, SVGTransformable and SVGViewSpec.
     12
     13        * Headers.cmake:
     14        * WebCore.xcodeproj/project.pbxproj:
     15        Export ParsingUtilities.h, which is now included by SVGParserUtilities.h
     16       
     17        * Sources.txt:
     18        Add implementation files for SVGLengthList, SVGNumberList, SVGPointList, SVGStringList
     19        and SVGTransformList to hold large functions are unlikely to benefit from inlining.
     20       
     21        * html/parser/ParsingUtilities.h:
     22        (WebCore::skipCharactersExactly):
     23        Add new skipCharactersExactly, which takes a c-array (NOT null-terminated) of characters
     24        to compare against.
     25
     26        * svg/SVGAngleValue.cpp:
     27        (WebCore::parseAngleType):
     28        (WebCore::SVGAngleValue::setValueAsString):
     29        Adopt StringParsingBuffer.
     30
     31        * svg/SVGAnimateTransformElement.cpp:
     32        (WebCore::SVGAnimateTransformElement::parseAttribute):
     33        Adapt to new shared parseTransformType, which now returns an Optional and default to
     34        SVG_TRANSFORM_UNKNOWN on parse failure as the old parseTransformType did.
     35       
     36        * svg/SVGAnimationElement.cpp:
     37        (WebCore::parseKeySplines):
     38        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     39        StringView::upconvertedCharacters()
     40       
     41        * svg/SVGFitToViewBox.cpp:
     42        (WebCore::SVGFitToViewBox::parseViewBox):
     43        (WebCore::SVGFitToViewBox::parseViewBoxGeneric):
     44        * svg/SVGFitToViewBox.h:
     45        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     46        StringView::upconvertedCharacters()
     47
     48        * svg/SVGLengthList.cpp: Added.
     49        (WebCore::SVGLengthList::parse):
     50        (WebCore::SVGLengthList::valueAsString const):
     51        * svg/SVGLengthList.h:
     52        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     53        StringView::upconvertedCharacters(). Move parse and valueAsString out of line.
     54
     55        * svg/SVGLengthValue.cpp:
     56        (WebCore::parseLengthType):
     57        (WebCore::SVGLengthValue::construct):
     58        (WebCore::SVGLengthValue::setValueAsString):
     59        * svg/SVGLengthValue.h:
     60        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     61        StringView::upconvertedCharacters()
     62
     63        * svg/SVGNumberList.cpp: Added.
     64        (WebCore::SVGNumberList::parse):
     65        (WebCore::SVGNumberList::valueAsString const):
     66        * svg/SVGNumberList.h:
     67        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     68        StringView::upconvertedCharacters(). Move parse and valueAsString out of line.
     69
     70        * svg/SVGParserUtilities.cpp:
     71        (WebCore::genericParseNumber):
     72        (WebCore::parseNumber):
     73        (WebCore::genericParseArcFlag):
     74        (WebCore::parseArcFlag):
     75        (WebCore::parseNumberOptionalNumber):
     76        (WebCore::parsePoint):
     77        (WebCore::parseRect):
     78        (WebCore::parseGlyphName):
     79        (WebCore::parseUnicodeRange):
     80        (WebCore::parseKerningUnicodeString):
     81        (WebCore::genericParseFloatPoint):
     82        (WebCore::parseFloatPoint):
     83        * svg/SVGParserUtilities.h:
     84        (WebCore::isSVGSpaceOrComma):
     85        (WebCore::skipOptionalSVGSpaces):
     86        (WebCore::skipOptionalSVGSpacesOrDelimiter):
     87        (WebCore::skipString): Deleted.
     88        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     89        StringView::upconvertedCharacters(). Move parse and valueAsString out of line.
     90
     91        * svg/SVGPathSource.h:
     92        Add missing include, which is now needed do to removing unncessary includes in other files.
     93
     94        * svg/SVGPathStringSource.cpp:
     95        (WebCore::SVGPathStringSource::SVGPathStringSource):
     96        (WebCore::SVGPathStringSource::hasMoreData const):
     97        (WebCore::SVGPathStringSource::moveToNextToken):
     98        (WebCore::nextCommandHelper):
     99        (WebCore::SVGPathStringSource::nextCommand):
     100        (WebCore::SVGPathStringSource::parse):
     101        (WebCore::SVGPathStringSource::parseSVGSegmentType):
     102        (WebCore::SVGPathStringSource::parseMoveToSegment):
     103        (WebCore::SVGPathStringSource::parseLineToSegment):
     104        (WebCore::SVGPathStringSource::parseLineToHorizontalSegment):
     105        (WebCore::SVGPathStringSource::parseLineToVerticalSegment):
     106        (WebCore::SVGPathStringSource::parseCurveToCubicSegment):
     107        (WebCore::SVGPathStringSource::parseCurveToCubicSmoothSegment):
     108        (WebCore::SVGPathStringSource::parseCurveToQuadraticSegment):
     109        (WebCore::SVGPathStringSource::parseCurveToQuadraticSmoothSegment):
     110        (WebCore::SVGPathStringSource::parseArcToSegment):
     111        (WebCore::parseSVGSegmentTypeHelper): Deleted.
     112        * svg/SVGPathStringSource.h:
     113        Adopt StringParsingBuffer. Replace existing set of unions with a single
     114        union of StringParsingBuffers.
     115   
     116        * svg/SVGPointList.cpp: Added.
     117        (WebCore::SVGPointList::parse):
     118        (WebCore::SVGPointList::valueAsString const):
     119        * svg/SVGPointList.h:
     120        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     121        StringView::upconvertedCharacters(). Move parse and valueAsString out of line.
     122
     123        * svg/SVGPreserveAspectRatioValue.cpp:
     124        (WebCore::SVGPreserveAspectRatioValue::SVGPreserveAspectRatioValue):
     125        (WebCore::SVGPreserveAspectRatioValue::parse):
     126        (WebCore::SVGPreserveAspectRatioValue::parseInternal):
     127        (WebCore::SVGPreserveAspectRatioValue::valueAsString const):
     128        * svg/SVGPreserveAspectRatioValue.h:
     129        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     130        StringView::upconvertedCharacters().
     131
     132        * svg/SVGStringList.cpp: Added.
     133        (WebCore::SVGStringList::parse):
     134        (WebCore::SVGStringList::valueAsString const):
     135        * svg/SVGStringList.h:
     136        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     137        StringView::upconvertedCharacters(). Move parse and valueAsString out of line.
     138
     139        * svg/SVGTransformList.cpp: Added.
     140        (WebCore::SVGTransformList::consolidate):
     141        (WebCore::SVGTransformList::concatenate const):
     142        (WebCore::SVGTransformList::parseGeneric):
     143        (WebCore::SVGTransformList::parse):
     144        (WebCore::SVGTransformList::valueAsString const):
     145        * svg/SVGTransformList.h:
     146        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     147        StringView::upconvertedCharacters(). Move parse, valueAsString, consolidate and
     148        concatenate out of line.
     149
     150        * svg/SVGTransformable.cpp:
     151        (WebCore::parseTransformParamList):
     152        (WebCore::parseTransformValueGeneric):
     153        (WebCore::SVGTransformable::parseTransformValue):
     154        (WebCore::parseTransformTypeGeneric):
     155        (WebCore::SVGTransformable::parseTransformType):
     156        (WebCore::SVGTransformable::parseAndSkipType): Deleted.
     157        * svg/SVGTransformable.h:
     158        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     159        StringView::upconvertedCharacters(). Unify parseTransformType implementations to all
     160        use a single implementation and return an Optional<SVGTransformType>.
     161
     162        * svg/SVGViewSpec.cpp:
     163        (WebCore::SVGViewSpec::parseViewSpec):
     164        * svg/SVGViewSpec.h:
     165        Adopt StringParsingBuffer and readCharactersForParsing to replace unnecessary call to
     166        StringView::upconvertedCharacters().
     167
     168        * svg/SVGZoomAndPan.cpp:
     169        (WebCore::parseZoomAndPanGeneric):
     170        (WebCore::SVGZoomAndPan::parseZoomAndPan):
     171        * svg/SVGZoomAndPan.h:
     172        Adopt StringParsingBuffer.
     173
    11742020-06-26  Jer Noble  <jer.noble@apple.com>
    2175
  • trunk/Source/WebCore/Headers.cmake

    r263498 r263617  
    666666    html/forms/FileIconLoader.h
    667667
     668    html/parser/ParsingUtilities.h
    668669    html/parser/HTMLParserIdioms.h
    669670
  • trunk/Source/WebCore/Sources.txt

    r263453 r263617  
    25412541svg/SVGImageLoader.cpp
    25422542svg/SVGLengthContext.cpp
     2543svg/SVGLengthList.cpp
    25432544svg/SVGLengthValue.cpp
    25442545svg/SVGLineElement.cpp
     
    25502551svg/SVGMetadataElement.cpp
    25512552svg/SVGMissingGlyphElement.cpp
     2553svg/SVGNumberList.cpp
    25522554svg/SVGParserUtilities.cpp
    25532555svg/SVGPathBlender.cpp
     
    25642566svg/SVGPathUtilities.cpp
    25652567svg/SVGPatternElement.cpp
     2568svg/SVGPointList.cpp
    25662569svg/SVGPolyElement.cpp
    25672570svg/SVGPolygonElement.cpp
     
    25742577svg/SVGSetElement.cpp
    25752578svg/SVGStopElement.cpp
     2579svg/SVGStringList.cpp
    25762580svg/SVGStyleElement.cpp
    25772581svg/SVGSwitchElement.cpp
     
    25872591svg/SVGToOTFFontConversion.cpp
    25882592svg/SVGTransformDistance.cpp
     2593svg/SVGTransformList.cpp
    25892594svg/SVGTransformable.cpp
    25902595svg/SVGURIReference.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r263498 r263617  
    15911591                5351D4B11DF916B4008010CD /* FileHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 5351D4AF1DF916AC008010CD /* FileHandle.h */; settings = {ATTRIBUTES = (Private, ); }; };
    15921592                536D5A20193E18E900CE4CAB /* HTMLSrcsetParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 536D5A1F193E18E900CE4CAB /* HTMLSrcsetParser.h */; };
    1593                 536D5A23193E8E0C00CE4CAB /* ParsingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 536D5A22193E8E0C00CE4CAB /* ParsingUtilities.h */; };
     1593                536D5A23193E8E0C00CE4CAB /* ParsingUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 536D5A22193E8E0C00CE4CAB /* ParsingUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
    15941594                538EC8021F96AF81004D22A8 /* UnifiedSource1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 538EC7FA1F96AA70004D22A8 /* UnifiedSource1.cpp */; };
    15951595                538EC8031F96AF81004D22A8 /* UnifiedSource1-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 538EC7F31F96AA5B004D22A8 /* UnifiedSource1-mm.mm */; };
     
    1019710197                7CD494CA1A86EB1D000A87EC /* RenderAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderAttachment.cpp; sourceTree = "<group>"; };
    1019810198                7CD494CB1A86EB1D000A87EC /* RenderAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderAttachment.h; sourceTree = "<group>"; };
     10199                7CD70C3D24A28A3A00E61040 /* SVGLengthList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGLengthList.cpp; sourceTree = "<group>"; };
     10200                7CD70C4024A28AC900E61040 /* SVGNumberList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGNumberList.cpp; sourceTree = "<group>"; };
     10201                7CD70C4224A28B7000E61040 /* SVGPointList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPointList.cpp; sourceTree = "<group>"; };
     10202                7CD70C4324A28BEC00E61040 /* SVGStringList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGStringList.cpp; sourceTree = "<group>"; };
     10203                7CD70C4624A28CD700E61040 /* SVGTransformList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SVGTransformList.cpp; sourceTree = "<group>"; };
    1019910204                7CDE73961F9BD59500390312 /* Settings.yaml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Settings.yaml; sourceTree = "<group>"; };
    1020010205                7CDE8EBC1F193BC500168FE7 /* CSSStyleDeclaration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSStyleDeclaration.cpp; sourceTree = "<group>"; };
     
    2514625151                                7134496B146941B300720312 /* SVGLengthContext.cpp */,
    2514725152                                7134496C146941B300720312 /* SVGLengthContext.h */,
     25153                                7CD70C3D24A28A3A00E61040 /* SVGLengthList.cpp */,
    2514825154                                B22278A00D00BF200071B782 /* SVGLengthList.h */,
    2514925155                                B22278A10D00BF200071B782 /* SVGLengthList.idl */,
     
    2517825184                                7CE58D4F1DD69A1E00128552 /* SVGNumber.h */,
    2517925185                                B22278B90D00BF200071B782 /* SVGNumber.idl */,
     25186                                7CD70C4024A28AC900E61040 /* SVGNumberList.cpp */,
    2518025187                                B22278BB0D00BF200071B782 /* SVGNumberList.h */,
    2518125188                                B22278BC0D00BF200071B782 /* SVGNumberList.idl */,
     
    2524125248                                7CE58D491DD64A5B00128552 /* SVGPoint.h */,
    2524225249                                B22278F40D00BF210071B782 /* SVGPoint.idl */,
     25250                                7CD70C4224A28B7000E61040 /* SVGPointList.cpp */,
    2524325251                                B22278F60D00BF210071B782 /* SVGPointList.h */,
    2524425252                                B22278F70D00BF210071B782 /* SVGPointList.idl */,
     
    2527425282                                B22279130D00BF210071B782 /* SVGStopElement.h */,
    2527525283                                B22279140D00BF210071B782 /* SVGStopElement.idl */,
     25284                                7CD70C4324A28BEC00E61040 /* SVGStringList.cpp */,
    2527625285                                B22279160D00BF210071B782 /* SVGStringList.h */,
    2527725286                                B22279170D00BF210071B782 /* SVGStringList.idl */,
     
    2531525324                                B22279460D00BF210071B782 /* SVGTransformDistance.cpp */,
    2531625325                                B22279470D00BF210071B782 /* SVGTransformDistance.h */,
     25326                                7CD70C4624A28CD700E61040 /* SVGTransformList.cpp */,
    2531725327                                B22279490D00BF210071B782 /* SVGTransformList.h */,
    2531825328                                B222794A0D00BF210071B782 /* SVGTransformList.idl */,
  • trunk/Source/WebCore/html/parser/ParsingUtilities.h

    r263581 r263617  
    143143}
    144144
     145template<typename CharacterType, unsigned characterCount> constexpr bool skipCharactersExactly(const CharacterType*& ptr, const CharacterType* end, const CharacterType(&str)[characterCount])
     146{
     147    if (end - ptr < characterCount)
     148        return false;
     149    if (memcmp(str, ptr, sizeof(CharacterType) * characterCount))
     150        return false;
     151    ptr += characterCount;
     152    return true;
     153}
     154
     155template<typename CharacterType, unsigned characterCount> constexpr bool skipCharactersExactly(StringParsingBuffer<CharacterType>& buffer, const CharacterType(&str)[characterCount])
     156{
     157    if (buffer.lengthRemaining() < characterCount)
     158        return false;
     159    if (memcmp(str, buffer.position(), sizeof(CharacterType) * characterCount))
     160        return false;
     161    buffer += characterCount;
     162    return true;
     163}
     164
    145165} // namespace WebCore
  • trunk/Source/WebCore/svg/SVGAngleValue.cpp

    r263334 r263617  
    2626#include <wtf/MathExtras.h>
    2727#include <wtf/text/StringConcatenateNumbers.h>
     28#include <wtf/text/StringParsingBuffer.h>
    2829
    2930namespace WebCore {
     
    8182}
    8283
    83 template<typename CharacterType> static inline SVGAngleValue::Type parseAngleType(const CharacterType* ptr, const CharacterType* end)
    84 {
    85     switch (end - ptr) {
     84template<typename CharacterType> static inline SVGAngleValue::Type parseAngleType(StringParsingBuffer<CharacterType> buffer)
     85{
     86    switch (buffer.lengthRemaining()) {
    8687    case 0:
    8788        return SVGAngleValue::SVG_ANGLETYPE_UNSPECIFIED;
    8889    case 3:
    89         if (ptr[0] == 'd' && ptr[1] == 'e' && ptr[2] == 'g')
     90        if (buffer[0] == 'd' && buffer[1] == 'e' && buffer[2] == 'g')
    9091            return SVGAngleValue::SVG_ANGLETYPE_DEG;
    91         if (ptr[0] == 'r' && ptr[1] == 'a' && ptr[2] == 'd')
     92        if (buffer[0] == 'r' && buffer[1] == 'a' && buffer[2] == 'd')
    9293            return SVGAngleValue::SVG_ANGLETYPE_RAD;
    9394        break;
    9495    case 4:
    95         if (ptr[0] == 'g' && ptr[1] == 'r' && ptr[2] == 'a' && ptr[3] == 'd')
     96        if (buffer[0] == 'g' && buffer[1] == 'r' && buffer[2] == 'a' && buffer[3] == 'd')
    9697            return SVGAngleValue::SVG_ANGLETYPE_GRAD;
    9798        break;
     
    107108    }
    108109
    109     auto helper = [&](auto* ptr, auto* end) -> ExceptionOr<void> {
    110         auto valueInSpecifiedUnits = parseNumber(ptr, end, SuffixSkippingPolicy::DontSkip);
     110    return readCharactersForParsing(value, [&](auto buffer) -> ExceptionOr<void> {
     111        auto valueInSpecifiedUnits = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
    111112        if (!valueInSpecifiedUnits)
    112113            return Exception { SyntaxError };
    113114
    114         auto unitType = parseAngleType(ptr, end);
     115        auto unitType = parseAngleType(buffer);
    115116        if (unitType == SVGAngleValue::SVG_ANGLETYPE_UNKNOWN)
    116117            return Exception { SyntaxError };
     
    119120        m_valueInSpecifiedUnits = *valueInSpecifiedUnits;
    120121        return { };
    121     };
    122 
    123     if (value.is8Bit()) {
    124         auto* ptr = value.characters8();
    125         return helper(ptr, ptr + value.length());
    126     }
    127 
    128     auto* ptr = value.characters16();
    129     return helper(ptr, ptr + value.length());
     122    });
    130123}
    131124
  • trunk/Source/WebCore/svg/SVGAnimateTransformElement.cpp

    r246490 r263617  
    5858{
    5959    if (name == SVGNames::typeAttr) {
    60         m_type = SVGTransformable::parseTransformType(value);
     60        m_type = SVGTransformable::parseTransformType(value).valueOr(SVGTransformValue::SVG_TRANSFORM_UNKNOWN);
    6161        if (m_type == SVGTransformValue::SVG_TRANSFORM_MATRIX)
    6262            m_type = SVGTransformValue::SVG_TRANSFORM_UNKNOWN;
  • trunk/Source/WebCore/svg/SVGAnimationElement.cpp

    r263334 r263617  
    4242#include <wtf/MathExtras.h>
    4343#include <wtf/NeverDestroyed.h>
     44#include <wtf/text/StringParsingBuffer.h>
    4445#include <wtf/text/StringView.h>
    4546
     
    7879}
    7980
    80 static Optional<Vector<UnitBezier>> parseKeySplines(const StringView& parse)
    81 {
    82     if (parse.isEmpty())
     81static Optional<Vector<UnitBezier>> parseKeySplines(StringView string)
     82{
     83    if (string.isEmpty())
    8384        return WTF::nullopt;
    8485
    85     auto upconvertedCharacters = parse.upconvertedCharacters();
    86     const UChar* cur = upconvertedCharacters;
    87     const UChar* end = cur + parse.length();
    88 
    89     skipOptionalSVGSpaces(cur, end);
    90 
    91     Vector<UnitBezier> result;
    92 
    93     bool delimParsed = false;
    94     while (cur < end) {
    95         delimParsed = false;
    96         auto posA = parseNumber(cur, end);
    97         if (!posA)
     86    return readCharactersForParsing(string, [&](auto buffer) -> Optional<Vector<UnitBezier>> {
     87        skipOptionalSVGSpaces(buffer);
     88
     89        Vector<UnitBezier> result;
     90
     91        bool delimParsed = false;
     92        while (buffer.hasCharactersRemaining()) {
     93            delimParsed = false;
     94            auto posA = parseNumber(buffer);
     95            if (!posA)
     96                return WTF::nullopt;
     97
     98            auto posB = parseNumber(buffer);
     99            if (!posB)
     100                return WTF::nullopt;
     101
     102            auto posC = parseNumber(buffer);
     103            if (!posC)
     104                return WTF::nullopt;
     105
     106            auto posD = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
     107            if (!posD)
     108                return WTF::nullopt;
     109
     110            skipOptionalSVGSpaces(buffer);
     111
     112            if (skipExactly(buffer, ';'))
     113                delimParsed = true;
     114
     115            skipOptionalSVGSpaces(buffer);
     116
     117            result.append(UnitBezier { *posA, *posB, *posC, *posD });
     118        }
     119
     120        if (!(buffer.atEnd() && !delimParsed))
    98121            return WTF::nullopt;
    99122
    100         auto posB = parseNumber(cur, end);
    101         if (!posB)
    102             return WTF::nullopt;
    103 
    104         auto posC = parseNumber(cur, end);
    105         if (!posC)
    106             return WTF::nullopt;
    107 
    108         auto posD = parseNumber(cur, end, SuffixSkippingPolicy::DontSkip);
    109         if (!posD)
    110             return WTF::nullopt;
    111 
    112         skipOptionalSVGSpaces(cur, end);
    113 
    114         if (cur < end && *cur == ';') {
    115             delimParsed = true;
    116             cur++;
    117         }
    118 
    119         skipOptionalSVGSpaces(cur, end);
    120 
    121         result.append(UnitBezier { *posA, *posB, *posC, *posD });
    122     }
    123 
    124     if (!(cur == end && !delimParsed))
    125         return WTF::nullopt;
    126 
    127     return result;
     123        return result;
     124    });
    128125}
    129126
  • trunk/Source/WebCore/svg/SVGFitToViewBox.cpp

    r263334 r263617  
    3131#include "SVGParserUtilities.h"
    3232#include "SVGPreserveAspectRatioValue.h"
     33#include <wtf/text/StringParsingBuffer.h>
    3334#include <wtf/text/StringView.h>
    3435
     
    8586}
    8687
    87 Optional<FloatRect> SVGFitToViewBox::parseViewBox(const StringView& value)
     88Optional<FloatRect> SVGFitToViewBox::parseViewBox(StringView value)
    8889{
    89     auto upconvertedCharacters = value.upconvertedCharacters();
    90     const UChar* characters = upconvertedCharacters;
    91     return parseViewBox(characters, characters + value.length());
     90    return readCharactersForParsing(value, [&](auto buffer) {
     91        return parseViewBoxGeneric(buffer);
     92    });
    9293}
    9394
    94 Optional<FloatRect> SVGFitToViewBox::parseViewBox(const UChar*& c, const UChar* end, bool validate)
     95Optional<FloatRect> SVGFitToViewBox::parseViewBox(StringParsingBuffer<LChar>& buffer, bool validate)
    9596{
    96     StringView str(c, end - c);
     97    return parseViewBoxGeneric(buffer, validate);
     98}
    9799
    98     skipOptionalSVGSpaces(c, end);
     100Optional<FloatRect> SVGFitToViewBox::parseViewBox(StringParsingBuffer<UChar>& buffer, bool validate)
     101{
     102    return parseViewBoxGeneric(buffer, validate);
     103}
    99104
    100     auto x = parseNumber(c, end);
    101     auto y = parseNumber(c, end);
    102     auto width = parseNumber(c, end);
    103     auto height = parseNumber(c, end, SuffixSkippingPolicy::DontSkip);
     105template<typename CharacterType> Optional<FloatRect> SVGFitToViewBox::parseViewBoxGeneric(StringParsingBuffer<CharacterType>& buffer, bool validate)
     106{
     107    StringView stringToParse = buffer.stringViewOfCharactersRemaining();
     108
     109    skipOptionalSVGSpaces(buffer);
     110
     111    auto x = parseNumber(buffer);
     112    auto y = parseNumber(buffer);
     113    auto width = parseNumber(buffer);
     114    auto height = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
    104115
    105116    if (validate) {
     
    107118
    108119        if (!x || !y || !width || !height) {
    109             document.accessSVGExtensions().reportWarning(makeString("Problem parsing viewBox=\"", str, "\""));
     120            document.accessSVGExtensions().reportWarning(makeString("Problem parsing viewBox=\"", stringToParse, "\""));
    110121            return WTF::nullopt;
    111122        }
     
    124135
    125136        // Nothing should come after the last, fourth number.
    126         skipOptionalSVGSpaces(c, end);
    127         if (c < end) {
    128             document.accessSVGExtensions().reportWarning(makeString("Problem parsing viewBox=\"", str, "\""));
     137        skipOptionalSVGSpaces(buffer);
     138        if (buffer.hasCharactersRemaining()) {
     139            document.accessSVGExtensions().reportWarning(makeString("Problem parsing viewBox=\"", stringToParse, "\""));
    129140            return WTF::nullopt;
    130141        }
  • trunk/Source/WebCore/svg/SVGFitToViewBox.h

    r263334 r263617  
    6666    void reset();
    6767    bool parseAttribute(const QualifiedName&, const AtomString&);
    68     Optional<FloatRect> parseViewBox(const StringView& value);
    69     Optional<FloatRect> parseViewBox(const UChar*& start, const UChar* end, bool validate = true);
     68    Optional<FloatRect> parseViewBox(StringView);
     69    Optional<FloatRect> parseViewBox(StringParsingBuffer<LChar>&, bool validate = true);
     70    Optional<FloatRect> parseViewBox(StringParsingBuffer<UChar>&, bool validate = true);
    7071
    7172private:
     73    template<typename CharacterType> Optional<FloatRect> parseViewBoxGeneric(StringParsingBuffer<CharacterType>&, bool validate = true);
     74
    7275    Ref<SVGAnimatedRect> m_viewBox;
    7376    Ref<SVGAnimatedPreserveAspectRatio> m_preserveAspectRatio;
  • trunk/Source/WebCore/svg/SVGLengthList.h

    r254514 r263617  
    2828#include "SVGLength.h"
    2929#include "SVGValuePropertyList.h"
    30 #include <wtf/text/StringBuilder.h>
    3130
    3231namespace WebCore {
    3332
    34 class SVGLengthList : public SVGValuePropertyList<SVGLength> {
     33class SVGLengthList final : public SVGValuePropertyList<SVGLength> {
    3534    using Base = SVGValuePropertyList<SVGLength>;
    3635    using Base::Base;
     
    5453    SVGLengthMode lengthMode() const { return m_lengthMode; }
    5554
    56     bool parse(const String& value)
    57     {
    58         clearItems();
     55    bool parse(StringView);
    5956
    60         auto upconvertedCharacters = StringView(value).upconvertedCharacters();
    61         const UChar* ptr = upconvertedCharacters;
    62         const UChar* end = ptr + value.length();
    63         while (ptr < end) {
    64             const UChar* start = ptr;
    65             while (ptr < end && *ptr != ',' && !isSVGSpace(*ptr))
    66                 ptr++;
    67             if (ptr == start)
    68                 break;
    69 
    70             String valueString(start, ptr - start);
    71             SVGLengthValue value(m_lengthMode);
    72             if (value.setValueAsString(valueString).hasException())
    73                 break;
    74 
    75             append(SVGLength::create(value));
    76             skipOptionalSVGSpacesOrDelimiter(ptr, end);
    77         }
    78 
    79         return ptr == end;
    80     }
    81 
    82     String valueAsString() const override
    83     {
    84         StringBuilder builder;
    85 
    86         for (const auto& length : m_items) {
    87             if (builder.length())
    88                 builder.append(' ');
    89 
    90             builder.append(length->value().valueAsString());
    91         }
    92 
    93         return builder.toString();
    94     }
     57    String valueAsString() const override;
    9558   
    9659private:
  • trunk/Source/WebCore/svg/SVGLengthValue.cpp

    r263334 r263617  
    2828#include "SVGParserUtilities.h"
    2929#include <wtf/text/StringConcatenateNumbers.h>
     30#include <wtf/text/StringParsingBuffer.h>
    3031#include <wtf/text/TextStream.h>
    3132
     
    6263}
    6364
    64 static inline SVGLengthType parseLengthType(const UChar* ptr, const UChar* end)
    65 {
    66     if (ptr == end)
     65template<typename CharacterType> static inline SVGLengthType parseLengthType(StringParsingBuffer<CharacterType>& buffer)
     66{
     67    if (buffer.atEnd())
    6768        return SVGLengthType::Number;
    6869
    69     const UChar firstChar = *ptr;
    70 
    71     if (++ptr == end)
     70    auto firstChar = *buffer++;
     71
     72    if (buffer.atEnd())
    7273        return firstChar == '%' ? SVGLengthType::Percentage : SVGLengthType::Unknown;
    7374
    74     const UChar secondChar = *ptr;
    75 
    76     if (++ptr != end)
     75    auto secondChar = *buffer++;
     76
     77    if (!buffer.atEnd())
    7778        return SVGLengthType::Unknown;
    7879
     
    181182}
    182183
    183 SVGLengthValue SVGLengthValue::construct(SVGLengthMode lengthMode, const String& valueAsString, SVGParsingError& parseError, SVGLengthNegativeValuesMode negativeValuesMode)
     184Optional<SVGLengthValue> SVGLengthValue::construct(SVGLengthMode lengthMode, StringView valueAsString)
     185{
     186    SVGLengthValue length { lengthMode };
     187    if (length.setValueAsString(valueAsString).hasException())
     188        return WTF::nullopt;
     189    return length;
     190}
     191
     192SVGLengthValue SVGLengthValue::construct(SVGLengthMode lengthMode, StringView valueAsString, SVGParsingError& parseError, SVGLengthNegativeValuesMode negativeValuesMode)
    184193{
    185194    SVGLengthValue length(lengthMode);
     
    240249}
    241250
    242 ExceptionOr<void> SVGLengthValue::setValueAsString(const String& valueAsString, SVGLengthMode lengthMode)
     251ExceptionOr<void> SVGLengthValue::setValueAsString(StringView valueAsString, SVGLengthMode lengthMode)
    243252{
    244253    m_valueInSpecifiedUnits = 0;
     
    287296}
    288297
    289 ExceptionOr<void> SVGLengthValue::setValueAsString(const String& string)
     298ExceptionOr<void> SVGLengthValue::setValueAsString(StringView string)
    290299{
    291300    if (string.isEmpty())
    292301        return { };
    293302
    294     auto upconvertedCharacters = StringView(string).upconvertedCharacters();
    295     const UChar* ptr = upconvertedCharacters;
    296     const UChar* end = ptr + string.length();
    297 
    298     auto convertedNumber = parseNumber(ptr, end, SuffixSkippingPolicy::DontSkip);
    299     if (!convertedNumber)
    300         return Exception { SyntaxError };
    301 
    302     auto lengthType = parseLengthType(ptr, end);
    303     if (lengthType == SVGLengthType::Unknown)
    304         return Exception { SyntaxError };
    305 
    306     m_lengthType = lengthType;
    307     m_valueInSpecifiedUnits = *convertedNumber;
    308     return { };
     303    return readCharactersForParsing(string, [&](auto buffer) -> ExceptionOr<void> {
     304        auto convertedNumber = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
     305        if (!convertedNumber)
     306            return Exception { SyntaxError };
     307
     308        auto lengthType = parseLengthType(buffer);
     309        if (lengthType == SVGLengthType::Unknown)
     310            return Exception { SyntaxError };
     311
     312        m_lengthType = lengthType;
     313        m_valueInSpecifiedUnits = *convertedNumber;
     314        return { };
     315    });
    309316}
    310317
  • trunk/Source/WebCore/svg/SVGLengthValue.h

    r249822 r263617  
    5959    WTF_MAKE_FAST_ALLOCATED;
    6060public:
    61     SVGLengthValue(SVGLengthMode = SVGLengthMode::Other, const String& valueAsString = String());
     61    SVGLengthValue(SVGLengthMode = SVGLengthMode::Other, const String& valueAsString = { });
    6262    SVGLengthValue(float valueInSpecifiedUnits, SVGLengthType, SVGLengthMode = SVGLengthMode::Other);
    6363    SVGLengthValue(const SVGLengthContext&, float, SVGLengthType = SVGLengthType::Number, SVGLengthMode = SVGLengthMode::Other);
    6464
    65     static SVGLengthValue construct(SVGLengthMode, const String&, SVGParsingError&, SVGLengthNegativeValuesMode = SVGLengthNegativeValuesMode::Allow);
     65    static Optional<SVGLengthValue> construct(SVGLengthMode, StringView);
     66    static SVGLengthValue construct(SVGLengthMode, StringView, SVGParsingError&, SVGLengthNegativeValuesMode = SVGLengthNegativeValuesMode::Allow);
    6667    static SVGLengthValue blend(const SVGLengthValue& from, const SVGLengthValue& to, float progress);
    67    
     68
    6869    static SVGLengthValue fromCSSPrimitiveValue(const CSSPrimitiveValue&);
    6970    static Ref<CSSPrimitiveValue> toCSSPrimitiveValue(const SVGLengthValue&);
     
    8687    ExceptionOr<void> setValue(const SVGLengthContext&, float, SVGLengthType, SVGLengthMode);
    8788
    88     ExceptionOr<void> setValueAsString(const String&);
    89     ExceptionOr<void> setValueAsString(const String&, SVGLengthMode);
     89    ExceptionOr<void> setValueAsString(StringView);
     90    ExceptionOr<void> setValueAsString(StringView, SVGLengthMode);
    9091
    9192    ExceptionOr<void> convertToSpecifiedUnits(const SVGLengthContext&, SVGLengthType);
  • trunk/Source/WebCore/svg/SVGNumberList.cpp

    r263616 r263617  
    11/*
    2  * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #pragma once
     26#include "config.h"
     27#include "SVGNumberList.h"
    2728
    28 #include "SVGNumber.h"
    29 #include "SVGValuePropertyList.h"
     29#include <wtf/text/StringBuilder.h>
     30#include <wtf/text/StringParsingBuffer.h>
    3031
    3132namespace WebCore {
    3233
    33 class SVGNumberList : public SVGValuePropertyList<SVGNumber> {
    34     using Base = SVGValuePropertyList<SVGNumber>;
    35     using Base::Base;
     34bool SVGNumberList::parse(StringView value)
     35{
     36    clearItems();
    3637
    37 public:
    38     static Ref<SVGNumberList> create()
    39     {
    40         return adoptRef(*new SVGNumberList());
    41     }
    42 
    43     static Ref<SVGNumberList> create(SVGPropertyOwner* owner, SVGPropertyAccess access)
    44     {
    45         return adoptRef(*new SVGNumberList(owner, access));
    46     }
    47 
    48     static Ref<SVGNumberList> create(const SVGNumberList& other, SVGPropertyAccess access)
    49     {
    50         return adoptRef(*new SVGNumberList(other, access));
    51     }
    52 
    53     bool parse(const String& value)
    54     {
    55         clearItems();
    56 
    57         auto upconvertedCharacters = StringView(value).upconvertedCharacters();
    58         const UChar* ptr = upconvertedCharacters;
    59         const UChar* end = ptr + value.length();
    60 
     38    return readCharactersForParsing(value, [&](auto buffer) {
    6139        // The spec (section 4.1) strangely doesn't allow leading whitespace.
    6240        // We might choose to violate that intentionally.
    63         while (ptr < end) {
    64             auto number = parseNumber(ptr, end);
     41        while (buffer.hasCharactersRemaining()) {
     42            auto number = parseNumber(buffer);
    6543            if (!number)
    6644                break;
     
    6846        }
    6947
    70         return ptr == end;
     48        // FIXME: Should this clearItems() on failure like SVGTransformList does?
     49
     50        return buffer.atEnd();
     51    });
     52}
     53
     54String SVGNumberList::valueAsString() const
     55{
     56    StringBuilder builder;
     57
     58    for (const auto& number : m_items) {
     59        if (builder.length())
     60            builder.append(' ');
     61
     62        builder.append(number->value());
    7163    }
    7264
    73     String valueAsString() const override
    74     {
    75         StringBuilder builder;
     65    return builder.toString();
     66}
    7667
    77         for (const auto& number : m_items) {
    78             if (builder.length())
    79                 builder.append(' ');
     68}
    8069
    81             builder.append(number->value());
    82         }
    83 
    84         return builder.toString();
    85     }
    86 };
    87 
    88 } // namespace WebCore
  • trunk/Source/WebCore/svg/SVGNumberList.h

    r263334 r263617  
    3131namespace WebCore {
    3232
    33 class SVGNumberList : public SVGValuePropertyList<SVGNumber> {
     33class SVGNumberList final : public SVGValuePropertyList<SVGNumber> {
    3434    using Base = SVGValuePropertyList<SVGNumber>;
    3535    using Base::Base;
     
    5151    }
    5252
    53     bool parse(const String& value)
    54     {
    55         clearItems();
    56 
    57         auto upconvertedCharacters = StringView(value).upconvertedCharacters();
    58         const UChar* ptr = upconvertedCharacters;
    59         const UChar* end = ptr + value.length();
    60 
    61         // The spec (section 4.1) strangely doesn't allow leading whitespace.
    62         // We might choose to violate that intentionally.
    63         while (ptr < end) {
    64             auto number = parseNumber(ptr, end);
    65             if (!number)
    66                 break;
    67             append(SVGNumber::create(*number));
    68         }
    69 
    70         return ptr == end;
    71     }
    72 
    73     String valueAsString() const override
    74     {
    75         StringBuilder builder;
    76 
    77         for (const auto& number : m_items) {
    78             if (builder.length())
    79                 builder.append(' ');
    80 
    81             builder.append(number->value());
    82         }
    83 
    84         return builder.toString();
    85     }
     53    bool parse(StringView);
     54    String valueAsString() const override;
    8655};
    8756
  • trunk/Source/WebCore/svg/SVGParserUtilities.cpp

    r263334 r263617  
    2828#include <limits>
    2929#include <wtf/ASCIICType.h>
     30#include <wtf/text/StringParsingBuffer.h>
    3031#include <wtf/text/StringView.h>
    3132
     
    4243// complexity.
    4344// FIXME: Can this be shared/replaced with number parsing in WTF?
    44 template <typename CharacterType, typename FloatType = float> static Optional<FloatType> genericParseNumber(const CharacterType*& ptr, const CharacterType* end, SuffixSkippingPolicy skip = SuffixSkippingPolicy::Skip)
     45template <typename CharacterType, typename FloatType = float> static Optional<FloatType> genericParseNumber(StringParsingBuffer<CharacterType>& buffer, SuffixSkippingPolicy skip = SuffixSkippingPolicy::Skip)
    4546{
    4647    FloatType number = 0;
     
    5152    int sign = 1;
    5253    int expsign = 1;
    53     const CharacterType* start = ptr;
     54    auto start = buffer.position();
    5455
    5556    // read the sign
    56     if (ptr < end && *ptr == '+')
    57         ptr++;
    58     else if (ptr < end && *ptr == '-') {
    59         ptr++;
     57    if (buffer.hasCharactersRemaining() && *buffer == '+')
     58        ++buffer;
     59    else if (buffer.hasCharactersRemaining() && *buffer == '-') {
     60        ++buffer;
    6061        sign = -1;
    6162    }
    6263   
    63     if (ptr == end || (!isASCIIDigit(*ptr) && *ptr != '.'))
     64    if (buffer.atEnd() || (!isASCIIDigit(*buffer) && *buffer != '.'))
    6465        return WTF::nullopt;
    6566
    6667    // read the integer part, build right-to-left
    67     const CharacterType* ptrStartIntPart = ptr;
    68     while (ptr < end && isASCIIDigit(*ptr))
    69         ++ptr; // Advance to first non-digit.
    70 
    71     if (ptr != ptrStartIntPart) {
    72         const CharacterType* ptrScanIntPart = ptr - 1;
     68    auto ptrStartIntPart = buffer.position();
     69   
     70    // Advance to first non-digit.
     71    skipWhile<CharacterType, isASCIIDigit>(buffer);
     72
     73    if (buffer.position() != ptrStartIntPart) {
     74        auto ptrScanIntPart = buffer.position() - 1;
    7375        FloatType multiplier = 1;
    7476        while (ptrScanIntPart >= ptrStartIntPart) {
     
    8183    }
    8284
    83     if (ptr < end && *ptr == '.') { // read the decimals
    84         ptr++;
     85    // read the decimals
     86    if (buffer.hasCharactersRemaining() && *buffer == '.') {
     87        ++buffer;
    8588       
    8689        // There must be a least one digit following the .
    87         if (ptr >= end || !isASCIIDigit(*ptr))
    88             return WTF::nullopt;
    89        
    90         while (ptr < end && isASCIIDigit(*ptr))
    91             decimal += (*(ptr++) - '0') * (frac *= static_cast<FloatType>(0.1));
     90        if (buffer.atEnd() || !isASCIIDigit(*buffer))
     91            return WTF::nullopt;
     92       
     93        while (buffer.hasCharactersRemaining() && isASCIIDigit(*buffer))
     94            decimal += (*(buffer++) - '0') * (frac *= static_cast<FloatType>(0.1));
    9295    }
    9396
    9497    // read the exponent part
    95     if (ptr != start && ptr + 1 < end && (*ptr == 'e' || *ptr == 'E')
    96         && (ptr[1] != 'x' && ptr[1] != 'm')) {
    97         ptr++;
     98    if (buffer.position() != start && buffer.position() + 1 < buffer.end() && (*buffer == 'e' || *buffer == 'E')
     99        && (buffer[1] != 'x' && buffer[1] != 'm')) {
     100        ++buffer;
    98101
    99102        // read the sign of the exponent
    100         if (*ptr == '+')
    101             ptr++;
    102         else if (*ptr == '-') {
    103             ptr++;
     103        if (*buffer == '+')
     104            ++buffer;
     105        else if (*buffer == '-') {
     106            ++buffer;
    104107            expsign = -1;
    105108        }
    106109       
    107110        // There must be an exponent
    108         if (ptr >= end || !isASCIIDigit(*ptr))
    109             return WTF::nullopt;
    110 
    111         while (ptr < end && isASCIIDigit(*ptr)) {
     111        if (buffer.atEnd() || !isASCIIDigit(*buffer))
     112            return WTF::nullopt;
     113
     114        while (buffer.hasCharactersRemaining() && isASCIIDigit(*buffer)) {
    112115            exponent *= static_cast<FloatType>(10);
    113             exponent += *ptr - '0';
    114             ptr++;
     116            exponent += *buffer++ - '0';
    115117        }
    116118        // Make sure exponent is valid.
     
    129131        return WTF::nullopt;
    130132
    131     if (start == ptr)
     133    if (start == buffer.position())
    132134        return WTF::nullopt;
    133135
    134136    if (skip == SuffixSkippingPolicy::Skip)
    135         skipOptionalSVGSpacesOrDelimiter(ptr, end);
     137        skipOptionalSVGSpacesOrDelimiter(buffer);
    136138
    137139    return number;
    138140}
    139141
    140 Optional<float> parseNumber(const LChar*& ptr, const LChar* end, SuffixSkippingPolicy skip)
    141 {
    142     return genericParseNumber(ptr, end, skip);
    143 }
    144 
    145 Optional<float> parseNumber(const UChar*& ptr, const UChar* end, SuffixSkippingPolicy skip)
    146 {
    147     return genericParseNumber(ptr, end, skip);
     142Optional<float> parseNumber(StringParsingBuffer<LChar>& buffer, SuffixSkippingPolicy skip)
     143{
     144    return genericParseNumber(buffer, skip);
     145}
     146
     147Optional<float> parseNumber(StringParsingBuffer<UChar>& buffer, SuffixSkippingPolicy skip)
     148{
     149    return genericParseNumber(buffer, skip);
    148150}
    149151
    150152Optional<float> parseNumber(const StringView& string, SuffixSkippingPolicy skip)
    151153{
    152     auto upconvertedCharacters = string.upconvertedCharacters();
    153     const UChar* ptr = upconvertedCharacters;
    154     const UChar* end = ptr + string.length();
    155     auto result = genericParseNumber(ptr, end, skip);
    156     if (ptr != end)
    157         return WTF::nullopt;
    158     return result;
     154    return readCharactersForParsing(string, [skip](auto buffer) -> Optional<float> {
     155        auto result = genericParseNumber(buffer, skip);
     156        if (!buffer.atEnd())
     157            return WTF::nullopt;
     158        return result;
     159    });
    159160}
    160161
    161162// only used to parse largeArcFlag and sweepFlag which must be a "0" or "1"
    162163// and might not have any whitespace/comma after it
    163 template <typename CharacterType> Optional<bool> genericParseArcFlag(const CharacterType*& ptr, const CharacterType* end)
    164 {
    165     if (ptr >= end)
    166         return WTF::nullopt;
    167 
    168     const CharacterType flagChar = *ptr++;
     164template <typename CharacterType> Optional<bool> genericParseArcFlag(StringParsingBuffer<CharacterType>& buffer)
     165{
     166    if (buffer.atEnd())
     167        return WTF::nullopt;
     168
     169    const CharacterType flagChar = *buffer;
     170    ++buffer;
    169171
    170172    bool flag;
     
    176178        return WTF::nullopt;
    177179
    178     skipOptionalSVGSpacesOrDelimiter(ptr, end);
     180    skipOptionalSVGSpacesOrDelimiter(buffer);
    179181   
    180182    return flag;
    181183}
    182184
    183 Optional<bool> parseArcFlag(const LChar*& ptr, const LChar* end)
    184 {
    185     return genericParseArcFlag(ptr, end);
    186 }
    187 
    188 Optional<bool> parseArcFlag(const UChar*& ptr, const UChar* end)
    189 {
    190     return genericParseArcFlag(ptr, end);
     185Optional<bool> parseArcFlag(StringParsingBuffer<LChar>& buffer)
     186{
     187    return genericParseArcFlag(buffer);
     188}
     189
     190Optional<bool> parseArcFlag(StringParsingBuffer<UChar>& buffer)
     191{
     192    return genericParseArcFlag(buffer);
    191193}
    192194
     
    196198        return WTF::nullopt;
    197199
    198     auto upconvertedCharacters = string.upconvertedCharacters();
    199     const UChar* cur = upconvertedCharacters;
    200     const UChar* end = cur + string.length();
    201 
    202     auto x = parseNumber(cur, end);
    203     if (!x)
    204         return WTF::nullopt;
    205 
    206     if (cur == end)
    207         return std::make_pair(*x, *x);
    208 
    209     auto y = parseNumber(cur, end, SuffixSkippingPolicy::DontSkip);
    210     if (!y)
    211         return WTF::nullopt;
    212 
    213     if (cur != end)
    214         return WTF::nullopt;
    215 
    216     return std::make_pair(*x, *y);
     200    return readCharactersForParsing(string, [](auto buffer) -> Optional<std::pair<float, float>> {
     201        auto x = parseNumber(buffer);
     202        if (!x)
     203            return WTF::nullopt;
     204
     205        if (buffer.atEnd())
     206            return std::make_pair(*x, *x);
     207
     208        auto y = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
     209        if (!y)
     210            return WTF::nullopt;
     211
     212        if (!buffer.atEnd())
     213            return WTF::nullopt;
     214
     215        return std::make_pair(*x, *y);
     216    });
    217217}
    218218
     
    222222        return WTF::nullopt;
    223223
    224     auto upconvertedCharacters = string.upconvertedCharacters();
    225     const UChar* cur = upconvertedCharacters;
    226     const UChar* end = cur + string.length();
    227 
    228     if (!skipOptionalSVGSpaces(cur, end))
    229         return WTF::nullopt;
    230 
    231     auto point = parseFloatPoint(cur, end);
    232     if (!point)
    233         return WTF::nullopt;
    234 
    235     // Disallow anything except spaces at the end.
    236     skipOptionalSVGSpaces(cur, end);
    237    
    238     return point;
     224    return readCharactersForParsing(string, [](auto buffer) -> Optional<FloatPoint> {
     225        if (!skipOptionalSVGSpaces(buffer))
     226            return WTF::nullopt;
     227
     228        auto point = parseFloatPoint(buffer);
     229        if (!point)
     230            return WTF::nullopt;
     231
     232        // Disallow anything except spaces at the end.
     233        skipOptionalSVGSpaces(buffer);
     234       
     235        return point;
     236    });
    239237}
    240238
    241239Optional<FloatRect> parseRect(const StringView& string)
    242240{
    243     auto upconvertedCharacters = string.upconvertedCharacters();
    244     const UChar* ptr = upconvertedCharacters;
    245     const UChar* end = ptr + string.length();
    246    
    247     skipOptionalSVGSpaces(ptr, end);
    248    
    249     auto x = parseNumber(ptr, end);
    250     if (!x)
    251         return WTF::nullopt;
    252     auto y = parseNumber(ptr, end);
    253     if (!y)
    254         return WTF::nullopt;
    255     auto width = parseNumber(ptr, end);
    256     if (!width)
    257         return WTF::nullopt;
    258     auto height = parseNumber(ptr, end, SuffixSkippingPolicy::DontSkip);
    259     if (!height)
    260         return WTF::nullopt;
    261 
    262     return FloatRect { *x, *y, *width, *height };
     241    return readCharactersForParsing(string, [](auto buffer) -> Optional<FloatRect> {
     242        skipOptionalSVGSpaces(buffer);
     243       
     244        auto x = parseNumber(buffer);
     245        if (!x)
     246            return WTF::nullopt;
     247        auto y = parseNumber(buffer);
     248        if (!y)
     249            return WTF::nullopt;
     250        auto width = parseNumber(buffer);
     251        if (!width)
     252            return WTF::nullopt;
     253        auto height = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
     254        if (!height)
     255            return WTF::nullopt;
     256
     257        return FloatRect { *x, *y, *width, *height };
     258    });
    263259}
    264260
     
    267263    // FIXME: Parsing error detection is missing.
    268264
    269     auto upconvertedCharacters = string.upconvertedCharacters();
    270     const UChar* ptr = upconvertedCharacters;
    271     const UChar* end = ptr + string.length();
    272     skipOptionalSVGSpaces(ptr, end);
    273 
    274     HashSet<String> values;
    275 
    276     while (ptr < end) {
    277         // Leading and trailing white space, and white space before and after separators, will be ignored.
    278         const UChar* inputStart = ptr;
    279         while (ptr < end && *ptr != ',')
    280             ++ptr;
    281 
    282         if (ptr == inputStart)
    283             break;
    284 
    285         // walk backwards from the ; to ignore any whitespace
    286         const UChar* inputEnd = ptr - 1;
    287         while (inputStart < inputEnd && isSVGSpace(*inputEnd))
    288             --inputEnd;
    289 
    290         values.add(String(inputStart, inputEnd - inputStart + 1));
    291         skipOptionalSVGSpacesOrDelimiter(ptr, end, ',');
    292     }
    293 
    294     return values;
    295 }
    296 
    297 static Optional<UnicodeRange> parseUnicodeRange(const UChar* characters, unsigned length)
    298 {
    299     if (length < 2 || characters[0] != 'U' || characters[1] != '+')
    300         return WTF::nullopt;
    301    
     265    return readCharactersForParsing(string, [](auto buffer) -> HashSet<String> {
     266        skipOptionalSVGSpaces(buffer);
     267
     268        HashSet<String> values;
     269
     270        while (buffer.hasCharactersRemaining()) {
     271            // Leading and trailing white space, and white space before and after separators, will be ignored.
     272            auto inputStart = buffer.position();
     273
     274            skipUntil(buffer, ',');
     275
     276            if (buffer.position() == inputStart)
     277                break;
     278
     279            // walk backwards from the ; to ignore any whitespace
     280            auto inputEnd = buffer.position() - 1;
     281            while (inputStart < inputEnd && isSVGSpace(*inputEnd))
     282                --inputEnd;
     283
     284            values.add(String(inputStart, inputEnd - inputStart + 1));
     285            skipOptionalSVGSpacesOrDelimiter(buffer, ',');
     286        }
     287        return values;
     288    });
     289
     290}
     291
     292template<typename CharacterType> static Optional<UnicodeRange> parseUnicodeRange(StringParsingBuffer<CharacterType> buffer)
     293{
     294    unsigned length = buffer.lengthRemaining();
     295    if (length < 2 || buffer[0] != 'U' || buffer[1] != '+')
     296        return WTF::nullopt;
     297
     298    buffer += 2;
     299
    302300    // Parse the starting hex number (or its prefix).
    303301    unsigned startRange = 0;
    304302    unsigned startLength = 0;
    305303
    306     const UChar* ptr = characters + 2;
    307     const UChar* end = characters + length;
    308     while (ptr < end) {
    309         if (!isASCIIHexDigit(*ptr))
     304    while (buffer.hasCharactersRemaining()) {
     305        if (!isASCIIHexDigit(*buffer))
    310306            break;
    311307        ++startLength;
    312308        if (startLength > 6)
    313309            return WTF::nullopt;
    314         startRange = (startRange << 4) | toASCIIHexValue(*ptr);
    315         ++ptr;
     310        startRange = (startRange << 4) | toASCIIHexValue(*buffer);
     311        ++buffer;
    316312    }
    317313
    318314    // Handle the case of ranges separated by "-" sign.
    319     if (2 + startLength < length && *ptr == '-') {
     315    if (2 + startLength < length && *buffer == '-') {
    320316        if (!startLength)
    321317            return WTF::nullopt;
     
    324320        unsigned endRange = 0;
    325321        unsigned endLength = 0;
    326         ++ptr;
    327         while (ptr < end) {
    328             if (!isASCIIHexDigit(*ptr))
     322        ++buffer;
     323        while (buffer.hasCharactersRemaining()) {
     324            if (!isASCIIHexDigit(*buffer))
    329325                break;
    330326            ++endLength;
    331327            if (endLength > 6)
    332328                return WTF::nullopt;
    333             endRange = (endRange << 4) | toASCIIHexValue(*ptr);
    334             ++ptr;
     329            endRange = (endRange << 4) | toASCIIHexValue(*buffer);
     330            ++buffer;
    335331        }
    336332       
     
    346342    // Handle the case of a number with some optional trailing question marks.
    347343    unsigned endRange = startRange;
    348     while (ptr < end) {
    349         if (*ptr != '?')
     344    while (buffer.hasCharactersRemaining()) {
     345        if (*buffer != '?')
    350346            break;
    351347        ++startLength;
     
    354350        startRange <<= 4;
    355351        endRange = (endRange << 4) | 0xF;
    356         ++ptr;
     352        ++buffer;
    357353    }
    358354   
     
    370366    // FIXME: Parsing error detection is missing.
    371367
    372     auto upconvertedCharacters = string.upconvertedCharacters();
    373     const UChar* ptr = upconvertedCharacters;
    374     const UChar* end = ptr + string.length();
    375 
    376     UnicodeRanges rangeList;
    377     HashSet<String> stringList;
    378 
    379     while (ptr < end) {
    380         const UChar* inputStart = ptr;
    381         while (ptr < end && *ptr != ',')
    382             ++ptr;
    383 
    384         if (ptr == inputStart)
    385             break;
    386 
    387         // Try to parse unicode range first
    388         if (auto range = parseUnicodeRange(inputStart, ptr - inputStart))
    389             rangeList.append(WTFMove(*range));
    390         else
    391             stringList.add(String(inputStart, ptr - inputStart));
    392         ++ptr;
    393     }
    394 
    395     return std::make_pair(rangeList, stringList);
    396 }
    397 
    398 template <typename CharacterType> static Optional<FloatPoint> genericParseFloatPoint(const CharacterType*& current, const CharacterType* end)
    399 {
    400     auto x = parseNumber(current, end);
     368    return readCharactersForParsing(string, [](auto buffer) -> std::pair<UnicodeRanges, HashSet<String>> {
     369        UnicodeRanges rangeList;
     370        HashSet<String> stringList;
     371
     372        while (1) {
     373            auto inputStart = buffer.position();
     374
     375            skipUntil(buffer, ',');
     376
     377            if (buffer.position() == inputStart)
     378                break;
     379
     380            // Try to parse unicode range first
     381            if (auto range = parseUnicodeRange(StringParsingBuffer { inputStart, buffer.position() }))
     382                rangeList.append(WTFMove(*range));
     383            else
     384                stringList.add(String(inputStart, buffer.position() - inputStart));
     385
     386            if (buffer.atEnd())
     387                break;
     388
     389            ++buffer;
     390        }
     391
     392        return std::make_pair(WTFMove(rangeList), WTFMove(stringList));
     393    });
     394}
     395
     396template <typename CharacterType> static Optional<FloatPoint> genericParseFloatPoint(StringParsingBuffer<CharacterType>& buffer)
     397{
     398    auto x = parseNumber(buffer);
    401399    if (!x)
    402400        return WTF::nullopt;
    403401
    404     auto y = parseNumber(current, end);
     402    auto y = parseNumber(buffer);
    405403    if (!y)
    406404        return WTF::nullopt;
     
    409407}
    410408
    411 Optional<FloatPoint> parseFloatPoint(const LChar*& current, const LChar* end)
    412 {
    413     return genericParseFloatPoint(current, end);
    414 }
    415 
    416 Optional<FloatPoint> parseFloatPoint(const UChar*& current, const UChar* end)
    417 {
    418     return genericParseFloatPoint(current, end);
    419 }
    420 
    421 }
     409Optional<FloatPoint> parseFloatPoint(StringParsingBuffer<LChar>& buffer)
     410{
     411    return genericParseFloatPoint(buffer);
     412}
     413
     414Optional<FloatPoint> parseFloatPoint(StringParsingBuffer<UChar>& buffer)
     415{
     416    return genericParseFloatPoint(buffer);
     417}
     418
     419}
  • trunk/Source/WebCore/svg/SVGParserUtilities.h

    r263334 r263617  
    2222#pragma once
    2323
     24#include "ParsingUtilities.h"
    2425#include <wtf/HashSet.h>
    2526#include <wtf/Vector.h>
    26 #include <wtf/text/WTFString.h>
    2727
    2828typedef std::pair<UChar32, UChar32> UnicodeRange;
     
    3939};
    4040
    41 Optional<float> parseNumber(const LChar*& current, const LChar* end, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);
    42 Optional<float> parseNumber(const UChar*& current, const UChar* end, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);
     41Optional<float> parseNumber(StringParsingBuffer<LChar>&, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);
     42Optional<float> parseNumber(StringParsingBuffer<UChar>&, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);
    4343Optional<float> parseNumber(const StringView&, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);
    4444
    4545Optional<std::pair<float, float>> parseNumberOptionalNumber(const StringView&);
    4646
    47 Optional<bool> parseArcFlag(const LChar*& current, const LChar* end);
    48 Optional<bool> parseArcFlag(const UChar*& current, const UChar* end);
     47Optional<bool> parseArcFlag(StringParsingBuffer<LChar>&);
     48Optional<bool> parseArcFlag(StringParsingBuffer<UChar>&);
    4949
    5050Optional<FloatPoint> parsePoint(const StringView&);
    5151Optional<FloatRect> parseRect(const StringView&);
    5252
    53 Optional<FloatPoint> parseFloatPoint(const LChar*& current, const LChar* end);
    54 Optional<FloatPoint> parseFloatPoint(const UChar*& current, const UChar* end);
     53Optional<FloatPoint> parseFloatPoint(StringParsingBuffer<LChar>&);
     54Optional<FloatPoint> parseFloatPoint(StringParsingBuffer<UChar>&);
    5555
    5656Optional<std::pair<UnicodeRanges, HashSet<String>>> parseKerningUnicodeString(const StringView&);
     
    6565}
    6666
     67template<typename CharacterType> constexpr bool isSVGSpaceOrComma(CharacterType c)
     68{
     69    return isSVGSpace(c) || c == ',';
     70}
     71
    6772template<typename CharacterType> constexpr bool skipOptionalSVGSpaces(const CharacterType*& ptr, const CharacterType* end)
    6873{
    69     while (ptr < end && isSVGSpace(*ptr))
    70         ptr++;
     74    skipWhile<CharacterType, isSVGSpace>(ptr, end);
    7175    return ptr < end;
     76}
     77
     78template<typename CharacterType> constexpr bool skipOptionalSVGSpaces(StringParsingBuffer<CharacterType>& characters)
     79{
     80    skipWhile<CharacterType, isSVGSpace>(characters);
     81    return characters.hasCharactersRemaining();
    7282}
    7383
     
    8595}
    8696
    87 constexpr bool skipString(const UChar*& ptr, const UChar* end, const UChar* name, int length)
     97template<typename CharacterType> constexpr bool skipOptionalSVGSpacesOrDelimiter(StringParsingBuffer<CharacterType>& characters, char delimiter = ',')
    8898{
    89     if (end - ptr < length)
     99    if (characters.hasCharactersRemaining() && !isSVGSpace(*characters) && *characters != delimiter)
    90100        return false;
    91     if (memcmp(name, ptr, sizeof(UChar) * length))
    92         return false;
    93     ptr += length;
    94     return true;
    95 }
    96 
    97 template<unsigned characterCount>
    98 inline bool skipString(const UChar*& ptr, const UChar* end, const char (&str)[characterCount])
    99 {
    100     int length = characterCount - 1;
    101     if (end - ptr < length)
    102         return false;
    103     for (int i = 0; i < length; ++i) {
    104         if (ptr[i] != str[i])
    105             return false;
     101    if (skipOptionalSVGSpaces(characters)) {
     102        if (characters.hasCharactersRemaining() && *characters == delimiter) {
     103            characters++;
     104            skipOptionalSVGSpaces(characters);
     105        }
    106106    }
    107     ptr += length;
    108     return true;
     107    return characters.hasCharactersRemaining();
    109108}
    110109
  • trunk/Source/WebCore/svg/SVGPathSource.h

    r263334 r263617  
    2020#pragma once
    2121
     22#include "FloatPoint.h"
    2223#include "SVGPathSeg.h"
    2324
    2425namespace WebCore {
    2526
    26 class FloatPoint;
    2727
    2828class SVGPathSource {
  • trunk/Source/WebCore/svg/SVGPathStringSource.cpp

    r263334 r263617  
    2222#include "SVGPathStringSource.h"
    2323
    24 #include "FloatPoint.h"
    2524#include "SVGParserUtilities.h"
    2625
     
    3332    ASSERT(!string.isEmpty());
    3433
    35     if (m_is8BitSource) {
    36         m_current.m_character8 = string.characters8();
    37         m_end.m_character8 = m_current.m_character8 + string.length();
    38     } else {
    39         m_current.m_character16 = string.characters16();
    40         m_end.m_character16 = m_current.m_character16 + string.length();
    41     }
     34    if (m_is8BitSource)
     35        m_buffer8 = { string.characters8(), string.length() };
     36    else
     37        m_buffer16 = { string.characters16(), string.length() };
    4238}
    4339
     
    4541{
    4642    if (m_is8BitSource)
    47         return m_current.m_character8 < m_end.m_character8;
    48     return m_current.m_character16 < m_end.m_character16;
     43        return m_buffer8.hasCharactersRemaining();
     44    return m_buffer16.hasCharactersRemaining();
    4945}
    5046
     
    5248{
    5349    if (m_is8BitSource)
    54         return skipOptionalSVGSpaces(m_current.m_character8, m_end.m_character8);
    55     return skipOptionalSVGSpaces(m_current.m_character16, m_end.m_character16);
    56 }
    57 
    58 template <typename CharacterType> static Optional<SVGPathSegType> nextCommandHelper(const CharacterType*& current, SVGPathSegType previousCommand)
     50        return skipOptionalSVGSpaces(m_buffer8);
     51    return skipOptionalSVGSpaces(m_buffer16);
     52}
     53
     54template <typename CharacterType> static Optional<SVGPathSegType> nextCommandHelper(StringParsingBuffer<CharacterType>& buffer, SVGPathSegType previousCommand)
    5955{
    6056    // Check for remaining coordinates in the current command.
    61     if ((*current == '+' || *current == '-' || *current == '.' || isASCIIDigit(*current))
     57    if ((*buffer == '+' || *buffer == '-' || *buffer == '.' || isASCIIDigit(*buffer))
    6258        && previousCommand != PathSegClosePath) {
    6359        if (previousCommand == PathSegMoveToAbs)
     
    7470{
    7571    if (m_is8BitSource) {
    76         if (auto nextCommand = nextCommandHelper(m_current.m_character8, previousCommand))
     72        if (auto nextCommand = nextCommandHelper(m_buffer8, previousCommand))
    7773            return *nextCommand;
    7874    } else {
    79         if (auto nextCommand = nextCommandHelper(m_current.m_character16, previousCommand))
     75        if (auto nextCommand = nextCommandHelper(m_buffer16, previousCommand))
    8076            return *nextCommand;
    8177    }
     
    8480}
    8581
    86 template <typename CharacterType> static SVGPathSegType parseSVGSegmentTypeHelper(const CharacterType*& current)
    87 {
    88     switch (*(current++)) {
    89     case 'Z':
    90     case 'z':
    91         return PathSegClosePath;
    92     case 'M':
    93         return PathSegMoveToAbs;
    94     case 'm':
    95         return PathSegMoveToRel;
    96     case 'L':
    97         return PathSegLineToAbs;
    98     case 'l':
    99         return PathSegLineToRel;
    100     case 'C':
    101         return PathSegCurveToCubicAbs;
    102     case 'c':
    103         return PathSegCurveToCubicRel;
    104     case 'Q':
    105         return PathSegCurveToQuadraticAbs;
    106     case 'q':
    107         return PathSegCurveToQuadraticRel;
    108     case 'A':
    109         return PathSegArcAbs;
    110     case 'a':
    111         return PathSegArcRel;
    112     case 'H':
    113         return PathSegLineToHorizontalAbs;
    114     case 'h':
    115         return PathSegLineToHorizontalRel;
    116     case 'V':
    117         return PathSegLineToVerticalAbs;
    118     case 'v':
    119         return PathSegLineToVerticalRel;
    120     case 'S':
    121         return PathSegCurveToCubicSmoothAbs;
    122     case 's':
    123         return PathSegCurveToCubicSmoothRel;
    124     case 'T':
    125         return PathSegCurveToQuadraticSmoothAbs;
    126     case 't':
    127         return PathSegCurveToQuadraticSmoothRel;
    128     default:
    129         return PathSegUnknown;
    130     }
     82template<typename F> decltype(auto) SVGPathStringSource::parse(F&& functor)
     83{
     84    if (m_is8BitSource)
     85        return functor(m_buffer8);
     86    return functor(m_buffer16);
    13187}
    13288
    13389Optional<SVGPathSegType> SVGPathStringSource::parseSVGSegmentType()
    13490{
    135     if (m_is8BitSource)
    136         return parseSVGSegmentTypeHelper(m_current.m_character8);
    137     return parseSVGSegmentTypeHelper(m_current.m_character16);
     91    return parse([](auto& buffer) -> SVGPathSegType {
     92        auto character = *buffer;
     93        buffer++;
     94        switch (character) {
     95        case 'Z':
     96        case 'z':
     97            return PathSegClosePath;
     98        case 'M':
     99            return PathSegMoveToAbs;
     100        case 'm':
     101            return PathSegMoveToRel;
     102        case 'L':
     103            return PathSegLineToAbs;
     104        case 'l':
     105            return PathSegLineToRel;
     106        case 'C':
     107            return PathSegCurveToCubicAbs;
     108        case 'c':
     109            return PathSegCurveToCubicRel;
     110        case 'Q':
     111            return PathSegCurveToQuadraticAbs;
     112        case 'q':
     113            return PathSegCurveToQuadraticRel;
     114        case 'A':
     115            return PathSegArcAbs;
     116        case 'a':
     117            return PathSegArcRel;
     118        case 'H':
     119            return PathSegLineToHorizontalAbs;
     120        case 'h':
     121            return PathSegLineToHorizontalRel;
     122        case 'V':
     123            return PathSegLineToVerticalAbs;
     124        case 'v':
     125            return PathSegLineToVerticalRel;
     126        case 'S':
     127            return PathSegCurveToCubicSmoothAbs;
     128        case 's':
     129            return PathSegCurveToCubicSmoothRel;
     130        case 'T':
     131            return PathSegCurveToQuadraticSmoothAbs;
     132        case 't':
     133            return PathSegCurveToQuadraticSmoothRel;
     134        default:
     135            return PathSegUnknown;
     136        }
     137    });
    138138}
    139139
    140140Optional<SVGPathSource::MoveToSegment> SVGPathStringSource::parseMoveToSegment()
    141141{
    142     auto helper = [](const auto*& current, const auto* end) -> Optional<MoveToSegment> {
    143         auto targetPoint = parseFloatPoint(current, end);
     142    return parse([](auto& buffer) -> Optional<MoveToSegment> {
     143        auto targetPoint = parseFloatPoint(buffer);
    144144        if (!targetPoint)
    145145            return WTF::nullopt;
     
    148148        segment.targetPoint = WTFMove(*targetPoint);
    149149        return segment;
    150     };
    151 
    152     if (m_is8BitSource)
    153         return helper(m_current.m_character8, m_end.m_character8);
    154     return helper(m_current.m_character16, m_end.m_character16);
     150    });
    155151}
    156152
    157153Optional<SVGPathSource::LineToSegment> SVGPathStringSource::parseLineToSegment()
    158154{
    159     auto helper = [](const auto*& current, const auto* end) -> Optional<LineToSegment> {
    160         auto targetPoint = parseFloatPoint(current, end);
     155    return parse([](auto& buffer) -> Optional<LineToSegment> {
     156        auto targetPoint = parseFloatPoint(buffer);
    161157        if (!targetPoint)
    162158            return WTF::nullopt;
     
    165161        segment.targetPoint = WTFMove(*targetPoint);
    166162        return segment;
    167     };
    168 
    169     if (m_is8BitSource)
    170         return helper(m_current.m_character8, m_end.m_character8);
    171     return helper(m_current.m_character16, m_end.m_character16);
     163    });
    172164}
    173165
    174166Optional<SVGPathSource::LineToHorizontalSegment> SVGPathStringSource::parseLineToHorizontalSegment()
    175167{
    176     auto helper = [](const auto*& current, const auto* end) -> Optional<LineToHorizontalSegment> {
    177         auto x = parseNumber(current, end);
     168    return parse([](auto& buffer) -> Optional<LineToHorizontalSegment> {
     169        auto x = parseNumber(buffer);
    178170        if (!x)
    179171            return WTF::nullopt;
     
    182174        segment.x = *x;
    183175        return segment;
    184     };
    185 
    186     if (m_is8BitSource)
    187         return helper(m_current.m_character8, m_end.m_character8);
    188     return helper(m_current.m_character16, m_end.m_character16);
     176    });
    189177}
    190178
    191179Optional<SVGPathSource::LineToVerticalSegment> SVGPathStringSource::parseLineToVerticalSegment()
    192180{
    193     auto helper = [](const auto*& current, const auto* end) -> Optional<LineToVerticalSegment> {
    194         auto y = parseNumber(current, end);
     181    return parse([](auto& buffer) -> Optional<LineToVerticalSegment> {
     182        auto y = parseNumber(buffer);
    195183        if (!y)
    196184            return WTF::nullopt;
     
    199187        segment.y = *y;
    200188        return segment;
    201     };
    202 
    203     if (m_is8BitSource)
    204         return helper(m_current.m_character8, m_end.m_character8);
    205     return helper(m_current.m_character16, m_end.m_character16);
     189    });
    206190}
    207191
    208192Optional<SVGPathSource::CurveToCubicSegment> SVGPathStringSource::parseCurveToCubicSegment()
    209193{
    210     auto helper = [](const auto*& current, const auto* end) -> Optional<CurveToCubicSegment> {
    211         auto point1 = parseFloatPoint(current, end);
     194    return parse([](auto& buffer) -> Optional<CurveToCubicSegment> {
     195        auto point1 = parseFloatPoint(buffer);
    212196        if (!point1)
    213197            return WTF::nullopt;
    214198
    215         auto point2 = parseFloatPoint(current, end);
     199        auto point2 = parseFloatPoint(buffer);
    216200        if (!point2)
    217201            return WTF::nullopt;
    218202
    219         auto targetPoint = parseFloatPoint(current, end);
     203        auto targetPoint = parseFloatPoint(buffer);
    220204        if (!targetPoint)
    221205            return WTF::nullopt;
     
    226210        segment.targetPoint = *targetPoint;
    227211        return segment;
    228     };
    229 
    230     if (m_is8BitSource)
    231         return helper(m_current.m_character8, m_end.m_character8);
    232     return helper(m_current.m_character16, m_end.m_character16);
     212    });
    233213}
    234214
    235215Optional<SVGPathSource::CurveToCubicSmoothSegment> SVGPathStringSource::parseCurveToCubicSmoothSegment()
    236216{
    237     auto helper = [](const auto*& current, const auto* end) -> Optional<CurveToCubicSmoothSegment> {
    238         auto point2 = parseFloatPoint(current, end);
     217    return parse([](auto& buffer) -> Optional<CurveToCubicSmoothSegment> {
     218        auto point2 = parseFloatPoint(buffer);
    239219        if (!point2)
    240220            return WTF::nullopt;
    241221
    242         auto targetPoint = parseFloatPoint(current, end);
     222        auto targetPoint = parseFloatPoint(buffer);
    243223        if (!targetPoint)
    244224            return WTF::nullopt;
     
    248228        segment.targetPoint = *targetPoint;
    249229        return segment;
    250     };
    251 
    252     if (m_is8BitSource)
    253         return helper(m_current.m_character8, m_end.m_character8);
    254     return helper(m_current.m_character16, m_end.m_character16);
     230    });
    255231}
    256232
    257233Optional<SVGPathSource::CurveToQuadraticSegment> SVGPathStringSource::parseCurveToQuadraticSegment()
    258234{
    259     auto helper = [](const auto*& current, const auto* end) -> Optional<CurveToQuadraticSegment> {
    260         auto point1 = parseFloatPoint(current, end);
     235    return parse([](auto& buffer) -> Optional<CurveToQuadraticSegment> {
     236        auto point1 = parseFloatPoint(buffer);
    261237        if (!point1)
    262238            return WTF::nullopt;
    263239
    264         auto targetPoint = parseFloatPoint(current, end);
     240        auto targetPoint = parseFloatPoint(buffer);
    265241        if (!targetPoint)
    266242            return WTF::nullopt;
     
    270246        segment.targetPoint = *targetPoint;
    271247        return segment;
    272     };
    273 
    274     if (m_is8BitSource)
    275         return helper(m_current.m_character8, m_end.m_character8);
    276     return helper(m_current.m_character16, m_end.m_character16);
     248    });
    277249}
    278250
    279251Optional<SVGPathSource::CurveToQuadraticSmoothSegment> SVGPathStringSource::parseCurveToQuadraticSmoothSegment()
    280252{
    281     auto helper = [](const auto*& current, const auto* end) -> Optional<CurveToQuadraticSmoothSegment> {
    282         auto targetPoint = parseFloatPoint(current, end);
     253    return parse([](auto& buffer) -> Optional<CurveToQuadraticSmoothSegment> {
     254        auto targetPoint = parseFloatPoint(buffer);
    283255        if (!targetPoint)
    284256            return WTF::nullopt;
     
    287259        segment.targetPoint = *targetPoint;
    288260        return segment;
    289     };
    290 
    291     if (m_is8BitSource)
    292         return helper(m_current.m_character8, m_end.m_character8);
    293     return helper(m_current.m_character16, m_end.m_character16);
     261    });
    294262}
    295263
    296264Optional<SVGPathSource::ArcToSegment> SVGPathStringSource::parseArcToSegment()
    297265{
    298     auto helper = [](const auto*& current, const auto* end) -> Optional<ArcToSegment> {
    299         auto rx = parseNumber(current, end);
     266    return parse([](auto& buffer) -> Optional<ArcToSegment> {
     267        auto rx = parseNumber(buffer);
    300268        if (!rx)
    301269            return WTF::nullopt;
    302         auto ry = parseNumber(current, end);
     270        auto ry = parseNumber(buffer);
    303271        if (!ry)
    304272            return WTF::nullopt;
    305         auto angle = parseNumber(current, end);
     273        auto angle = parseNumber(buffer);
    306274        if (!angle)
    307275            return WTF::nullopt;
    308         auto largeArc = parseArcFlag(current, end);
     276        auto largeArc = parseArcFlag(buffer);
    309277        if (!largeArc)
    310278            return WTF::nullopt;
    311         auto sweep = parseArcFlag(current, end);
     279        auto sweep = parseArcFlag(buffer);
    312280        if (!sweep)
    313281            return WTF::nullopt;
    314         auto targetPoint = parseFloatPoint(current, end);
     282        auto targetPoint = parseFloatPoint(buffer);
    315283        if (!targetPoint)
    316284            return WTF::nullopt;
     
    324292        segment.targetPoint = *targetPoint;
    325293        return segment;
    326     };
    327 
    328     if (m_is8BitSource)
    329         return helper(m_current.m_character8, m_end.m_character8);
    330     return helper(m_current.m_character16, m_end.m_character16);
     294    });
    331295}
    332296
  • trunk/Source/WebCore/svg/SVGPathStringSource.h

    r263334 r263617  
    2222
    2323#include "SVGPathSource.h"
     24#include <wtf/text/StringParsingBuffer.h>
    2425#include <wtf/text/WTFString.h>
    2526
     
    4647    Optional<ArcToSegment> parseArcToSegment() final;
    4748
     49    template<typename Function> decltype(auto) parse(Function&&);
     50
    4851    String m_string;
    4952    bool m_is8BitSource;
    5053
    5154    union {
    52         const LChar* m_character8;
    53         const UChar* m_character16;
    54     } m_current;
    55     union {
    56         const LChar* m_character8;
    57         const UChar* m_character16;
    58     } m_end;
     55        StringParsingBuffer<LChar> m_buffer8;
     56        StringParsingBuffer<UChar> m_buffer16;
     57    };
    5958};
    6059
  • trunk/Source/WebCore/svg/SVGPointList.cpp

    r263616 r263617  
    11/*
    2  * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #pragma once
     26#include "config.h"
     27#include "SVGPointList.h"
    2728
    28 #include "SVGPoint.h"
    29 #include "SVGValuePropertyList.h"
     29#include <wtf/text/StringBuilder.h>
     30#include <wtf/text/StringParsingBuffer.h>
    3031
    3132namespace WebCore {
    3233
    33 class SVGPointList : public SVGValuePropertyList<SVGPoint> {
    34     using Base = SVGValuePropertyList<SVGPoint>;
    35     using Base::Base;
     34bool SVGPointList::parse(StringView value)
     35{
     36    clearItems();
    3637
    37 public:
    38     static Ref<SVGPointList> create()
    39     {
    40         return adoptRef(*new SVGPointList());
    41     }
    42 
    43     static Ref<SVGPointList> create(SVGPropertyOwner* owner, SVGPropertyAccess access)
    44     {
    45         return adoptRef(*new SVGPointList(owner, access));
    46     }
    47 
    48     static Ref<SVGPointList> create(const SVGPointList& other, SVGPropertyAccess access)
    49     {
    50         return adoptRef(*new SVGPointList(other, access));
    51     }
    52 
    53     bool parse(const String& value)
    54     {
    55         clearItems();
    56 
    57         auto upconvertedCharacters = StringView(value).upconvertedCharacters();
    58         const UChar* cur = upconvertedCharacters;
    59         const UChar* end = cur + value.length();
    60 
    61         skipOptionalSVGSpaces(cur, end);
     38    return readCharactersForParsing(value, [&](auto buffer) {
     39        skipOptionalSVGSpaces(buffer);
    6240
    6341        bool delimParsed = false;
    64         while (cur < end) {
     42        while (buffer.hasCharactersRemaining()) {
    6543            delimParsed = false;
    6644
    67             auto xPos = parseNumber(cur, end);
     45            auto xPos = parseNumber(buffer);
    6846            if (!xPos)
    6947                return false;
    7048
    71             auto yPos = parseNumber(cur, end, SuffixSkippingPolicy::DontSkip);
     49            auto yPos = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
    7250            if (!yPos)
    7351                return false;
    7452
    75             skipOptionalSVGSpaces(cur, end);
     53            skipOptionalSVGSpaces(buffer);
    7654
    77             if (cur < end && *cur == ',') {
     55            if (skipExactly(buffer, ','))
    7856                delimParsed = true;
    79                 cur++;
    80             }
    81             skipOptionalSVGSpaces(cur, end);
     57
     58            skipOptionalSVGSpaces(buffer);
    8259
    8360            append(SVGPoint::create({ *xPos, *yPos }));
    8461        }
    8562
     63        // FIXME: Should this clearItems() on failure like SVGTransformList does?
     64
    8665        return !delimParsed;
     66    });
     67}
     68
     69String SVGPointList::valueAsString() const
     70{
     71    StringBuilder builder;
     72
     73    for (const auto& point : m_items) {
     74        if (builder.length())
     75            builder.append(' ');
     76
     77        builder.append(point->x(), ' ', point->y());
    8778    }
    8879
    89     String valueAsString() const override
    90     {
    91         StringBuilder builder;
    92 
    93         for (const auto& point : m_items) {
    94             if (builder.length())
    95                 builder.append(' ');
    96 
    97             builder.append(point->x(), ' ', point->y());
    98         }
    99 
    100         return builder.toString();
    101     }
    102 };
     80    return builder.toString();
     81}
    10382
    10483}
  • trunk/Source/WebCore/svg/SVGPointList.h

    r263334 r263617  
    3131namespace WebCore {
    3232
    33 class SVGPointList : public SVGValuePropertyList<SVGPoint> {
     33class SVGPointList final : public SVGValuePropertyList<SVGPoint> {
    3434    using Base = SVGValuePropertyList<SVGPoint>;
    3535    using Base::Base;
     
    5151    }
    5252
    53     bool parse(const String& value)
    54     {
    55         clearItems();
    56 
    57         auto upconvertedCharacters = StringView(value).upconvertedCharacters();
    58         const UChar* cur = upconvertedCharacters;
    59         const UChar* end = cur + value.length();
    60 
    61         skipOptionalSVGSpaces(cur, end);
    62 
    63         bool delimParsed = false;
    64         while (cur < end) {
    65             delimParsed = false;
    66 
    67             auto xPos = parseNumber(cur, end);
    68             if (!xPos)
    69                 return false;
    70 
    71             auto yPos = parseNumber(cur, end, SuffixSkippingPolicy::DontSkip);
    72             if (!yPos)
    73                 return false;
    74 
    75             skipOptionalSVGSpaces(cur, end);
    76 
    77             if (cur < end && *cur == ',') {
    78                 delimParsed = true;
    79                 cur++;
    80             }
    81             skipOptionalSVGSpaces(cur, end);
    82 
    83             append(SVGPoint::create({ *xPos, *yPos }));
    84         }
    85 
    86         return !delimParsed;
    87     }
    88 
    89     String valueAsString() const override
    90     {
    91         StringBuilder builder;
    92 
    93         for (const auto& point : m_items) {
    94             if (builder.length())
    95                 builder.append(' ');
    96 
    97             builder.append(point->x(), ' ', point->y());
    98         }
    99 
    100         return builder.toString();
    101     }
     53    bool parse(StringView);
     54    String valueAsString() const override;
    10255};
    10356
  • trunk/Source/WebCore/svg/SVGPreserveAspectRatioValue.cpp

    r254703 r263617  
    2727#include "SVGParserUtilities.h"
    2828#include <wtf/text/StringConcatenateNumbers.h>
     29#include <wtf/text/StringParsingBuffer.h>
    2930#include <wtf/text/StringView.h>
    3031
     
    3738}
    3839
    39 SVGPreserveAspectRatioValue::SVGPreserveAspectRatioValue(const String& value)
     40SVGPreserveAspectRatioValue::SVGPreserveAspectRatioValue(StringView value)
    4041{
    4142    parse(value);
     
    6061}
    6162
    62 void SVGPreserveAspectRatioValue::parse(const String& value)
    63 {
    64     auto upconvertedCharacters = StringView(value).upconvertedCharacters();
    65     const UChar* begin = upconvertedCharacters;
    66     parseInternal(begin, begin + value.length(), true);
    67 }
    68 
    69 bool SVGPreserveAspectRatioValue::parse(const UChar*& currParam, const UChar* end, bool validate)
    70 {
    71     return parseInternal(currParam, end, validate);
    72 }
    73 
    74 bool SVGPreserveAspectRatioValue::parseInternal(const UChar*& currParam, const UChar* end, bool validate)
     63bool SVGPreserveAspectRatioValue::parse(StringView value)
     64{
     65    return readCharactersForParsing(value, [&](auto buffer) {
     66        return parseInternal(buffer, true);
     67    });
     68}
     69
     70bool SVGPreserveAspectRatioValue::parse(StringParsingBuffer<LChar>& buffer, bool validate)
     71{
     72    return parseInternal(buffer, validate);
     73}
     74
     75bool SVGPreserveAspectRatioValue::parse(StringParsingBuffer<UChar>& buffer, bool validate)
     76{
     77    return parseInternal(buffer, validate);
     78}
     79
     80template<typename CharacterType> static constexpr CharacterType deferDesc[] =  {'d', 'e', 'f', 'e', 'r'};
     81template<typename CharacterType> static constexpr CharacterType noneDesc[] =  {'n', 'o', 'n', 'e'};
     82template<typename CharacterType> static constexpr CharacterType meetDesc[] =  {'m', 'e', 'e', 't'};
     83template<typename CharacterType> static constexpr CharacterType sliceDesc[] =  {'s', 'l', 'i', 'c', 'e'};
     84
     85template<typename CharacterType> bool SVGPreserveAspectRatioValue::parseInternal(StringParsingBuffer<CharacterType>& buffer, bool validate)
    7586{
    7687    SVGPreserveAspectRatioType align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
     
    8091    m_meetOrSlice = meetOrSlice;
    8192
    82     if (!skipOptionalSVGSpaces(currParam, end))
     93    if (!skipOptionalSVGSpaces(buffer))
    8394        return false;
    8495
    85     if (*currParam == 'd') {
    86         if (!skipString(currParam, end, "defer")) {
     96    if (*buffer == 'd') {
     97        if (!skipCharactersExactly(buffer, deferDesc<CharacterType>)) {
    8798            LOG_ERROR("Skipped to parse except for *defer* value.");
    8899            return false;
     
    90101
    91102        // FIXME: We just ignore the "defer" here.
    92         if (currParam == end)
     103        if (buffer.atEnd())
    93104            return true;
    94105
    95         if (!skipOptionalSVGSpaces(currParam, end))
    96             return false;
    97     }
    98 
    99     if (*currParam == 'n') {
    100         if (!skipString(currParam, end, "none")) {
     106        if (!skipOptionalSVGSpaces(buffer))
     107            return false;
     108    }
     109
     110    if (*buffer == 'n') {
     111        if (!skipCharactersExactly(buffer, noneDesc<CharacterType>)) {
    101112            LOG_ERROR("Skipped to parse except for *none* value.");
    102113            return false;
    103114        }
    104115        align = SVG_PRESERVEASPECTRATIO_NONE;
    105         skipOptionalSVGSpaces(currParam, end);
    106     } else if (*currParam == 'x') {
    107         if ((end - currParam) < 8)
    108             return false;
    109         if (currParam[1] != 'M' || currParam[4] != 'Y' || currParam[5] != 'M')
    110             return false;
    111         if (currParam[2] == 'i') {
    112             if (currParam[3] == 'n') {
    113                 if (currParam[6] == 'i') {
    114                     if (currParam[7] == 'n')
     116        skipOptionalSVGSpaces(buffer);
     117    } else if (*buffer == 'x') {
     118        if (buffer.lengthRemaining() < 8)
     119            return false;
     120        if (buffer[1] != 'M' || buffer[4] != 'Y' || buffer[5] != 'M')
     121            return false;
     122        if (buffer[2] == 'i') {
     123            if (buffer[3] == 'n') {
     124                if (buffer[6] == 'i') {
     125                    if (buffer[7] == 'n')
    115126                        align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
    116                     else if (currParam[7] == 'd')
     127                    else if (buffer[7] == 'd')
    117128                        align = SVG_PRESERVEASPECTRATIO_XMINYMID;
    118129                    else
    119130                        return false;
    120                 } else if (currParam[6] == 'a' && currParam[7] == 'x')
     131                } else if (buffer[6] == 'a' && buffer[7] == 'x')
    121132                    align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
    122133                else
    123134                    return false;
    124              } else if (currParam[3] == 'd') {
    125                 if (currParam[6] == 'i') {
    126                     if (currParam[7] == 'n')
     135            } else if (buffer[3] == 'd') {
     136                if (buffer[6] == 'i') {
     137                    if (buffer[7] == 'n')
    127138                        align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
    128                     else if (currParam[7] == 'd')
     139                    else if (buffer[7] == 'd')
    129140                        align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
    130141                    else
    131142                        return false;
    132                 } else if (currParam[6] == 'a' && currParam[7] == 'x')
     143                } else if (buffer[6] == 'a' && buffer[7] == 'x')
    133144                    align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
    134145                else
     
    136147            } else
    137148                return false;
    138         } else if (currParam[2] == 'a' && currParam[3] == 'x') {
    139             if (currParam[6] == 'i') {
    140                 if (currParam[7] == 'n')
     149        } else if (buffer[2] == 'a' && buffer[3] == 'x') {
     150            if (buffer[6] == 'i') {
     151                if (buffer[7] == 'n')
    141152                    align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
    142                 else if (currParam[7] == 'd')
     153                else if (buffer[7] == 'd')
    143154                    align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
    144155                else
    145156                    return false;
    146             } else if (currParam[6] == 'a' && currParam[7] == 'x')
     157            } else if (buffer[6] == 'a' && buffer[7] == 'x')
    147158                align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
    148159            else
     
    150161        } else
    151162            return false;
    152         currParam += 8;
    153         skipOptionalSVGSpaces(currParam, end);
     163        buffer += 8;
     164        skipOptionalSVGSpaces(buffer);
    154165    } else
    155166        return false;
    156167
    157     if (currParam < end) {
    158         if (*currParam == 'm') {
    159             if (!skipString(currParam, end, "meet")) {
     168    if (buffer.hasCharactersRemaining()) {
     169        if (*buffer == 'm') {
     170            if (!skipCharactersExactly(buffer, meetDesc<CharacterType>)) {
    160171                LOG_ERROR("Skipped to parse except for *meet* or *slice* value.");
    161172                return false;
    162173            }
    163             skipOptionalSVGSpaces(currParam, end);
    164         } else if (*currParam == 's') {
    165             if (!skipString(currParam, end, "slice")) {
     174            skipOptionalSVGSpaces(buffer);
     175        } else if (*buffer == 's') {
     176            if (!skipCharactersExactly(buffer, sliceDesc<CharacterType>)) {
    166177                LOG_ERROR("Skipped to parse except for *meet* or *slice* value.");
    167178                return false;
    168179            }
    169             skipOptionalSVGSpaces(currParam, end);
     180            skipOptionalSVGSpaces(buffer);
    170181            if (align != SVG_PRESERVEASPECTRATIO_NONE)
    171182                meetOrSlice = SVG_MEETORSLICE_SLICE;
     
    173184    }
    174185
    175     if (end != currParam && validate)
     186    if (!buffer.atEnd() && validate)
    176187        return false;
    177188
     
    329340String SVGPreserveAspectRatioValue::valueAsString() const
    330341{
    331     String alignType;
    332 
    333     switch (m_align) {
    334     case SVG_PRESERVEASPECTRATIO_NONE:
    335         alignType = "none";
    336         break;
    337     case SVG_PRESERVEASPECTRATIO_XMINYMIN:
    338         alignType = "xMinYMin";
    339         break;
    340     case SVG_PRESERVEASPECTRATIO_XMIDYMIN:
    341         alignType = "xMidYMin";
    342         break;
    343     case SVG_PRESERVEASPECTRATIO_XMAXYMIN:
    344         alignType = "xMaxYMin";
    345         break;
    346     case SVG_PRESERVEASPECTRATIO_XMINYMID:
    347         alignType = "xMinYMid";
    348         break;
    349     case SVG_PRESERVEASPECTRATIO_XMIDYMID:
    350         alignType = "xMidYMid";
    351         break;
    352     case SVG_PRESERVEASPECTRATIO_XMAXYMID:
    353         alignType = "xMaxYMid";
    354         break;
    355     case SVG_PRESERVEASPECTRATIO_XMINYMAX:
    356         alignType = "xMinYMax";
    357         break;
    358     case SVG_PRESERVEASPECTRATIO_XMIDYMAX:
    359         alignType = "xMidYMax";
    360         break;
    361     case SVG_PRESERVEASPECTRATIO_XMAXYMAX:
    362         alignType = "xMaxYMax";
    363         break;
    364     case SVG_PRESERVEASPECTRATIO_UNKNOWN:
    365         alignType = "unknown";
    366         break;
     342    auto alignType = [&]() {
     343        switch (m_align) {
     344        case SVG_PRESERVEASPECTRATIO_NONE:
     345            return "none"_s;
     346        case SVG_PRESERVEASPECTRATIO_XMINYMIN:
     347            return "xMinYMin"_s;
     348        case SVG_PRESERVEASPECTRATIO_XMIDYMIN:
     349            return "xMidYMin"_s;
     350        case SVG_PRESERVEASPECTRATIO_XMAXYMIN:
     351            return "xMaxYMin"_s;
     352        case SVG_PRESERVEASPECTRATIO_XMINYMID:
     353            return "xMinYMid"_s;
     354        case SVG_PRESERVEASPECTRATIO_XMIDYMID:
     355            return "xMidYMid"_s;
     356        case SVG_PRESERVEASPECTRATIO_XMAXYMID:
     357            return "xMaxYMid"_s;
     358        case SVG_PRESERVEASPECTRATIO_XMINYMAX:
     359            return "xMinYMax"_s;
     360        case SVG_PRESERVEASPECTRATIO_XMIDYMAX:
     361            return "xMidYMax"_s;
     362        case SVG_PRESERVEASPECTRATIO_XMAXYMAX:
     363            return "xMaxYMax"_s;
     364        case SVG_PRESERVEASPECTRATIO_UNKNOWN:
     365            return "unknown"_s;
     366        };
     367
     368        ASSERT_NOT_REACHED();
     369        return "unknown"_s;
    367370    };
    368371
     
    370373    default:
    371374    case SVG_MEETORSLICE_UNKNOWN:
    372         return alignType;
     375        return alignType();
    373376    case SVG_MEETORSLICE_MEET:
    374         return alignType + " meet";
     377        return makeString(alignType(), " meet");
    375378    case SVG_MEETORSLICE_SLICE:
    376         return alignType + " slice";
    377     }
    378 }
    379 
    380 }
     379        return makeString(alignType(), " slice");
     380    }
     381}
     382
     383}
  • trunk/Source/WebCore/svg/SVGPreserveAspectRatioValue.h

    r239427 r263617  
    5353
    5454    SVGPreserveAspectRatioValue();
    55     SVGPreserveAspectRatioValue(const String&);
     55    SVGPreserveAspectRatioValue(StringView);
    5656
    5757    ExceptionOr<void> setAlign(unsigned short);
     
    6565    AffineTransform getCTM(float logicalX, float logicalY, float logicalWidth, float logicalHeight, float physicalWidth, float physicalHeight) const;
    6666
    67     void parse(const String&);
    68     bool parse(const UChar*& currParam, const UChar* end, bool validate);
     67    bool parse(StringView);
     68    bool parse(StringParsingBuffer<LChar>&, bool validate);
     69    bool parse(StringParsingBuffer<UChar>&, bool validate);
    6970
    7071    String valueAsString() const;
     
    7475    SVGMeetOrSliceType m_meetOrSlice;
    7576
    76     bool parseInternal(const UChar*& currParam, const UChar* end, bool validate);
     77    template<typename CharacterType> bool parseInternal(StringParsingBuffer<CharacterType>&, bool validate);
    7778};
    7879
  • trunk/Source/WebCore/svg/SVGStringList.h

    r250201 r263617  
    5252    }
    5353
    54     bool parse(const String& data, UChar delimiter)
    55     {
    56         clearItems();
    57 
    58         auto upconvertedCharacters = StringView(data).upconvertedCharacters();
    59         const UChar* ptr = upconvertedCharacters;
    60         const UChar* end = ptr + data.length();
    61         while (ptr < end) {
    62             const UChar* start = ptr;
    63             while (ptr < end && *ptr != delimiter && !isSVGSpace(*ptr))
    64                 ptr++;
    65             if (ptr == start)
    66                 break;
    67             m_items.append(String(start, ptr - start));
    68             skipOptionalSVGSpacesOrDelimiter(ptr, end, delimiter);
    69         }
    70 
    71         return ptr == end;
    72     }
    73 
    74     String valueAsString() const override
    75     {
    76         StringBuilder builder;
    77 
    78         for (const auto& string : m_items) {
    79             if (builder.length())
    80                 builder.append(' ');
    81 
    82             builder.append(string);
    83         }
    84 
    85         return builder.toString();
    86     }
     54    bool parse(StringView, UChar delimiter);
     55    String valueAsString() const override;
    8756};
    8857
  • trunk/Source/WebCore/svg/SVGTransformList.h

    r263334 r263617  
    5757    }
    5858
    59     ExceptionOr<RefPtr<SVGTransform>> consolidate()
    60     {
    61         auto result = canAlterList();
    62         if (result.hasException())
    63             return result.releaseException();
    64         ASSERT(result.releaseReturnValue());
     59    ExceptionOr<RefPtr<SVGTransform>> consolidate();
     60    AffineTransform concatenate() const;
    6561
    66         // Spec: If the list was empty, then a value of null is returned.
    67         if (m_items.isEmpty())
    68             return nullptr;
    69 
    70         if (m_items.size() == 1)
    71             return makeRefPtr(at(0).get());
    72 
    73         auto newItem = SVGTransform::create(concatenate());
    74         clearItems();
    75 
    76         auto item = append(WTFMove(newItem));
    77         commitChange();
    78         return makeRefPtr(item.get());
    79     }
    80 
    81     void parse(const String& value)
    82     {
    83         clearItems();
    84 
    85         auto upconvertedCharacters = StringView(value).upconvertedCharacters();
    86         const UChar* start = upconvertedCharacters;
    87         if (!parse(start, start + value.length()))
    88             clearItems();
    89     }
    90 
    91     AffineTransform concatenate() const
    92     {
    93         AffineTransform result;
    94         for (const auto& transform : m_items)
    95             result *= transform->matrix()->value();
    96         return result;
    97     }
    98 
    99     String valueAsString() const override
    100     {
    101         StringBuilder builder;
    102         for (const auto& transfrom : m_items) {
    103             if (builder.length())
    104                 builder.append(' ');
    105 
    106             builder.append(transfrom->value().valueAsString());
    107         }
    108         return builder.toString();
    109     }
     62    void parse(StringView);
     63    String valueAsString() const override;
    11064
    11165private:
    112     bool parse(const UChar*& start, const UChar* end)
    113     {
    114         bool delimParsed = false;
    115         while (start < end) {
    116             delimParsed = false;
    117             skipOptionalSVGSpaces(start, end);
    118            
    119             auto type = SVGTransformable::parseAndSkipType(start, end);
    120             if (!type)
    121                 return false;
    122 
    123             auto parsedTransformValue = SVGTransformable::parseTransformValue(*type, start, end);
    124             if (!parsedTransformValue)
    125                 return false;
    126 
    127             append(SVGTransform::create(*parsedTransformValue));
    128 
    129             skipOptionalSVGSpaces(start, end);
    130             if (start < end && *start == ',') {
    131                 delimParsed = true;
    132                 ++start;
    133             }
    134 
    135             skipOptionalSVGSpaces(start, end);
    136         }
    137         return !delimParsed;
    138     }
     66    template<typename CharacterType> bool parseGeneric(StringParsingBuffer<CharacterType>&);
     67    bool parse(StringParsingBuffer<LChar>&);
     68    bool parse(StringParsingBuffer<UChar>&);
    13969};
    14070
  • trunk/Source/WebCore/svg/SVGTransformable.cpp

    r263334 r263617  
    2828#include "SVGNames.h"
    2929#include "SVGParserUtilities.h"
     30#include <wtf/text/StringParsingBuffer.h>
    3031#include <wtf/text/StringView.h>
    3132
    3233namespace WebCore {
    3334
    34 static int parseTransformParamList(const UChar*& ptr, const UChar* end, float* values, int required, int optional)
     35SVGTransformable::~SVGTransformable() = default;
     36
     37template<typename CharacterType> static int parseTransformParamList(StringParsingBuffer<CharacterType>& buffer, float* values, int required, int optional)
    3538{
    3639    int optionalParams = 0, requiredParams = 0;
    3740   
    38     if (!skipOptionalSVGSpaces(ptr, end) || *ptr != '(')
     41    if (!skipOptionalSVGSpaces(buffer) || *buffer != '(')
    3942        return -1;
    4043   
    41     ptr++;
     44    ++buffer;
    4245   
    43     skipOptionalSVGSpaces(ptr, end);
     46    skipOptionalSVGSpaces(buffer);
    4447
    4548    while (requiredParams < required) {
    46         if (ptr >= end)
    47             return -1;
    48         auto parsedNumber = parseNumber(ptr, end, SuffixSkippingPolicy::DontSkip);
     49        if (buffer.atEnd())
     50            return -1;
     51        auto parsedNumber = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
    4952        if (!parsedNumber)
    5053            return -1;
     
    5255        requiredParams++;
    5356        if (requiredParams < required)
    54             skipOptionalSVGSpacesOrDelimiter(ptr, end);
    55     }
    56     if (!skipOptionalSVGSpaces(ptr, end))
     57            skipOptionalSVGSpacesOrDelimiter(buffer);
     58    }
     59    if (!skipOptionalSVGSpaces(buffer))
    5760        return -1;
    5861   
    59     bool delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end);
    60 
    61     if (ptr >= end)
     62    bool delimParsed = skipOptionalSVGSpacesOrDelimiter(buffer);
     63
     64    if (buffer.atEnd())
    6265        return -1;
    6366   
    64     if (*ptr == ')') { // skip optionals
    65         ptr++;
     67    if (*buffer == ')') {
     68        // skip optionals
     69        ++buffer;
    6670        if (delimParsed)
    6771            return -1;
    6872    } else {
    6973        while (optionalParams < optional) {
    70             if (ptr >= end)
     74            if (buffer.atEnd())
    7175                return -1;
    72             auto parsedNumber = parseNumber(ptr, end, SuffixSkippingPolicy::DontSkip);
     76            auto parsedNumber = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
    7377            if (!parsedNumber)
    7478                return -1;
     
    7680            optionalParams++;
    7781            if (optionalParams < optional)
    78                 skipOptionalSVGSpacesOrDelimiter(ptr, end);
     82                skipOptionalSVGSpacesOrDelimiter(buffer);
    7983        }
    8084       
    81         if (!skipOptionalSVGSpaces(ptr, end))
     85        if (!skipOptionalSVGSpaces(buffer))
    8286            return -1;
    8387       
    84         delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end);
     88        delimParsed = skipOptionalSVGSpacesOrDelimiter(buffer);
    8589       
    86         if (ptr >= end || *ptr != ')' || delimParsed)
    87             return -1;
    88         ptr++;
     90        if (buffer.atEnd() || *buffer != ')' || delimParsed)
     91            return -1;
     92        ++buffer;
    8993    }
    9094
     
    9397
    9498// These should be kept in sync with enum SVGTransformType
    95 static const int requiredValuesForType[] =  {0, 6, 1, 1, 1, 1, 1};
    96 static const int optionalValuesForType[] =  {0, 0, 1, 1, 2, 0, 0};
    97 
    98 // This destructor is needed in order to link correctly with Intel ICC.
    99 SVGTransformable::~SVGTransformable() = default;
    100 
    101 Optional<SVGTransformValue> SVGTransformable::parseTransformValue(SVGTransformValue::SVGTransformType type, const UChar*& ptr, const UChar* end)
     99static constexpr int requiredValuesForType[] =  { 0, 6, 1, 1, 1, 1, 1 };
     100static constexpr int optionalValuesForType[] =  { 0, 0, 1, 1, 2, 0, 0 };
     101
     102template<typename CharacterType> static Optional<SVGTransformValue> parseTransformValueGeneric(SVGTransformValue::SVGTransformType type, StringParsingBuffer<CharacterType>& buffer)
    102103{
    103104    if (type == SVGTransformValue::SVG_TRANSFORM_UNKNOWN)
     
    106107    int valueCount = 0;
    107108    float values[] = {0, 0, 0, 0, 0, 0};
    108     if ((valueCount = parseTransformParamList(ptr, end, values, requiredValuesForType[type], optionalValuesForType[type])) < 0)
     109    if ((valueCount = parseTransformParamList(buffer, values, requiredValuesForType[type], optionalValuesForType[type])) < 0)
    109110        return WTF::nullopt;
    110111
     
    146147}
    147148
    148 static const UChar skewXDesc[] =  {'s', 'k', 'e', 'w', 'X'};
    149 static const UChar skewYDesc[] =  {'s', 'k', 'e', 'w', 'Y'};
    150 static const UChar scaleDesc[] =  {'s', 'c', 'a', 'l', 'e'};
    151 static const UChar translateDesc[] =  {'t', 'r', 'a', 'n', 's', 'l', 'a', 't', 'e'};
    152 static const UChar rotateDesc[] =  {'r', 'o', 't', 'a', 't', 'e'};
    153 static const UChar matrixDesc[] =  {'m', 'a', 't', 'r', 'i', 'x'};
    154 
    155 Optional<SVGTransformValue::SVGTransformType> SVGTransformable::parseAndSkipType(const UChar*& currTransform, const UChar* end)
    156 {
    157     if (currTransform >= end)
    158         return WTF::nullopt;
    159 
    160     if (*currTransform == 's') {
    161         if (skipString(currTransform, end, skewXDesc, WTF_ARRAY_LENGTH(skewXDesc)))
     149Optional<SVGTransformValue> SVGTransformable::parseTransformValue(SVGTransformValue::SVGTransformType type, StringParsingBuffer<LChar>& buffer)
     150{
     151    return parseTransformValueGeneric(type, buffer);
     152}
     153
     154Optional<SVGTransformValue> SVGTransformable::parseTransformValue(SVGTransformValue::SVGTransformType type, StringParsingBuffer<UChar>& buffer)
     155{
     156    return parseTransformValueGeneric(type, buffer);
     157}
     158
     159template<typename CharacterType> static constexpr CharacterType skewXDesc[] =  {'s', 'k', 'e', 'w', 'X'};
     160template<typename CharacterType> static constexpr CharacterType skewYDesc[] =  {'s', 'k', 'e', 'w', 'Y'};
     161template<typename CharacterType> static constexpr CharacterType scaleDesc[] =  {'s', 'c', 'a', 'l', 'e'};
     162template<typename CharacterType> static constexpr CharacterType translateDesc[] =  {'t', 'r', 'a', 'n', 's', 'l', 'a', 't', 'e'};
     163template<typename CharacterType> static constexpr CharacterType rotateDesc[] =  {'r', 'o', 't', 'a', 't', 'e'};
     164template<typename CharacterType> static constexpr CharacterType matrixDesc[] =  {'m', 'a', 't', 'r', 'i', 'x'};
     165
     166template<typename CharacterType> static Optional<SVGTransformValue::SVGTransformType> parseTransformTypeGeneric(StringParsingBuffer<CharacterType>& buffer)
     167{
     168    if (buffer.atEnd())
     169        return WTF::nullopt;
     170
     171    if (*buffer == 's') {
     172        if (skipCharactersExactly(buffer, skewXDesc<CharacterType>))
    162173            return SVGTransformValue::SVG_TRANSFORM_SKEWX;
    163         else if (skipString(currTransform, end, skewYDesc, WTF_ARRAY_LENGTH(skewYDesc)))
     174        if (skipCharactersExactly(buffer, skewYDesc<CharacterType>))
    164175            return SVGTransformValue::SVG_TRANSFORM_SKEWY;
    165         else if (skipString(currTransform, end, scaleDesc, WTF_ARRAY_LENGTH(scaleDesc)))
     176        if (skipCharactersExactly(buffer, scaleDesc<CharacterType>))
    166177            return SVGTransformValue::SVG_TRANSFORM_SCALE;
    167         else
    168             return WTF::nullopt;
    169     } else if (skipString(currTransform, end, translateDesc, WTF_ARRAY_LENGTH(translateDesc)))
     178        return WTF::nullopt;
     179    }
     180
     181    if (skipCharactersExactly(buffer, translateDesc<CharacterType>))
    170182        return SVGTransformValue::SVG_TRANSFORM_TRANSLATE;
    171     else if (skipString(currTransform, end, rotateDesc, WTF_ARRAY_LENGTH(rotateDesc)))
     183    if (skipCharactersExactly(buffer, rotateDesc<CharacterType>))
    172184        return SVGTransformValue::SVG_TRANSFORM_ROTATE;
    173     else if (skipString(currTransform, end, matrixDesc, WTF_ARRAY_LENGTH(matrixDesc)))
     185    if (skipCharactersExactly(buffer, matrixDesc<CharacterType>))
    174186        return SVGTransformValue::SVG_TRANSFORM_MATRIX;
    175187
     
    177189}
    178190
    179 SVGTransformValue::SVGTransformType SVGTransformable::parseTransformType(const String& typeString)
    180 {
    181     auto upconvertedCharacters = StringView(typeString).upconvertedCharacters();
    182     const UChar* characters = upconvertedCharacters;
    183     return parseAndSkipType(characters, characters + typeString.length()).valueOr(SVGTransformValue::SVG_TRANSFORM_UNKNOWN);
    184 }
    185 
    186 }
     191Optional<SVGTransformValue::SVGTransformType> SVGTransformable::parseTransformType(StringView string)
     192{
     193    return readCharactersForParsing(string, [](auto buffer) {
     194        return parseTransformType(buffer);
     195    });
     196}
     197
     198Optional<SVGTransformValue::SVGTransformType> SVGTransformable::parseTransformType(StringParsingBuffer<LChar>& buffer)
     199{
     200    return parseTransformTypeGeneric(buffer);
     201}
     202
     203Optional<SVGTransformValue::SVGTransformType> SVGTransformable::parseTransformType(StringParsingBuffer<UChar>& buffer)
     204{
     205    return parseTransformTypeGeneric(buffer);
     206}
     207
     208}
  • trunk/Source/WebCore/svg/SVGTransformable.h

    r263334 r263617  
    2323#include "SVGLocatable.h"
    2424#include "SVGTransformValue.h"
    25 #include <wtf/text/WTFString.h>
    2625
    2726namespace WebCore {
     
    3332    virtual ~SVGTransformable();
    3433
    35     static Optional<SVGTransformValue> parseTransformValue(SVGTransformValue::SVGTransformType, const UChar*& ptr, const UChar* end);
    36     static SVGTransformValue::SVGTransformType parseTransformType(const String&);
    37     static Optional<SVGTransformValue::SVGTransformType> parseAndSkipType(const UChar*& currTransform, const UChar* end);
     34    static Optional<SVGTransformValue> parseTransformValue(SVGTransformValue::SVGTransformType, StringParsingBuffer<LChar>&);
     35    static Optional<SVGTransformValue> parseTransformValue(SVGTransformValue::SVGTransformType, StringParsingBuffer<UChar>&);
     36
     37    static Optional<SVGTransformValue::SVGTransformType> parseTransformType(StringView);
     38    static Optional<SVGTransformValue::SVGTransformType> parseTransformType(StringParsingBuffer<LChar>&);
     39    static Optional<SVGTransformValue::SVGTransformType> parseTransformType(StringParsingBuffer<UChar>&);
    3840
    3941    AffineTransform localCoordinateSpaceTransform(SVGLocatable::CTMScope) const override { return animatedLocalTransform(); }
  • trunk/Source/WebCore/svg/SVGViewSpec.cpp

    r263334 r263617  
    2929#include "SVGTransformList.h"
    3030#include "SVGTransformable.h"
     31#include <wtf/text/StringParsingBuffer.h>
    3132
    3233namespace WebCore {
     
    6162}
    6263
    63 static const UChar svgViewSpec[] = {'s', 'v', 'g', 'V', 'i', 'e', 'w'};
    64 static const UChar viewBoxSpec[] = {'v', 'i', 'e', 'w', 'B', 'o', 'x'};
    65 static const UChar preserveAspectRatioSpec[] = {'p', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'A', 's', 'p', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o'};
    66 static const UChar transformSpec[] = {'t', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm'};
    67 static const UChar zoomAndPanSpec[] = {'z', 'o', 'o', 'm', 'A', 'n', 'd', 'P', 'a', 'n'};
    68 static const UChar viewTargetSpec[] =  {'v', 'i', 'e', 'w', 'T', 'a', 'r', 'g', 'e', 't'};
     64template<typename CharacterType> static constexpr CharacterType svgViewSpec[] = {'s', 'v', 'g', 'V', 'i', 'e', 'w'};
     65template<typename CharacterType> static constexpr CharacterType viewBoxSpec[] = {'v', 'i', 'e', 'w', 'B', 'o', 'x'};
     66template<typename CharacterType> static constexpr CharacterType preserveAspectRatioSpec[] = {'p', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'A', 's', 'p', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o'};
     67template<typename CharacterType> static constexpr CharacterType transformSpec[] = {'t', 'r', 'a', 'n', 's', 'f', 'o', 'r', 'm'};
     68template<typename CharacterType> static constexpr CharacterType zoomAndPanSpec[] = {'z', 'o', 'o', 'm', 'A', 'n', 'd', 'P', 'a', 'n'};
     69template<typename CharacterType> static constexpr CharacterType viewTargetSpec[] =  {'v', 'i', 'e', 'w', 'T', 'a', 'r', 'g', 'e', 't'};
    6970
    70 bool SVGViewSpec::parseViewSpec(const String& viewSpec)
     71bool SVGViewSpec::parseViewSpec(const StringView& string)
    7172{
    72     auto upconvertedCharacters = StringView(viewSpec).upconvertedCharacters();
    73     const UChar* currViewSpec = upconvertedCharacters;
    74     const UChar* end = currViewSpec + viewSpec.length();
     73    return readCharactersForParsing(string, [&](auto buffer) -> bool {
     74        using CharacterType = typename decltype(buffer)::CharacterType;
    7575
    76     if (currViewSpec >= end || !m_contextElement)
    77         return false;
     76        if (buffer.atEnd() || !m_contextElement)
     77            return false;
    7878
    79     if (!skipString(currViewSpec, end, svgViewSpec, WTF_ARRAY_LENGTH(svgViewSpec)))
    80         return false;
     79        if (!skipCharactersExactly(buffer, svgViewSpec<CharacterType>))
     80            return false;
    8181
    82     if (currViewSpec >= end || *currViewSpec != '(')
    83         return false;
    84     currViewSpec++;
     82        if (!skipExactly(buffer, '('))
     83            return false;
    8584
    86     while (currViewSpec < end && *currViewSpec != ')') {
    87         if (*currViewSpec == 'v') {
    88             if (skipString(currViewSpec, end, viewBoxSpec, WTF_ARRAY_LENGTH(viewBoxSpec))) {
    89                 if (currViewSpec >= end || *currViewSpec != '(')
     85        while (buffer.hasCharactersRemaining() && *buffer != ')') {
     86            if (*buffer == 'v') {
     87                if (skipCharactersExactly(buffer, viewBoxSpec<CharacterType>)) {
     88                    if (!skipExactly(buffer, '('))
     89                        return false;
     90                    auto viewBox = SVGFitToViewBox::parseViewBox(buffer, false);
     91                    if (!viewBox)
     92                        return false;
     93                    setViewBox(WTFMove(*viewBox));
     94                    if (!skipExactly(buffer, ')'))
     95                        return false;
     96                } else if (skipCharactersExactly(buffer, viewTargetSpec<CharacterType>)) {
     97                    if (!skipExactly(buffer, '('))
     98                        return false;
     99                    auto viewTargetStart = buffer.position();
     100                    skipUntil(buffer, ')');
     101                    if (buffer.atEnd())
     102                        return false;
     103                    m_viewTargetString = String(viewTargetStart, buffer.position() - viewTargetStart);
     104                    ++buffer;
     105                } else
    90106                    return false;
    91                 currViewSpec++;
    92                 auto viewBox = SVGFitToViewBox::parseViewBox(currViewSpec, end, false);
    93                 if (!viewBox)
     107            } else if (*buffer == 'z') {
     108                if (!skipCharactersExactly(buffer, zoomAndPanSpec<CharacterType>))
    94109                    return false;
    95                 setViewBox(WTFMove(*viewBox));
    96                 if (currViewSpec >= end || *currViewSpec != ')')
     110                if (!skipExactly(buffer, '('))
    97111                    return false;
    98                 currViewSpec++;
    99             } else if (skipString(currViewSpec, end, viewTargetSpec, WTF_ARRAY_LENGTH(viewTargetSpec))) {
    100                 if (currViewSpec >= end || *currViewSpec != '(')
     112                auto zoomAndPan = SVGZoomAndPan::parseZoomAndPan(buffer);
     113                if (!zoomAndPan)
    101114                    return false;
    102                 const UChar* viewTargetStart = ++currViewSpec;
    103                 while (currViewSpec < end && *currViewSpec != ')')
    104                     currViewSpec++;
    105                 if (currViewSpec >= end)
     115                setZoomAndPan(*zoomAndPan);
     116                if (!skipExactly(buffer, ')'))
    106117                    return false;
    107                 m_viewTargetString = String(viewTargetStart, currViewSpec - viewTargetStart);
    108                 currViewSpec++;
     118            } else if (*buffer == 'p') {
     119                if (!skipCharactersExactly(buffer, preserveAspectRatioSpec<CharacterType>))
     120                    return false;
     121                if (!skipExactly(buffer, '('))
     122                    return false;
     123                SVGPreserveAspectRatioValue preserveAspectRatio;
     124                if (!preserveAspectRatio.parse(buffer, false))
     125                    return false;
     126                setPreserveAspectRatio(preserveAspectRatio);
     127                if (!skipExactly(buffer, ')'))
     128                    return false;
     129            } else if (*buffer == 't') {
     130                if (!skipCharactersExactly(buffer, transformSpec<CharacterType>))
     131                    return false;
     132                if (!skipExactly(buffer, '('))
     133                    return false;
     134                m_transform->parse(buffer);
     135                if (!skipExactly(buffer, ')'))
     136                    return false;
    109137            } else
    110138                return false;
    111         } else if (*currViewSpec == 'z') {
    112             if (!skipString(currViewSpec, end, zoomAndPanSpec, WTF_ARRAY_LENGTH(zoomAndPanSpec)))
    113                 return false;
    114             if (currViewSpec >= end || *currViewSpec != '(')
    115                 return false;
    116             currViewSpec++;
    117             if (!SVGZoomAndPan::parseZoomAndPan(currViewSpec, end))
    118                 return false;
    119             if (currViewSpec >= end || *currViewSpec != ')')
    120                 return false;
    121             currViewSpec++;
    122         } else if (*currViewSpec == 'p') {
    123             if (!skipString(currViewSpec, end, preserveAspectRatioSpec, WTF_ARRAY_LENGTH(preserveAspectRatioSpec)))
    124                 return false;
    125             if (currViewSpec >= end || *currViewSpec != '(')
    126                 return false;
    127             currViewSpec++;
    128             SVGPreserveAspectRatioValue preserveAspectRatio;
    129             if (!preserveAspectRatio.parse(currViewSpec, end, false))
    130                 return false;
    131             setPreserveAspectRatio(preserveAspectRatio);
    132             if (currViewSpec >= end || *currViewSpec != ')')
    133                 return false;
    134             currViewSpec++;
    135         } else if (*currViewSpec == 't') {
    136             if (!skipString(currViewSpec, end, transformSpec, WTF_ARRAY_LENGTH(transformSpec)))
    137                 return false;
    138             if (currViewSpec >= end || *currViewSpec != '(')
    139                 return false;
    140             currViewSpec++;
    141             m_transform->parse(currViewSpec, end);
    142             if (currViewSpec >= end || *currViewSpec != ')')
    143                 return false;
    144             currViewSpec++;
    145         } else
     139
     140            skipExactly(buffer, ';');
     141        }
     142
     143        if (buffer.atEnd() || *buffer != ')')
    146144            return false;
    147145
    148         if (currViewSpec < end && *currViewSpec == ';')
    149             currViewSpec++;
    150     }
    151    
    152     if (currViewSpec >= end || *currViewSpec != ')')
    153         return false;
    154 
    155     return true;
     146        return true;
     147    });
    156148}
    157149
  • trunk/Source/WebCore/svg/SVGViewSpec.h

    r244115 r263617  
    3737    }
    3838
    39     bool parseViewSpec(const String&);
     39    bool parseViewSpec(const StringView&);
    4040    void reset();
    4141    void resetContextElement() { m_contextElement = nullptr; }
  • trunk/Source/WebCore/svg/SVGZoomAndPan.cpp

    r254703 r263617  
    2323#include "SVGZoomAndPan.h"
    2424
    25 #include <wtf/text/StringConcatenateNumbers.h>
    26 
    2725namespace WebCore {
    2826
    29 bool SVGZoomAndPan::parseZoomAndPan(const UChar*& start, const UChar* end)
     27template<typename CharacterType> static constexpr CharacterType disable[] = { 'd', 'i', 's', 'a', 'b', 'l', 'e' };
     28template<typename CharacterType> static constexpr CharacterType magnify[] = { 'm', 'a', 'g', 'n', 'i', 'f', 'y' };
     29
     30template<typename CharacterType> static Optional<SVGZoomAndPanType> parseZoomAndPanGeneric(StringParsingBuffer<CharacterType>& buffer)
    3031{
    31     static const UChar disable[] = { 'd', 'i', 's', 'a', 'b', 'l', 'e' };
    32     if (skipString(start, end, disable, WTF_ARRAY_LENGTH(disable))) {
    33         m_zoomAndPan = SVGZoomAndPanDisable;
    34         return true;
    35     }
     32    if (skipCharactersExactly(buffer, disable<CharacterType>))
     33        return SVGZoomAndPanDisable;
    3634
    37     static const UChar magnify[] = { 'm', 'a', 'g', 'n', 'i', 'f', 'y' };
    38     if (skipString(start, end, magnify, WTF_ARRAY_LENGTH(magnify))) {
    39         m_zoomAndPan = SVGZoomAndPanMagnify;
    40         return true;
    41     }
     35    if (skipCharactersExactly(buffer, magnify<CharacterType>))
     36        return SVGZoomAndPanMagnify;
    4237
    43     return false;
     38    return WTF::nullopt;
     39}
     40
     41Optional<SVGZoomAndPanType> SVGZoomAndPan::parseZoomAndPan(StringParsingBuffer<LChar>& buffer)
     42{
     43    return parseZoomAndPanGeneric(buffer);
     44}
     45
     46Optional<SVGZoomAndPanType> SVGZoomAndPan::parseZoomAndPan(StringParsingBuffer<UChar>& buffer)
     47{
     48    return parseZoomAndPanGeneric(buffer);
    4449}
    4550
  • trunk/Source/WebCore/svg/SVGZoomAndPan.h

    r246490 r263617  
    4949    SVGZoomAndPan() = default;
    5050
    51     bool parseZoomAndPan(const UChar*&, const UChar*);
     51    static Optional<SVGZoomAndPanType> parseZoomAndPan(StringParsingBuffer<LChar>&);
     52    static Optional<SVGZoomAndPanType> parseZoomAndPan(StringParsingBuffer<UChar>&);
    5253
    5354private:
Note: See TracChangeset for help on using the changeset viewer.