📄 stringprototype.cpp
字号:
/* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */#include "config.h"#include "StringPrototype.h"#include "JSArray.h"#include "JSFunction.h"#include "ObjectPrototype.h"#include "PropertyNameArray.h"#include "RegExpConstructor.h"#include "RegExpObject.h"#include <wtf/ASCIICType.h>#include <wtf/MathExtras.h>#include <wtf/unicode/Collator.h>using namespace WTF;namespace JSC {ASSERT_CLASS_FITS_IN_CELL(StringPrototype);static JSValuePtr stringProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncCharAt(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncConcat(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncMatch(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncReplace(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncSearch(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncSlice(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncSplit(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncSubstr(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncSubstring(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncBig(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncSmall(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncBlink(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncBold(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncFixed(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncItalics(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncStrike(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncSub(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncSup(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncFontcolor(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncFontsize(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncAnchor(ExecState*, JSObject*, JSValuePtr, const ArgList&);static JSValuePtr stringProtoFuncLink(ExecState*, JSObject*, JSValuePtr, const ArgList&);}#include "StringPrototype.lut.h"namespace JSC {const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, ExecState::stringTable };/* Source for StringPrototype.lut.h@begin stringTable 26 toString stringProtoFuncToString DontEnum|Function 0 valueOf stringProtoFuncToString DontEnum|Function 0 charAt stringProtoFuncCharAt DontEnum|Function 1 charCodeAt stringProtoFuncCharCodeAt DontEnum|Function 1 concat stringProtoFuncConcat DontEnum|Function 1 indexOf stringProtoFuncIndexOf DontEnum|Function 1 lastIndexOf stringProtoFuncLastIndexOf DontEnum|Function 1 match stringProtoFuncMatch DontEnum|Function 1 replace stringProtoFuncReplace DontEnum|Function 2 search stringProtoFuncSearch DontEnum|Function 1 slice stringProtoFuncSlice DontEnum|Function 2 split stringProtoFuncSplit DontEnum|Function 2 substr stringProtoFuncSubstr DontEnum|Function 2 substring stringProtoFuncSubstring DontEnum|Function 2 toLowerCase stringProtoFuncToLowerCase DontEnum|Function 0 toUpperCase stringProtoFuncToUpperCase DontEnum|Function 0 localeCompare stringProtoFuncLocaleCompare DontEnum|Function 1 # toLocaleLowerCase and toLocaleUpperCase are currently identical to toLowerCase and toUpperCase toLocaleLowerCase stringProtoFuncToLowerCase DontEnum|Function 0 toLocaleUpperCase stringProtoFuncToUpperCase DontEnum|Function 0 big stringProtoFuncBig DontEnum|Function 0 small stringProtoFuncSmall DontEnum|Function 0 blink stringProtoFuncBlink DontEnum|Function 0 bold stringProtoFuncBold DontEnum|Function 0 fixed stringProtoFuncFixed DontEnum|Function 0 italics stringProtoFuncItalics DontEnum|Function 0 strike stringProtoFuncStrike DontEnum|Function 0 sub stringProtoFuncSub DontEnum|Function 0 sup stringProtoFuncSup DontEnum|Function 0 fontcolor stringProtoFuncFontcolor DontEnum|Function 1 fontsize stringProtoFuncFontsize DontEnum|Function 1 anchor stringProtoFuncAnchor DontEnum|Function 1 link stringProtoFuncLink DontEnum|Function 1@end*/// ECMA 15.5.4StringPrototype::StringPrototype(ExecState* exec, PassRefPtr<Structure> structure) : StringObject(exec, structure){ // The constructor will be added later, after StringConstructor has been built putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);}bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot){ return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot);}// ------------------------------ Functions --------------------------static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg){ UString substitutedReplacement; int offset = 0; int i = -1; while ((i = replacement.find('$', i + 1)) != -1) { if (i + 1 == replacement.size()) break; UChar ref = replacement[i + 1]; if (ref == '$') { // "$$" -> "$" ++i; substitutedReplacement.append(replacement.data() + offset, i - offset); offset = i + 1; continue; } int backrefStart; int backrefLength; int advance = 0; if (ref == '&') { backrefStart = ovector[0]; backrefLength = ovector[1] - backrefStart; } else if (ref == '`') { backrefStart = 0; backrefLength = ovector[0]; } else if (ref == '\'') { backrefStart = ovector[1]; backrefLength = source.size() - backrefStart; } else if (reg && ref >= '0' && ref <= '9') { // 1- and 2-digit back references are allowed unsigned backrefIndex = ref - '0'; if (backrefIndex > reg->numSubpatterns()) continue; if (replacement.size() > i + 2) { ref = replacement[i + 2]; if (ref >= '0' && ref <= '9') { backrefIndex = 10 * backrefIndex + ref - '0'; if (backrefIndex > reg->numSubpatterns()) backrefIndex = backrefIndex / 10; // Fall back to the 1-digit reference else advance = 1; } } if (!backrefIndex) continue; backrefStart = ovector[2 * backrefIndex]; backrefLength = ovector[2 * backrefIndex + 1] - backrefStart; } else continue; if (i - offset) substitutedReplacement.append(replacement.data() + offset, i - offset); i += 1 + advance; offset = i + 1; substitutedReplacement.append(source.data() + backrefStart, backrefLength); } if (!offset) return replacement; if (replacement.size() - offset) substitutedReplacement.append(replacement.data() + offset, replacement.size() - offset); return substitutedReplacement;}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());}JSValuePtr stringProtoFuncReplace(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args){ JSString* sourceVal = thisValue.toThisJSString(exec); const UString& source = sourceVal->value(); JSValuePtr pattern = args.at(exec, 0); JSValuePtr replacement = args.at(exec, 1); UString replacementString; CallData callData; CallType callType = replacement.getCallData(callData); if (callType == CallTypeNone) replacementString = replacement.toString(exec); if (pattern.isObject(&RegExpObject::info)) { RegExp* reg = asRegExpObject(pattern)->regExp(); bool global = reg->global(); RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int lastIndex = 0; int startPosition = 0; Vector<UString::Range, 16> sourceRanges; Vector<UString, 16> replacements; // This is either a loop (if global is set) or a one-way (if not). do { int matchIndex; int matchLen; int* ovector; regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); if (matchIndex < 0) break; sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); if (callType != CallTypeNone) { int completeMatchStart = ovector[0]; ArgList args; for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) { int matchStart = ovector[i * 2]; int matchLen = ovector[i * 2 + 1] - matchStart; if (matchStart < 0) args.append(jsUndefined()); else args.append(jsSubstring(exec, source, matchStart, matchLen)); } args.append(jsNumber(exec, completeMatchStart)); args.append(sourceVal); replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec)); if (exec->hadException()) break; } else replacements.append(substituteBackreferences(replacementString, source, ovector, reg)); lastIndex = matchIndex + matchLen; startPosition = lastIndex; // special case of empty match if (matchLen == 0) { startPosition++; if (startPosition > source.size()) break; } } while (global); if (lastIndex < source.size()) sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex)); UString result = source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()); if (result == source)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -