Changeset 798 in webkit for trunk/JavaScriptCore/kjs/regexp_object.cpp
- Timestamp:
- Mar 21, 2002, 4:31:57 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/regexp_object.cpp
r6 r798 1 // -*- c-basic-offset: 2 -*- 1 2 /* 2 3 * This file is part of the KDE libraries … … 16 17 * License along with this library; if not, write to the Free Software 17 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 * $Id$ 18 21 */ 19 22 20 23 #include <stdio.h> 21 24 22 #include "kjs.h" 25 #include "value.h" 26 #include "object.h" 27 #include "types.h" 28 #include "interpreter.h" 23 29 #include "operations.h" 24 #include "types.h"25 30 #include "internal.h" 26 31 #include "regexp.h" 27 32 #include "regexp_object.h" 33 #include "error_object.h" 28 34 29 35 using namespace KJS; 30 36 31 RegExpObject::RegExpObject(const Object& funcProto, const Object ®Proto) 32 : ConstructorImp(funcProto, 2) 33 { 37 // ------------------------------ RegExpPrototypeImp --------------------------- 38 39 // ECMA 15.9.4 40 41 RegExpPrototypeImp::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 58 RegExpProtoFuncImp::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 66 bool RegExpProtoFuncImp::implementsCall() const 67 { 68 return true; 69 } 70 71 Value 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 134 const ClassInfo RegExpImp::info = {"RegExp", 0, 0, 0}; 135 136 RegExpImp::RegExpImp(RegExpPrototypeImp *regexpProto) 137 : ObjectImp(Object(regexpProto)), reg(0L) 138 { 139 } 140 141 RegExpImp::~RegExpImp() 142 { 143 delete reg; 144 } 145 146 // ------------------------------ RegExpObjectImp ------------------------------ 147 148 RegExpObjectImp::RegExpObjectImp(ExecState *exec, 149 RegExpPrototypeImp *regProto, 150 FunctionPrototypeImp *funcProto) 151 : InternalFunctionImp(funcProto), lastOvector(0L), lastNrSubPatterns(0) 152 { 153 Value protect(this); 34 154 // 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 161 RegExpObjectImp::~RegExpObjectImp() 162 { 163 if (lastOvector) 164 delete [] lastOvector; 165 } 166 167 int **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 177 Value 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 191 Value 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 210 bool RegExpObjectImp::implementsConstruct() const 211 { 212 return true; 213 } 214 215 // ECMA 15.10.4 216 Object RegExpObjectImp::construct(ExecState *exec, const List &args) 217 { 218 String p = args[0].toString(exec); 219 String f = args[1].toString(exec); 50 220 UString flags = f.value(); 51 221 52 RegExpImp *dat = new RegExpImp(); 222 RegExpPrototypeImp *proto = static_cast<RegExpPrototypeImp*>(exec->interpreter()->builtinRegExpPrototype().imp()); 223 RegExpImp *dat = new RegExpImp(proto); 53 224 Object obj(dat); // protect from GC 54 225 … … 56 227 bool ignoreCase = (flags.find("i") >= 0); 57 228 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)); 70 246 71 247 return obj; 72 248 } 73 249 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 } 250 bool RegExpObjectImp::implementsCall() const 251 { 252 return true; 253 } 254 255 // ECMA 15.10.3 256 Value 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.