Changeset 54531 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Feb 8, 2010, 11:40:57 PM (15 years ago)
Author:
[email protected]
Message:

Make String.replace throw an exception on out-of-memory, rather than
returning a null (err, empty-ish) string. Move String::replaceRange
and String::spliceSubstringsWithSeparators out to StringPrototype -
these were fairly specific use anyway, and we can better integrate
throwing the JS expcetion this way.

Reviewed by Oliver Hunt

Also removes redundant assignment operator from UString.

(JSC::StringRange::StringRange):
(JSC::jsSpliceSubstringsWithSeparators):
(JSC::jsReplaceRange):
(JSC::stringProtoFuncReplace):

  • runtime/UString.cpp:
  • runtime/UString.h:
Location:
trunk/JavaScriptCore/runtime
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/StringPrototype.cpp

    r54394 r54531  
    229229}
    230230
     231struct StringRange {
     232public:
     233    StringRange(int pos, int len)
     234        : position(pos)
     235        , length(len)
     236    {
     237    }
     238
     239    StringRange()
     240    {
     241    }
     242
     243    int position;
     244    int length;
     245};
     246
     247JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount)
     248{
     249    if (rangeCount == 1 && separatorCount == 0) {
     250        int sourceSize = source.size();
     251        int position = substringRanges[0].position;
     252        int length = substringRanges[0].length;
     253        if (position <= 0 && length >= sourceSize)
     254            return sourceVal;
     255        // We could call UString::substr, but this would result in redundant checks
     256        return jsString(exec, UStringImpl::create(source.rep(), max(0, position), min(sourceSize, length)));
     257    }
     258
     259    int totalLength = 0;
     260    for (int i = 0; i < rangeCount; i++)
     261        totalLength += substringRanges[i].length;
     262    for (int i = 0; i < separatorCount; i++)
     263        totalLength += separators[i].size();
     264
     265    if (totalLength == 0)
     266        return jsString(exec, "");
     267
     268    UChar* buffer;
     269    PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer);
     270    if (!impl)
     271        return throwOutOfMemoryError(exec);
     272
     273    int maxCount = max(rangeCount, separatorCount);
     274    int bufferPos = 0;
     275    for (int i = 0; i < maxCount; i++) {
     276        if (i < rangeCount) {
     277            UStringImpl::copyChars(buffer + bufferPos, source.data() + substringRanges[i].position, substringRanges[i].length);
     278            bufferPos += substringRanges[i].length;
     279        }
     280        if (i < separatorCount) {
     281            UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
     282            bufferPos += separators[i].size();
     283        }
     284    }
     285
     286    return jsString(exec, impl);
     287}
     288
     289JSValue jsReplaceRange(ExecState* exec, const UString& source, int rangeStart, int rangeLength, const UString& replacement)
     290{
     291    int replacementLength = replacement.size();
     292    int totalLength = source.size() - rangeLength + replacementLength;
     293    if (totalLength == 0)
     294        return jsString(exec, "");
     295
     296    UChar* buffer;
     297    PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer);
     298    if (!impl)
     299        return throwOutOfMemoryError(exec);
     300
     301    UStringImpl::copyChars(buffer, source.data(), rangeStart);
     302    UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength);
     303    int rangeEnd = rangeStart + rangeLength;
     304    UStringImpl::copyChars(buffer + rangeStart + replacementLength, source.data() + rangeEnd, source.size() - rangeEnd);
     305
     306    return jsString(exec, impl);
     307}
     308
    231309JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
    232310{
     
    252330        int startPosition = 0;
    253331
    254         Vector<UString::Range, 16> sourceRanges;
     332        Vector<StringRange, 16> sourceRanges;
    255333        Vector<UString, 16> replacements;
    256334
     
    271349                    break;
    272350               
    273                 sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
     351                sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
    274352
    275353                int completeMatchStart = ovector[0];
     
    313391                    break;
    314392
    315                 sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
     393                sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
    316394
    317395                if (callType != CallTypeNone) {
     
    354432
    355433        if (lastIndex < source.size())
    356             sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex));
    357 
    358         return jsString(exec, source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(),
    359             replacements.data(), replacements.size()));
     434            sourceRanges.append(StringRange(lastIndex, source.size() - lastIndex));
     435
     436        return jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size());
    360437    }
    361438
     
    379456
    380457    int ovector[2] = { matchPos, matchPos + matchLen };
    381     return jsString(exec, source.replaceRange(matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0)));
     458    return jsReplaceRange(exec, source, matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0));
    382459}
    383460
  • trunk/JavaScriptCore/runtime/UString.cpp

    r54464 r54531  
    312312}
    313313
    314 UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
    315 {
    316     m_rep->checkConsistency();
    317 
    318     if (rangeCount == 1 && separatorCount == 0) {
    319         int thisSize = size();
    320         int position = substringRanges[0].position;
    321         int length = substringRanges[0].length;
    322         if (position <= 0 && length >= thisSize)
    323             return *this;
    324         return UString::Rep::create(m_rep, max(0, position), min(thisSize, length));
    325     }
    326 
    327     int totalLength = 0;
    328     for (int i = 0; i < rangeCount; i++)
    329         totalLength += substringRanges[i].length;
    330     for (int i = 0; i < separatorCount; i++)
    331         totalLength += separators[i].size();
    332 
    333     if (totalLength == 0)
    334         return "";
    335 
    336     UChar* buffer;
    337     PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer);
    338     if (!rep)
    339         return null();
    340 
    341     int maxCount = max(rangeCount, separatorCount);
    342     int bufferPos = 0;
    343     for (int i = 0; i < maxCount; i++) {
    344         if (i < rangeCount) {
    345             UStringImpl::copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length);
    346             bufferPos += substringRanges[i].length;
    347         }
    348         if (i < separatorCount) {
    349             UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
    350             bufferPos += separators[i].size();
    351         }
    352     }
    353 
    354     return rep;
    355 }
    356 
    357 UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const
    358 {
    359     m_rep->checkConsistency();
    360 
    361     int replacementLength = replacement.size();
    362     int totalLength = size() - rangeLength + replacementLength;
    363     if (totalLength == 0)
    364         return "";
    365 
    366     UChar* buffer;
    367     PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer);
    368     if (!rep)
    369         return null();
    370 
    371     UStringImpl::copyChars(buffer, data(), rangeStart);
    372     UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength);
    373     int rangeEnd = rangeStart + rangeLength;
    374     UStringImpl::copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd);
    375 
    376     return rep;
    377 }
    378 
    379314bool UString::getCString(CStringBuffer& buffer) const
    380315{
     
    420355
    421356    return asciiBuffer;
    422 }
    423 
    424 UString& UString::operator=(const char* c)
    425 {
    426     if (!c) {
    427         m_rep = s_nullRep;
    428         return *this;
    429     }
    430 
    431     if (!c[0]) {
    432         m_rep = &Rep::empty();
    433         return *this;
    434     }
    435 
    436     int l = static_cast<int>(strlen(c));
    437     UChar* d = 0;
    438     m_rep = Rep::tryCreateUninitialized(l, d);
    439     if (m_rep) {
    440         for (int i = 0; i < l; i++)
    441             d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
    442     } else
    443         m_rep = s_nullRep;;
    444 
    445     return *this;
    446357}
    447358
  • trunk/JavaScriptCore/runtime/UString.h

    r54518 r54531  
    118118        static UString from(double);
    119119
    120         struct Range {
    121         public:
    122             Range(int pos, int len)
    123                 : position(pos)
    124                 , length(len)
    125             {
    126             }
    127 
    128             Range()
    129             {
    130             }
    131 
    132             int position;
    133             int length;
    134         };
    135 
    136         UString spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const;
    137 
    138         UString replaceRange(int rangeStart, int RangeEnd, const UString& replacement) const;
    139 
    140120        bool getCString(CStringBuffer&) const;
    141121
     
    153133         */
    154134        CString UTF8String(bool strict = false) const;
    155 
    156         UString& operator=(const char*c);
    157135
    158136        const UChar* data() const { return m_rep->data(); }
Note: See TracChangeset for help on using the changeset viewer.