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/regexp_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 *
     20 *  $Id$
    1821 */
    1922
    2023#include <stdio.h>
    2124
    22 #include "kjs.h"
     25#include "value.h"
     26#include "object.h"
     27#include "types.h"
     28#include "interpreter.h"
    2329#include "operations.h"
    24 #include "types.h"
    2530#include "internal.h"
    2631#include "regexp.h"
    2732#include "regexp_object.h"
     33#include "error_object.h"
    2834
    2935using namespace KJS;
    3036
    31 RegExpObject::RegExpObject(const Object& funcProto, const Object &regProto)
    32     : ConstructorImp(funcProto, 2)
    33 {
     37// ------------------------------ RegExpPrototypeImp ---------------------------
     38
     39// ECMA 15.9.4
     40
     41RegExpPrototypeImp::RegExpPrototypeImp(ExecState *exec,
     42                                       ObjectPrototypeImp *objProto,
     43                                       FunctionPrototypeImp *funcProto)
     44  : ObjectImp(Object(objProto))
     45{
     46  Value protect(this);
     47  setInternalValue(String(""));
     48
     49  // The constructor will be added later in RegExpObject's constructor (?)
     50
     51  put(exec, "exec",     Object(new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::Exec,     0)), DontEnum);
     52  put(exec, "test",     Object(new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::Test,     0)), DontEnum);
     53  put(exec, "toString", Object(new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::ToString, 0)), DontEnum);
     54}
     55
     56// ------------------------------ RegExpProtoFuncImp ---------------------------
     57
     58RegExpProtoFuncImp::RegExpProtoFuncImp(ExecState *exec,
     59                                       FunctionPrototypeImp *funcProto, int i, int len)
     60  : InternalFunctionImp(funcProto), id(i)
     61{
     62  Value protect(this);
     63  put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
     64}
     65
     66bool RegExpProtoFuncImp::implementsCall() const
     67{
     68  return true;
     69}
     70
     71Value RegExpProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
     72{
     73  if (!thisObj.inherits(&RegExpImp::info)) {
     74    Object err = Error::create(exec,TypeError);
     75    exec->setException(err);
     76    return err;
     77  }
     78
     79  RegExpImp *reimp = static_cast<RegExpImp*>(thisObj.imp());
     80  RegExp *re = reimp->regExp();
     81  String s;
     82  UString str;
     83  switch (id) {
     84  case Exec:      // 15.10.6.2
     85  case Test:
     86  {
     87    s = args[0].toString(exec);
     88    int length = s.value().size();
     89    Value lastIndex = thisObj.get(exec,"lastIndex");
     90    int i = lastIndex.isNull() ? 0 : lastIndex.toInt32(exec);
     91    bool globalFlag = thisObj.get(exec,"global").toBoolean(exec);
     92    if (!globalFlag)
     93      i = 0;
     94    if (i < 0 || i > length) {
     95      thisObj.put(exec,"lastIndex", Number(0), DontDelete | DontEnum);
     96      return Null();
     97    }
     98    RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
     99    int **ovector = regExpObj->registerRegexp( re, s.value() );
     100
     101    str = re->match(s.value(), i, 0L, ovector);
     102
     103    if (id == Test)
     104      return Boolean(!str.isNull());
     105
     106    if (str.isNull()) // no match
     107    {
     108      if (globalFlag)
     109        thisObj.put(exec,"lastIndex",Number(0), DontDelete | DontEnum);
     110      return Null();
     111    }
     112    else // success
     113    {
     114      if (globalFlag)
     115        thisObj.put(exec,"lastIndex",Number( (*ovector)[1] ), DontDelete | DontEnum);
     116      return regExpObj->arrayOfMatches(exec,str);
     117    }
     118  }
     119  break;
     120  case ToString:
     121    s = thisObj.get(exec,"source").toString(exec);
     122    str = "/";
     123    str += s.value();
     124    str += "/";
     125    // TODO append the flags
     126    return String(str);
     127  }
     128
     129  return Undefined();
     130}
     131
     132// ------------------------------ RegExpImp ------------------------------------
     133
     134const ClassInfo RegExpImp::info = {"RegExp", 0, 0, 0};
     135
     136RegExpImp::RegExpImp(RegExpPrototypeImp *regexpProto)
     137  : ObjectImp(Object(regexpProto)), reg(0L)
     138{
     139}
     140
     141RegExpImp::~RegExpImp()
     142{
     143  delete reg;
     144}
     145
     146// ------------------------------ RegExpObjectImp ------------------------------
     147
     148RegExpObjectImp::RegExpObjectImp(ExecState *exec,
     149                                 RegExpPrototypeImp *regProto,
     150                                 FunctionPrototypeImp *funcProto)
     151  : InternalFunctionImp(funcProto), lastOvector(0L), lastNrSubPatterns(0)
     152{
     153  Value protect(this);
    34154  // ECMA 15.10.5.1 RegExp.prototype
    35   setPrototypeProperty(regProto);
    36 }
    37 
    38 // ECMA 15.9.2
    39 Completion RegExpObject::execute(const List &)
    40 {
    41   return Completion(ReturnValue, Undefined());
    42 }
    43 
    44 // ECMA 15.9.3
    45 Object RegExpObject::construct(const List &args)
    46 {
    47   /* TODO: regexp arguments */
    48   String p = args[0].toString();
    49   String f = args[1].toString();
     155  put(exec,"prototype", Object(regProto), DontEnum|DontDelete|ReadOnly);
     156
     157  // no. of arguments for constructor
     158  put(exec,"length", Number(2), ReadOnly|DontDelete|DontEnum);
     159}
     160
     161RegExpObjectImp::~RegExpObjectImp()
     162{
     163  if (lastOvector)
     164    delete [] lastOvector;
     165}
     166
     167int **RegExpObjectImp::registerRegexp( const RegExp* re, const UString& s )
     168{
     169  lastString = s;
     170  if (lastOvector)
     171    delete [] lastOvector;
     172  lastOvector = 0;
     173  lastNrSubPatterns = re->subPatterns();
     174  return &lastOvector;
     175}
     176
     177Value RegExpObjectImp::arrayOfMatches(ExecState *exec, const UString &result) const
     178{
     179  List list;
     180  // The returned array contains 'result' as first item, followed by the list of matches
     181  list.append(String(result));
     182  if ( lastOvector )
     183    for ( uint i = 1 ; i < lastNrSubPatterns + 1 ; ++i )
     184    {
     185      UString substring = lastString.substr( lastOvector[2*i], lastOvector[2*i+1] - lastOvector[2*i] );
     186      list.append(String(substring));
     187    }
     188  return exec->interpreter()->builtinArray().construct(exec, list);
     189}
     190
     191Value RegExpObjectImp::get(ExecState *, const UString &p) const
     192{
     193  if (p[0] == '$' && lastOvector)
     194  {
     195    bool ok;
     196    unsigned long i = p.substr(1).toULong(&ok);
     197    if (ok)
     198    {
     199      if (i < lastNrSubPatterns + 1)
     200      {
     201        UString substring = lastString.substr( lastOvector[2*i], lastOvector[2*i+1] - lastOvector[2*i] );
     202        return String(substring);
     203      }
     204      return String("");
     205    }
     206  }
     207  return Undefined();
     208}
     209
     210bool RegExpObjectImp::implementsConstruct() const
     211{
     212  return true;
     213}
     214
     215// ECMA 15.10.4
     216Object RegExpObjectImp::construct(ExecState *exec, const List &args)
     217{
     218  String p = args[0].toString(exec);
     219  String f = args[1].toString(exec);
    50220  UString flags = f.value();
    51221
    52   RegExpImp *dat = new RegExpImp();
     222  RegExpPrototypeImp *proto = static_cast<RegExpPrototypeImp*>(exec->interpreter()->builtinRegExpPrototype().imp());
     223  RegExpImp *dat = new RegExpImp(proto);
    53224  Object obj(dat); // protect from GC
    54225
     
    56227  bool ignoreCase = (flags.find("i") >= 0);
    57228  bool multiline = (flags.find("m") >= 0);
    58   /* TODO: throw an error on invalid flags */
    59 
    60   dat->put("global", Boolean(global));
    61   dat->put("ignoreCase", Boolean(ignoreCase));
    62   dat->put("multiline", Boolean(multiline));
    63 
    64   dat->put("source", String(p.value()));
    65   dat->put("lastIndex", 0, DontDelete | DontEnum);
    66 
    67   dat->setRegExp(new RegExp(p.value() /* TODO flags */));
    68   obj.setClass(RegExpClass);
    69   obj.setPrototype(Global::current().get("[[RegExp.prototype]]"));
     229  // TODO: throw a syntax error on invalid flags
     230
     231  dat->put(exec, "global", Boolean(global));
     232  dat->put(exec, "ignoreCase", Boolean(ignoreCase));
     233  dat->put(exec, "multiline", Boolean(multiline));
     234
     235  dat->put(exec, "source", String(p.value()));
     236  dat->put(exec, "lastIndex", Number(0), DontDelete | DontEnum);
     237
     238  int reflags = RegExp::None;
     239  if (global)
     240      reflags |= RegExp::Global;
     241  if (ignoreCase)
     242      reflags |= RegExp::IgnoreCase;
     243  if (multiline)
     244      reflags |= RegExp::Multiline;
     245  dat->setRegExp(new RegExp(p.value(), reflags));
    70246
    71247  return obj;
    72248}
    73249
    74 // ECMA 15.9.4
    75 RegExpPrototype::RegExpPrototype(const Object& proto)
    76   : ObjectImp(RegExpClass, String(""), proto)
    77 {
    78   // The constructor will be added later in RegExpObject's constructor
    79 }
    80 
    81 KJSO RegExpPrototype::get(const UString &p) const
    82 {
    83   int id = -1;
    84   if (p == "exec")
    85     id = RegExpProtoFunc::Exec;
    86   else if (p == "test")
    87     id = RegExpProtoFunc::Test;
    88   else if (p == "toString")
    89     id = RegExpProtoFunc::ToString;
    90 
    91   if (id >= 0)
    92     return Function(new RegExpProtoFunc(id));
    93   else
    94     return Imp::get(p);
    95 }
    96 
    97 Completion RegExpProtoFunc::execute(const List &args)
    98 {
    99   KJSO result;
    100 
    101   Object thisObj = Object::dynamicCast(thisValue());
    102 
    103   if (thisObj.getClass() != RegExpClass) {
    104     result = Error::create(TypeError);
    105     return Completion(ReturnValue, result);
    106   }
    107 
    108   RegExp *re = static_cast<RegExpImp*>(thisObj.imp())->regExp();
    109   String s;
    110   KJSO lastIndex, tmp;
    111   UString str;
    112   int length, i;
    113   switch (id) {
    114   case Exec:
    115   case Test:
    116     s = args[0].toString();
    117     length = s.value().size();
    118     lastIndex = thisObj.get("lastIndex");
    119     i = lastIndex.toInt32();
    120     tmp = thisObj.get("global");
    121     if (tmp.toBoolean().value() == false)
    122       i = 0;
    123     if (i < 0 || i > length) {
    124       thisObj.put("lastIndex", 0);
    125       result = Null();
    126       break;
    127     }
    128     str = re->match(s.value(), i);
    129     if (id == Test) {
    130       result = Boolean(str.size() != 0);
    131       break;
    132     }
    133     /* TODO complete */
    134     result = String(str);
    135     break;
    136   case ToString:
    137     s = thisObj.get("source").toString();
    138     str = "/";
    139     str += s.value();
    140     str += "/";
    141     result = String(str);
    142     break;
    143   }
    144 
    145   return Completion(ReturnValue, result);
    146 }
     250bool RegExpObjectImp::implementsCall() const
     251{
     252  return true;
     253}
     254
     255// ECMA 15.10.3
     256Value RegExpObjectImp::call(ExecState */*exec*/, Object &/*thisObj*/, const List &/*args*/)
     257{
     258  // TODO: implement constructor
     259  return Undefined();
     260}
Note: See TracChangeset for help on using the changeset viewer.