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 Thu Sep 30 05:17:58 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2003