⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286062 in webkit


Ignore:
Timestamp:
Nov 19, 2021, 7:57:39 AM (5 years ago)
Author:
commit-queue@webkit.org
Message:

Remove allocation in JSON::Value::parseJSON
https://bugs.webkit.org/show_bug.cgi?id=233346

Patch by Alex Christensen <achristensen@webkit.org> on 2021-11-19
Reviewed by Yusuke Suzuki.

Parse the characters as Latin1 characters if we have an 8 bit string rather than converting them to UTF-16 just to be parsed.

  • wtf/JSONValues.cpp:

(WTF::JSONImpl::Value::parseJSON):

Location:
trunk/Source/WTF
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r286048 r286062  
     12021-11-19  Alex Christensen  <achristensen@webkit.org>
     2
     3        Remove allocation in JSON::Value::parseJSON
     4        https://bugs.webkit.org/show_bug.cgi?id=233346
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        Parse the characters as Latin1 characters if we have an 8 bit string rather than converting them to UTF-16 just to be parsed.
     9
     10        * wtf/JSONValues.cpp:
     11        (WTF::JSONImpl::Value::parseJSON):
     12
    1132021-11-18  Antoine Quint  <graouts@webkit.org>
    214
  • trunk/Source/WTF/wtf/JSONValues.cpp

    r285443 r286062  
    6262const char* const falseToken = "false";
    6363
    64 bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEnd, const char* token)
     64template<typename CodeUnit>
     65bool parseConstToken(const CodeUnit* start, const CodeUnit* end, const CodeUnit** tokenEnd, const char* token)
    6566{
    6667    while (start < end && *token != '\0' && *start++ == *token++) { }
     
    7374}
    7475
    75 bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros)
     76template<typename CodeUnit>
     77bool readInt(const CodeUnit* start, const CodeUnit* end, const CodeUnit** tokenEnd, bool canHaveLeadingZeros)
    7678{
    7779    if (start == end)
     
    9597}
    9698
    97 bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
     99template<typename CodeUnit>
     100bool parseNumberToken(const CodeUnit* start, const CodeUnit* end, const CodeUnit** tokenEnd)
    98101{
    99102    // We just grab the number here. We validate the size in DecodeNumber.
     
    102105        return false;
    103106
    104     UChar c = *start;
     107    CodeUnit c = *start;
    105108    if ('-' == c)
    106109        ++start;
     
    146149}
    147150
    148 bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits)
     151template<typename CodeUnit>
     152bool readHexDigits(const CodeUnit* start, const CodeUnit* end, const CodeUnit** tokenEnd, int digits)
    149153{
    150154    if (end - start < digits)
     
    160164}
    161165
    162 bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
     166template<typename CodeUnit>
     167bool parseStringToken(const CodeUnit* start, const CodeUnit* end, const CodeUnit** tokenEnd)
    163168{
    164169    while (start < end) {
    165         UChar c = *start++;
     170        CodeUnit c = *start++;
    166171        if ('\\' == c && start < end) {
    167172            c = *start++;
     
    198203}
    199204
    200 Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, const UChar** tokenEnd)
     205template<typename CodeUnit>
     206Token parseToken(const CodeUnit* start, const CodeUnit* end, const CodeUnit** tokenStart, const CodeUnit** tokenEnd)
    201207{
    202208    while (start < end && isSpaceOrNewline(*start))
     
    262268}
    263269
    264 bool decodeString(const UChar* start, const UChar* end, StringBuilder& output)
     270template<typename CodeUnit>
     271bool decodeString(const CodeUnit* start, const CodeUnit* end, StringBuilder& output)
    265272{
    266273    while (start < end) {
     
    317324}
    318325
    319 bool decodeString(const UChar* start, const UChar* end, String& output)
     326template<typename CodeUnit>
     327bool decodeString(const CodeUnit* start, const CodeUnit* end, String& output)
    320328{
    321329    if (start == end) {
     
    336344}
    337345
    338 RefPtr<JSON::Value> buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth)
     346template<typename CodeUnit>
     347RefPtr<JSON::Value> buildValue(const CodeUnit* start, const CodeUnit* end, const CodeUnit** valueTokenEnd, int depth)
    339348{
    340349    if (depth > stackLimit)
     
    342351
    343352    RefPtr<JSON::Value> result;
    344     const UChar* tokenStart;
    345     const UChar* tokenEnd;
     353    const CodeUnit* tokenStart;
     354    const CodeUnit* tokenEnd;
    346355    Token token = parseToken(start, end, &tokenStart, &tokenEnd);
    347356    switch (token) {
     
    507516RefPtr<Value> Value::parseJSON(const String& json)
    508517{
    509     // FIXME: This whole file should just use StringView instead of UChar/length and avoid upconverting.
    510     auto characters = StringView(json).upconvertedCharacters();
    511     const UChar* start = characters;
    512     const UChar* end = start + json.length();
    513     const UChar* tokenEnd;
    514     auto result = buildValue(start, end, &tokenEnd, 0);
    515     if (!result)
    516         return nullptr;
    517 
    518     for (const UChar* valueEnd = tokenEnd; valueEnd < end; ++valueEnd) {
    519         if (!isSpaceOrNewline(*valueEnd))
     518    auto containsNonSpace = [] (const auto* begin, const auto* end) {
     519        if (!begin)
     520            return false;
     521        for (const auto* it = begin; it < end; it++) {
     522            if (!isSpaceOrNewline(*it))
     523                return true;
     524        }
     525        return false;
     526    };
     527
     528    RefPtr<Value> result;
     529    if (json.is8Bit()) {
     530        const LChar* start = json.characters8();
     531        const LChar* end = start + json.length();
     532        const LChar* tokenEnd { nullptr };
     533        result = buildValue(start, end, &tokenEnd, 0);
     534        if (containsNonSpace(tokenEnd, end))
    520535            return nullptr;
    521     }
    522 
     536    } else {
     537        const UChar* start = json.characters16();
     538        const UChar* end = start + json.length();
     539        const UChar* tokenEnd { nullptr };
     540        result = buildValue(start, end, &tokenEnd, 0);
     541        if (containsNonSpace(tokenEnd, end))
     542            return nullptr;
     543    }
    523544    return result;
    524545}
Note: See TracChangeset for help on using the changeset viewer.