RegExpObject.cpp 5.49 KB
Newer Older
1 2
/*
 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
weinig@apple.com's avatar
weinig@apple.com committed
3
 *  Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
mjs's avatar
mjs committed
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
 *
19 20
 */

mjs's avatar
mjs committed
21
#include "config.h"
darin@apple.com's avatar
darin@apple.com committed
22
#include "RegExpObject.h"
23

24
#include "JSArray.h"
25
#include "JSGlobalObject.h"
26
#include "JSString.h"
27 28
#include "RegExpConstructor.h"
#include "RegExpPrototype.h"
harrison's avatar
harrison committed
29

30
namespace JSC {
31

weinig@apple.com's avatar
weinig@apple.com committed
32 33 34 35 36 37 38 39 40 41 42 43 44
static JSValue* regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&);
static JSValue* regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&);
static JSValue* regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&);
static JSValue* regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&);
static JSValue* regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&);
static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue*);

} // namespace JSC

#include "RegExpObject.lut.h"

namespace JSC {

ggaren@apple.com's avatar
ggaren@apple.com committed
45 46
ASSERT_CLASS_FITS_IN_CELL(RegExpObject);

darin@apple.com's avatar
darin@apple.com committed
47
const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
ggaren@apple.com's avatar
ggaren@apple.com committed
48

darin@apple.com's avatar
darin@apple.com committed
49
/* Source for RegExpObject.lut.h
darin@apple.com's avatar
darin@apple.com committed
50
@begin regExpTable
weinig@apple.com's avatar
weinig@apple.com committed
51 52 53 54 55
    global        regExpObjectGlobal       DontDelete|ReadOnly|DontEnum
    ignoreCase    regExpObjectIgnoreCase   DontDelete|ReadOnly|DontEnum
    multiline     regExpObjectMultiline    DontDelete|ReadOnly|DontEnum
    source        regExpObjectSource       DontDelete|ReadOnly|DontEnum
    lastIndex     regExpObjectLastIndex    DontDelete|DontEnum
ggaren@apple.com's avatar
ggaren@apple.com committed
56 57
@end
*/
58

darin@apple.com's avatar
darin@apple.com committed
59 60
RegExpObject::RegExpObject(PassRefPtr<StructureID> structure, PassRefPtr<RegExp> regExp)
    : JSObject(structure)
ggaren@apple.com's avatar
ggaren@apple.com committed
61
    , d(new RegExpObjectData(regExp, 0))
62 63 64
{
}

darin@apple.com's avatar
darin@apple.com committed
65
RegExpObject::~RegExpObject()
66 67 68
{
}

darin@apple.com's avatar
darin@apple.com committed
69
bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
ggaren@apple.com's avatar
ggaren@apple.com committed
70
{
weinig@apple.com's avatar
weinig@apple.com committed
71
    return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
ggaren@apple.com's avatar
ggaren@apple.com committed
72 73
}

weinig@apple.com's avatar
weinig@apple.com committed
74
JSValue* regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
ggaren@apple.com's avatar
ggaren@apple.com committed
75
{
weinig@apple.com's avatar
weinig@apple.com committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    return jsBoolean(static_cast<RegExpObject*>(slot.slotBase())->regExp()->global());
}

JSValue* regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot)
{
    return jsBoolean(static_cast<RegExpObject*>(slot.slotBase())->regExp()->ignoreCase());
}
 
JSValue* regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
{            
    return jsBoolean(static_cast<RegExpObject*>(slot.slotBase())->regExp()->multiline());
}

JSValue* regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
    return jsString(exec, static_cast<RegExpObject*>(slot.slotBase())->regExp()->pattern());
}

JSValue* regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
    return jsNumber(exec, static_cast<RegExpObject*>(slot.slotBase())->lastIndex());
ggaren@apple.com's avatar
ggaren@apple.com committed
97 98
}

weinig@apple.com's avatar
weinig@apple.com committed
99
void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
ggaren@apple.com's avatar
ggaren@apple.com committed
100
{
weinig@apple.com's avatar
weinig@apple.com committed
101
    lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot);
ggaren@apple.com's avatar
ggaren@apple.com committed
102 103
}

weinig@apple.com's avatar
weinig@apple.com committed
104
void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue* value)
ggaren@apple.com's avatar
ggaren@apple.com committed
105
{
weinig@apple.com's avatar
weinig@apple.com committed
106
    static_cast<RegExpObject*>(baseObject)->setLastIndex(value->toInteger(exec));
ggaren@apple.com's avatar
ggaren@apple.com committed
107 108
}

darin@apple.com's avatar
darin@apple.com committed
109
bool RegExpObject::match(ExecState* exec, const ArgList& args)
darin@apple.com's avatar
darin@apple.com committed
110
{
darin@apple.com's avatar
darin@apple.com committed
111
    RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
darin@apple.com's avatar
darin@apple.com committed
112 113 114

    UString input;
    if (!args.isEmpty())
ggaren@apple.com's avatar
ggaren@apple.com committed
115
        input = args.at(exec, 0)->toString(exec);
darin@apple.com's avatar
darin@apple.com committed
116 117 118 119 120 121 122 123
    else {
        input = regExpObj->input();
        if (input.isNull()) {
            throwError(exec, GeneralError, "No input.");
            return false;
        }
    }

mjs@apple.com's avatar
mjs@apple.com committed
124
    bool global = get(exec, exec->propertyNames().global)->toBoolean(exec);
darin@apple.com's avatar
darin@apple.com committed
125 126
    int lastIndex = 0;
    if (global) {
ggaren@apple.com's avatar
ggaren@apple.com committed
127 128
        if (d->lastIndex < 0 || d->lastIndex > input.size()) {
            d->lastIndex = 0;
darin@apple.com's avatar
darin@apple.com committed
129 130
            return false;
        }
ggaren@apple.com's avatar
ggaren@apple.com committed
131
        lastIndex = static_cast<int>(d->lastIndex);
darin@apple.com's avatar
darin@apple.com committed
132 133 134 135
    }

    int foundIndex;
    int foundLength;
ggaren@apple.com's avatar
ggaren@apple.com committed
136
    regExpObj->performMatch(d->regExp.get(), input, lastIndex, foundIndex, foundLength);
darin@apple.com's avatar
darin@apple.com committed
137 138 139

    if (global) {
        lastIndex = foundIndex < 0 ? 0 : foundIndex + foundLength;
ggaren@apple.com's avatar
ggaren@apple.com committed
140
        d->lastIndex = lastIndex;
darin@apple.com's avatar
darin@apple.com committed
141 142 143 144 145
    }

    return foundIndex >= 0;
}

darin@apple.com's avatar
darin@apple.com committed
146
JSValue* RegExpObject::test(ExecState* exec, const ArgList& args)
darin@apple.com's avatar
darin@apple.com committed
147 148 149 150
{
    return jsBoolean(match(exec, args));
}

darin@apple.com's avatar
darin@apple.com committed
151
JSValue* RegExpObject::exec(ExecState* exec, const ArgList& args)
darin@apple.com's avatar
darin@apple.com committed
152
{
weinig@apple.com's avatar
weinig@apple.com committed
153 154 155
    if (match(exec, args))
        return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec);
    return jsNull();
darin@apple.com's avatar
darin@apple.com committed
156 157
}

darin@apple.com's avatar
darin@apple.com committed
158
static JSValue* callRegExpObject(ExecState* exec, JSObject* function, JSValue*, const ArgList& args)
darin@apple.com's avatar
darin@apple.com committed
159
{
darin@apple.com's avatar
darin@apple.com committed
160
    return static_cast<RegExpObject*>(function)->exec(exec, args);
darin@apple.com's avatar
darin@apple.com committed
161 162
}

darin@apple.com's avatar
darin@apple.com committed
163
CallType RegExpObject::getCallData(CallData& callData)
darin@apple.com's avatar
darin@apple.com committed
164
{
darin@apple.com's avatar
darin@apple.com committed
165
    callData.native.function = callRegExpObject;
ggaren@apple.com's avatar
ggaren@apple.com committed
166
    return CallTypeHost;
darin@apple.com's avatar
darin@apple.com committed
167 168
}

169
} // namespace JSC