kjs Library API Documentation

regexp_object.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Lesser General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Lesser General Public
00017  *  License along with this library; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #include <stdio.h>
00023 
00024 #include "value.h"
00025 #include "object.h"
00026 #include "types.h"
00027 #include "interpreter.h"
00028 #include "operations.h"
00029 #include "internal.h"
00030 #include "regexp.h"
00031 #include "regexp_object.h"
00032 #include "error_object.h"
00033 #include "lookup.h"
00034 
00035 using namespace KJS;
00036 
00037 // ------------------------------ RegExpPrototypeImp ---------------------------
00038 
00039 // ECMA 15.9.4
00040 
00041 RegExpPrototypeImp::RegExpPrototypeImp(ExecState *exec,
00042                                        ObjectPrototypeImp *objProto,
00043                                        FunctionPrototypeImp *funcProto)
00044   : ObjectImp(Object(objProto))
00045 {
00046   Value protect(this);
00047   setInternalValue(String(""));
00048 
00049   // The constructor will be added later in RegExpObject's constructor (?)
00050 
00051   put(exec, "exec",     Object(new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::Exec,     0)), DontEnum);
00052   put(exec, "test",     Object(new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::Test,     0)), DontEnum);
00053   put(exec, "toString", Object(new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::ToString, 0)), DontEnum);
00054 }
00055 
00056 // ------------------------------ RegExpProtoFuncImp ---------------------------
00057 
00058 RegExpProtoFuncImp::RegExpProtoFuncImp(ExecState *exec,
00059                                        FunctionPrototypeImp *funcProto, int i, int len)
00060   : InternalFunctionImp(funcProto), id(i)
00061 {
00062   Value protect(this);
00063   put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
00064 }
00065 
00066 bool RegExpProtoFuncImp::implementsCall() const
00067 {
00068   return true;
00069 }
00070 
00071 Value RegExpProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
00072 {
00073   KJS_CHECK_THIS( RegExpImp, thisObj );
00074 
00075   RegExpImp *reimp = static_cast<RegExpImp*>(thisObj.imp());
00076   RegExp *re = reimp->regExp();
00077   String s;
00078   UString str;
00079   switch (id) {
00080   case Exec:      // 15.10.6.2
00081   case Test:
00082   {
00083     s = args[0].toString(exec);
00084     int length = s.value().size();
00085 
00086     // Get values from the last time (in case of /g)
00087     Value lastIndex = thisObj.get(exec,"lastIndex");
00088     int i = lastIndex.isNull() ? 0 : lastIndex.toInt32(exec);
00089     bool globalFlag = thisObj.get(exec,"global").toBoolean(exec);
00090     if (!globalFlag)
00091       i = 0;
00092     if (i < 0 || i > length) {
00093       thisObj.put(exec,"lastIndex", Number(0), DontDelete | DontEnum);
00094       if (id == Test)
00095         return Boolean(false);
00096       else
00097         Null();
00098     }
00099     RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
00100     int **ovector = regExpObj->registerRegexp( re, s.value() );
00101 
00102     str = re->match(s.value(), i, 0L, ovector);
00103     regExpObj->setSubPatterns(re->subPatterns());
00104 
00105     if (id == Test)
00106       return Boolean(!str.isNull());
00107 
00108     if (str.isNull()) // no match
00109     {
00110       if (globalFlag)
00111         thisObj.put(exec,"lastIndex",Number(0), DontDelete | DontEnum);
00112       return Null();
00113     }
00114     else // success
00115     {
00116       if (globalFlag)
00117         thisObj.put(exec,"lastIndex",Number( (*ovector)[1] ), DontDelete | DontEnum);
00118       return regExpObj->arrayOfMatches(exec,str);
00119     }
00120   }
00121   break;
00122   case ToString:
00123     s = thisObj.get(exec,"source").toString(exec);
00124     str = "/";
00125     str += s.value();
00126     str += "/";
00127     // TODO append the flags
00128     return String(str);
00129   }
00130 
00131   return Undefined();
00132 }
00133 
00134 // ------------------------------ RegExpImp ------------------------------------
00135 
00136 const ClassInfo RegExpImp::info = {"RegExp", 0, 0, 0};
00137 
00138 RegExpImp::RegExpImp(RegExpPrototypeImp *regexpProto)
00139   : ObjectImp(Object(regexpProto)), reg(0L)
00140 {
00141 }
00142 
00143 RegExpImp::~RegExpImp()
00144 {
00145   delete reg;
00146 }
00147 
00148 // ------------------------------ RegExpObjectImp ------------------------------
00149 
00150 RegExpObjectImp::RegExpObjectImp(ExecState *exec,
00151                                  FunctionPrototypeImp *funcProto,
00152                                  RegExpPrototypeImp *regProto)
00153 
00154   : InternalFunctionImp(funcProto), lastOvector(0L), lastNrSubPatterns(0)
00155 {
00156   Value protect(this);
00157   // ECMA 15.10.5.1 RegExp.prototype
00158   put(exec,"prototype", Object(regProto), DontEnum|DontDelete|ReadOnly);
00159 
00160   // no. of arguments for constructor
00161   put(exec,"length", Number(2), ReadOnly|DontDelete|DontEnum);
00162 }
00163 
00164 RegExpObjectImp::~RegExpObjectImp()
00165 {
00166   delete [] lastOvector;
00167 }
00168 
00169 int **RegExpObjectImp::registerRegexp( const RegExp* re, const UString& s )
00170 {
00171   lastString = s;
00172   delete [] lastOvector;
00173   lastOvector = 0;
00174   lastNrSubPatterns = re->subPatterns();
00175   return &lastOvector;
00176 }
00177 
00178 Object RegExpObjectImp::arrayOfMatches(ExecState *exec, const UString &result) const
00179 {
00180   List list;
00181   // The returned array contains 'result' as first item, followed by the list of matches
00182   list.append(String(result));
00183   if ( lastOvector )
00184     for ( uint i = 1 ; i < lastNrSubPatterns + 1 ; ++i )
00185     {
00186       UString substring = lastString.substr( lastOvector[2*i], lastOvector[2*i+1] - lastOvector[2*i] );
00187       list.append(String(substring));
00188     }
00189   Object arr = exec->interpreter()->builtinArray().construct(exec, list);
00190   arr.put(exec, "index", Number(lastOvector[0]));
00191   arr.put(exec, "input", String(lastString));
00192   return arr;
00193 }
00194 
00195 Value RegExpObjectImp::get(ExecState *exec, const UString &p) const
00196 {
00197   if (p[0] == '$' && lastOvector)
00198   {
00199     bool ok;
00200     unsigned long i = p.substr(1).toULong(&ok);
00201     if (ok)
00202     {
00203       if (i < lastNrSubPatterns + 1)
00204       {
00205         UString substring = lastString.substr( lastOvector[2*i], lastOvector[2*i+1] - lastOvector[2*i] );
00206         return String(substring);
00207       }
00208       return String("");
00209     }
00210   }
00211   return InternalFunctionImp::get(exec, p);
00212 }
00213 
00214 bool RegExpObjectImp::implementsConstruct() const
00215 {
00216   return true;
00217 }
00218 
00219 // ECMA 15.10.4
00220 Object RegExpObjectImp::construct(ExecState *exec, const List &args)
00221 {
00222   String p = args.isEmpty() ? UString("") : args[0].toString(exec);
00223   UString flags = args[1].toString(exec);
00224 
00225   RegExpPrototypeImp *proto = static_cast<RegExpPrototypeImp*>(exec->interpreter()->builtinRegExpPrototype().imp());
00226   RegExpImp *dat = new RegExpImp(proto);
00227   Object obj(dat); // protect from GC
00228 
00229   bool global = (flags.find("g") >= 0);
00230   bool ignoreCase = (flags.find("i") >= 0);
00231   bool multiline = (flags.find("m") >= 0);
00232   // TODO: throw a syntax error on invalid flags
00233 
00234   dat->put(exec, "global", Boolean(global));
00235   dat->put(exec, "ignoreCase", Boolean(ignoreCase));
00236   dat->put(exec, "multiline", Boolean(multiline));
00237 
00238   dat->put(exec, "source", p);
00239   dat->put(exec, "lastIndex", Number(0), DontDelete | DontEnum);
00240 
00241   int reflags = RegExp::None;
00242   if (global)
00243       reflags |= RegExp::Global;
00244   if (ignoreCase)
00245       reflags |= RegExp::IgnoreCase;
00246   if (multiline)
00247       reflags |= RegExp::Multiline;
00248   dat->setRegExp(new RegExp(p.value(), reflags));
00249 
00250   return obj;
00251 }
00252 
00253 bool RegExpObjectImp::implementsCall() const
00254 {
00255   return true;
00256 }
00257 
00258 // ECMA 15.10.3
00259 Value RegExpObjectImp::call(ExecState *exec, Object &/*thisObj*/,
00260                 const List &args)
00261 {
00262   // TODO: handle RegExp argument case (15.10.3.1)
00263 
00264   return construct(exec, args);
00265 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:21:15 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001