kjs Library: string_object.cpp Source File (kjs Library)

| # kjs Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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   toLocaleLowerCase StringProtoFuncImp::ToLocaleLowerCase DontEnum|Function 0
    00138   toLocaleUpperCase     StringProtoFuncImp::ToLocaleUpperCase DontEnum|Function 0
    00139 #
    00140 # Under here: html extension, should only exist if KJS_PURE_ECMA is not defined
    00141 # I guess we need to generate two hashtables in the .lut.h file, and use #ifdef
    00142 # to select the right one... TODO. #####
    00143   big           StringProtoFuncImp::Big     DontEnum|Function   0
    00144   small         StringProtoFuncImp::Small   DontEnum|Function   0
    00145   blink         StringProtoFuncImp::Blink   DontEnum|Function   0
    00146   bold          StringProtoFuncImp::Bold    DontEnum|Function   0
    00147   fixed         StringProtoFuncImp::Fixed   DontEnum|Function   0
    00148   italics       StringProtoFuncImp::Italics DontEnum|Function   0
    00149   strike        StringProtoFuncImp::Strike  DontEnum|Function   0
    00150   sub           StringProtoFuncImp::Sub     DontEnum|Function   0
    00151   sup           StringProtoFuncImp::Sup     DontEnum|Function   0
    00152   fontcolor     StringProtoFuncImp::Fontcolor   DontEnum|Function   1
    00153   fontsize      StringProtoFuncImp::Fontsize    DontEnum|Function   1
    00154   anchor        StringProtoFuncImp::Anchor  DontEnum|Function   1
    00155   link          StringProtoFuncImp::Link    DontEnum|Function   1
    00156 @end
    00157 */
    00158 // ECMA 15.5.4
    00159 StringPrototypeImp::StringPrototypeImp(ExecState * /*exec*/,
    00160                                        ObjectPrototypeImp *objProto)
    00161   : StringInstanceImp(objProto)
    00162 {
    00163   Value protect(this);
    00164   // The constructor will be added later, after StringObjectImp has been built
    00165   putDirect(lengthPropertyName, NumberImp::zero(), DontDelete|ReadOnly|DontEnum);
    00166
    00167 }
    00168
    00169 Value StringPrototypeImp::get(ExecState *exec, const Identifier &propertyName) const
    00170 {
    00171   return lookupGetFunction<StringProtoFuncImp, StringInstanceImp>( exec, propertyName, &stringTable, this );
    00172 }
    00173
    00174 // ------------------------------ StringProtoFuncImp ---------------------------
    00175
    00176 StringProtoFuncImp::StringProtoFuncImp(ExecState *exec, int i, int len)
    00177   : InternalFunctionImp(
    00178     static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
    00179     ), id(i)
    00180 {
    00181   Value protect(this);
    00182   putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
    00183 }
    00184
    00185 bool StringProtoFuncImp::implementsCall() const
    00186 {
    00187   return true;
    00188 }
    00189
    00190 // ECMA 15.5.4.2 - 15.5.4.20
    00191 Value StringProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
    00192 {
    00193   Value result;
    00194
    00195   // toString and valueOf are no generic functions.
    00196   if (id == ToString || id == ValueOf) {
    00197     KJS_CHECK_THIS( StringInstanceImp, thisObj );
    00198
    00199     return String(thisObj.internalValue().toString(exec));
    00200   }
    00201
    00202   int n, m;
    00203   UString u2, u3;
    00204   int pos, p0, i;
    00205   double d = 0.0;
    00206
    00207   UString s = thisObj.toString(exec);
    00208
    00209   int len = s.size();
    00210   Value a0 = args[0];
    00211   Value a1 = args[1];
    00212
    00213   switch (id) {
    00214   case ToString:
    00215   case ValueOf:
    00216     // handled above
    00217     break;
    00218   case CharAt:
    00219     pos = a0.toInteger(exec);
    00220     if (pos < 0 || pos >= len)
    00221       s = "";
    00222     else
    00223       s = s.substr(pos, 1);
    00224     result = String(s);
    00225     break;
    00226   case CharCodeAt:
    00227     pos = a0.toInteger(exec);
    00228     if (pos < 0 || pos >= len)
    00229       d = NaN;
    00230     else {
    00231       UChar c = s[pos];
    00232       d = (c.high() << 8) + c.low();
    00233     }
    00234     result = Number(d);
    00235     break;
    00236   case Concat: {
    00237     ListIterator it = args.begin();
    00238     for ( ; it != args.end() ; ++it) {
    00239         s += it->dispatchToString(exec);
    00240     }
    00241     result = String(s);
    00242     break;
    00243   }
    00244   case IndexOf:
    00245     u2 = a0.toString(exec);
    00246     if (a1.type() == UndefinedType)
    00247       pos = 0;
    00248     else
    00249       pos = a1.toInteger(exec);
    00250     d = s.find(u2, pos);
    00251     result = Number(d);
    00252     break;
    00253   case LastIndexOf:
    00254     u2 = a0.toString(exec);
    00255     d = a1.toNumber(exec);
    00256     if (a1.type() == UndefinedType || KJS::isNaN(d) || KJS::isPosInf(d))
    00257       pos = len;
    00258     else
    00259       pos = a1.toInteger(exec);
    00260     if (pos < 0)
    00261       pos = 0;
    00262     d = s.rfind(u2, pos);
    00263     result = Number(d);
    00264     break;
    00265   case Match:
    00266   case Search: {
    00267     RegExp *reg, *tmpReg = 0;
    00268     RegExpImp *imp = 0;
    00269     if (a0.isA(ObjectType) && a0.toObject(exec).inherits(&RegExpImp::info))
    00270     {
    00271       imp = static_cast<RegExpImp *>( a0.toObject(exec).imp() );
    00272       reg = imp->regExp();
    00273     }
    00274     else
    00275     { /*
    00276        *  ECMA 15.5.4.12 String.prototype.search (regexp)
    00277        *  If regexp is not an object whose [[Class]] property is "RegExp", it is
    00278        *  replaced with the result of the expression new RegExp(regexp).
    00279        */
    00280       reg = tmpReg = new RegExp(a0.toString(exec), RegExp::None);
    00281     }
    00282     RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
    00283     int **ovector = regExpObj->registerRegexp(reg, s);
    00284     UString mstr = reg->match(s, -1, &pos, ovector);
    00285     if (id == Search) {
    00286       result = Number(pos);
    00287     } else { // Match
    00288       if (mstr.isNull()) {
    00289         result = Null(); // no match
    00290       } else if ((reg->flags() & RegExp::Global) == 0) {
    00291     // case without 'g' flag is handled like RegExp.prototype.exec
    00292     regExpObj->setSubPatterns(reg->subPatterns());
    00293     result = regExpObj->arrayOfMatches(exec,mstr);
    00294       } else {
    00295     // return array of matches
    00296     List list;
    00297     while (pos >= 0) {
    00298       list.append(String(mstr));
    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   case ToLocaleLowerCase: // FIXME: To get this 100% right we need to detect Turkish and change I to lowercase i without a dot.
    00508     for (i = 0; i < len; i++)
    00509       s[i] = s[i].toLower();
    00510     result = String(s);
    00511     break;
    00512   case ToUpperCase:
    00513   case ToLocaleUpperCase: // FIXME: To get this 100% right we need to detect Turkish and change i to uppercase I with a dot.
    00514     for (i = 0; i < len; i++)
    00515       s[i] = s[i].toUpper();
    00516     result = String(s);
    00517     break;
    00518 #ifndef KJS_PURE_ECMA
    00519   case Big:
    00520     result = String("<big>" + s + "</big>");
    00521     break;
    00522   case Small:
    00523     result = String("<small>" + s + "</small>");
    00524     break;
    00525   case Blink:
    00526     result = String("<blink>" + s + "</blink>");
    00527     break;
    00528   case Bold:
    00529     result = String("<b>" + s + "</b>");
    00530     break;
    00531   case Fixed:
    00532     result = String("<tt>" + s + "</tt>");
    00533     break;
    00534   case Italics:
    00535     result = String("<i>" + s + "</i>");
    00536     break;
    00537   case Strike:
    00538     result = String("<strike>" + s + "</strike>");
    00539     break;
    00540   case Sub:
    00541     result = String("<sub>" + s + "</sub>");
    00542     break;
    00543   case Sup:
    00544     result = String("<sup>" + s + "</sup>");
    00545     break;
    00546   case Fontcolor:
    00547     result = String("<font color=\"" + a0.toString(exec) + "\">" + s + "</font>");
    00548     break;
    00549   case Fontsize:
    00550     result = String("<font size=\"" + a0.toString(exec) + "\">" + s + "</font>");
    00551     break;
    00552   case Anchor:
    00553     result = String("<a name=\"" + a0.toString(exec) + "\">" + s + "</a>");
    00554     break;
    00555   case Link:
    00556     result = String("<a href=\"" + a0.toString(exec) + "\">" + s + "</a>");
    00557     break;
    00558 #endif
    00559   }
    00560
    00561   return result;
    00562 }
    00563
    00564 // ------------------------------ StringObjectImp ------------------------------
    00565
    00566 StringObjectImp::StringObjectImp(ExecState *exec,
    00567                                  FunctionPrototypeImp *funcProto,
    00568                                  StringPrototypeImp *stringProto)
    00569   : InternalFunctionImp(funcProto)
    00570 {
    00571   Value protect(this);
    00572   // ECMA 15.5.3.1 String.prototype
    00573   putDirect(prototypePropertyName, stringProto, DontEnum|DontDelete|ReadOnly);
    00574
    00575   putDirect("fromCharCode", new StringObjectFuncImp(exec,funcProto), DontEnum);
    00576
    00577   // no. of arguments for constructor
    00578   putDirect(lengthPropertyName, NumberImp::one(), ReadOnly|DontDelete|DontEnum);
    00579 }
    00580
    00581
    00582 bool StringObjectImp::implementsConstruct() const
    00583 {
    00584   return true;
    00585 }
    00586
    00587 // ECMA 15.5.2
    00588 Object StringObjectImp::construct(ExecState *exec, const List &args)
    00589 {
    00590   ObjectImp *proto = exec->interpreter()->builtinStringPrototype().imp();
    00591   if (args.size() == 0)
    00592     return Object(new StringInstanceImp(proto));
    00593   return Object(new StringInstanceImp(proto, args.begin()->dispatchToString(exec)));
    00594 }
    00595
    00596 bool StringObjectImp::implementsCall() const
    00597 {
    00598   return true;
    00599 }
    00600
    00601 // ECMA 15.5.1
    00602 Value StringObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
    00603 {
    00604   if (args.isEmpty())
    00605     return String("");
    00606   else {
    00607     Value v = args[0];
    00608     return String(v.toString(exec));
    00609   }
    00610 }
    00611
    00612 // ------------------------------ StringObjectFuncImp --------------------------
    00613
    00614 // ECMA 15.5.3.2 fromCharCode()
    00615 StringObjectFuncImp::StringObjectFuncImp(ExecState* /*exec*/, FunctionPrototypeImp *funcProto)
    00616   : InternalFunctionImp(funcProto)
    00617 {
    00618   Value protect(this);
    00619   putDirect(lengthPropertyName, NumberImp::one(), DontDelete|ReadOnly|DontEnum);
    00620 }
    00621
    00622 bool StringObjectFuncImp::implementsCall() const
    00623 {
    00624   return true;
    00625 }
    00626
    00627 Value StringObjectFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
    00628 {
    00629   UString s;
    00630   if (args.size()) {
    00631     UChar *buf = new UChar[args.size()];
    00632     UChar *p = buf;
    00633     ListIterator it = args.begin();
    00634     while (it != args.end()) {
    00635       unsigned short u = it->toUInt16(exec);
    00636       *p++ = UChar(u);
    00637       it++;
    00638     }
    00639     s = UString(buf, args.size(), false);
    00640   } else
    00641     s = "";
    00642
    00643   return String(s);
    00644 }

This file is part of the documentation for kjs Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:23:07 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003