Ignore:
Timestamp:
Mar 21, 2002, 4:31:57 PM (23 years ago)
Author:
mjs
Message:

Merged changes from LABYRINTH_KDE_3_MERGE branch.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/string_object.cpp

    r6 r798  
     1// -*- c-basic-offset: 2 -*-
    12/*
    23 *  This file is part of the KDE libraries
     
    1617 *  License along with this library; if not, write to the Free Software
    1718 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     19 *
    1820 */
    1921
    20 #include "kjs.h"
     22#include "value.h"
     23#include "object.h"
     24#include "types.h"
     25#include "interpreter.h"
    2126#include "operations.h"
    22 #include "types.h"
    2327#include "regexp.h"
     28#include "regexp_object.h"
    2429#include "string_object.h"
     30#include "error_object.h"
    2531#include <stdio.h>
     32#include "string_object.lut.h"
    2633
    2734using namespace KJS;
    2835
    29 StringObject::StringObject(const Object &funcProto, const Object &stringProto)
    30   : ConstructorImp(funcProto, 1)
    31 {
     36// ------------------------------ StringInstanceImp ----------------------------
     37
     38const ClassInfo StringInstanceImp::info = {"String", 0, 0, 0};
     39
     40StringInstanceImp::StringInstanceImp(const Object &proto)
     41  : ObjectImp(proto)
     42{
     43  setInternalValue(String(""));
     44}
     45
     46// ------------------------------ StringPrototypeImp ---------------------------
     47const ClassInfo StringPrototypeImp::info = {"String", &StringInstanceImp::info, &stringTable, 0};
     48/* Source for string_object.lut.h
     49@begin stringTable 26
     50  toString              StringProtoFuncImp::ToString    DontEnum|Function       0
     51  valueOf               StringProtoFuncImp::ValueOf     DontEnum|Function       0
     52  charAt                StringProtoFuncImp::CharAt      DontEnum|Function       1
     53  charCodeAt            StringProtoFuncImp::CharCodeAt  DontEnum|Function       1
     54  concat                StringProtoFuncImp::Concat      DontEnum|Function       1
     55  indexOf               StringProtoFuncImp::IndexOf     DontEnum|Function       2
     56  lastIndexOf           StringProtoFuncImp::LastIndexOf DontEnum|Function       2
     57  match                 StringProtoFuncImp::Match       DontEnum|Function       1
     58  replace               StringProtoFuncImp::Replace     DontEnum|Function       2
     59  search                StringProtoFuncImp::Search      DontEnum|Function       1
     60  slice                 StringProtoFuncImp::Slice       DontEnum|Function       0
     61  split                 StringProtoFuncImp::Split       DontEnum|Function       1
     62  substr                StringProtoFuncImp::Substr      DontEnum|Function       2
     63  substring             StringProtoFuncImp::Substring   DontEnum|Function       2
     64  toLowerCase           StringProtoFuncImp::ToLowerCase DontEnum|Function       0
     65  toUpperCase           StringProtoFuncImp::ToUpperCase DontEnum|Function       0
     66#
     67# Under here: html extension, should only exist if KJS_PURE_ECMA is not defined
     68# I guess we need to generate two hashtables in the .lut.h file, and use #ifdef
     69# to select the right one... TODO. #####
     70  big                   StringProtoFuncImp::Big         DontEnum|Function       0
     71  small                 StringProtoFuncImp::Small       DontEnum|Function       0
     72  blink                 StringProtoFuncImp::Blink       DontEnum|Function       0
     73  bold                  StringProtoFuncImp::Bold        DontEnum|Function       0
     74  fixed                 StringProtoFuncImp::Fixed       DontEnum|Function       0
     75  italics               StringProtoFuncImp::Italics     DontEnum|Function       0
     76  strike                StringProtoFuncImp::Strike      DontEnum|Function       0
     77  sub                   StringProtoFuncImp::Sub         DontEnum|Function       0
     78  sup                   StringProtoFuncImp::Sup         DontEnum|Function       0
     79  fontcolor             StringProtoFuncImp::Fontcolor   DontEnum|Function       1
     80  fontsize              StringProtoFuncImp::Fontsize    DontEnum|Function       1
     81  anchor                StringProtoFuncImp::Anchor      DontEnum|Function       1
     82  link                  StringProtoFuncImp::Link        DontEnum|Function       1
     83@end
     84*/
     85// ECMA 15.5.4
     86StringPrototypeImp::StringPrototypeImp(ExecState *exec,
     87                                       ObjectPrototypeImp *objProto)
     88  : StringInstanceImp(Object(objProto))
     89{
     90  Value protect(this);
     91  // The constructor will be added later, after StringObjectImp has been built
     92  put(exec,"length",Number(0),DontDelete|ReadOnly|DontEnum);
     93
     94}
     95
     96Value StringPrototypeImp::get(ExecState *exec, const UString &propertyName) const
     97{
     98  return lookupGetFunction<StringProtoFuncImp, StringInstanceImp>( exec, propertyName, &stringTable, this );
     99}
     100
     101// ------------------------------ StringProtoFuncImp ---------------------------
     102
     103StringProtoFuncImp::StringProtoFuncImp(ExecState *exec, int i, int len)
     104  : InternalFunctionImp(
     105    static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
     106    ), id(i)
     107{
     108  Value protect(this);
     109  put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
     110}
     111
     112bool StringProtoFuncImp::implementsCall() const
     113{
     114  return true;
     115}
     116
     117// ECMA 15.5.4.2 - 15.5.4.20
     118Value StringProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
     119{
     120  Value result;
     121
     122  // toString and valueOf are no generic function.
     123  if (id == ToString || id == ValueOf) {
     124    if (thisObj.isNull() || !thisObj.inherits(&StringInstanceImp::info)) {
     125      Object err = Error::create(exec,TypeError);
     126      exec->setException(err);
     127      return err;
     128    }
     129
     130    return String(thisObj.internalValue().toString(exec));
     131  }
     132
     133  int n, m;
     134  UString u, u2, u3;
     135  int pos, p0, i;
     136  double d = 0.0;
     137
     138  UString s = thisObj.toString(exec);
     139
     140  int len = s.size();
     141  Value a0 = args[0];
     142  Value a1 = args[1];
     143
     144  switch (id) {
     145  case ToString:
     146  case ValueOf:
     147    // handled above
     148    break;
     149  case CharAt:
     150    pos = a0.toInteger(exec);
     151    if (pos < 0 || pos >= len)
     152      u = "";
     153    else
     154      u = s.substr(pos, 1);
     155    result = String(u);
     156    break;
     157  case CharCodeAt:
     158    pos = a0.toInteger(exec);
     159    if (pos < 0 || pos >= len)
     160      d = NaN;
     161    else {
     162      UChar c = s[pos];
     163      d = (c.high() << 8) + c.low();
     164    }
     165    result = Number(d);
     166    break;
     167  case Concat: {
     168    ListIterator it = args.begin();
     169    for ( ; it != args.end() ; ++it) {
     170        s += it->toString(exec);
     171    }
     172    result = String(s);
     173    break;
     174  }
     175  case IndexOf:
     176    u2 = a0.toString(exec);
     177    if (a1.type() == UndefinedType)
     178      pos = 0;
     179    else
     180      pos = a1.toInteger(exec);
     181    d = s.find(u2, pos);
     182    result = Number(d);
     183    break;
     184  case LastIndexOf:
     185    u2 = a0.toString(exec);
     186    d = a1.toNumber(exec);
     187    if (a1.type() == UndefinedType || KJS::isNaN(d) || KJS::isPosInf(d))
     188      pos = len;
     189    else
     190      pos = a1.toInteger(exec);
     191    if (pos < 0)
     192      pos = 0;
     193    d = s.rfind(u2, pos);
     194    result = Number(d);
     195    break;
     196  case Match:
     197  case Search: {
     198    u = s;
     199    RegExp* reg = 0;
     200    if (a0.isA(ObjectType) && a0.toObject(exec).inherits(&RegExpImp::info))
     201    {
     202      RegExpImp* imp = static_cast<RegExpImp *>( a0.toObject(exec).imp() );
     203      reg = imp->regExp();
     204    }
     205    else if (a0.isA(StringType))
     206    {
     207      reg = new RegExp(a0.toString(exec), RegExp::None);
     208    }
     209    else
     210    {
     211#ifndef NDEBUG
     212      printf("KJS: Match/Search. Argument is not a RegExp nor a String - returning Undefined\n");
     213#endif
     214      result = Undefined();
     215      break;
     216    }
     217    RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
     218    int **ovector = regExpObj->registerRegexp( reg, u );
     219    UString mstr = reg->match(u, -1, &pos, ovector);
     220    if (a0.isA(StringType))
     221      delete reg;
     222    if (id == Search) {
     223      result = Number(pos);
     224      break;
     225    }
     226    if (mstr.isNull())
     227      result = Null();
     228    else
     229      result = regExpObj->arrayOfMatches(exec,mstr);
     230  }
     231    break;
     232  case Replace:
     233    u = s;
     234    if (a0.type() == ObjectType && a0.toObject(exec).inherits(&RegExpImp::info)) {
     235      RegExpImp* imp = static_cast<RegExpImp *>( a0.toObject(exec).imp() );
     236      RegExp *reg = imp->regExp();
     237      bool global = false;
     238      Value tmp = imp->get(exec,"global");
     239      if (tmp.type() != UndefinedType && tmp.toBoolean(exec) == true)
     240        global = true;
     241
     242      RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
     243      int **ovector = regExpObj->registerRegexp( reg, u );
     244      int lastIndex = 0;
     245      u3 = a1.toString(exec); // replacement string
     246      // This is either a loop (if global is set) or a one-way (if not).
     247      do {
     248        UString mstr = reg->match(u, lastIndex, &pos, ovector);
     249        len = mstr.size();
     250        lastIndex = pos + u3.size();
     251        if ( pos != -1 )
     252          u = u.substr(0, pos) + u3 + u.substr(pos + len);
     253        //fprintf(stderr,"pos=%d,len=%d,lastIndex=%d,u=%s\n",pos,len,lastIndex,u.ascii());
     254      } while ( global && pos != -1 );
     255
     256      result = String(u);
     257    } else { // First arg is a string
     258      u2 = a0.toString(exec);
     259      pos = u.find(u2);
     260      len = u2.size();
     261      // Do the replacement
     262      if (pos == -1)
     263        result = String(s);
     264      else {
     265        u3 = u.substr(0, pos) + a1.toString(exec) +
     266             u.substr(pos + len);
     267        result = String(u3);
     268      }
     269    }
     270    break;
     271  case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/string.htm#1194366
     272    {
     273        // The arg processing is very much like ArrayProtoFunc::Slice
     274        // We return a new array
     275        result = exec->interpreter()->builtinArray().construct(exec,List::empty());
     276        int begin = args[0].toUInt32(exec);
     277        int end = len;
     278        if (args[1].type() != UndefinedType)
     279        {
     280          end = args[1].toUInt32(exec);
     281          if ( end < 0 )
     282            end += len;
     283        }
     284        // safety tests
     285        if ( begin < 0 || end < 0 || begin >= end ) {
     286            result = String();
     287            break;
     288        }
     289        //printf( "Slicing from %d to %d \n", begin, end );
     290        result = String(s.substr(begin, end-begin));
     291        break;
     292    }
     293    case Split: {
     294    Object constructor = exec->interpreter()->builtinArray();
     295    Object res = Object::dynamicCast(constructor.construct(exec,List::empty()));
     296    result = res;
     297    u = s;
     298    i = p0 = 0;
     299    d = (a1.type() != UndefinedType) ? a1.toInteger(exec) : -1; // optional max number
     300    if (a0.type() == ObjectType && Object::dynamicCast(a0).inherits(&RegExpImp::info)) {
     301      Object obj0 = Object::dynamicCast(a0);
     302      RegExp reg(obj0.get(exec,"source").toString(exec));
     303      if (u.isEmpty() && !reg.match(u, 0).isNull()) {
     304        // empty string matched by regexp -> empty array
     305        res.put(exec,"length", Number(0));
     306        break;
     307      }
     308      int *ovector;
     309      int mpos;
     310      pos = 0;
     311      while (1) {
     312        // TODO: back references
     313        UString mstr = reg.match(u, pos, &mpos, &ovector);
     314        if (mpos < 0)
     315          break;
     316        pos = mpos + (mstr.isEmpty() ? 1 : mstr.size());
     317        if (mpos != p0 || !mstr.isEmpty()) {
     318          res.put(exec,UString::from(i), String(u.substr(p0, mpos-p0)));
     319          p0 = mpos + mstr.size();
     320          i++;
     321        }
     322      }
     323      delete ovector;
     324    } else if (a0.type() != UndefinedType) {
     325      u2 = a0.toString(exec);
     326      if (u2.isEmpty()) {
     327        if (u.isEmpty()) {
     328          // empty separator matches empty string -> empty array
     329          put(exec,"length", Number(0));
     330          break;
     331        } else {
     332          while (i != d && i < u.size()-1)
     333            res.put(exec,UString::from(i++), String(u.substr(p0++, 1)));
     334        }
     335      } else {
     336        while (i != d && (pos = u.find(u2, p0)) >= 0) {
     337          res.put(exec,UString::from(i), String(u.substr(p0, pos-p0)));
     338          p0 = pos + u2.size();
     339          i++;
     340        }
     341      }
     342    }
     343    // add remaining string, if any
     344    if (i != d)
     345      res.put(exec,UString::from(i++), String(u.substr(p0)));
     346    res.put(exec,"length", Number(i));
     347    }
     348    break;
     349  case Substr: {
     350    n = a0.toInteger(exec);
     351    m = a1.toInteger(exec);
     352    int d, d2;
     353    if (n >= 0)
     354      d = n;
     355    else
     356      d = maxInt(len + n, 0);
     357    if (a1.type() == UndefinedType)
     358      d2 = len - d;
     359    else
     360      d2 = minInt(maxInt(m, 0), len - d);
     361    result = String(s.substr(d, d2));
     362    break;
     363  }
     364  case Substring: {
     365    double start = a0.toNumber(exec);
     366    double end = a1.toNumber(exec);
     367    if (KJS::isNaN(start))
     368      start = 0;
     369    if (KJS::isNaN(end))
     370      end = 0;
     371    if (start < 0)
     372      start = 0;
     373    if (end < 0)
     374      end = 0;
     375    if (start > len)
     376      start = len;
     377    if (end > len)
     378      end = len;
     379    if (a1.type() == UndefinedType)
     380      end = len;
     381    if (start > end) {
     382      double temp = end;
     383      end = start;
     384      start = temp;
     385    }
     386    result = String(s.substr((int)start, (int)end-(int)start));
     387    }
     388    break;
     389  case ToLowerCase:
     390    u = s;
     391    for (i = 0; i < len; i++)
     392      u[i] = u[i].toLower();
     393    result = String(u);
     394    break;
     395  case ToUpperCase:
     396    u = s;
     397    for (i = 0; i < len; i++)
     398      u[i] = u[i].toUpper();
     399    result = String(u);
     400    break;
     401#ifndef KJS_PURE_ECMA
     402  case Big:
     403    result = String("<BIG>" + s + "</BIG>");
     404    break;
     405  case Small:
     406    result = String("<SMALL>" + s + "</SMALL>");
     407    break;
     408  case Blink:
     409    result = String("<BLINK>" + s + "</BLINK>");
     410    break;
     411  case Bold:
     412    result = String("<B>" + s + "</B>");
     413    break;
     414  case Fixed:
     415    result = String("<TT>" + s + "</TT>");
     416    break;
     417  case Italics:
     418    result = String("<I>" + s + "</I>");
     419    break;
     420  case Strike:
     421    result = String("<STRIKE>" + s + "</STRIKE>");
     422    break;
     423  case Sub:
     424    result = String("<SUB>" + s + "</SUB>");
     425    break;
     426  case Sup:
     427    result = String("<SUP>" + s + "</SUP>");
     428    break;
     429  case Fontcolor:
     430    result = String("<FONT COLOR=" + a0.toString(exec) + ">"
     431                    + s + "</FONT>");
     432    break;
     433  case Fontsize:
     434    result = String("<FONT SIZE=" + a0.toString(exec) + ">"
     435                    + s + "</FONT>");
     436    break;
     437  case Anchor:
     438    result = String("<a name=" + a0.toString(exec) + ">"
     439                    + s + "</a>");
     440    break;
     441  case Link:
     442    result = String("<a href=" + a0.toString(exec) + ">"
     443                    + s + "</a>");
     444    break;
     445#endif
     446  }
     447
     448  return result;
     449}
     450
     451// ------------------------------ StringObjectImp ------------------------------
     452
     453StringObjectImp::StringObjectImp(ExecState *exec,
     454                                 FunctionPrototypeImp *funcProto,
     455                                 StringPrototypeImp *stringProto)
     456  : InternalFunctionImp(funcProto)
     457{
     458  Value protect(this);
    32459  // ECMA 15.5.3.1 String.prototype
    33   setPrototypeProperty(stringProto);
    34 }
    35 
    36 KJSO StringObject::get(const UString &p) const
    37 {
    38   if (p == "fromCharCode")
    39     return Function(new StringObjectFunc());
     460  put(exec,"prototype", Object(stringProto), DontEnum|DontDelete|ReadOnly);
     461
     462  put(exec,"fromCharCode", Object(new StringObjectFuncImp(exec,funcProto)), DontEnum);
     463
     464  // no. of arguments for constructor
     465  put(exec,"length", Number(1), ReadOnly|DontDelete|DontEnum);
     466}
     467
     468
     469bool StringObjectImp::implementsConstruct() const
     470{
     471  return true;
     472}
     473
     474// ECMA 15.5.2
     475Object StringObjectImp::construct(ExecState *exec, const List &args)
     476{
     477  Object proto = exec->interpreter()->builtinStringPrototype();
     478  Object obj(new StringInstanceImp(proto ));
     479
     480  UString s;
     481  if (args.size() > 0)
     482    s = args.begin()->toString(exec);
    40483  else
    41     return Imp::get(p);
     484    s = UString("");
     485
     486  obj.setInternalValue(String(s));
     487  obj.put(exec, "length", Number(s.size()), ReadOnly|DontEnum|DontDelete);
     488
     489  return obj;
     490}
     491
     492bool StringObjectImp::implementsCall() const
     493{
     494  return true;
    42495}
    43496
    44497// ECMA 15.5.1
    45 Completion StringObject::execute(const List &args)
    46 {
    47   KJSO v;
    48   String s;
    49 
     498Value StringObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
     499{
    50500  if (args.isEmpty())
    51     s = String("");
     501    return String("");
    52502  else {
    53     v = args[0];
    54     s = v.toString();
     503    Value v = args[0];
     504    return String(v.toString(exec));
    55505  }
    56 
    57   return Completion(ReturnValue, s);
    58 }
    59 
    60 // ECMA 15.5.2
    61 Object StringObject::construct(const List &args)
    62 {
    63   String s;
    64   if (args.size() > 0)
    65     s = args.begin()->toString();
    66   else
    67     s = String("");
    68 
    69   return Object::create(StringClass, s);
    70 }
     506}
     507
     508// ------------------------------ StringObjectFuncImp --------------------------
    71509
    72510// ECMA 15.5.3.2 fromCharCode()
    73 Completion StringObjectFunc::execute(const List &args)
     511StringObjectFuncImp::StringObjectFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto)
     512  : InternalFunctionImp(funcProto)
     513{
     514  Value protect(this);
     515  put(exec,"length",Number(1),DontDelete|ReadOnly|DontEnum);
     516}
     517
     518bool StringObjectFuncImp::implementsCall() const
     519{
     520  return true;
     521}
     522
     523Value StringObjectFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
    74524{
    75525  UString s;
     
    79529    ListIterator it = args.begin();
    80530    while (it != args.end()) {
    81       unsigned short u = it->toUInt16();
     531      unsigned short u = it->toUInt16(exec);
    82532      *p++ = UChar(u);
    83533      it++;
     
    87537    s = "";
    88538
    89   return Completion(ReturnValue, String(s));
    90 }
    91 
    92 // ECMA 15.5.4
    93 StringPrototype::StringPrototype(const Object& proto)
    94   : ObjectImp(StringClass, String(""), proto)
    95 {
    96   // The constructor will be added later in StringObject's constructor
    97 }
    98 
    99 KJSO StringPrototype::get(const UString &p) const
    100 {
    101   int id;
    102 
    103   if (p == "toString")
    104     id = StringProtoFunc::ToString;
    105   else if (p == "valueOf")
    106     id = StringProtoFunc::ValueOf;
    107   else if (p == "charAt")
    108     id = StringProtoFunc::CharAt;
    109   else if (p == "charCodeAt")
    110     id = StringProtoFunc::CharCodeAt;
    111   else if (p == "indexOf")
    112     id = StringProtoFunc::IndexOf;
    113   else if (p == "lastIndexOf")
    114     id = StringProtoFunc::LastIndexOf;
    115   else if (p == "match")
    116     id = StringProtoFunc::Match;
    117   else if (p == "replace")
    118     id = StringProtoFunc::Replace;
    119   else if (p == "search")
    120     id = StringProtoFunc::Search;
    121   else if (p == "split")
    122     id = StringProtoFunc::Split;
    123   else if (p == "substr")
    124     id = StringProtoFunc::Substr;
    125   else if (p == "substring")
    126     id = StringProtoFunc::Substring;
    127   else if (p == "toLowerCase")
    128     id = StringProtoFunc::ToLowerCase;
    129   else if (p == "toUpperCase")
    130     id = StringProtoFunc::ToUpperCase;
    131 #ifndef KJS_PURE_ECMA
    132   else if (p == "big")
    133     id = StringProtoFunc::Big;
    134   else if (p == "small")
    135     id = StringProtoFunc::Small;
    136   else if (p == "blink")
    137     id = StringProtoFunc::Blink;
    138   else if (p == "bold")
    139     id = StringProtoFunc::Bold;
    140   else if (p == "fixed")
    141     id = StringProtoFunc::Fixed;
    142   else if (p == "italics")
    143     id = StringProtoFunc::Italics;
    144   else if (p == "strike")
    145     id = StringProtoFunc::Strike;
    146   else if (p == "sub")
    147     id = StringProtoFunc::Sub;
    148   else if (p == "sup")
    149     id = StringProtoFunc::Sup;
    150   else if (p == "fontcolor")
    151     id = StringProtoFunc::Fontcolor;
    152   else if (p == "fontsize")
    153     id = StringProtoFunc::Fontsize;
    154   else if (p == "anchor")
    155     id = StringProtoFunc::Anchor;
    156   else if (p == "link")
    157     id = StringProtoFunc::Link;
    158 #endif
    159   else
    160     return Imp::get(p);
    161 
    162   return Function(new StringProtoFunc(id));
    163 }
    164 
    165 StringProtoFunc::StringProtoFunc(int i)
    166   : id(i)
    167 {
    168 }
    169 
    170 // ECMA 15.5.4.2 - 15.5.4.20
    171 Completion StringProtoFunc::execute(const List &args)
    172 {
    173   KJSO result;
    174 
    175   Object thisObj = Object::dynamicCast(thisValue());
    176 
    177   // toString and valueOf are no generic function.
    178   if (id == ToString || id == ValueOf) {
    179     if (thisObj.isNull() || thisObj.getClass() != StringClass) {
    180       result = Error::create(TypeError);
    181       return Completion(ReturnValue, result);
    182     }
    183   }
    184 
    185   String s2;
    186   Number n, m;
    187   UString u, u2, u3;
    188   int pos, p0, i;
    189   double d, d2;
    190   KJSO v = thisObj.internalValue();
    191   String s = v.toString();
    192   int len = s.value().size();
    193   KJSO a0 = args[0];
    194   KJSO a1 = args[1];
    195 
    196   switch (id) {
    197   case ToString:
    198   case ValueOf:
    199     result = v.toString();
    200     break;
    201   case CharAt:
    202     n = a0.toInteger();
    203     pos = (int) n.value();
    204     if (pos < 0 || pos >= len)
    205       u = "";
    206     else
    207       u = s.value().substr(pos, 1);
    208     result = String(u);
    209     break;
    210   case CharCodeAt:
    211     n = a0.toInteger();
    212     pos = (int) n.value();
    213     if (pos < 0 || pos >= len)
    214       d = NaN;
    215     else {
    216       UChar c = s.value()[pos];
    217       d = (c.high() << 8) + c.low();
    218     }
    219     result = Number(d);
    220     break;
    221   case IndexOf:
    222     s2 = a0.toString();
    223     if (a1.isA(UndefinedType))
    224       pos = 0;
    225     else
    226       pos = a1.toInteger().intValue();
    227     d = s.value().find(s2.value(), pos);
    228     result = Number(d);
    229     break;
    230   case LastIndexOf:
    231     s2 = a0.toString();
    232     if (a1.isA(UndefinedType))
    233       pos = len;
    234     else
    235       pos = a1.toInteger().intValue();
    236     d = s.value().rfind(s2.value(), pos);
    237     result = Number(d);
    238     break;
    239   case Match:
    240   case Search:
    241     u = s.value();
    242     if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) {
    243       s2 = a0.get("source").toString();
    244       RegExp reg(s2.value());
    245       UString mstr = reg.match(u, -1, &pos);
    246       if (id == Search) {
    247         result = Number(pos);
    248         break;
    249       }
    250       if (mstr.isNull()) {
    251         result = Null();
    252         break;
    253       }
    254       /* TODO return an array, with the matches, etc. */
    255       result = String(mstr);
    256     } else
    257     {
    258       printf("Match/Search. Argument is not a RegExp - returning Undefined\n");
    259       result = Undefined(); // No idea what to do here
    260     }
    261     break;
    262   case Replace:
    263     /* TODO: this is just a hack to get the most common cases going */
    264     u = s.value();
    265     if (a0.isA(ObjectType) && a0.toObject().getClass() == RegExpClass) {
    266       s2 = a0.get("source").toString();
    267       RegExp reg(s2.value());
    268       UString mstr = reg.match(u, -1, &pos);
    269       len = mstr.size();
    270     } else {
    271       s2 = a0.toString();
    272       u2 = s2.value();
    273       pos = u.find(u2);
    274       len = u2.size();
    275     }
    276     if (pos == -1)
    277         result = s;
    278     else {
    279         u3 = u.substr(0, pos) + a1.toString().value() +
    280              u.substr(pos + len);
    281         result = String(u3);
    282     }
    283     break;
    284   case Split:
    285     result = Object::create(ArrayClass);
    286     u = s.value();
    287     i = p0 = 0;
    288     d = a1.isDefined() ? a1.toInteger().intValue() : -1; // optional max number
    289     if (a0.isA(ObjectType) && Object(a0.imp()).getClass() == RegExpClass) {
    290       RegExp reg(a0.get("source").toString().value());
    291       if (u.isEmpty() && !reg.match(u, 0).isNull()) {
    292         // empty string matched by regexp -> empty array
    293         result.put("length", 0);
    294         break;
    295       }
    296       int mpos;
    297       pos = 0;
    298       while (1) {
    299         /* TODO: back references */
    300         UString mstr = reg.match(u, pos, &mpos);
    301         if (mpos < 0)
    302           break;
    303         pos = mpos + (mstr.isEmpty() ? 1 : mstr.size());
    304         if (mpos != p0 || !mstr.isEmpty()) {
    305           result.put(UString::from(i), String(u.substr(p0, mpos-p0)));
    306           p0 = mpos + mstr.size();
    307           i++;
    308         }
    309       }
    310     } else if (a0.isDefined()) {
    311       u2 = a0.toString().value();
    312       if (u2.isEmpty()) {
    313         if (u.isEmpty()) {
    314           // empty separator matches empty string -> empty array
    315           put("length", 0);
    316           break;
    317         } else {
    318           while (i != d && i < u.size())
    319             result.put(UString::from(i++), String(u.substr(p0++, 1)));
    320         }
    321       } else {
    322         while (i != d && (pos = u.find(u2, p0)) >= 0) {
    323           result.put(UString::from(i), String(u.substr(p0, pos-p0)));
    324           p0 = pos + u2.size();
    325           i++;
    326         }
    327       }
    328     }
    329     // add remaining string, if any
    330     if (i != d && (p0 < len || i == 0))
    331       result.put(UString::from(i++), String(u.substr(p0)));
    332     result.put("length", i);
    333     break;
    334   case Substr:
    335     n = a0.toInteger();
    336     m = a1.toInteger();
    337     if (n.value() >= 0)
    338       d = n.value();
    339     else
    340       d = max(len + n.value(), 0);
    341     if (a1.isA(UndefinedType))
    342       d2 = len - d;
    343     else
    344       d2 = min(max(m.value(), 0), len - d);
    345     result = String(s.value().substr((int)d, (int)d2));
    346     break;
    347   case Substring:
    348     n = a0.toInteger();
    349     m = a1.toInteger();
    350     d = min(max(n.value(), 0), len);
    351     if (a1.isA(UndefinedType))
    352       d2 = len - d;
    353     else {
    354       d2 = min(max(m.value(), 0), len);
    355       d2 = max(d2-d, 0);
    356     }
    357     result = String(s.value().substr((int)d, (int)d2));
    358     break;
    359   case ToLowerCase:
    360     u = UString(s.value());
    361     for (i = 0; i < len; i++)
    362       u[i] = u[i].toLower();
    363     result = String(u);
    364     break;
    365   case ToUpperCase:
    366     u = UString(s.value());
    367     for (i = 0; i < len; i++)
    368       u[i] = u[i].toUpper();
    369     result = String(u);
    370     break;
    371 #ifndef KJS_PURE_ECMA
    372   case Big:
    373     result = String("<BIG>" + s.value() + "</BIG>");
    374     break;
    375   case Small:
    376     result = String("<SMALL>" + s.value() + "</SMALL>");
    377     break;
    378   case Blink:
    379     result = String("<BLINK>" + s.value() + "</BLINK>");
    380     break;
    381   case Bold:
    382     result = String("<B>" + s.value() + "</B>");
    383     break;
    384   case Fixed:
    385     result = String("<TT>" + s.value() + "</TT>");
    386     break;
    387   case Italics:
    388     result = String("<I>" + s.value() + "</I>");
    389     break;
    390   case Strike:
    391     result = String("<STRIKE>" + s.value() + "</STRIKE>");
    392     break;
    393   case Sub:
    394     result = String("<SUB>" + s.value() + "</SUB>");
    395     break;
    396   case Sup:
    397     result = String("<SUP>" + s.value() + "</SUP>");
    398     break;
    399   case Fontcolor:
    400     result = String("<FONT COLOR=" + a0.toString().value() + ">"
    401                     + s.value() + "</FONT>");
    402     break;
    403   case Fontsize:
    404     result = String("<FONT SIZE=" + a0.toString().value() + ">"
    405                     + s.value() + "</FONT>");
    406     break;
    407   case Anchor:
    408     result = String("<a name=" + a0.toString().value() + ">"
    409                     + s.value() + "</a>");
    410     break;
    411   case Link:
    412     result = String("<a href=" + a0.toString().value() + ">"
    413                     + s.value() + "</a>");
    414     break;
    415 #endif
    416   }
    417 
    418   return Completion(ReturnValue, result);
    419 }
     539  return String(s);
     540}
Note: See TracChangeset for help on using the changeset viewer.