Changeset 798 in webkit for trunk/JavaScriptCore/kjs/string_object.cpp
- Timestamp:
- Mar 21, 2002, 4:31:57 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/string_object.cpp
r6 r798 1 // -*- c-basic-offset: 2 -*- 1 2 /* 2 3 * This file is part of the KDE libraries … … 16 17 * License along with this library; if not, write to the Free Software 17 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 18 20 */ 19 21 20 #include "kjs.h" 22 #include "value.h" 23 #include "object.h" 24 #include "types.h" 25 #include "interpreter.h" 21 26 #include "operations.h" 22 #include "types.h"23 27 #include "regexp.h" 28 #include "regexp_object.h" 24 29 #include "string_object.h" 30 #include "error_object.h" 25 31 #include <stdio.h> 32 #include "string_object.lut.h" 26 33 27 34 using namespace KJS; 28 35 29 StringObject::StringObject(const Object &funcProto, const Object &stringProto) 30 : ConstructorImp(funcProto, 1) 31 { 36 // ------------------------------ StringInstanceImp ---------------------------- 37 38 const ClassInfo StringInstanceImp::info = {"String", 0, 0, 0}; 39 40 StringInstanceImp::StringInstanceImp(const Object &proto) 41 : ObjectImp(proto) 42 { 43 setInternalValue(String("")); 44 } 45 46 // ------------------------------ StringPrototypeImp --------------------------- 47 const ClassInfo StringPrototypeImp::info = {"String", &StringInstanceImp::info, &stringTable, 0}; 48 /* Source for string_object.lut.h 49 @begin stringTable 26 50 toString StringProtoFuncImp::ToString DontEnum|Function 0 51 valueOf StringProtoFuncImp::ValueOf DontEnum|Function 0 52 charAt StringProtoFuncImp::CharAt DontEnum|Function 1 53 charCodeAt StringProtoFuncImp::CharCodeAt DontEnum|Function 1 54 concat StringProtoFuncImp::Concat DontEnum|Function 1 55 indexOf StringProtoFuncImp::IndexOf DontEnum|Function 2 56 lastIndexOf StringProtoFuncImp::LastIndexOf DontEnum|Function 2 57 match StringProtoFuncImp::Match DontEnum|Function 1 58 replace StringProtoFuncImp::Replace DontEnum|Function 2 59 search StringProtoFuncImp::Search DontEnum|Function 1 60 slice StringProtoFuncImp::Slice DontEnum|Function 0 61 split StringProtoFuncImp::Split DontEnum|Function 1 62 substr StringProtoFuncImp::Substr DontEnum|Function 2 63 substring StringProtoFuncImp::Substring DontEnum|Function 2 64 toLowerCase StringProtoFuncImp::ToLowerCase DontEnum|Function 0 65 toUpperCase StringProtoFuncImp::ToUpperCase DontEnum|Function 0 66 # 67 # Under here: html extension, should only exist if KJS_PURE_ECMA is not defined 68 # I guess we need to generate two hashtables in the .lut.h file, and use #ifdef 69 # to select the right one... TODO. ##### 70 big StringProtoFuncImp::Big DontEnum|Function 0 71 small StringProtoFuncImp::Small DontEnum|Function 0 72 blink StringProtoFuncImp::Blink DontEnum|Function 0 73 bold StringProtoFuncImp::Bold DontEnum|Function 0 74 fixed StringProtoFuncImp::Fixed DontEnum|Function 0 75 italics StringProtoFuncImp::Italics DontEnum|Function 0 76 strike StringProtoFuncImp::Strike DontEnum|Function 0 77 sub StringProtoFuncImp::Sub DontEnum|Function 0 78 sup StringProtoFuncImp::Sup DontEnum|Function 0 79 fontcolor StringProtoFuncImp::Fontcolor DontEnum|Function 1 80 fontsize StringProtoFuncImp::Fontsize DontEnum|Function 1 81 anchor StringProtoFuncImp::Anchor DontEnum|Function 1 82 link StringProtoFuncImp::Link DontEnum|Function 1 83 @end 84 */ 85 // ECMA 15.5.4 86 StringPrototypeImp::StringPrototypeImp(ExecState *exec, 87 ObjectPrototypeImp *objProto) 88 : StringInstanceImp(Object(objProto)) 89 { 90 Value protect(this); 91 // The constructor will be added later, after StringObjectImp has been built 92 put(exec,"length",Number(0),DontDelete|ReadOnly|DontEnum); 93 94 } 95 96 Value StringPrototypeImp::get(ExecState *exec, const UString &propertyName) const 97 { 98 return lookupGetFunction<StringProtoFuncImp, StringInstanceImp>( exec, propertyName, &stringTable, this ); 99 } 100 101 // ------------------------------ StringProtoFuncImp --------------------------- 102 103 StringProtoFuncImp::StringProtoFuncImp(ExecState *exec, int i, int len) 104 : InternalFunctionImp( 105 static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp()) 106 ), id(i) 107 { 108 Value protect(this); 109 put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum); 110 } 111 112 bool StringProtoFuncImp::implementsCall() const 113 { 114 return true; 115 } 116 117 // ECMA 15.5.4.2 - 15.5.4.20 118 Value StringProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args) 119 { 120 Value result; 121 122 // toString and valueOf are no generic function. 123 if (id == ToString || id == ValueOf) { 124 if (thisObj.isNull() || !thisObj.inherits(&StringInstanceImp::info)) { 125 Object err = Error::create(exec,TypeError); 126 exec->setException(err); 127 return err; 128 } 129 130 return String(thisObj.internalValue().toString(exec)); 131 } 132 133 int n, m; 134 UString u, u2, u3; 135 int pos, p0, i; 136 double d = 0.0; 137 138 UString s = thisObj.toString(exec); 139 140 int len = s.size(); 141 Value a0 = args[0]; 142 Value a1 = args[1]; 143 144 switch (id) { 145 case ToString: 146 case ValueOf: 147 // handled above 148 break; 149 case CharAt: 150 pos = a0.toInteger(exec); 151 if (pos < 0 || pos >= len) 152 u = ""; 153 else 154 u = s.substr(pos, 1); 155 result = String(u); 156 break; 157 case CharCodeAt: 158 pos = a0.toInteger(exec); 159 if (pos < 0 || pos >= len) 160 d = NaN; 161 else { 162 UChar c = s[pos]; 163 d = (c.high() << 8) + c.low(); 164 } 165 result = Number(d); 166 break; 167 case Concat: { 168 ListIterator it = args.begin(); 169 for ( ; it != args.end() ; ++it) { 170 s += it->toString(exec); 171 } 172 result = String(s); 173 break; 174 } 175 case IndexOf: 176 u2 = a0.toString(exec); 177 if (a1.type() == UndefinedType) 178 pos = 0; 179 else 180 pos = a1.toInteger(exec); 181 d = s.find(u2, pos); 182 result = Number(d); 183 break; 184 case LastIndexOf: 185 u2 = a0.toString(exec); 186 d = a1.toNumber(exec); 187 if (a1.type() == UndefinedType || KJS::isNaN(d) || KJS::isPosInf(d)) 188 pos = len; 189 else 190 pos = a1.toInteger(exec); 191 if (pos < 0) 192 pos = 0; 193 d = s.rfind(u2, pos); 194 result = Number(d); 195 break; 196 case Match: 197 case Search: { 198 u = s; 199 RegExp* reg = 0; 200 if (a0.isA(ObjectType) && a0.toObject(exec).inherits(&RegExpImp::info)) 201 { 202 RegExpImp* imp = static_cast<RegExpImp *>( a0.toObject(exec).imp() ); 203 reg = imp->regExp(); 204 } 205 else if (a0.isA(StringType)) 206 { 207 reg = new RegExp(a0.toString(exec), RegExp::None); 208 } 209 else 210 { 211 #ifndef NDEBUG 212 printf("KJS: Match/Search. Argument is not a RegExp nor a String - returning Undefined\n"); 213 #endif 214 result = Undefined(); 215 break; 216 } 217 RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp()); 218 int **ovector = regExpObj->registerRegexp( reg, u ); 219 UString mstr = reg->match(u, -1, &pos, ovector); 220 if (a0.isA(StringType)) 221 delete reg; 222 if (id == Search) { 223 result = Number(pos); 224 break; 225 } 226 if (mstr.isNull()) 227 result = Null(); 228 else 229 result = regExpObj->arrayOfMatches(exec,mstr); 230 } 231 break; 232 case Replace: 233 u = s; 234 if (a0.type() == ObjectType && a0.toObject(exec).inherits(&RegExpImp::info)) { 235 RegExpImp* imp = static_cast<RegExpImp *>( a0.toObject(exec).imp() ); 236 RegExp *reg = imp->regExp(); 237 bool global = false; 238 Value tmp = imp->get(exec,"global"); 239 if (tmp.type() != UndefinedType && tmp.toBoolean(exec) == true) 240 global = true; 241 242 RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp()); 243 int **ovector = regExpObj->registerRegexp( reg, u ); 244 int lastIndex = 0; 245 u3 = a1.toString(exec); // replacement string 246 // This is either a loop (if global is set) or a one-way (if not). 247 do { 248 UString mstr = reg->match(u, lastIndex, &pos, ovector); 249 len = mstr.size(); 250 lastIndex = pos + u3.size(); 251 if ( pos != -1 ) 252 u = u.substr(0, pos) + u3 + u.substr(pos + len); 253 //fprintf(stderr,"pos=%d,len=%d,lastIndex=%d,u=%s\n",pos,len,lastIndex,u.ascii()); 254 } while ( global && pos != -1 ); 255 256 result = String(u); 257 } else { // First arg is a string 258 u2 = a0.toString(exec); 259 pos = u.find(u2); 260 len = u2.size(); 261 // Do the replacement 262 if (pos == -1) 263 result = String(s); 264 else { 265 u3 = u.substr(0, pos) + a1.toString(exec) + 266 u.substr(pos + len); 267 result = String(u3); 268 } 269 } 270 break; 271 case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/string.htm#1194366 272 { 273 // The arg processing is very much like ArrayProtoFunc::Slice 274 // We return a new array 275 result = exec->interpreter()->builtinArray().construct(exec,List::empty()); 276 int begin = args[0].toUInt32(exec); 277 int end = len; 278 if (args[1].type() != UndefinedType) 279 { 280 end = args[1].toUInt32(exec); 281 if ( end < 0 ) 282 end += len; 283 } 284 // safety tests 285 if ( begin < 0 || end < 0 || begin >= end ) { 286 result = String(); 287 break; 288 } 289 //printf( "Slicing from %d to %d \n", begin, end ); 290 result = String(s.substr(begin, end-begin)); 291 break; 292 } 293 case Split: { 294 Object constructor = exec->interpreter()->builtinArray(); 295 Object res = Object::dynamicCast(constructor.construct(exec,List::empty())); 296 result = res; 297 u = s; 298 i = p0 = 0; 299 d = (a1.type() != UndefinedType) ? a1.toInteger(exec) : -1; // optional max number 300 if (a0.type() == ObjectType && Object::dynamicCast(a0).inherits(&RegExpImp::info)) { 301 Object obj0 = Object::dynamicCast(a0); 302 RegExp reg(obj0.get(exec,"source").toString(exec)); 303 if (u.isEmpty() && !reg.match(u, 0).isNull()) { 304 // empty string matched by regexp -> empty array 305 res.put(exec,"length", Number(0)); 306 break; 307 } 308 int *ovector; 309 int mpos; 310 pos = 0; 311 while (1) { 312 // TODO: back references 313 UString mstr = reg.match(u, pos, &mpos, &ovector); 314 if (mpos < 0) 315 break; 316 pos = mpos + (mstr.isEmpty() ? 1 : mstr.size()); 317 if (mpos != p0 || !mstr.isEmpty()) { 318 res.put(exec,UString::from(i), String(u.substr(p0, mpos-p0))); 319 p0 = mpos + mstr.size(); 320 i++; 321 } 322 } 323 delete ovector; 324 } else if (a0.type() != UndefinedType) { 325 u2 = a0.toString(exec); 326 if (u2.isEmpty()) { 327 if (u.isEmpty()) { 328 // empty separator matches empty string -> empty array 329 put(exec,"length", Number(0)); 330 break; 331 } else { 332 while (i != d && i < u.size()-1) 333 res.put(exec,UString::from(i++), String(u.substr(p0++, 1))); 334 } 335 } else { 336 while (i != d && (pos = u.find(u2, p0)) >= 0) { 337 res.put(exec,UString::from(i), String(u.substr(p0, pos-p0))); 338 p0 = pos + u2.size(); 339 i++; 340 } 341 } 342 } 343 // add remaining string, if any 344 if (i != d) 345 res.put(exec,UString::from(i++), String(u.substr(p0))); 346 res.put(exec,"length", Number(i)); 347 } 348 break; 349 case Substr: { 350 n = a0.toInteger(exec); 351 m = a1.toInteger(exec); 352 int d, d2; 353 if (n >= 0) 354 d = n; 355 else 356 d = maxInt(len + n, 0); 357 if (a1.type() == UndefinedType) 358 d2 = len - d; 359 else 360 d2 = minInt(maxInt(m, 0), len - d); 361 result = String(s.substr(d, d2)); 362 break; 363 } 364 case Substring: { 365 double start = a0.toNumber(exec); 366 double end = a1.toNumber(exec); 367 if (KJS::isNaN(start)) 368 start = 0; 369 if (KJS::isNaN(end)) 370 end = 0; 371 if (start < 0) 372 start = 0; 373 if (end < 0) 374 end = 0; 375 if (start > len) 376 start = len; 377 if (end > len) 378 end = len; 379 if (a1.type() == UndefinedType) 380 end = len; 381 if (start > end) { 382 double temp = end; 383 end = start; 384 start = temp; 385 } 386 result = String(s.substr((int)start, (int)end-(int)start)); 387 } 388 break; 389 case ToLowerCase: 390 u = s; 391 for (i = 0; i < len; i++) 392 u[i] = u[i].toLower(); 393 result = String(u); 394 break; 395 case ToUpperCase: 396 u = s; 397 for (i = 0; i < len; i++) 398 u[i] = u[i].toUpper(); 399 result = String(u); 400 break; 401 #ifndef KJS_PURE_ECMA 402 case Big: 403 result = String("<BIG>" + s + "</BIG>"); 404 break; 405 case Small: 406 result = String("<SMALL>" + s + "</SMALL>"); 407 break; 408 case Blink: 409 result = String("<BLINK>" + s + "</BLINK>"); 410 break; 411 case Bold: 412 result = String("<B>" + s + "</B>"); 413 break; 414 case Fixed: 415 result = String("<TT>" + s + "</TT>"); 416 break; 417 case Italics: 418 result = String("<I>" + s + "</I>"); 419 break; 420 case Strike: 421 result = String("<STRIKE>" + s + "</STRIKE>"); 422 break; 423 case Sub: 424 result = String("<SUB>" + s + "</SUB>"); 425 break; 426 case Sup: 427 result = String("<SUP>" + s + "</SUP>"); 428 break; 429 case Fontcolor: 430 result = String("<FONT COLOR=" + a0.toString(exec) + ">" 431 + s + "</FONT>"); 432 break; 433 case Fontsize: 434 result = String("<FONT SIZE=" + a0.toString(exec) + ">" 435 + s + "</FONT>"); 436 break; 437 case Anchor: 438 result = String("<a name=" + a0.toString(exec) + ">" 439 + s + "</a>"); 440 break; 441 case Link: 442 result = String("<a href=" + a0.toString(exec) + ">" 443 + s + "</a>"); 444 break; 445 #endif 446 } 447 448 return result; 449 } 450 451 // ------------------------------ StringObjectImp ------------------------------ 452 453 StringObjectImp::StringObjectImp(ExecState *exec, 454 FunctionPrototypeImp *funcProto, 455 StringPrototypeImp *stringProto) 456 : InternalFunctionImp(funcProto) 457 { 458 Value protect(this); 32 459 // ECMA 15.5.3.1 String.prototype 33 setPrototypeProperty(stringProto); 34 } 35 36 KJSO StringObject::get(const UString &p) const 37 { 38 if (p == "fromCharCode") 39 return Function(new StringObjectFunc()); 460 put(exec,"prototype", Object(stringProto), DontEnum|DontDelete|ReadOnly); 461 462 put(exec,"fromCharCode", Object(new StringObjectFuncImp(exec,funcProto)), DontEnum); 463 464 // no. of arguments for constructor 465 put(exec,"length", Number(1), ReadOnly|DontDelete|DontEnum); 466 } 467 468 469 bool StringObjectImp::implementsConstruct() const 470 { 471 return true; 472 } 473 474 // ECMA 15.5.2 475 Object StringObjectImp::construct(ExecState *exec, const List &args) 476 { 477 Object proto = exec->interpreter()->builtinStringPrototype(); 478 Object obj(new StringInstanceImp(proto )); 479 480 UString s; 481 if (args.size() > 0) 482 s = args.begin()->toString(exec); 40 483 else 41 return Imp::get(p); 484 s = UString(""); 485 486 obj.setInternalValue(String(s)); 487 obj.put(exec, "length", Number(s.size()), ReadOnly|DontEnum|DontDelete); 488 489 return obj; 490 } 491 492 bool StringObjectImp::implementsCall() const 493 { 494 return true; 42 495 } 43 496 44 497 // ECMA 15.5.1 45 Completion StringObject::execute(const List &args) 46 { 47 KJSO v; 48 String s; 49 498 Value StringObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args) 499 { 50 500 if (args.isEmpty()) 51 s =String("");501 return String(""); 52 502 else { 53 v = args[0];54 s = v.toString();503 Value v = args[0]; 504 return String(v.toString(exec)); 55 505 } 56 57 return Completion(ReturnValue, s); 58 } 59 60 // ECMA 15.5.2 61 Object StringObject::construct(const List &args) 62 { 63 String s; 64 if (args.size() > 0) 65 s = args.begin()->toString(); 66 else 67 s = String(""); 68 69 return Object::create(StringClass, s); 70 } 506 } 507 508 // ------------------------------ StringObjectFuncImp -------------------------- 71 509 72 510 // ECMA 15.5.3.2 fromCharCode() 73 Completion StringObjectFunc::execute(const List &args) 511 StringObjectFuncImp::StringObjectFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto) 512 : InternalFunctionImp(funcProto) 513 { 514 Value protect(this); 515 put(exec,"length",Number(1),DontDelete|ReadOnly|DontEnum); 516 } 517 518 bool StringObjectFuncImp::implementsCall() const 519 { 520 return true; 521 } 522 523 Value StringObjectFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args) 74 524 { 75 525 UString s; … … 79 529 ListIterator it = args.begin(); 80 530 while (it != args.end()) { 81 unsigned short u = it->toUInt16( );531 unsigned short u = it->toUInt16(exec); 82 532 *p++ = UChar(u); 83 533 it++; … … 87 537 s = ""; 88 538 89 return Completion(ReturnValue, String(s)); 90 } 91 92 // ECMA 15.5.4 93 StringPrototype::StringPrototype(const Object& proto) 94 : ObjectImp(StringClass, String(""), proto) 95 { 96 // The constructor will be added later in StringObject's constructor 97 } 98 99 KJSO StringPrototype::get(const UString &p) const 100 { 101 int id; 102 103 if (p == "toString") 104 id = StringProtoFunc::ToString; 105 else if (p == "valueOf") 106 id = StringProtoFunc::ValueOf; 107 else if (p == "charAt") 108 id = StringProtoFunc::CharAt; 109 else if (p == "charCodeAt") 110 id = StringProtoFunc::CharCodeAt; 111 else if (p == "indexOf") 112 id = StringProtoFunc::IndexOf; 113 else if (p == "lastIndexOf") 114 id = StringProtoFunc::LastIndexOf; 115 else if (p == "match") 116 id = StringProtoFunc::Match; 117 else if (p == "replace") 118 id = StringProtoFunc::Replace; 119 else if (p == "search") 120 id = StringProtoFunc::Search; 121 else if (p == "split") 122 id = StringProtoFunc::Split; 123 else if (p == "substr") 124 id = StringProtoFunc::Substr; 125 else if (p == "substring") 126 id = StringProtoFunc::Substring; 127 else if (p == "toLowerCase") 128 id = StringProtoFunc::ToLowerCase; 129 else if (p == "toUpperCase") 130 id = StringProtoFunc::ToUpperCase; 131 #ifndef KJS_PURE_ECMA 132 else if (p == "big") 133 id = StringProtoFunc::Big; 134 else if (p == "small") 135 id = StringProtoFunc::Small; 136 else if (p == "blink") 137 id = StringProtoFunc::Blink; 138 else if (p == "bold") 139 id = StringProtoFunc::Bold; 140 else if (p == "fixed") 141 id = StringProtoFunc::Fixed; 142 else if (p == "italics") 143 id = StringProtoFunc::Italics; 144 else if (p == "strike") 145 id = StringProtoFunc::Strike; 146 else if (p == "sub") 147 id = StringProtoFunc::Sub; 148 else if (p == "sup") 149 id = StringProtoFunc::Sup; 150 else if (p == "fontcolor") 151 id = StringProtoFunc::Fontcolor; 152 else if (p == "fontsize") 153 id = StringProtoFunc::Fontsize; 154 else if (p == "anchor") 155 id = StringProtoFunc::Anchor; 156 else if (p == "link") 157 id = StringProtoFunc::Link; 158 #endif 159 else 160 return Imp::get(p); 161 162 return Function(new StringProtoFunc(id)); 163 } 164 165 StringProtoFunc::StringProtoFunc(int i) 166 : id(i) 167 { 168 } 169 170 // ECMA 15.5.4.2 - 15.5.4.20 171 Completion StringProtoFunc::execute(const List &args) 172 { 173 KJSO result; 174 175 Object thisObj = Object::dynamicCast(thisValue()); 176 177 // toString and valueOf are no generic function. 178 if (id == ToString || id == ValueOf) { 179 if (thisObj.isNull() || thisObj.getClass() != StringClass) { 180 result = Error::create(TypeError); 181 return Completion(ReturnValue, result); 182 } 183 } 184 185 String s2; 186 Number n, m; 187 UString u, u2, u3; 188 int pos, p0, i; 189 double d, d2; 190 KJSO v = thisObj.internalValue(); 191 String s = v.toString(); 192 int len = s.value().size(); 193 KJSO a0 = args[0]; 194 KJSO a1 = args[1]; 195 196 switch (id) { 197 case ToString: 198 case ValueOf: 199 result = v.toString(); 200 break; 201 case CharAt: 202 n = a0.toInteger(); 203 pos = (int) n.value(); 204 if (pos < 0 || pos >= len) 205 u = ""; 206 else 207 u = s.value().substr(pos, 1); 208 result = String(u); 209 break; 210 case CharCodeAt: 211 n = a0.toInteger(); 212 pos = (int) n.value(); 213 if (pos < 0 || pos >= len) 214 d = NaN; 215 else { 216 UChar c = s.value()[pos]; 217 d = (c.high() << 8) + c.low(); 218 } 219 result = Number(d); 220 break; 221 case IndexOf: 222 s2 = a0.toString(); 223 if (a1.isA(UndefinedType)) 224 pos = 0; 225 else 226 pos = a1.toInteger().intValue(); 227 d = s.value().find(s2.value(), pos); 228 result = Number(d); 229 break; 230 case LastIndexOf: 231 s2 = a0.toString(); 232 if (a1.isA(UndefinedType)) 233 pos = len; 234 else 235 pos = a1.toInteger().intValue(); 236 d = s.value().rfind(s2.value(), pos); 237 result = Number(d); 238 break; 239 case Match: 240 case Search: 241 u = s.value(); 242 if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) { 243 s2 = a0.get("source").toString(); 244 RegExp reg(s2.value()); 245 UString mstr = reg.match(u, -1, &pos); 246 if (id == Search) { 247 result = Number(pos); 248 break; 249 } 250 if (mstr.isNull()) { 251 result = Null(); 252 break; 253 } 254 /* TODO return an array, with the matches, etc. */ 255 result = String(mstr); 256 } else 257 { 258 printf("Match/Search. Argument is not a RegExp - returning Undefined\n"); 259 result = Undefined(); // No idea what to do here 260 } 261 break; 262 case Replace: 263 /* TODO: this is just a hack to get the most common cases going */ 264 u = s.value(); 265 if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) { 266 s2 = a0.get("source").toString(); 267 RegExp reg(s2.value()); 268 UString mstr = reg.match(u, -1, &pos); 269 len = mstr.size(); 270 } else { 271 s2 = a0.toString(); 272 u2 = s2.value(); 273 pos = u.find(u2); 274 len = u2.size(); 275 } 276 if (pos == -1) 277 result = s; 278 else { 279 u3 = u.substr(0, pos) + a1.toString().value() + 280 u.substr(pos + len); 281 result = String(u3); 282 } 283 break; 284 case Split: 285 result = Object::create(ArrayClass); 286 u = s.value(); 287 i = p0 = 0; 288 d = a1.isDefined() ? a1.toInteger().intValue() : -1; // optional max number 289 if (a0.isA(ObjectType) && Object(a0.imp()).getClass() == RegExpClass) { 290 RegExp reg(a0.get("source").toString().value()); 291 if (u.isEmpty() && !reg.match(u, 0).isNull()) { 292 // empty string matched by regexp -> empty array 293 result.put("length", 0); 294 break; 295 } 296 int mpos; 297 pos = 0; 298 while (1) { 299 /* TODO: back references */ 300 UString mstr = reg.match(u, pos, &mpos); 301 if (mpos < 0) 302 break; 303 pos = mpos + (mstr.isEmpty() ? 1 : mstr.size()); 304 if (mpos != p0 || !mstr.isEmpty()) { 305 result.put(UString::from(i), String(u.substr(p0, mpos-p0))); 306 p0 = mpos + mstr.size(); 307 i++; 308 } 309 } 310 } else if (a0.isDefined()) { 311 u2 = a0.toString().value(); 312 if (u2.isEmpty()) { 313 if (u.isEmpty()) { 314 // empty separator matches empty string -> empty array 315 put("length", 0); 316 break; 317 } else { 318 while (i != d && i < u.size()) 319 result.put(UString::from(i++), String(u.substr(p0++, 1))); 320 } 321 } else { 322 while (i != d && (pos = u.find(u2, p0)) >= 0) { 323 result.put(UString::from(i), String(u.substr(p0, pos-p0))); 324 p0 = pos + u2.size(); 325 i++; 326 } 327 } 328 } 329 // add remaining string, if any 330 if (i != d && (p0 < len || i == 0)) 331 result.put(UString::from(i++), String(u.substr(p0))); 332 result.put("length", i); 333 break; 334 case Substr: 335 n = a0.toInteger(); 336 m = a1.toInteger(); 337 if (n.value() >= 0) 338 d = n.value(); 339 else 340 d = max(len + n.value(), 0); 341 if (a1.isA(UndefinedType)) 342 d2 = len - d; 343 else 344 d2 = min(max(m.value(), 0), len - d); 345 result = String(s.value().substr((int)d, (int)d2)); 346 break; 347 case Substring: 348 n = a0.toInteger(); 349 m = a1.toInteger(); 350 d = min(max(n.value(), 0), len); 351 if (a1.isA(UndefinedType)) 352 d2 = len - d; 353 else { 354 d2 = min(max(m.value(), 0), len); 355 d2 = max(d2-d, 0); 356 } 357 result = String(s.value().substr((int)d, (int)d2)); 358 break; 359 case ToLowerCase: 360 u = UString(s.value()); 361 for (i = 0; i < len; i++) 362 u[i] = u[i].toLower(); 363 result = String(u); 364 break; 365 case ToUpperCase: 366 u = UString(s.value()); 367 for (i = 0; i < len; i++) 368 u[i] = u[i].toUpper(); 369 result = String(u); 370 break; 371 #ifndef KJS_PURE_ECMA 372 case Big: 373 result = String("<BIG>" + s.value() + "</BIG>"); 374 break; 375 case Small: 376 result = String("<SMALL>" + s.value() + "</SMALL>"); 377 break; 378 case Blink: 379 result = String("<BLINK>" + s.value() + "</BLINK>"); 380 break; 381 case Bold: 382 result = String("<B>" + s.value() + "</B>"); 383 break; 384 case Fixed: 385 result = String("<TT>" + s.value() + "</TT>"); 386 break; 387 case Italics: 388 result = String("<I>" + s.value() + "</I>"); 389 break; 390 case Strike: 391 result = String("<STRIKE>" + s.value() + "</STRIKE>"); 392 break; 393 case Sub: 394 result = String("<SUB>" + s.value() + "</SUB>"); 395 break; 396 case Sup: 397 result = String("<SUP>" + s.value() + "</SUP>"); 398 break; 399 case Fontcolor: 400 result = String("<FONT COLOR=" + a0.toString().value() + ">" 401 + s.value() + "</FONT>"); 402 break; 403 case Fontsize: 404 result = String("<FONT SIZE=" + a0.toString().value() + ">" 405 + s.value() + "</FONT>"); 406 break; 407 case Anchor: 408 result = String("<a name=" + a0.toString().value() + ">" 409 + s.value() + "</a>"); 410 break; 411 case Link: 412 result = String("<a href=" + a0.toString().value() + ">" 413 + s.value() + "</a>"); 414 break; 415 #endif 416 } 417 418 return Completion(ReturnValue, result); 419 } 539 return String(s); 540 }
Note:
See TracChangeset
for help on using the changeset viewer.