Merged changes from LABYRINTH_KDE_3_MERGE branch.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@798 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/string_object.cpp b/JavaScriptCore/kjs/string_object.cpp
index 8e088bc..5f47f0f 100644
--- a/JavaScriptCore/kjs/string_object.cpp
+++ b/JavaScriptCore/kjs/string_object.cpp
@@ -1,3 +1,4 @@
+// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
@@ -15,62 +16,511 @@
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
*/
-#include "kjs.h"
-#include "operations.h"
+#include "value.h"
+#include "object.h"
#include "types.h"
+#include "interpreter.h"
+#include "operations.h"
#include "regexp.h"
+#include "regexp_object.h"
#include "string_object.h"
+#include "error_object.h"
#include <stdio.h>
+#include "string_object.lut.h"
using namespace KJS;
-StringObject::StringObject(const Object &funcProto, const Object &stringProto)
- : ConstructorImp(funcProto, 1)
+// ------------------------------ StringInstanceImp ----------------------------
+
+const ClassInfo StringInstanceImp::info = {"String", 0, 0, 0};
+
+StringInstanceImp::StringInstanceImp(const Object &proto)
+ : ObjectImp(proto)
{
- // ECMA 15.5.3.1 String.prototype
- setPrototypeProperty(stringProto);
+ setInternalValue(String(""));
}
-KJSO StringObject::get(const UString &p) const
+// ------------------------------ StringPrototypeImp ---------------------------
+const ClassInfo StringPrototypeImp::info = {"String", &StringInstanceImp::info, &stringTable, 0};
+/* Source for string_object.lut.h
+@begin stringTable 26
+ toString StringProtoFuncImp::ToString DontEnum|Function 0
+ valueOf StringProtoFuncImp::ValueOf DontEnum|Function 0
+ charAt StringProtoFuncImp::CharAt DontEnum|Function 1
+ charCodeAt StringProtoFuncImp::CharCodeAt DontEnum|Function 1
+ concat StringProtoFuncImp::Concat DontEnum|Function 1
+ indexOf StringProtoFuncImp::IndexOf DontEnum|Function 2
+ lastIndexOf StringProtoFuncImp::LastIndexOf DontEnum|Function 2
+ match StringProtoFuncImp::Match DontEnum|Function 1
+ replace StringProtoFuncImp::Replace DontEnum|Function 2
+ search StringProtoFuncImp::Search DontEnum|Function 1
+ slice StringProtoFuncImp::Slice DontEnum|Function 0
+ split StringProtoFuncImp::Split DontEnum|Function 1
+ substr StringProtoFuncImp::Substr DontEnum|Function 2
+ substring StringProtoFuncImp::Substring DontEnum|Function 2
+ toLowerCase StringProtoFuncImp::ToLowerCase DontEnum|Function 0
+ toUpperCase StringProtoFuncImp::ToUpperCase DontEnum|Function 0
+#
+# Under here: html extension, should only exist if KJS_PURE_ECMA is not defined
+# I guess we need to generate two hashtables in the .lut.h file, and use #ifdef
+# to select the right one... TODO. #####
+ big StringProtoFuncImp::Big DontEnum|Function 0
+ small StringProtoFuncImp::Small DontEnum|Function 0
+ blink StringProtoFuncImp::Blink DontEnum|Function 0
+ bold StringProtoFuncImp::Bold DontEnum|Function 0
+ fixed StringProtoFuncImp::Fixed DontEnum|Function 0
+ italics StringProtoFuncImp::Italics DontEnum|Function 0
+ strike StringProtoFuncImp::Strike DontEnum|Function 0
+ sub StringProtoFuncImp::Sub DontEnum|Function 0
+ sup StringProtoFuncImp::Sup DontEnum|Function 0
+ fontcolor StringProtoFuncImp::Fontcolor DontEnum|Function 1
+ fontsize StringProtoFuncImp::Fontsize DontEnum|Function 1
+ anchor StringProtoFuncImp::Anchor DontEnum|Function 1
+ link StringProtoFuncImp::Link DontEnum|Function 1
+@end
+*/
+// ECMA 15.5.4
+StringPrototypeImp::StringPrototypeImp(ExecState *exec,
+ ObjectPrototypeImp *objProto)
+ : StringInstanceImp(Object(objProto))
{
- if (p == "fromCharCode")
- return Function(new StringObjectFunc());
- else
- return Imp::get(p);
+ Value protect(this);
+ // The constructor will be added later, after StringObjectImp has been built
+ put(exec,"length",Number(0),DontDelete|ReadOnly|DontEnum);
+
}
-// ECMA 15.5.1
-Completion StringObject::execute(const List &args)
+Value StringPrototypeImp::get(ExecState *exec, const UString &propertyName) const
{
- KJSO v;
- String s;
+ return lookupGetFunction<StringProtoFuncImp, StringInstanceImp>( exec, propertyName, &stringTable, this );
+}
- if (args.isEmpty())
- s = String("");
- else {
- v = args[0];
- s = v.toString();
+// ------------------------------ StringProtoFuncImp ---------------------------
+
+StringProtoFuncImp::StringProtoFuncImp(ExecState *exec, int i, int len)
+ : InternalFunctionImp(
+ static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
+ ), id(i)
+{
+ Value protect(this);
+ put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
+}
+
+bool StringProtoFuncImp::implementsCall() const
+{
+ return true;
+}
+
+// ECMA 15.5.4.2 - 15.5.4.20
+Value StringProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
+{
+ Value result;
+
+ // toString and valueOf are no generic function.
+ if (id == ToString || id == ValueOf) {
+ if (thisObj.isNull() || !thisObj.inherits(&StringInstanceImp::info)) {
+ Object err = Error::create(exec,TypeError);
+ exec->setException(err);
+ return err;
+ }
+
+ return String(thisObj.internalValue().toString(exec));
}
- return Completion(ReturnValue, s);
+ int n, m;
+ UString u, u2, u3;
+ int pos, p0, i;
+ double d = 0.0;
+
+ UString s = thisObj.toString(exec);
+
+ int len = s.size();
+ Value a0 = args[0];
+ Value a1 = args[1];
+
+ switch (id) {
+ case ToString:
+ case ValueOf:
+ // handled above
+ break;
+ case CharAt:
+ pos = a0.toInteger(exec);
+ if (pos < 0 || pos >= len)
+ u = "";
+ else
+ u = s.substr(pos, 1);
+ result = String(u);
+ break;
+ case CharCodeAt:
+ pos = a0.toInteger(exec);
+ if (pos < 0 || pos >= len)
+ d = NaN;
+ else {
+ UChar c = s[pos];
+ d = (c.high() << 8) + c.low();
+ }
+ result = Number(d);
+ break;
+ case Concat: {
+ ListIterator it = args.begin();
+ for ( ; it != args.end() ; ++it) {
+ s += it->toString(exec);
+ }
+ result = String(s);
+ break;
+ }
+ case IndexOf:
+ u2 = a0.toString(exec);
+ if (a1.type() == UndefinedType)
+ pos = 0;
+ else
+ pos = a1.toInteger(exec);
+ d = s.find(u2, pos);
+ result = Number(d);
+ break;
+ case LastIndexOf:
+ u2 = a0.toString(exec);
+ d = a1.toNumber(exec);
+ if (a1.type() == UndefinedType || KJS::isNaN(d) || KJS::isPosInf(d))
+ pos = len;
+ else
+ pos = a1.toInteger(exec);
+ if (pos < 0)
+ pos = 0;
+ d = s.rfind(u2, pos);
+ result = Number(d);
+ break;
+ case Match:
+ case Search: {
+ u = s;
+ RegExp* reg = 0;
+ if (a0.isA(ObjectType) && a0.toObject(exec).inherits(&RegExpImp::info))
+ {
+ RegExpImp* imp = static_cast<RegExpImp *>( a0.toObject(exec).imp() );
+ reg = imp->regExp();
+ }
+ else if (a0.isA(StringType))
+ {
+ reg = new RegExp(a0.toString(exec), RegExp::None);
+ }
+ else
+ {
+#ifndef NDEBUG
+ printf("KJS: Match/Search. Argument is not a RegExp nor a String - returning Undefined\n");
+#endif
+ result = Undefined();
+ break;
+ }
+ RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
+ int **ovector = regExpObj->registerRegexp( reg, u );
+ UString mstr = reg->match(u, -1, &pos, ovector);
+ if (a0.isA(StringType))
+ delete reg;
+ if (id == Search) {
+ result = Number(pos);
+ break;
+ }
+ if (mstr.isNull())
+ result = Null();
+ else
+ result = regExpObj->arrayOfMatches(exec,mstr);
+ }
+ break;
+ case Replace:
+ u = s;
+ if (a0.type() == ObjectType && a0.toObject(exec).inherits(&RegExpImp::info)) {
+ RegExpImp* imp = static_cast<RegExpImp *>( a0.toObject(exec).imp() );
+ RegExp *reg = imp->regExp();
+ bool global = false;
+ Value tmp = imp->get(exec,"global");
+ if (tmp.type() != UndefinedType && tmp.toBoolean(exec) == true)
+ global = true;
+
+ RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
+ int **ovector = regExpObj->registerRegexp( reg, u );
+ int lastIndex = 0;
+ u3 = a1.toString(exec); // replacement string
+ // This is either a loop (if global is set) or a one-way (if not).
+ do {
+ UString mstr = reg->match(u, lastIndex, &pos, ovector);
+ len = mstr.size();
+ lastIndex = pos + u3.size();
+ if ( pos != -1 )
+ u = u.substr(0, pos) + u3 + u.substr(pos + len);
+ //fprintf(stderr,"pos=%d,len=%d,lastIndex=%d,u=%s\n",pos,len,lastIndex,u.ascii());
+ } while ( global && pos != -1 );
+
+ result = String(u);
+ } else { // First arg is a string
+ u2 = a0.toString(exec);
+ pos = u.find(u2);
+ len = u2.size();
+ // Do the replacement
+ if (pos == -1)
+ result = String(s);
+ else {
+ u3 = u.substr(0, pos) + a1.toString(exec) +
+ u.substr(pos + len);
+ result = String(u3);
+ }
+ }
+ break;
+ case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/string.htm#1194366
+ {
+ // The arg processing is very much like ArrayProtoFunc::Slice
+ // We return a new array
+ result = exec->interpreter()->builtinArray().construct(exec,List::empty());
+ int begin = args[0].toUInt32(exec);
+ int end = len;
+ if (args[1].type() != UndefinedType)
+ {
+ end = args[1].toUInt32(exec);
+ if ( end < 0 )
+ end += len;
+ }
+ // safety tests
+ if ( begin < 0 || end < 0 || begin >= end ) {
+ result = String();
+ break;
+ }
+ //printf( "Slicing from %d to %d \n", begin, end );
+ result = String(s.substr(begin, end-begin));
+ break;
+ }
+ case Split: {
+ Object constructor = exec->interpreter()->builtinArray();
+ Object res = Object::dynamicCast(constructor.construct(exec,List::empty()));
+ result = res;
+ u = s;
+ i = p0 = 0;
+ d = (a1.type() != UndefinedType) ? a1.toInteger(exec) : -1; // optional max number
+ if (a0.type() == ObjectType && Object::dynamicCast(a0).inherits(&RegExpImp::info)) {
+ Object obj0 = Object::dynamicCast(a0);
+ RegExp reg(obj0.get(exec,"source").toString(exec));
+ if (u.isEmpty() && !reg.match(u, 0).isNull()) {
+ // empty string matched by regexp -> empty array
+ res.put(exec,"length", Number(0));
+ break;
+ }
+ int *ovector;
+ int mpos;
+ pos = 0;
+ while (1) {
+ // TODO: back references
+ UString mstr = reg.match(u, pos, &mpos, &ovector);
+ if (mpos < 0)
+ break;
+ pos = mpos + (mstr.isEmpty() ? 1 : mstr.size());
+ if (mpos != p0 || !mstr.isEmpty()) {
+ res.put(exec,UString::from(i), String(u.substr(p0, mpos-p0)));
+ p0 = mpos + mstr.size();
+ i++;
+ }
+ }
+ delete ovector;
+ } else if (a0.type() != UndefinedType) {
+ u2 = a0.toString(exec);
+ if (u2.isEmpty()) {
+ if (u.isEmpty()) {
+ // empty separator matches empty string -> empty array
+ put(exec,"length", Number(0));
+ break;
+ } else {
+ while (i != d && i < u.size()-1)
+ res.put(exec,UString::from(i++), String(u.substr(p0++, 1)));
+ }
+ } else {
+ while (i != d && (pos = u.find(u2, p0)) >= 0) {
+ res.put(exec,UString::from(i), String(u.substr(p0, pos-p0)));
+ p0 = pos + u2.size();
+ i++;
+ }
+ }
+ }
+ // add remaining string, if any
+ if (i != d)
+ res.put(exec,UString::from(i++), String(u.substr(p0)));
+ res.put(exec,"length", Number(i));
+ }
+ break;
+ case Substr: {
+ n = a0.toInteger(exec);
+ m = a1.toInteger(exec);
+ int d, d2;
+ if (n >= 0)
+ d = n;
+ else
+ d = maxInt(len + n, 0);
+ if (a1.type() == UndefinedType)
+ d2 = len - d;
+ else
+ d2 = minInt(maxInt(m, 0), len - d);
+ result = String(s.substr(d, d2));
+ break;
+ }
+ case Substring: {
+ double start = a0.toNumber(exec);
+ double end = a1.toNumber(exec);
+ if (KJS::isNaN(start))
+ start = 0;
+ if (KJS::isNaN(end))
+ end = 0;
+ if (start < 0)
+ start = 0;
+ if (end < 0)
+ end = 0;
+ if (start > len)
+ start = len;
+ if (end > len)
+ end = len;
+ if (a1.type() == UndefinedType)
+ end = len;
+ if (start > end) {
+ double temp = end;
+ end = start;
+ start = temp;
+ }
+ result = String(s.substr((int)start, (int)end-(int)start));
+ }
+ break;
+ case ToLowerCase:
+ u = s;
+ for (i = 0; i < len; i++)
+ u[i] = u[i].toLower();
+ result = String(u);
+ break;
+ case ToUpperCase:
+ u = s;
+ for (i = 0; i < len; i++)
+ u[i] = u[i].toUpper();
+ result = String(u);
+ break;
+#ifndef KJS_PURE_ECMA
+ case Big:
+ result = String("<BIG>" + s + "</BIG>");
+ break;
+ case Small:
+ result = String("<SMALL>" + s + "</SMALL>");
+ break;
+ case Blink:
+ result = String("<BLINK>" + s + "</BLINK>");
+ break;
+ case Bold:
+ result = String("<B>" + s + "</B>");
+ break;
+ case Fixed:
+ result = String("<TT>" + s + "</TT>");
+ break;
+ case Italics:
+ result = String("<I>" + s + "</I>");
+ break;
+ case Strike:
+ result = String("<STRIKE>" + s + "</STRIKE>");
+ break;
+ case Sub:
+ result = String("<SUB>" + s + "</SUB>");
+ break;
+ case Sup:
+ result = String("<SUP>" + s + "</SUP>");
+ break;
+ case Fontcolor:
+ result = String("<FONT COLOR=" + a0.toString(exec) + ">"
+ + s + "</FONT>");
+ break;
+ case Fontsize:
+ result = String("<FONT SIZE=" + a0.toString(exec) + ">"
+ + s + "</FONT>");
+ break;
+ case Anchor:
+ result = String("<a name=" + a0.toString(exec) + ">"
+ + s + "</a>");
+ break;
+ case Link:
+ result = String("<a href=" + a0.toString(exec) + ">"
+ + s + "</a>");
+ break;
+#endif
+ }
+
+ return result;
+}
+
+// ------------------------------ StringObjectImp ------------------------------
+
+StringObjectImp::StringObjectImp(ExecState *exec,
+ FunctionPrototypeImp *funcProto,
+ StringPrototypeImp *stringProto)
+ : InternalFunctionImp(funcProto)
+{
+ Value protect(this);
+ // ECMA 15.5.3.1 String.prototype
+ put(exec,"prototype", Object(stringProto), DontEnum|DontDelete|ReadOnly);
+
+ put(exec,"fromCharCode", Object(new StringObjectFuncImp(exec,funcProto)), DontEnum);
+
+ // no. of arguments for constructor
+ put(exec,"length", Number(1), ReadOnly|DontDelete|DontEnum);
+}
+
+
+bool StringObjectImp::implementsConstruct() const
+{
+ return true;
}
// ECMA 15.5.2
-Object StringObject::construct(const List &args)
+Object StringObjectImp::construct(ExecState *exec, const List &args)
{
- String s;
- if (args.size() > 0)
- s = args.begin()->toString();
- else
- s = String("");
+ Object proto = exec->interpreter()->builtinStringPrototype();
+ Object obj(new StringInstanceImp(proto ));
- return Object::create(StringClass, s);
+ UString s;
+ if (args.size() > 0)
+ s = args.begin()->toString(exec);
+ else
+ s = UString("");
+
+ obj.setInternalValue(String(s));
+ obj.put(exec, "length", Number(s.size()), ReadOnly|DontEnum|DontDelete);
+
+ return obj;
}
+bool StringObjectImp::implementsCall() const
+{
+ return true;
+}
+
+// ECMA 15.5.1
+Value StringObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
+{
+ if (args.isEmpty())
+ return String("");
+ else {
+ Value v = args[0];
+ return String(v.toString(exec));
+ }
+}
+
+// ------------------------------ StringObjectFuncImp --------------------------
+
// ECMA 15.5.3.2 fromCharCode()
-Completion StringObjectFunc::execute(const List &args)
+StringObjectFuncImp::StringObjectFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto)
+ : InternalFunctionImp(funcProto)
+{
+ Value protect(this);
+ put(exec,"length",Number(1),DontDelete|ReadOnly|DontEnum);
+}
+
+bool StringObjectFuncImp::implementsCall() const
+{
+ return true;
+}
+
+Value StringObjectFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
{
UString s;
if (args.size()) {
@@ -78,7 +528,7 @@
UChar *p = buf;
ListIterator it = args.begin();
while (it != args.end()) {
- unsigned short u = it->toUInt16();
+ unsigned short u = it->toUInt16(exec);
*p++ = UChar(u);
it++;
}
@@ -86,334 +536,5 @@
} else
s = "";
- return Completion(ReturnValue, String(s));
-}
-
-// ECMA 15.5.4
-StringPrototype::StringPrototype(const Object& proto)
- : ObjectImp(StringClass, String(""), proto)
-{
- // The constructor will be added later in StringObject's constructor
-}
-
-KJSO StringPrototype::get(const UString &p) const
-{
- int id;
-
- if (p == "toString")
- id = StringProtoFunc::ToString;
- else if (p == "valueOf")
- id = StringProtoFunc::ValueOf;
- else if (p == "charAt")
- id = StringProtoFunc::CharAt;
- else if (p == "charCodeAt")
- id = StringProtoFunc::CharCodeAt;
- else if (p == "indexOf")
- id = StringProtoFunc::IndexOf;
- else if (p == "lastIndexOf")
- id = StringProtoFunc::LastIndexOf;
- else if (p == "match")
- id = StringProtoFunc::Match;
- else if (p == "replace")
- id = StringProtoFunc::Replace;
- else if (p == "search")
- id = StringProtoFunc::Search;
- else if (p == "split")
- id = StringProtoFunc::Split;
- else if (p == "substr")
- id = StringProtoFunc::Substr;
- else if (p == "substring")
- id = StringProtoFunc::Substring;
- else if (p == "toLowerCase")
- id = StringProtoFunc::ToLowerCase;
- else if (p == "toUpperCase")
- id = StringProtoFunc::ToUpperCase;
-#ifndef KJS_PURE_ECMA
- else if (p == "big")
- id = StringProtoFunc::Big;
- else if (p == "small")
- id = StringProtoFunc::Small;
- else if (p == "blink")
- id = StringProtoFunc::Blink;
- else if (p == "bold")
- id = StringProtoFunc::Bold;
- else if (p == "fixed")
- id = StringProtoFunc::Fixed;
- else if (p == "italics")
- id = StringProtoFunc::Italics;
- else if (p == "strike")
- id = StringProtoFunc::Strike;
- else if (p == "sub")
- id = StringProtoFunc::Sub;
- else if (p == "sup")
- id = StringProtoFunc::Sup;
- else if (p == "fontcolor")
- id = StringProtoFunc::Fontcolor;
- else if (p == "fontsize")
- id = StringProtoFunc::Fontsize;
- else if (p == "anchor")
- id = StringProtoFunc::Anchor;
- else if (p == "link")
- id = StringProtoFunc::Link;
-#endif
- else
- return Imp::get(p);
-
- return Function(new StringProtoFunc(id));
-}
-
-StringProtoFunc::StringProtoFunc(int i)
- : id(i)
-{
-}
-
-// ECMA 15.5.4.2 - 15.5.4.20
-Completion StringProtoFunc::execute(const List &args)
-{
- KJSO result;
-
- Object thisObj = Object::dynamicCast(thisValue());
-
- // toString and valueOf are no generic function.
- if (id == ToString || id == ValueOf) {
- if (thisObj.isNull() || thisObj.getClass() != StringClass) {
- result = Error::create(TypeError);
- return Completion(ReturnValue, result);
- }
- }
-
- String s2;
- Number n, m;
- UString u, u2, u3;
- int pos, p0, i;
- double d, d2;
- KJSO v = thisObj.internalValue();
- String s = v.toString();
- int len = s.value().size();
- KJSO a0 = args[0];
- KJSO a1 = args[1];
-
- switch (id) {
- case ToString:
- case ValueOf:
- result = v.toString();
- break;
- case CharAt:
- n = a0.toInteger();
- pos = (int) n.value();
- if (pos < 0 || pos >= len)
- u = "";
- else
- u = s.value().substr(pos, 1);
- result = String(u);
- break;
- case CharCodeAt:
- n = a0.toInteger();
- pos = (int) n.value();
- if (pos < 0 || pos >= len)
- d = NaN;
- else {
- UChar c = s.value()[pos];
- d = (c.high() << 8) + c.low();
- }
- result = Number(d);
- break;
- case IndexOf:
- s2 = a0.toString();
- if (a1.isA(UndefinedType))
- pos = 0;
- else
- pos = a1.toInteger().intValue();
- d = s.value().find(s2.value(), pos);
- result = Number(d);
- break;
- case LastIndexOf:
- s2 = a0.toString();
- if (a1.isA(UndefinedType))
- pos = len;
- else
- pos = a1.toInteger().intValue();
- d = s.value().rfind(s2.value(), pos);
- result = Number(d);
- break;
- case Match:
- case Search:
- u = s.value();
- if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) {
- s2 = a0.get("source").toString();
- RegExp reg(s2.value());
- UString mstr = reg.match(u, -1, &pos);
- if (id == Search) {
- result = Number(pos);
- break;
- }
- if (mstr.isNull()) {
- result = Null();
- break;
- }
- /* TODO return an array, with the matches, etc. */
- result = String(mstr);
- } else
- {
- printf("Match/Search. Argument is not a RegExp - returning Undefined\n");
- result = Undefined(); // No idea what to do here
- }
- break;
- case Replace:
- /* TODO: this is just a hack to get the most common cases going */
- u = s.value();
- if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) {
- s2 = a0.get("source").toString();
- RegExp reg(s2.value());
- UString mstr = reg.match(u, -1, &pos);
- len = mstr.size();
- } else {
- s2 = a0.toString();
- u2 = s2.value();
- pos = u.find(u2);
- len = u2.size();
- }
- if (pos == -1)
- result = s;
- else {
- u3 = u.substr(0, pos) + a1.toString().value() +
- u.substr(pos + len);
- result = String(u3);
- }
- break;
- case Split:
- result = Object::create(ArrayClass);
- u = s.value();
- i = p0 = 0;
- d = a1.isDefined() ? a1.toInteger().intValue() : -1; // optional max number
- if (a0.isA(ObjectType) && Object(a0.imp()).getClass() == RegExpClass) {
- RegExp reg(a0.get("source").toString().value());
- if (u.isEmpty() && !reg.match(u, 0).isNull()) {
- // empty string matched by regexp -> empty array
- result.put("length", 0);
- break;
- }
- int mpos;
- pos = 0;
- while (1) {
- /* TODO: back references */
- UString mstr = reg.match(u, pos, &mpos);
- if (mpos < 0)
- break;
- pos = mpos + (mstr.isEmpty() ? 1 : mstr.size());
- if (mpos != p0 || !mstr.isEmpty()) {
- result.put(UString::from(i), String(u.substr(p0, mpos-p0)));
- p0 = mpos + mstr.size();
- i++;
- }
- }
- } else if (a0.isDefined()) {
- u2 = a0.toString().value();
- if (u2.isEmpty()) {
- if (u.isEmpty()) {
- // empty separator matches empty string -> empty array
- put("length", 0);
- break;
- } else {
- while (i != d && i < u.size())
- result.put(UString::from(i++), String(u.substr(p0++, 1)));
- }
- } else {
- while (i != d && (pos = u.find(u2, p0)) >= 0) {
- result.put(UString::from(i), String(u.substr(p0, pos-p0)));
- p0 = pos + u2.size();
- i++;
- }
- }
- }
- // add remaining string, if any
- if (i != d && (p0 < len || i == 0))
- result.put(UString::from(i++), String(u.substr(p0)));
- result.put("length", i);
- break;
- case Substr:
- n = a0.toInteger();
- m = a1.toInteger();
- if (n.value() >= 0)
- d = n.value();
- else
- d = max(len + n.value(), 0);
- if (a1.isA(UndefinedType))
- d2 = len - d;
- else
- d2 = min(max(m.value(), 0), len - d);
- result = String(s.value().substr((int)d, (int)d2));
- break;
- case Substring:
- n = a0.toInteger();
- m = a1.toInteger();
- d = min(max(n.value(), 0), len);
- if (a1.isA(UndefinedType))
- d2 = len - d;
- else {
- d2 = min(max(m.value(), 0), len);
- d2 = max(d2-d, 0);
- }
- result = String(s.value().substr((int)d, (int)d2));
- break;
- case ToLowerCase:
- u = UString(s.value());
- for (i = 0; i < len; i++)
- u[i] = u[i].toLower();
- result = String(u);
- break;
- case ToUpperCase:
- u = UString(s.value());
- for (i = 0; i < len; i++)
- u[i] = u[i].toUpper();
- result = String(u);
- break;
-#ifndef KJS_PURE_ECMA
- case Big:
- result = String("<BIG>" + s.value() + "</BIG>");
- break;
- case Small:
- result = String("<SMALL>" + s.value() + "</SMALL>");
- break;
- case Blink:
- result = String("<BLINK>" + s.value() + "</BLINK>");
- break;
- case Bold:
- result = String("<B>" + s.value() + "</B>");
- break;
- case Fixed:
- result = String("<TT>" + s.value() + "</TT>");
- break;
- case Italics:
- result = String("<I>" + s.value() + "</I>");
- break;
- case Strike:
- result = String("<STRIKE>" + s.value() + "</STRIKE>");
- break;
- case Sub:
- result = String("<SUB>" + s.value() + "</SUB>");
- break;
- case Sup:
- result = String("<SUP>" + s.value() + "</SUP>");
- break;
- case Fontcolor:
- result = String("<FONT COLOR=" + a0.toString().value() + ">"
- + s.value() + "</FONT>");
- break;
- case Fontsize:
- result = String("<FONT SIZE=" + a0.toString().value() + ">"
- + s.value() + "</FONT>");
- break;
- case Anchor:
- result = String("<a name=" + a0.toString().value() + ">"
- + s.value() + "</a>");
- break;
- case Link:
- result = String("<a href=" + a0.toString().value() + ">"
- + s.value() + "</a>");
- break;
-#endif
- }
-
- return Completion(ReturnValue, result);
+ return String(s);
}