JavaScriptCore:
[WebKit-https.git] / JavaScriptCore / runtime / RegExpObject.cpp
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  */
20
21 #include "config.h"
22 #include "RegExpObject.h"
23
24 #include "JSArray.h"
25 #include "JSGlobalObject.h"
26 #include "JSString.h"
27 #include "RegExpConstructor.h"
28 #include "RegExpPrototype.h"
29
30 namespace JSC {
31
32 static JSValue* regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&);
33 static JSValue* regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&);
34 static JSValue* regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&);
35 static JSValue* regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&);
36 static JSValue* regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&);
37 static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue*);
38
39 } // namespace JSC
40
41 #include "RegExpObject.lut.h"
42
43 namespace JSC {
44
45 ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
46
47 const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
48
49 /* Source for RegExpObject.lut.h
50 @begin regExpTable
51     global        regExpObjectGlobal       DontDelete|ReadOnly|DontEnum
52     ignoreCase    regExpObjectIgnoreCase   DontDelete|ReadOnly|DontEnum
53     multiline     regExpObjectMultiline    DontDelete|ReadOnly|DontEnum
54     source        regExpObjectSource       DontDelete|ReadOnly|DontEnum
55     lastIndex     regExpObjectLastIndex    DontDelete|DontEnum
56 @end
57 */
58
59 RegExpObject::RegExpObject(PassRefPtr<Structure> structure, PassRefPtr<RegExp> regExp)
60     : JSObject(structure)
61     , d(new RegExpObjectData(regExp, 0))
62 {
63 }
64
65 RegExpObject::~RegExpObject()
66 {
67 }
68
69 bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
70 {
71     return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
72 }
73
74 JSValue* regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
75 {
76     return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global());
77 }
78
79 JSValue* regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot)
80 {
81     return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->ignoreCase());
82 }
83  
84 JSValue* regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
85 {            
86     return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->multiline());
87 }
88
89 JSValue* regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot)
90 {
91     return jsString(exec, asRegExpObject(slot.slotBase())->regExp()->pattern());
92 }
93
94 JSValue* regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot)
95 {
96     return jsNumber(exec, asRegExpObject(slot.slotBase())->lastIndex());
97 }
98
99 void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
100 {
101     lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot);
102 }
103
104 void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue* value)
105 {
106     asRegExpObject(baseObject)->setLastIndex(value->toInteger(exec));
107 }
108
109 bool RegExpObject::match(ExecState* exec, const ArgList& args)
110 {
111     RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
112
113     UString input;
114     if (!args.isEmpty())
115         input = args.at(exec, 0)->toString(exec);
116     else {
117         input = regExpObj->input();
118         if (input.isNull()) {
119             throwError(exec, GeneralError, "No input.");
120             return false;
121         }
122     }
123
124     bool global = get(exec, exec->propertyNames().global)->toBoolean(exec);
125     int lastIndex = 0;
126     if (global) {
127         if (d->lastIndex < 0 || d->lastIndex > input.size()) {
128             d->lastIndex = 0;
129             return false;
130         }
131         lastIndex = static_cast<int>(d->lastIndex);
132     }
133
134     int foundIndex;
135     int foundLength;
136     regExpObj->performMatch(d->regExp.get(), input, lastIndex, foundIndex, foundLength);
137
138     if (global) {
139         lastIndex = foundIndex < 0 ? 0 : foundIndex + foundLength;
140         d->lastIndex = lastIndex;
141     }
142
143     return foundIndex >= 0;
144 }
145
146 JSValue* RegExpObject::test(ExecState* exec, const ArgList& args)
147 {
148     return jsBoolean(match(exec, args));
149 }
150
151 JSValue* RegExpObject::exec(ExecState* exec, const ArgList& args)
152 {
153     if (match(exec, args))
154         return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec);
155     return jsNull();
156 }
157
158 static JSValue* callRegExpObject(ExecState* exec, JSObject* function, JSValue*, const ArgList& args)
159 {
160     return asRegExpObject(function)->exec(exec, args);
161 }
162
163 CallType RegExpObject::getCallData(CallData& callData)
164 {
165     callData.native.function = callRegExpObject;
166     return CallTypeHost;
167 }
168
169 } // namespace JSC