2 * Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
3 * Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2009 Torch Mobile, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <wtf/Assertions.h>
29 #include <wtf/OwnArrayPtr.h>
34 #include "yarr/RegexCompiler.h"
36 #include "yarr/RegexJIT.h"
38 #include "yarr/RegexInterpreter.h"
45 #include "WRECGenerator.h"
47 #include <pcre/pcre.h>
57 inline RegExp::RegExp(JSGlobalData
* globalData
, const UString
& pattern
)
60 , m_constructionError(0)
66 inline RegExp::RegExp(JSGlobalData
* globalData
, const UString
& pattern
, const UString
& flags
)
69 , m_constructionError(0)
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)
76 if (flags
.find('i') != -1)
77 m_flagBits
|= IgnoreCase
;
78 if (flags
.find('m') != -1)
79 m_flagBits
|= Multiline
;
87 jsRegExpFree(m_regExp
);
91 PassRefPtr
<RegExp
> RegExp::create(JSGlobalData
* globalData
, const UString
& pattern
)
93 return adoptRef(new RegExp(globalData
, pattern
));
96 PassRefPtr
<RegExp
> RegExp::create(JSGlobalData
* globalData
, const UString
& pattern
, const UString
& flags
)
98 return adoptRef(new RegExp(globalData
, pattern
, flags
));
103 void RegExp::compile(JSGlobalData
* globalData
)
106 Yarr::jitCompileRegex(globalData
, m_regExpJITCode
, m_pattern
, m_numSubpatterns
, m_constructionError
, ignoreCase(), multiline());
108 UNUSED_PARAM(globalData
);
109 m_regExpBytecode
.set(Yarr::byteCompileRegex(m_pattern
, m_numSubpatterns
, m_constructionError
, ignoreCase(), multiline()));
113 int RegExp::match(const UString
& s
, int startOffset
, Vector
<int, 32>* ovector
)
120 if (startOffset
> s
.size() || s
.isNull())
124 if (!!m_regExpJITCode
) {
126 if (m_regExpBytecode
) {
128 int offsetVectorSize
= (m_numSubpatterns
+ 1) * 3; // FIXME: should be 2 - but adding temporary fallback to pcre.
130 Vector
<int, 32> nonReturnedOvector
;
132 ovector
->resize(offsetVectorSize
);
133 offsetVector
= ovector
->data();
135 nonReturnedOvector
.resize(offsetVectorSize
);
136 offsetVector
= nonReturnedOvector
.data();
139 ASSERT(offsetVector
);
140 for (int j
= 0; j
< offsetVectorSize
; ++j
)
141 offsetVector
[j
] = -1;
145 int result
= Yarr::executeRegex(m_regExpJITCode
, s
.data(), startOffset
, s
.size(), offsetVector
, offsetVectorSize
);
147 int result
= Yarr::interpretRegex(m_regExpBytecode
.get(), s
.data(), startOffset
, s
.size(), offsetVector
);
152 // TODO: define up a symbol, rather than magic -1
154 fprintf(stderr
, "jsRegExpExecute failed with result %d\n", result
);
167 void RegExp::compile(JSGlobalData
* globalData
)
171 m_wrecFunction
= Generator::compileRegExp(globalData
, m_pattern
, &m_numSubpatterns
, &m_constructionError
, m_executablePool
, ignoreCase(), multiline());
172 if (m_wrecFunction
|| m_constructionError
)
174 // Fall through to non-WREC case.
176 UNUSED_PARAM(globalData
);
179 JSRegExpIgnoreCaseOption ignoreCaseOption
= ignoreCase() ? JSRegExpIgnoreCase
: JSRegExpDoNotIgnoreCase
;
180 JSRegExpMultilineOption multilineOption
= multiline() ? JSRegExpMultiline
: JSRegExpSingleLine
;
181 m_regExp
= jsRegExpCompile(reinterpret_cast<const UChar
*>(m_pattern
.data()), m_pattern
.size(), ignoreCaseOption
, multilineOption
, &m_numSubpatterns
, &m_constructionError
);
184 int RegExp::match(const UString
& s
, int startOffset
, Vector
<int, 32>* ovector
)
191 if (startOffset
> s
.size() || s
.isNull())
195 if (m_wrecFunction
) {
196 int offsetVectorSize
= (m_numSubpatterns
+ 1) * 2;
198 Vector
<int, 32> nonReturnedOvector
;
200 ovector
->resize(offsetVectorSize
);
201 offsetVector
= ovector
->data();
203 nonReturnedOvector
.resize(offsetVectorSize
);
204 offsetVector
= nonReturnedOvector
.data();
206 ASSERT(offsetVector
);
207 for (int j
= 0; j
< offsetVectorSize
; ++j
)
208 offsetVector
[j
] = -1;
210 int result
= m_wrecFunction(s
.data(), startOffset
, s
.size(), offsetVector
);
214 // TODO: define up a symbol, rather than magic -1
216 fprintf(stderr
, "jsRegExpExecute failed with result %d\n", result
);
225 // Set up the offset vector for the result.
226 // First 2/3 used for result, the last third used by PCRE.
228 int offsetVectorSize
;
229 int fixedSizeOffsetVector
[3];
231 offsetVectorSize
= 3;
232 offsetVector
= fixedSizeOffsetVector
;
234 offsetVectorSize
= (m_numSubpatterns
+ 1) * 3;
235 ovector
->resize(offsetVectorSize
);
236 offsetVector
= ovector
->data();
239 int numMatches
= jsRegExpExecute(m_regExp
, reinterpret_cast<const UChar
*>(s
.data()), s
.size(), startOffset
, offsetVector
, offsetVectorSize
);
241 if (numMatches
< 0) {
243 if (numMatches
!= JSRegExpErrorNoMatch
)
244 fprintf(stderr
, "jsRegExpExecute failed with result %d\n", numMatches
);
251 return offsetVector
[0];