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         // special case of empty match
00333         if (len == 0 && lastIndex > 0) {
00334           pos = lastIndex + 1;
00335           if (pos > s.size())
00336             break;
00337         }
00338 
00339         UString rstr;
00340         // Prepare replacement
00341         if (!o1.isValid())
00342         {
00343           rstr = u3;
00344           bool ok;
00345           // check if u3 matches $1 or $2 etc
00346           for (int i = 0; (i = rstr.find(UString("$"), i)) != -1; i++) {
00347             if (i+1<rstr.size() && rstr[i+1] == '$') {  // "$$" -> "$"
00348               rstr = rstr.substr(0,i) + "$" + rstr.substr(i+2);
00349               continue;
00350             }
00351             // Assume number part is one char exactly
00352             unsigned long pos = rstr.substr(i+1,1).toULong(&ok, false /* tolerate empty string */);
00353             if (ok && pos <= (unsigned)reg->subPatterns()) {
00354               rstr = rstr.substr(0,i)
00355                      + s.substr((*ovector)[2*pos],
00356                                 (*ovector)[2*pos+1]-(*ovector)[2*pos])
00357                      + rstr.substr(i+2);
00358               i += (*ovector)[2*pos+1]-(*ovector)[2*pos] - 1; // -1 offsets i++
00359             }
00360           }
00361         } else // 2nd arg is a function call. Spec from http://devedge.netscape.com/library/manuals/2000/javascript/1.5/reference/string.html#1194258
00362         {
00363           List l;
00364           l.append(String(mstr)); // First arg: complete matched substring
00365           // Then the submatch strings
00366           for ( unsigned int sub = 1; sub <= reg->subPatterns() ; ++sub )
00367             l.append( String( s.substr((*ovector)[2*sub],
00368                                (*ovector)[2*sub+1]-(*ovector)[2*sub]) ) );
00369           l.append(Number(pos)); // The offset within the string where the match occurred
00370           l.append(String(s)); // Last arg: the string itself. Can't see the difference with the 1st arg!
00371           Object thisObj = exec->interpreter()->globalObject();
00372           rstr = o1.call( exec, thisObj, l ).toString(exec);
00373         }
00374         lastIndex = pos + rstr.size();
00375         s = s.substr(0, pos) + rstr + s.substr(pos + len);
00376         //fprintf(stderr,"pos=%d,len=%d,lastIndex=%d,u=%s\n",pos,len,lastIndex,u.ascii());
00377       } while (global);
00378 
00379       result = String(s);
00380     } else { // First arg is a string
00381       u2 = a0.toString(exec);
00382       pos = s.find(u2);
00383       len = u2.size();
00384       // Do the replacement
00385       if (pos == -1)
00386         result = String(s);
00387       else {
00388         u3 = s.substr(0, pos) + a1.toString(exec) +
00389              s.substr(pos + len);
00390         result = String(u3);
00391       }
00392     }
00393     break;
00394   case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/string.htm#1194366 or 15.5.4.13
00395     {
00396         // The arg processing is very much like ArrayProtoFunc::Slice
00397         int begin = args[0].toUInt32(exec);
00398         if (begin < 0)
00399           begin = maxInt(begin + len, 0);
00400         else
00401           begin = minInt(begin, len);
00402         int end = len;
00403         if (args[1].type() != UndefinedType) {
00404           end = args[1].toInteger(exec);
00405           if (end < 0)
00406             end = maxInt(len + end, 0);
00407           else
00408             end = minInt(end, len);
00409         }
00410         //printf( "Slicing from %d to %d \n", begin, end );
00411         result = String(s.substr(begin, end-begin));
00412         break;
00413     }
00414     case Split: { // 15.5.4.14
00415     Object constructor = exec->interpreter()->builtinArray();
00416     Object res = Object::dynamicCast(constructor.construct(exec,List::empty()));
00417     result = res;
00418     i = p0 = 0;
00419     d = (a1.type() != UndefinedType) ? a1.toInteger(exec) : -1; // optional max number
00420     if (a0.type() == ObjectType && Object::dynamicCast(a0).inherits(&RegExpImp::info)) {
00421       Object obj0 = Object::dynamicCast(a0);
00422       RegExp reg(obj0.get(exec,"source").toString(exec));
00423       if (s.isEmpty() && !reg.match(s, 0).isNull()) {
00424     // empty string matched by regexp -> empty array
00425     res.put(exec, lengthPropertyName, Number(0), DontDelete|ReadOnly|DontEnum);
00426     break;
00427       }
00428       pos = 0;
00429       while (pos < s.size()) {
00430     // TODO: back references
00431         int mpos;
00432         int *ovector = 0L;
00433     UString mstr = reg.match(s, pos, &mpos, &ovector);
00434         delete [] ovector; ovector = 0L;
00435     if (mpos < 0)
00436       break;
00437     pos = mpos + (mstr.isEmpty() ? 1 : mstr.size());
00438     if (mpos != p0 || !mstr.isEmpty()) {
00439       res.put(exec,i, String(s.substr(p0, mpos-p0)));
00440       p0 = mpos + mstr.size();
00441       i++;
00442     }
00443       }
00444     } else if (a0.type() != UndefinedType) {
00445       u2 = a0.toString(exec);
00446       if (u2.isEmpty()) {
00447     if (s.isEmpty()) {
00448       // empty separator matches empty string -> empty array
00449       put(exec,lengthPropertyName, Number(0));
00450       break;
00451     } else {
00452       while (i != d && i < s.size()-1)
00453         res.put(exec,i++, String(s.substr(p0++, 1)));
00454     }
00455       } else {
00456     while (i != d && (pos = s.find(u2, p0)) >= 0) {
00457       res.put(exec,i, String(s.substr(p0, pos-p0)));
00458       p0 = pos + u2.size();
00459       i++;
00460     }
00461       }
00462     }
00463     // add remaining string, if any
00464     if (i != d)
00465       res.put(exec,i++, String(s.substr(p0)));
00466     res.put(exec,lengthPropertyName, Number(i));
00467     }
00468     break;
00469   case Substr: {
00470     n = a0.toInteger(exec);
00471     m = a1.toInteger(exec);
00472     int d, d2;
00473     if (n >= 0)
00474       d = n;
00475     else
00476       d = maxInt(len + n, 0);
00477     if (a1.type() == UndefinedType)
00478       d2 = len - d;
00479     else
00480       d2 = minInt(maxInt(m, 0), len - d);
00481     result = String(s.substr(d, d2));
00482     break;
00483   }
00484   case Substring: {
00485     double start = a0.toNumber(exec);
00486     double end = a1.toNumber(exec);
00487     if (KJS::isNaN(start))
00488       start = 0;
00489     if (KJS::isNaN(end))
00490       end = 0;
00491     if (start < 0)
00492       start = 0;
00493     if (end < 0)
00494       end = 0;
00495     if (start > len)
00496       start = len;
00497     if (end > len)
00498       end = len;
00499     if (a1.type() == UndefinedType)
00500       end = len;
00501     if (start > end) {
00502       double temp = end;
00503       end = start;
00504       start = temp;
00505     }
00506     result = String(s.substr((int)start, (int)end-(int)start));
00507     }
00508     break;
00509   case ToLowerCase:
00510     for (i = 0; i < len; i++)
00511       s[i] = s[i].toLower();
00512     result = String(s);
00513     break;
00514   case ToUpperCase:
00515     for (i = 0; i < len; i++)
00516       s[i] = s[i].toUpper();
00517     result = String(s);
00518     break;
00519 #ifndef KJS_PURE_ECMA
00520   case Big:
00521     result = String("<BIG>" + s + "</BIG>");
00522     break;
00523   case Small:
00524     result = String("<SMALL>" + s + "</SMALL>");
00525     break;
00526   case Blink:
00527     result = String("<BLINK>" + s + "</BLINK>");
00528     break;
00529   case Bold:
00530     result = String("<B>" + s + "</B>");
00531     break;
00532   case Fixed:
00533     result = String("<TT>" + s + "</TT>");
00534     break;
00535   case Italics:
00536     result = String("<I>" + s + "</I>");
00537     break;
00538   case Strike:
00539     result = String("<STRIKE>" + s + "</STRIKE>");
00540     break;
00541   case Sub:
00542     result = String("<SUB>" + s + "</SUB>");
00543     break;
00544   case Sup:
00545     result = String("<SUP>" + s + "</SUP>");
00546     break;
00547   case Fontcolor:
00548     result = String("<FONT COLOR=" + a0.toString(exec) + ">"
00549             + s + "</FONT>");
00550     break;
00551   case Fontsize:
00552     result = String("<FONT SIZE=" + a0.toString(exec) + ">"
00553             + s + "</FONT>");
00554     break;
00555   case Anchor:
00556     result = String("<a name=" + a0.toString(exec) + ">"
00557             + s + "</a>");
00558     break;
00559   case Link:
00560     result = String("<a href=" + a0.toString(exec) + ">"
00561             + s + "</a>");
00562     break;
00563 #endif
00564   }
00565 
00566   return result;
00567 }
00568 
00569 // ------------------------------ StringObjectImp ------------------------------
00570 
00571 StringObjectImp::StringObjectImp(ExecState *exec,
00572                                  FunctionPrototypeImp *funcProto,
00573                                  StringPrototypeImp *stringProto)
00574   : InternalFunctionImp(funcProto)
00575 {
00576   Value protect(this);
00577   // ECMA 15.5.3.1 String.prototype
00578   putDirect(prototypePropertyName, stringProto, DontEnum|DontDelete|ReadOnly);
00579 
00580   putDirect("fromCharCode", new StringObjectFuncImp(exec,funcProto), DontEnum);
00581 
00582   // no. of arguments for constructor
00583   putDirect(lengthPropertyName, NumberImp::one(), ReadOnly|DontDelete|DontEnum);
00584 }
00585 
00586 
00587 bool StringObjectImp::implementsConstruct() const
00588 {
00589   return true;
00590 }
00591 
00592 // ECMA 15.5.2
00593 Object StringObjectImp::construct(ExecState *exec, const List &args)
00594 {
00595   ObjectImp *proto = exec->interpreter()->builtinStringPrototype().imp();
00596   if (args.size() == 0)
00597     return Object(new StringInstanceImp(proto));
00598   return Object(new StringInstanceImp(proto, args.begin()->dispatchToString(exec)));
00599 }
00600 
00601 bool StringObjectImp::implementsCall() const
00602 {
00603   return true;
00604 }
00605 
00606 // ECMA 15.5.1
00607 Value StringObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
00608 {
00609   if (args.isEmpty())
00610     return String("");
00611   else {
00612     Value v = args[0];
00613     return String(v.toString(exec));
00614   }
00615 }
00616 
00617 // ------------------------------ StringObjectFuncImp --------------------------
00618 
00619 // ECMA 15.5.3.2 fromCharCode()
00620 StringObjectFuncImp::StringObjectFuncImp(ExecState */*exec*/, FunctionPrototypeImp *funcProto)
00621   : InternalFunctionImp(funcProto)
00622 {
00623   Value protect(this);
00624   putDirect(lengthPropertyName, NumberImp::one(), DontDelete|ReadOnly|DontEnum);
00625 }
00626 
00627 bool StringObjectFuncImp::implementsCall() const
00628 {
00629   return true;
00630 }
00631 
00632 Value StringObjectFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
00633 {
00634   UString s;
00635   if (args.size()) {
00636     UChar *buf = new UChar[args.size()];
00637     UChar *p = buf;
00638     ListIterator it = args.begin();
00639     while (it != args.end()) {
00640       unsigned short u = it->toUInt16(exec);
00641       *p++ = UChar(u);
00642       it++;
00643     }
00644     s = UString(buf, args.size(), false);
00645   } else
00646     s = "";
00647 
00648   return String(s);
00649 }
KDE Logo
This file is part of the documentation for kjs Library Version 3.2.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Feb 4 12:34:40 2004 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2003