00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include <stdio.h>
00024
00025
#include "value.h"
00026
#include "object.h"
00027
#include "types.h"
00028
#include "interpreter.h"
00029
#include "operations.h"
00030
#include "internal.h"
00031
#include "regexp.h"
00032
#include "regexp_object.h"
00033
#include "error_object.h"
00034
#include "lookup.h"
00035
00036
using namespace KJS;
00037
00038
00039
00040
00041
00042 RegExpPrototypeImp::RegExpPrototypeImp(
ExecState *exec,
00043 ObjectPrototypeImp *objProto,
00044
FunctionPrototypeImp *funcProto)
00045 : ObjectImp(objProto)
00046 {
00047
Value protect(
this);
00048
setInternalValue(
String(
""));
00049
00050
00051
00052
static const Identifier execPropertyName(
"exec");
00053 putDirect(execPropertyName,
00054
new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::Exec, 0, execPropertyName), DontEnum);
00055
static const Identifier testPropertyName(
"test");
00056 putDirect(testPropertyName,
00057
new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::Test, 0, testPropertyName), DontEnum);
00058 putDirect(toStringPropertyName,
00059
new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::ToString, 0, toStringPropertyName), DontEnum);
00060 }
00061
00062
00063
00064 RegExpProtoFuncImp::RegExpProtoFuncImp(
ExecState *,
FunctionPrototypeImp *funcProto,
00065
int i,
int len,
const Identifier &_ident)
00066 :
InternalFunctionImp(funcProto), id(i)
00067 {
00068
Value protect(
this);
00069 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
00070 ident = _ident;
00071 }
00072
00073
bool RegExpProtoFuncImp::implementsCall()
const
00074
{
00075
return true;
00076 }
00077
00078
Value RegExpProtoFuncImp::call(
ExecState *exec,
Object &thisObj,
const List &args)
00079 {
00080 KJS_CHECK_THIS( RegExpImp, thisObj );
00081
00082 RegExpImp *reimp = static_cast<RegExpImp*>(thisObj.
imp());
00083 RegExp *re = reimp->regExp();
00084
String s;
00085
UString str;
00086
switch (
id) {
00087
case Exec:
00088
case Test:
00089 {
00090 s = args[0].toString(exec);
00091
int length = s.
value().
size();
00092
00093
00094
Value lastIndex = thisObj.
get(exec,
"lastIndex");
00095
int i = lastIndex.
isValid() ? lastIndex.
toInt32(exec) : 0;
00096
bool globalFlag = thisObj.
get(exec,
"global").
toBoolean(exec);
00097
if (!globalFlag)
00098 i = 0;
00099
if (i < 0 || i > length) {
00100 thisObj.
put(exec,
"lastIndex",
Number(0), DontDelete | DontEnum);
00101
if (
id == Test)
00102
return Boolean(
false);
00103
else
00104
Null();
00105 }
00106 RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->
interpreter()->
builtinRegExp().
imp());
00107
int **ovector = regExpObj->registerRegexp( re, s.
value() );
00108
00109 str = re->match(s.
value(), i, 0L, ovector);
00110 regExpObj->setSubPatterns(re->subPatterns());
00111
00112
if (
id == Test)
00113
return Boolean(!str.
isNull());
00114
00115
if (str.
isNull())
00116 {
00117
if (globalFlag)
00118 thisObj.
put(exec,
"lastIndex",
Number(0), DontDelete | DontEnum);
00119
return Null();
00120 }
00121
else
00122 {
00123
if (globalFlag)
00124 thisObj.
put(exec,
"lastIndex",
Number( (*ovector)[1] ), DontDelete | DontEnum);
00125
return regExpObj->arrayOfMatches(exec,str);
00126 }
00127 }
00128
break;
00129
case ToString:
00130 s = thisObj.
get(exec,
"source").
toString(exec);
00131 str =
"/";
00132 str += s.
value();
00133 str +=
"/";
00134
00135
return String(str);
00136 }
00137
00138
return Undefined();
00139 }
00140
00141
00142
00143
const ClassInfo RegExpImp::info = {
"RegExp", 0, 0, 0};
00144
00145 RegExpImp::RegExpImp(RegExpPrototypeImp *regexpProto)
00146 : ObjectImp(regexpProto), reg(0L)
00147 {
00148 }
00149
00150 RegExpImp::~RegExpImp()
00151 {
00152
delete reg;
00153 }
00154
00155
00156
00157 RegExpObjectImp::RegExpObjectImp(
ExecState *,
00158
FunctionPrototypeImp *funcProto,
00159 RegExpPrototypeImp *regProto)
00160
00161 :
InternalFunctionImp(funcProto), lastOvector(0L), lastNrSubPatterns(0)
00162 {
00163
Value protect(
this);
00164
00165 putDirect(prototypePropertyName, regProto, DontEnum|DontDelete|ReadOnly);
00166
00167
00168 putDirect(lengthPropertyName, NumberImp::two(), ReadOnly|DontDelete|DontEnum);
00169 }
00170
00171 RegExpObjectImp::~RegExpObjectImp()
00172 {
00173
delete [] lastOvector;
00174 }
00175
00176
int **RegExpObjectImp::registerRegexp(
const RegExp* re,
const UString& s )
00177 {
00178 lastString = s;
00179
delete [] lastOvector;
00180 lastOvector = 0;
00181 lastNrSubPatterns = re->subPatterns();
00182
return &lastOvector;
00183 }
00184
00185
Object RegExpObjectImp::arrayOfMatches(
ExecState *exec,
const UString &result)
const
00186
{
00187
List list;
00188
00189 list.
append(
String(result));
00190
if ( lastOvector )
00191
for ( uint i = 1 ; i < lastNrSubPatterns + 1 ; ++i )
00192 {
00193
UString substring = lastString.substr( lastOvector[2*i], lastOvector[2*i+1] - lastOvector[2*i] );
00194 list.
append(
String(substring));
00195 }
00196
Object arr = exec->
interpreter()->
builtinArray().
construct(exec, list);
00197 arr.
put(exec,
"index",
Number(lastOvector[0]));
00198 arr.
put(exec,
"input",
String(lastString));
00199
return arr;
00200 }
00201
00202
Value RegExpObjectImp::get(
ExecState *exec,
const Identifier &p)
const
00203
{
00204
UString s = p.ustring();
00205
if (s[0] ==
'$' && lastOvector)
00206 {
00207
bool ok;
00208
unsigned long i = s.
substr(1).
toULong(&ok);
00209
if (ok)
00210 {
00211
if (i < lastNrSubPatterns + 1)
00212 {
00213
UString substring = lastString.
substr( lastOvector[2*i], lastOvector[2*i+1] - lastOvector[2*i] );
00214
return String(substring);
00215 }
00216
return String(
"");
00217 }
00218 }
00219
return InternalFunctionImp::get(exec, p);
00220 }
00221
00222
bool RegExpObjectImp::implementsConstruct()
const
00223
{
00224
return true;
00225 }
00226
00227
00228
Object RegExpObjectImp::construct(
ExecState *exec,
const List &args)
00229 {
00230
UString p;
00231
UString flags = args[1].toString(exec);
00232
if (args.
isEmpty()) {
00233 p =
"";
00234 }
else {
00235
Value a0 = args[0];
00236
if (a0.
isA(ObjectType) && a0.
toObject(exec).
inherits(&RegExpImp::info)) {
00237
00238
if (args.size() > 1 && args[1].
type() != UndefinedType) {
00239
Object err = Error::create(exec,TypeError);
00240 exec->
setException(err);
00241
return err;
00242 }
00243 }
00244 p = a0.
toString(exec);
00245 }
00246
00247 RegExpPrototypeImp *proto = static_cast<RegExpPrototypeImp*>(exec->
interpreter()->
builtinRegExpPrototype().
imp());
00248 RegExpImp *dat =
new RegExpImp(proto);
00249
Object obj(dat);
00250
00251
bool global = (flags.
find(
"g") >= 0);
00252
bool ignoreCase = (flags.
find(
"i") >= 0);
00253
bool multiline = (flags.
find(
"m") >= 0);
00254
00255
00256 dat->putDirect(
"global", global ? BooleanImp::staticTrue : BooleanImp::staticFalse);
00257 dat->putDirect(
"ignoreCase", ignoreCase ? BooleanImp::staticTrue : BooleanImp::staticFalse);
00258 dat->putDirect(
"multiline", multiline ? BooleanImp::staticTrue : BooleanImp::staticFalse);
00259
00260 dat->putDirect(
"source",
new StringImp(p));
00261 dat->putDirect(
"lastIndex", NumberImp::zero(), DontDelete | DontEnum);
00262
00263
int reflags = RegExp::None;
00264
if (global)
00265 reflags |= RegExp::Global;
00266
if (ignoreCase)
00267 reflags |= RegExp::IgnoreCase;
00268
if (multiline)
00269 reflags |= RegExp::Multiline;
00270 dat->setRegExp(
new RegExp(p, reflags));
00271
00272
return obj;
00273 }
00274
00275
bool RegExpObjectImp::implementsCall()
const
00276
{
00277
return true;
00278 }
00279
00280
00281
Value RegExpObjectImp::call(
ExecState *exec,
Object &,
00282
const List &args)
00283 {
00284
return construct(exec, args);
00285 }