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