]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/RegExp.cpp
b8251d279ea37065cc9a653e5c177ed2635e8a44
[apple/javascriptcore.git] / runtime / RegExp.cpp
1 /*
2 * Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
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
24 #include "JIT.h"
25 #include "Lexer.h"
26 #include "WRECGenerator.h"
27 #include <pcre/pcre.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <wtf/Assertions.h>
32 #include <wtf/OwnArrayPtr.h>
33
34 namespace JSC {
35
36 #if ENABLE(WREC)
37 using namespace WREC;
38 #endif
39
40 inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern)
41 : m_pattern(pattern)
42 , m_flagBits(0)
43 , m_regExp(0)
44 , m_constructionError(0)
45 , m_numSubpatterns(0)
46 {
47 #if ENABLE(WREC)
48 m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool);
49 if (m_wrecFunction || m_constructionError)
50 return;
51 // Fall through to non-WREC case.
52 #else
53 UNUSED_PARAM(globalData);
54 #endif
55 m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
56 JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError);
57 }
58
59 PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern)
60 {
61 return adoptRef(new RegExp(globalData, pattern));
62 }
63
64 inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
65 : m_pattern(pattern)
66 , m_flags(flags)
67 , m_flagBits(0)
68 , m_regExp(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
77 // FIXME: Eliminate duplication by adding a way ask a JSRegExp what its flags are?
78 JSRegExpIgnoreCaseOption ignoreCaseOption = JSRegExpDoNotIgnoreCase;
79 if (flags.find('i') != -1) {
80 m_flagBits |= IgnoreCase;
81 ignoreCaseOption = JSRegExpIgnoreCase;
82 }
83
84 JSRegExpMultilineOption multilineOption = JSRegExpSingleLine;
85 if (flags.find('m') != -1) {
86 m_flagBits |= Multiline;
87 multilineOption = JSRegExpMultiline;
88 }
89
90 #if ENABLE(WREC)
91 m_wrecFunction = Generator::compileRegExp(globalData, pattern, &m_numSubpatterns, &m_constructionError, m_executablePool, (m_flagBits & IgnoreCase), (m_flagBits & Multiline));
92 if (m_wrecFunction || m_constructionError)
93 return;
94 // Fall through to non-WREC case.
95 #else
96 UNUSED_PARAM(globalData);
97 #endif
98 m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(pattern.data()), pattern.size(),
99 ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
100 }
101
102 PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
103 {
104 return adoptRef(new RegExp(globalData, pattern, flags));
105 }
106
107 RegExp::~RegExp()
108 {
109 jsRegExpFree(m_regExp);
110 }
111
112 int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
113 {
114 if (startOffset < 0)
115 startOffset = 0;
116 if (ovector)
117 ovector->clear();
118
119 if (startOffset > s.size() || s.isNull())
120 return -1;
121
122 #if ENABLE(WREC)
123 if (m_wrecFunction) {
124 int offsetVectorSize = (m_numSubpatterns + 1) * 2;
125 int* offsetVector = new int [offsetVectorSize];
126 for (int j = 0; j < offsetVectorSize; ++j)
127 offsetVector[j] = -1;
128
129 OwnArrayPtr<int> nonReturnedOvector;
130 if (!ovector)
131 nonReturnedOvector.set(offsetVector);
132 else
133 ovector->set(offsetVector);
134
135 int result = m_wrecFunction(s.data(), startOffset, s.size(), offsetVector);
136
137 if (result < 0) {
138 #ifndef NDEBUG
139 // TODO: define up a symbol, rather than magic -1
140 if (result != -1)
141 fprintf(stderr, "jsRegExpExecute failed with result %d\n", result);
142 #endif
143 if (ovector)
144 ovector->clear();
145 }
146 return result;
147 } else
148 #endif
149 if (m_regExp) {
150 // Set up the offset vector for the result.
151 // First 2/3 used for result, the last third used by PCRE.
152 int* offsetVector;
153 int offsetVectorSize;
154 int fixedSizeOffsetVector[3];
155 if (!ovector) {
156 offsetVectorSize = 3;
157 offsetVector = fixedSizeOffsetVector;
158 } else {
159 offsetVectorSize = (m_numSubpatterns + 1) * 3;
160 offsetVector = new int [offsetVectorSize];
161 ovector->set(offsetVector);
162 }
163
164 int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), startOffset, offsetVector, offsetVectorSize);
165
166 if (numMatches < 0) {
167 #ifndef NDEBUG
168 if (numMatches != JSRegExpErrorNoMatch)
169 fprintf(stderr, "jsRegExpExecute failed with result %d\n", numMatches);
170 #endif
171 if (ovector)
172 ovector->clear();
173 return -1;
174 }
175
176 return offsetVector[0];
177 }
178
179 return -1;
180 }
181
182 } // namespace JSC