diff options
Diffstat (limited to 'JavaScriptCore/runtime/StringPrototype.cpp')
-rw-r--r-- | JavaScriptCore/runtime/StringPrototype.cpp | 118 |
1 files changed, 99 insertions, 19 deletions
diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp index d002e07..8c014ec 100644 --- a/JavaScriptCore/runtime/StringPrototype.cpp +++ b/JavaScriptCore/runtime/StringPrototype.cpp @@ -28,6 +28,7 @@ #include "JSGlobalObjectFunctions.h" #include "JSArray.h" #include "JSFunction.h" +#include "JSStringBuilder.h" #include "ObjectPrototype.h" #include "Operations.h" #include "PropertyNameArray.h" @@ -227,6 +228,86 @@ static inline int localeCompare(const UString& a, const UString& b) return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.data()), a.size(), reinterpret_cast<const ::UChar*>(b.data()), b.size()); } +struct StringRange { +public: + StringRange(int pos, int len) + : position(pos) + , length(len) + { + } + + StringRange() + { + } + + int position; + int length; +}; + +JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount); +JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount) +{ + if (rangeCount == 1 && separatorCount == 0) { + int sourceSize = source.size(); + int position = substringRanges[0].position; + int length = substringRanges[0].length; + if (position <= 0 && length >= sourceSize) + return sourceVal; + // We could call UString::substr, but this would result in redundant checks + return jsString(exec, UStringImpl::create(source.rep(), max(0, position), min(sourceSize, length))); + } + + int totalLength = 0; + for (int i = 0; i < rangeCount; i++) + totalLength += substringRanges[i].length; + for (int i = 0; i < separatorCount; i++) + totalLength += separators[i].size(); + + if (totalLength == 0) + return jsString(exec, ""); + + UChar* buffer; + PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer); + if (!impl) + return throwOutOfMemoryError(exec); + + int maxCount = max(rangeCount, separatorCount); + int bufferPos = 0; + for (int i = 0; i < maxCount; i++) { + if (i < rangeCount) { + UStringImpl::copyChars(buffer + bufferPos, source.data() + substringRanges[i].position, substringRanges[i].length); + bufferPos += substringRanges[i].length; + } + if (i < separatorCount) { + UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size()); + bufferPos += separators[i].size(); + } + } + + return jsString(exec, impl); +} + +JSValue jsReplaceRange(ExecState* exec, const UString& source, int rangeStart, int rangeLength, const UString& replacement); +JSValue jsReplaceRange(ExecState* exec, const UString& source, int rangeStart, int rangeLength, const UString& replacement) +{ + int replacementLength = replacement.size(); + int totalLength = source.size() - rangeLength + replacementLength; + if (totalLength == 0) + return jsString(exec, ""); + + UChar* buffer; + PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer); + if (!impl) + return throwOutOfMemoryError(exec); + + UStringImpl::copyChars(buffer, source.data(), rangeStart); + UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength); + int rangeEnd = rangeStart + rangeLength; + UStringImpl::copyChars(buffer + rangeStart + replacementLength, source.data() + rangeEnd, source.size() - rangeEnd); + + return jsString(exec, impl); +} + JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { JSString* sourceVal = thisValue.toThisJSString(exec); @@ -250,7 +331,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue int lastIndex = 0; int startPosition = 0; - Vector<UString::Range, 16> sourceRanges; + Vector<StringRange, 16> sourceRanges; Vector<UString, 16> replacements; // This is either a loop (if global is set) or a one-way (if not). @@ -269,7 +350,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue if (matchIndex < 0) break; - sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); int completeMatchStart = ovector[0]; unsigned i = 0; @@ -311,7 +392,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue if (matchIndex < 0) break; - sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); if (callType != CallTypeNone) { int completeMatchStart = ovector[0]; @@ -352,10 +433,9 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue return sourceVal; if (lastIndex < source.size()) - sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex)); + sourceRanges.append(StringRange(lastIndex, source.size() - lastIndex)); - return jsString(exec, source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), - replacements.data(), replacements.size())); + return jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()); } // Not a regular expression, so treat the pattern as a string. @@ -377,7 +457,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue } int ovector[2] = { matchPos, matchPos + matchLen }; - return jsString(exec, source.replaceRange(matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0))); + return jsReplaceRange(exec, source, matchPos, matchLen, substituteBackreferences(replacementString, source, ovector, 0)); } JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -789,62 +869,62 @@ JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, J JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<big>", s, "</big>")); + return jsMakeNontrivialString(exec, "<big>", s, "</big>"); } JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<small>", s, "</small>")); + return jsMakeNontrivialString(exec, "<small>", s, "</small>"); } JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<blink>", s, "</blink>")); + return jsMakeNontrivialString(exec, "<blink>", s, "</blink>"); } JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<b>", s, "</b>")); + return jsMakeNontrivialString(exec, "<b>", s, "</b>"); } JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsString(exec, makeString("<tt>", s, "</tt>")); + return jsMakeNontrivialString(exec, "<tt>", s, "</tt>"); } JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<i>", s, "</i>")); + return jsMakeNontrivialString(exec, "<i>", s, "</i>"); } JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<strike>", s, "</strike>")); + return jsMakeNontrivialString(exec, "<strike>", s, "</strike>"); } JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<sub>", s, "</sub>")); + return jsMakeNontrivialString(exec, "<sub>", s, "</sub>"); } JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, makeString("<sup>", s, "</sup>")); + return jsMakeNontrivialString(exec, "<sup>", s, "</sup>"); } JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); - return jsNontrivialString(exec, makeString("<font color=\"", a0.toString(exec), "\">", s, "</font>")); + return jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec), "\">", s, "</font>"); } JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -886,14 +966,14 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu return jsNontrivialString(exec, impl); } - return jsNontrivialString(exec, makeString("<font size=\"", a0.toString(exec), "\">", s, "</font>")); + return jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec), "\">", s, "</font>"); } JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); - return jsNontrivialString(exec, makeString("<a name=\"", a0.toString(exec), "\">", s, "</a>")); + return jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec), "\">", s, "</a>"); } JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) |