00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00038
00039
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
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
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:
00081 case Test:
00082 {
00083 s = args[0].toString(exec);
00084 int length = s.value().size();
00085
00086
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())
00109 {
00110 if (globalFlag)
00111 thisObj.put(exec,"lastIndex",Number(0), DontDelete | DontEnum);
00112 return Null();
00113 }
00114 else
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
00128 return String(str);
00129 }
00130
00131 return Undefined();
00132 }
00133
00134
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
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
00158 put(exec,"prototype", Object(regProto), DontEnum|DontDelete|ReadOnly);
00159
00160
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
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
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);
00228
00229 bool global = (flags.find("g") >= 0);
00230 bool ignoreCase = (flags.find("i") >= 0);
00231 bool multiline = (flags.find("m") >= 0);
00232
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
00259 Value RegExpObjectImp::call(ExecState *exec, Object &,
00260 const List &args)
00261 {
00262
00263
00264 return construct(exec, args);
00265 }