regexp_object.cpp Source File (kjs Library)

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

# 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 }

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:08:34 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001