kjs Library API Documentation

string_object.cpp

00001 // -*- c-basic-offset: 2 -*- 00002 /* 00003 * This file is part of the KDE libraries 00004 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 00005 * Copyright (C) 2003 Apple Computer, Inc. 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 * 00021 */ 00022 00023 #include "value.h" 00024 #include "object.h" 00025 #include "types.h" 00026 #include "interpreter.h" 00027 #include "operations.h" 00028 #include "regexp.h" 00029 #include "regexp_object.h" 00030 #include "string_object.h" 00031 #include "error_object.h" 00032 #include <stdio.h> 00033 #include "string_object.lut.h" 00034 00035 using namespace KJS; 00036 00037 // ------------------------------ StringInstanceImp ---------------------------- 00038 00039 const ClassInfo StringInstanceImp::info = {"String", 0, 0, 0}; 00040 00041 StringInstanceImp::StringInstanceImp(ObjectImp *proto) 00042 : ObjectImp(proto) 00043 { 00044 setInternalValue(String("")); 00045 } 00046 00047 StringInstanceImp::StringInstanceImp(ObjectImp *proto, const UString &string) 00048 : ObjectImp(proto) 00049 { 00050 setInternalValue(String(string)); 00051 } 00052 00053 Value StringInstanceImp::get(ExecState *exec, const Identifier &propertyName) const 00054 { 00055 if (propertyName == lengthPropertyName) 00056 return Number(internalValue().toString(exec).size()); 00057 00058 bool ok; 00059 unsigned index = propertyName.toULong(&ok); 00060 if (ok) { 00061 UString str = internalValue().toString(exec); 00062 if (index < (unsigned)str.size()) 00063 return String(str.substr(index,1)); 00064 } 00065 00066 return ObjectImp::get(exec, propertyName); 00067 } 00068 00069 void StringInstanceImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr) 00070 { 00071 if (propertyName == lengthPropertyName) 00072 return; 00073 ObjectImp::put(exec, propertyName, value, attr); 00074 } 00075 00076 bool StringInstanceImp::hasProperty(ExecState *exec, const Identifier &propertyName) const 00077 { 00078 if (propertyName == lengthPropertyName) 00079 return true; 00080 00081 bool ok; 00082 unsigned index = propertyName.toULong(&ok); 00083 if (ok && index < (unsigned)internalValue().toString(exec).size()) 00084 return true; 00085 00086 return ObjectImp::hasProperty(exec, propertyName); 00087 } 00088 00089 bool StringInstanceImp::deleteProperty(ExecState *exec, const Identifier &propertyName) 00090 { 00091 if (propertyName == lengthPropertyName) 00092 return false; 00093 00094 bool ok; 00095 unsigned index = propertyName.toULong(&ok); 00096 if (ok && index < (unsigned)internalValue().toString(exec).size()) 00097 return false; 00098 00099 return ObjectImp::deleteProperty(exec, propertyName); 00100 } 00101 00102 ReferenceList StringInstanceImp::propList(ExecState *exec, bool recursive) 00103 { 00104 ReferenceList properties = ObjectImp::propList(exec,recursive); 00105 00106 UString str = internalValue().toString(exec); 00107 for (int i = 0; i < str.size(); i++) 00108 if (!ObjectImp::hasProperty(exec,Identifier::from(i))) 00109 properties.append(Reference(this, i)); 00110 00111 return properties; 00112 } 00113 00114 // ------------------------------ StringPrototypeImp --------------------------- 00115 const ClassInfo StringPrototypeImp::info = {"String", &StringInstanceImp::info, &stringTable, 0}; 00116 /* Source for string_object.lut.h 00117 @begin stringTable 28 00118 toString StringProtoFuncImp::ToString DontEnum|Function 0 00119 valueOf StringProtoFuncImp::ValueOf DontEnum|Function 0 00120 charAt StringProtoFuncImp::CharAt DontEnum|Function 1 00121 charCodeAt StringProtoFuncImp::CharCodeAt DontEnum|Function 1 00122 concat StringProtoFuncImp::Concat DontEnum|Function 0 00123 indexOf StringProtoFuncImp::IndexOf DontEnum|Function 2 00124 lastIndexOf StringProtoFuncImp::LastIndexOf DontEnum|Function 2 00125 match StringProtoFuncImp::Match DontEnum|Function 1 00126 replace StringProtoFuncImp::Replace DontEnum|Function 2 00127 search StringProtoFuncImp::Search DontEnum|Function 1 00128 slice StringProtoFuncImp::Slice DontEnum|Function 2 00129 split StringProtoFuncImp::Split DontEnum|Function 2 00130 substr StringProtoFuncImp::Substr DontEnum|Function 2 00131 substring StringProtoFuncImp::Substring DontEnum|Function 2 00132 toLowerCase StringProtoFuncImp::ToLowerCase DontEnum|Function 0 00133 toUpperCase StringProtoFuncImp::ToUpperCase DontEnum|Function 0 00134 # 00135 # Under here: html extension, should only exist if KJS_PURE_ECMA is not defined 00136 # I guess we need to generate two hashtables in the .lut.h file, and use #ifdef 00137 # to select the right one... TODO. ##### 00138 big StringProtoFuncImp::Big DontEnum|Function 0 00139 small StringProtoFuncImp::Small DontEnum|Function 0 00140 blink StringProtoFuncImp::Blink DontEnum|Function 0 00141 bold StringProtoFuncImp::Bold DontEnum|Function 0 00142 fixed StringProtoFuncImp::Fixed DontEnum|Function 0 00143 italics StringProtoFuncImp::Italics DontEnum|Function 0 00144 strike StringProtoFuncImp::Strike DontEnum|Function 0 00145 sub StringProtoFuncImp::Sub DontEnum|Function 0 00146 sup StringProtoFuncImp::Sup DontEnum|Function 0 00147 fontcolor StringProtoFuncImp::Fontcolor DontEnum|Function 1 00148 fontsize StringProtoFuncImp::Fontsize DontEnum|Function 1 00149 anchor StringProtoFuncImp::Anchor DontEnum|Function 1 00150 link StringProtoFuncImp::Link DontEnum|Function 1 00151 @end 00152 */ 00153 // ECMA 15.5.4 00154 StringPrototypeImp::StringPrototypeImp(ExecState */*exec*/, 00155 ObjectPrototypeImp *objProto) 00156 : StringInstanceImp(objProto) 00157 { 00158 Value protect(this); 00159 // The constructor will be added later, after StringObjectImp has been built 00160 putDirect(lengthPropertyName, NumberImp::zero(), DontDelete|ReadOnly|DontEnum); 00161 00162 } 00163 00164 Value StringPrototypeImp::get(ExecState *exec, const Identifier &propertyName) const 00165 { 00166 return lookupGetFunction<StringProtoFuncImp, StringInstanceImp>( exec, propertyName, &stringTable, this ); 00167 } 00168 00169 // ------------------------------ StringProtoFuncImp --------------------------- 00170 00171 StringProtoFuncImp::StringProtoFuncImp(ExecState *exec, int i, int len) 00172 : InternalFunctionImp( 00173 static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp()) 00174 ), id(i) 00175 { 00176 Value protect(this); 00177 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum); 00178 } 00179 00180 bool StringProtoFuncImp::implementsCall() const 00181 { 00182 return true; 00183 } 00184 00185 // ECMA 15.5.4.2 - 15.5.4.20 00186 Value StringProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args) 00187 { 00188 Value result; 00189 00190 // toString and valueOf are no generic function. 00191 if (id == ToString || id == ValueOf) { 00192 KJS_CHECK_THIS( StringInstanceImp, thisObj ); 00193 00194 return String(thisObj.internalValue().toString(exec)); 00195 } 00196 00197 int n, m; 00198 UString u2, u3; 00199 int pos, p0, i; 00200 double d = 0.0; 00201 00202 UString s = thisObj.toString(exec); 00203 00204 int len = s.size(); 00205 Value a0 = args[0]; 00206 Value a1 = args[1]; 00207 00208 switch (id) { 00209 case ToString: 00210 case ValueOf: 00211 // handled above 00212 break; 00213 case CharAt: 00214 pos = a0.toInteger(exec); 00215 if (pos < 0 || pos >= len) 00216 s = ""; 00217 else 00218 s = s.substr(pos, 1); 00219 result = String(s); 00220 break; 00221 case CharCodeAt: 00222 pos = a0.toInteger(exec); 00223 if (pos < 0 || pos >= len) 00224 d = NaN; 00225 else { 00226 UChar c = s[pos]; 00227 d = (c.high() << 8) + c.low(); 00228 } 00229 result = Number(d); 00230 break; 00231 case Concat: { 00232 ListIterator it = args.begin(); 00233 for ( ; it != args.end() ; ++it) { 00234 s += it->dispatchToString(exec); 00235 } 00236 result = String(s); 00237 break; 00238 } 00239 case IndexOf: 00240 u2 = a0.toString(exec); 00241 if (a1.type() == UndefinedType) 00242 pos = 0; 00243 else 00244 pos = a1.toInteger(exec); 00245 d = s.find(u2, pos); 00246 result = Number(d); 00247 break; 00248 case LastIndexOf: 00249 u2 = a0.toString(exec); 00250 d = a1.toNumber(exec); 00251 if (a1.type() == UndefinedType || KJS::isNaN(d) || KJS::isPosInf(d)) 00252 pos = len; 00253 else 00254 pos = a1.toInteger(exec); 00255 if (pos < 0) 00256 pos = 0; 00257 d = s.rfind(u2, pos); 00258 result = Number(d); 00259 break; 00260 case Match: 00261 case Search: { 00262 RegExp *reg, *tmpReg = 0; 00263 RegExpImp *imp = 0; 00264 if (a0.isA(ObjectType) && a0.toObject(exec).inherits(&RegExpImp::info)) 00265 { 00266 imp = static_cast<RegExpImp *>( a0.toObject(exec).imp() ); 00267 reg = imp->regExp(); 00268 } 00269 else 00270 { /* 00271 * ECMA 15.5.4.12 String.prototype.search (regexp) 00272 * If regexp is not an object whose [[Class]] property is "RegExp", it is 00273 * replaced with the result of the expression new RegExp(regexp). 00274 */ 00275 reg = tmpReg = new RegExp(a0.toString(exec), RegExp::None); 00276 } 00277 RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp()); 00278 int **ovector = regExpObj->registerRegexp(reg, s); 00279 UString mstr = reg->match(s, -1, &pos, ovector); 00280 if (id == Search) { 00281 result = Number(pos); 00282 } else { // Match 00283 if (mstr.isNull()) { 00284 result = Null(); // no match 00285 } else if ((reg->flags() & RegExp::Global) == 0) { 00286 // case without 'g' flag is handled like RegExp.prototype.exec 00287 regExpObj->setSubPatterns(reg->subPatterns()); 00288 result = regExpObj->arrayOfMatches(exec,mstr); 00289 } else { 00290 // return array of matches 00291 List list; 00292 int lastIndex = 0; 00293 while (pos >= 0) { 00294 list.append(String(mstr)); 00295 lastIndex = pos; 00296 pos += mstr.isEmpty() ? 1 : mstr.size(); 00297 delete [] *ovector; 00298 mstr = reg->match(s, pos, &pos, ovector); 00299 } 00300 result = exec->interpreter()->builtinArray().construct(exec, list); 00301 } 00302 } 00303 delete tmpReg; 00304 break; 00305 } 00306 case Replace: 00307 if (a0.type() == ObjectType && a0.toObject(exec).inherits(&RegExpImp::info)) { 00308 RegExpImp* imp = static_cast<RegExpImp *>( a0.toObject(exec).imp() ); 00309 RegExp *reg = imp->regExp(); 00310 bool global = false; 00311 Value tmp = imp->get(exec,"global"); 00312 if (tmp.type() != UndefinedType && tmp.toBoolean(exec) == true) 00313 global = true; 00314 00315 RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp()); 00316 int lastIndex = 0; 00317 Object o1; 00318 // Test if 2nd arg is a function (new in JS 1.3) 00319 if ( a1.type() == ObjectType && a1.toObject(exec).implementsCall() ) 00320 o1 = a1.toObject(exec); 00321 else 00322 u3 = a1.toString(exec); // 2nd arg is the replacement string 00323 00324 // This is either a loop (if global is set) or a one-way (if not). 00325 do { 00326 int **ovector = regExpObj->registerRegexp( reg, s ); 00327 UString mstr = reg->match(s, lastIndex, &pos, ovector); 00328 regExpObj->setSubPatterns(reg->subPatterns()); 00329 if (pos == -1) 00330 break; 00331 len = mstr.size(); 00332 00333 UString rstr; 00334 // Prepare replacement 00335 if (!o1.isValid()) 00336 { 00337 rstr = u3; 00338 bool ok; 00339 // check if u3 matches $1 or $2 etc 00340 for (int i = 0; (i = rstr.find(UString("$"), i)) != -1; i++) { 00341 if (i+1<rstr.size() && rstr[i+1] == '$') { // "$$" -> "$" 00342 rstr = rstr.substr(0,i) + "$" + rstr.substr(i+2); 00343 continue; 00344 } 00345 // Assume number part is one char exactly 00346 unsigned long pos = rstr.substr(i+1,1).toULong(&ok, false /* tolerate empty string */); 00347 if (ok && pos <= (unsigned)reg->subPatterns()) { 00348 rstr = rstr.substr(0,i) 00349 + s.substr((*ovector)[2*pos], 00350 (*ovector)[2*pos+1]-(*ovector)[2*pos]) 00351 + rstr.substr(i+2); 00352 i += (*ovector)[2*pos+1]-(*ovector)[2*pos] - 1; // -1 offsets i++ 00353 } 00354 } 00355 } else // 2nd arg is a function call. Spec from http://devedge.netscape.com/library/manuals/2000/javascript/1.5/reference/string.html#1194258 00356 { 00357 List l; 00358 l.append(String(mstr)); // First arg: complete matched substring 00359 // Then the submatch strings 00360 for ( unsigned int sub = 1; sub <= reg->subPatterns() ; ++sub ) 00361 l.append( String( s.substr((*ovector)[2*sub], 00362 (*ovector)[2*sub+1]-(*ovector)[2*sub]) ) ); 00363 l.append(Number(pos)); // The offset within the string where the match occurred 00364 l.append(String(s)); // Last arg: the string itself. Can't see the difference with the 1st arg! 00365 Object thisObj = exec->interpreter()->globalObject(); 00366 rstr = o1.call( exec, thisObj, l ).toString(exec); 00367 } 00368 lastIndex = pos + rstr.size(); 00369 s = s.substr(0, pos) + rstr + s.substr(pos + len); 00370 //fprintf(stderr,"pos=%d,len=%d,lastIndex=%d,s=%s\n",pos,len,lastIndex,s.ascii()); 00371 } while (global); 00372 00373 result = String(s); 00374 } else { // First arg is a string 00375 u2 = a0.toString(exec); 00376 pos = s.find(u2); 00377 len = u2.size(); 00378 // Do the replacement 00379 if (pos == -1) 00380 result = String(s); 00381 else { 00382 u3 = s.substr(0, pos) + a1.toString(exec) + 00383 s.substr(pos + len); 00384 result = String(u3); 00385 } 00386 } 00387 break; 00388 case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/string.htm#1194366 or 15.5.4.13 00389 { 00390 // The arg processing is very much like ArrayProtoFunc::Slice 00391 int begin = args[0].toUInt32(exec); 00392 if (begin < 0) 00393 begin = maxInt(begin + len, 0); 00394 else 00395 begin = minInt(begin, len); 00396 int end = len; 00397 if (args[1].type() != UndefinedType) { 00398 end = args[1].toInteger(exec); 00399 if (end < 0) 00400 end = maxInt(len + end, 0); 00401 else 00402 end = minInt(end, len); 00403 } 00404 //printf( "Slicing from %d to %d \n", begin, end ); 00405 result = String(s.substr(begin, end-begin)); 00406 break; 00407 } 00408 case Split: { // 15.5.4.14 00409 Object constructor = exec->interpreter()->builtinArray(); 00410 Object res = Object::dynamicCast(constructor.construct(exec,List::empty())); 00411 result = res; 00412 i = p0 = 0; 00413 d = (a1.type() != UndefinedType) ? a1.toInteger(exec) : -1; // optional max number 00414 if (a0.type() == ObjectType && Object::dynamicCast(a0).inherits(&RegExpImp::info)) { 00415 Object obj0 = Object::dynamicCast(a0); 00416 RegExp reg(obj0.get(exec,"source").toString(exec)); 00417 if (s.isEmpty() && !reg.match(s, 0).isNull()) { 00418 // empty string matched by regexp -> empty array 00419 res.put(exec, lengthPropertyName, Number(0), DontDelete|ReadOnly|DontEnum); 00420 break; 00421 } 00422 pos = 0; 00423 while (pos < s.size()) { 00424 // TODO: back references 00425 int mpos; 00426 int *ovector = 0L; 00427 UString mstr = reg.match(s, pos, &mpos, &ovector); 00428 delete [] ovector; ovector = 0L; 00429 if (mpos < 0) 00430 break; 00431 pos = mpos + (mstr.isEmpty() ? 1 : mstr.size()); 00432 if (mpos != p0 || !mstr.isEmpty()) { 00433 res.put(exec,i, String(s.substr(p0, mpos-p0))); 00434 p0 = mpos + mstr.size(); 00435 i++; 00436 } 00437 } 00438 } else if (a0.type() != UndefinedType) { 00439 u2 = a0.toString(exec); 00440 if (u2.isEmpty()) { 00441 if (s.isEmpty()) { 00442 // empty separator matches empty string -> empty array 00443 put(exec,lengthPropertyName, Number(0)); 00444 break; 00445 } else { 00446 while (i != d && i < s.size()-1) 00447 res.put(exec,i++, String(s.substr(p0++, 1))); 00448 } 00449 } else { 00450 while (i != d && (pos = s.find(u2, p0)) >= 0) { 00451 res.put(exec,i, String(s.substr(p0, pos-p0))); 00452 p0 = pos + u2.size(); 00453 i++; 00454 } 00455 } 00456 } 00457 // add remaining string, if any 00458 if (i != d) 00459 res.put(exec,i++, String(s.substr(p0))); 00460 res.put(exec,lengthPropertyName, Number(i)); 00461 } 00462 break; 00463 case Substr: { 00464 n = a0.toInteger(exec); 00465 m = a1.toInteger(exec); 00466 int d, d2; 00467 if (n >= 0) 00468 d = n; 00469 else 00470 d = maxInt(len + n, 0); 00471 if (a1.type() == UndefinedType) 00472 d2 = len - d; 00473 else 00474 d2 = minInt(maxInt(m, 0), len - d); 00475 result = String(s.substr(d, d2)); 00476 break; 00477 } 00478 case Substring: { 00479 double start = a0.toNumber(exec); 00480 double end = a1.toNumber(exec); 00481 if (KJS::isNaN(start)) 00482 start = 0; 00483 if (KJS::isNaN(end)) 00484 end = 0; 00485 if (start < 0) 00486 start = 0; 00487 if (end < 0) 00488 end = 0; 00489 if (start > len) 00490 start = len; 00491 if (end > len) 00492 end = len; 00493 if (a1.type() == UndefinedType) 00494 end = len; 00495 if (start > end) { 00496 double temp = end; 00497 end = start; 00498 start = temp; 00499 } 00500 result = String(s.substr((int)start, (int)end-(int)start)); 00501 } 00502 break; 00503 case ToLowerCase: 00504 for (i = 0; i < len; i++) 00505 s[i] = s[i].toLower(); 00506 result = String(s); 00507 break; 00508 case ToUpperCase: 00509 for (i = 0; i < len; i++) 00510 s[i] = s[i].toUpper(); 00511 result = String(s); 00512 break; 00513 #ifndef KJS_PURE_ECMA 00514 case Big: 00515 result = String("<BIG>" + s + "</BIG>"); 00516 break; 00517 case Small: 00518 result = String("<SMALL>" + s + "</SMALL>"); 00519 break; 00520 case Blink: 00521 result = String("<BLINK>" + s + "</BLINK>"); 00522 break; 00523 case Bold: 00524 result = String("<B>" + s + "</B>"); 00525 break; 00526 case Fixed: 00527 result = String("<TT>" + s + "</TT>"); 00528 break; 00529 case Italics: 00530 result = String("<I>" + s + "</I>"); 00531 break; 00532 case Strike: 00533 result = String("<STRIKE>" + s + "</STRIKE>"); 00534 break; 00535 case Sub: 00536 result = String("<SUB>" + s + "</SUB>"); 00537 break; 00538 case Sup: 00539 result = String("<SUP>" + s + "</SUP>"); 00540 break; 00541 case Fontcolor: 00542 result = String("<FONT COLOR=" + a0.toString(exec) + ">" 00543 + s + "</FONT>"); 00544 break; 00545 case Fontsize: 00546 result = String("<FONT SIZE=" + a0.toString(exec) + ">" 00547 + s + "</FONT>"); 00548 break; 00549 case Anchor: 00550 result = String("<a name=" + a0.toString(exec) + ">" 00551 + s + "</a>"); 00552 break; 00553 case Link: 00554 result = String("<a href=" + a0.toString(exec) + ">" 00555 + s + "</a>"); 00556 break; 00557 #endif 00558 } 00559 00560 return result; 00561 } 00562 00563 // ------------------------------ StringObjectImp ------------------------------ 00564 00565 StringObjectImp::StringObjectImp(ExecState *exec, 00566 FunctionPrototypeImp *funcProto, 00567 StringPrototypeImp *stringProto) 00568 : InternalFunctionImp(funcProto) 00569 { 00570 Value protect(this); 00571 // ECMA 15.5.3.1 String.prototype 00572 putDirect(prototypePropertyName, stringProto, DontEnum|DontDelete|ReadOnly); 00573 00574 putDirect("fromCharCode", new StringObjectFuncImp(exec,funcProto), DontEnum); 00575 00576 // no. of arguments for constructor 00577 putDirect(lengthPropertyName, NumberImp::one(), ReadOnly|DontDelete|DontEnum); 00578 } 00579 00580 00581 bool StringObjectImp::implementsConstruct() const 00582 { 00583 return true; 00584 } 00585 00586 // ECMA 15.5.2 00587 Object StringObjectImp::construct(ExecState *exec, const List &args) 00588 { 00589 ObjectImp *proto = exec->interpreter()->builtinStringPrototype().imp(); 00590 if (args.size() == 0) 00591 return Object(new StringInstanceImp(proto)); 00592 return Object(new StringInstanceImp(proto, args.begin()->dispatchToString(exec))); 00593 } 00594 00595 bool StringObjectImp::implementsCall() const 00596 { 00597 return true; 00598 } 00599 00600 // ECMA 15.5.1 00601 Value StringObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args) 00602 { 00603 if (args.isEmpty()) 00604 return String(""); 00605 else { 00606 Value v = args[0]; 00607 return String(v.toString(exec)); 00608 } 00609 } 00610 00611 // ------------------------------ StringObjectFuncImp -------------------------- 00612 00613 // ECMA 15.5.3.2 fromCharCode() 00614 StringObjectFuncImp::StringObjectFuncImp(ExecState */*exec*/, FunctionPrototypeImp *funcProto) 00615 : InternalFunctionImp(funcProto) 00616 { 00617 Value protect(this); 00618 putDirect(lengthPropertyName, NumberImp::one(), DontDelete|ReadOnly|DontEnum); 00619 } 00620 00621 bool StringObjectFuncImp::implementsCall() const 00622 { 00623 return true; 00624 } 00625 00626 Value StringObjectFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args) 00627 { 00628 UString s; 00629 if (args.size()) { 00630 UChar *buf = new UChar[args.size()]; 00631 UChar *p = buf; 00632 ListIterator it = args.begin(); 00633 while (it != args.end()) { 00634 unsigned short u = it->toUInt16(exec); 00635 *p++ = UChar(u); 00636 it++; 00637 } 00638 s = UString(buf, args.size(), false); 00639 } else 00640 s = ""; 00641 00642 return String(s); 00643 }
KDE Logo
This file is part of the documentation for kjs Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 20 09:48:58 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003