source: webkit/trunk/JavaScriptCore/runtime/RegExp.cpp@ 44711

Last change on this file since 44711 was 44224, checked in by [email protected], 16 years ago

Revert 44221.

  • Property svn:eol-style set to native
File size: 7.1 KB
Line 
1/*
2 * Copyright (C) 1999-2001, 2004 Harri Porten ([email protected])
3 * Copyright (c) 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 "RegExp.h"
23#include "Lexer.h"
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <wtf/Assertions.h>
28#include <wtf/OwnArrayPtr.h>
29
30
31#if ENABLE(YARR)
32
33#include "yarr/RegexCompiler.h"
34#if ENABLE(YARR_JIT)
35#include "yarr/RegexJIT.h"
36#else
37#include "yarr/RegexInterpreter.h"
38#endif
39
40#else
41
42#if ENABLE(WREC)
43#include "JIT.h"
44#include "WRECGenerator.h"
45#endif
46#include <pcre/pcre.h>
47
48#endif
49
50namespace JSC {
51
52#if ENABLE(WREC)
53using namespace WREC;
54#endif
55
56inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern)
57 : m_pattern(pattern)
58 , m_flagBits(0)
59 , m_constructionError(0)
60 , m_numSubpatterns(0)
61{
62 compile(globalData);
63}
64
65inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
66 : m_pattern(pattern)
67 , m_flags(flags)
68 , m_flagBits(0)
69 , m_constructionError(0)
70 , m_numSubpatterns(0)
71{
72 // NOTE: The global flag is handled on a case-by-case basis by functions like
73 // String::match and RegExpObject::match.
74 if (flags.find('g') != -1)
75 m_flagBits |= Global;
76 if (flags.find('i') != -1)
77 m_flagBits |= IgnoreCase;
78 if (flags.find('m') != -1)
79 m_flagBits |= Multiline;
80
81 compile(globalData);
82}
83
84#if !ENABLE(YARR)
85RegExp::~RegExp()
86{
87 jsRegExpFree(m_regExp);
88}
89#endif
90
91PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern)
92{
93 return adoptRef(new RegExp(globalData, pattern));
94}
95
96PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
97{
98 return adoptRef(new RegExp(globalData, pattern, flags));
99}
100
101#if ENABLE(YARR)
102
103void RegExp::compile(JSGlobalData* globalData)
104{
105#if ENABLE(YARR_JIT)
106 Yarr::jitCompileRegex(globalData, m_regExpJITCode, m_pattern, m_numSubpatterns, m_constructionError, ignoreCase(), multiline());
107#else
108 UNUSED_PARAM(globalData);
109 m_regExpBytecode.set(Yarr::byteCompileRegex(m_pattern, m_numSubpatterns, m_constructionError, ignoreCase(), multiline()));
110#endif
111}
112
113int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
114{
115 if (startOffset < 0)
116 startOffset = 0;
117 if (ovector)
118 ovector->clear();
119
120 if (startOffset > s.size() || s.isNull())
121 return -1;
122
123#if ENABLE(YARR_JIT)
124 if (!!m_regExpJITCode) {
125#else
126 if (m_regExpBytecode) {
127#endif
128 int offsetVectorSize = (m_numSubpatterns + 1) * 3; // FIXME: should be 2 - but adding temporary fallback to pcre.
129 int* offsetVector = new int [offsetVectorSize];
130 ASSERT(offsetVector);
131 for (int j = 0; j < offsetVectorSize; ++j)
132 offsetVector[j] = -1;
133
134 OwnArrayPtr<int> nonReturnedOvector;
135 if (!ovector)
136 nonReturnedOvector.set(offsetVector);
137 else
138 ovector->set(offsetVector);
139
140#if ENABLE(YARR_JIT)
141 int result = Yarr::executeRegex(m_regExpJITCode, s.data(), startOffset, s.size(), offsetVector, offsetVectorSize);
142#else
143 int result = Yarr::interpretRegex(m_regExpBytecode.get(), s.data(), startOffset, s.size(), offsetVector);
144#endif
145
146 if (result < 0) {
147#ifndef NDEBUG
148 // TODO: define up a symbol, rather than magic -1
149 if (result != -1)
150 fprintf(stderr, "jsRegExpExecute failed with result %d\n", result);
151#endif
152 if (ovector)
153 ovector->clear();
154 }
155 return result;
156 }
157
158 return -1;
159}
160
161#else
162
163void RegExp::compile(JSGlobalData* globalData)
164{
165 m_regExp = 0;
166#if ENABLE(WREC)
167 m_wrecFunction = Generator::compileRegExp(globalData, m_pattern, &m_numSubpatterns, &m_constructionError, m_executablePool, ignoreCase(), multiline());
168 if (m_wrecFunction || m_constructionError)
169 return;
170 // Fall through to non-WREC case.
171#else
172 UNUSED_PARAM(globalData);
173#endif
174
175 JSRegExpIgnoreCaseOption ignoreCaseOption = ignoreCase() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase;
176 JSRegExpMultilineOption multilineOption = multiline() ? JSRegExpMultiline : JSRegExpSingleLine;
177 m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(m_pattern.data()), m_pattern.size(), ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
178}
179
180int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
181{
182 if (startOffset < 0)
183 startOffset = 0;
184 if (ovector)
185 ovector->clear();
186
187 if (startOffset > s.size() || s.isNull())
188 return -1;
189
190#if ENABLE(WREC)
191 if (m_wrecFunction) {
192 int offsetVectorSize = (m_numSubpatterns + 1) * 2;
193 int* offsetVector = new int [offsetVectorSize];
194 ASSERT(offsetVector);
195 for (int j = 0; j < offsetVectorSize; ++j)
196 offsetVector[j] = -1;
197
198 OwnArrayPtr<int> nonReturnedOvector;
199 if (!ovector)
200 nonReturnedOvector.set(offsetVector);
201 else
202 ovector->set(offsetVector);
203
204 int result = m_wrecFunction(s.data(), startOffset, s.size(), offsetVector);
205
206 if (result < 0) {
207#ifndef NDEBUG
208 // TODO: define up a symbol, rather than magic -1
209 if (result != -1)
210 fprintf(stderr, "jsRegExpExecute failed with result %d\n", result);
211#endif
212 if (ovector)
213 ovector->clear();
214 }
215 return result;
216 } else
217#endif
218 if (m_regExp) {
219 // Set up the offset vector for the result.
220 // First 2/3 used for result, the last third used by PCRE.
221 int* offsetVector;
222 int offsetVectorSize;
223 int fixedSizeOffsetVector[3];
224 if (!ovector) {
225 offsetVectorSize = 3;
226 offsetVector = fixedSizeOffsetVector;
227 } else {
228 offsetVectorSize = (m_numSubpatterns + 1) * 3;
229 offsetVector = new int [offsetVectorSize];
230 ovector->set(offsetVector);
231 }
232
233 int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), startOffset, offsetVector, offsetVectorSize);
234
235 if (numMatches < 0) {
236#ifndef NDEBUG
237 if (numMatches != JSRegExpErrorNoMatch)
238 fprintf(stderr, "jsRegExpExecute failed with result %d\n", numMatches);
239#endif
240 if (ovector)
241 ovector->clear();
242 return -1;
243 }
244
245 return offsetVector[0];
246 }
247
248 return -1;
249}
250
251#endif
252
253} // namespace JSC
Note: See TracBrowser for help on using the repository browser.