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
)
70 , m_constructionError(0)
73 // NOTE: The global flag is handled on a case-by-case basis by functions like
74 // String::match and RegExpObject::match.
75 if (flags
.find('g') != -1)
77 if (flags
.find('i') != -1)
78 m_flagBits
|= IgnoreCase
;
79 if (flags
.find('m') != -1)
80 m_flagBits
|= Multiline
;
88 jsRegExpFree(m_regExp
);
92 PassRefPtr
<RegExp
> RegExp::create(JSGlobalData
* globalData
, const UString
& pattern
)
94 return adoptRef(new RegExp(globalData
, pattern
));
97 PassRefPtr
<RegExp
> RegExp::create(JSGlobalData
* globalData
, const UString
& pattern
, const UString
& flags
)
99 return adoptRef(new RegExp(globalData
, pattern
, flags
));
104 void RegExp::compile(JSGlobalData
* globalData
)
107 Yarr::jitCompileRegex(globalData
, m_regExpJITCode
, m_pattern
, m_numSubpatterns
, m_constructionError
, ignoreCase(), multiline());
109 UNUSED_PARAM(globalData
);
110 m_regExpBytecode
.set(Yarr::byteCompileRegex(m_pattern
, m_numSubpatterns
, m_constructionError
, ignoreCase(), multiline()));
114 int RegExp::match(const UString
& s
, int startOffset
, Vector
<int, 32>* ovector
)
121 if (startOffset
> s
.size() || s
.isNull())
125 if (!!m_regExpJITCode
) {
127 if (m_regExpBytecode
) {
129 int offsetVectorSize
= (m_numSubpatterns
+ 1) * 3; // FIXME: should be 2 - but adding temporary fallback to pcre.
131 Vector
<int, 32> nonReturnedOvector
;
133 ovector
->resize(offsetVectorSize
);
134 offsetVector
= ovector
->data();
136 nonReturnedOvector
.resize(offsetVectorSize
);
137 offsetVector
= nonReturnedOvector
.data();
140 ASSERT(offsetVector
);
141 for (int j
= 0; j
< offsetVectorSize
; ++j
)
142 offsetVector
[j
] = -1;
146 int result
= Yarr::executeRegex(m_regExpJITCode
, s
.data(), startOffset
, s
.size(), offsetVector
, offsetVectorSize
);
148 int result
= Yarr::interpretRegex(m_regExpBytecode
.get(), s
.data(), startOffset
, s
.size(), offsetVector
);
153 // TODO: define up a symbol, rather than magic -1
155 fprintf(stderr
, "jsRegExpExecute failed with result %d\n", result
);
168 void RegExp::compile(JSGlobalData
* globalData
)
172 m_wrecFunction
= Generator::compileRegExp(globalData
, m_pattern
, &m_numSubpatterns
, &m_constructionError
, m_executablePool
, ignoreCase(), multiline());
173 if (m_wrecFunction
|| m_constructionError
)
175 // Fall through to non-WREC case.
177 UNUSED_PARAM(globalData
);
180 JSRegExpIgnoreCaseOption ignoreCaseOption
= ignoreCase() ? JSRegExpIgnoreCase
: JSRegExpDoNotIgnoreCase
;
181 JSRegExpMultilineOption multilineOption
= multiline() ? JSRegExpMultiline
: JSRegExpSingleLine
;
182 m_regExp
= jsRegExpCompile(reinterpret_cast<const UChar
*>(m_pattern
.data()), m_pattern
.size(), ignoreCaseOption
, multilineOption
, &m_numSubpatterns
, &m_constructionError
);
185 int RegExp::match(const UString
& s
, int startOffset
, Vector
<int, 32>* ovector
)
192 if (startOffset
> s
.size() || s
.isNull())
196 if (m_wrecFunction
) {
197 int offsetVectorSize
= (m_numSubpatterns
+ 1) * 2;
199 Vector
<int, 32> nonReturnedOvector
;
201 ovector
->resize(offsetVectorSize
);
202 offsetVector
= ovector
->data();
204 nonReturnedOvector
.resize(offsetVectorSize
);
205 offsetVector
= nonReturnedOvector
.data();
207 ASSERT(offsetVector
);
208 for (int j
= 0; j
< offsetVectorSize
; ++j
)
209 offsetVector
[j
] = -1;
211 int result
= m_wrecFunction(s
.data(), startOffset
, s
.size(), offsetVector
);
215 // TODO: define up a symbol, rather than magic -1
217 fprintf(stderr
, "jsRegExpExecute failed with result %d\n", result
);
226 // Set up the offset vector for the result.
227 // First 2/3 used for result, the last third used by PCRE.
229 int offsetVectorSize
;
230 int fixedSizeOffsetVector
[3];
232 offsetVectorSize
= 3;
233 offsetVector
= fixedSizeOffsetVector
;
235 offsetVectorSize
= (m_numSubpatterns
+ 1) * 3;
236 ovector
->resize(offsetVectorSize
);
237 offsetVector
= ovector
->data();
240 int numMatches
= jsRegExpExecute(m_regExp
, reinterpret_cast<const UChar
*>(s
.data()), s
.size(), startOffset
, offsetVector
, offsetVectorSize
);
242 if (numMatches
< 0) {
244 if (numMatches
!= JSRegExpErrorNoMatch
)
245 fprintf(stderr
, "jsRegExpExecute failed with result %d\n", numMatches
);
252 return offsetVector
[0];