source: webkit/trunk/JavaScriptCore/kjs/regexp.cpp@ 12512

Last change on this file since 12512 was 12317, checked in by mjs, 19 years ago

Reviewed by Tim Hatcher.


  • it's "Franklin Street", not "Franklin Steet"
  • kjs/array_instance.h:
  • kjs/array_object.cpp:
  • kjs/array_object.h:
  • kjs/bool_object.cpp:
  • kjs/bool_object.h:
  • kjs/collector.cpp:
  • kjs/collector.h:
  • kjs/completion.h:
  • kjs/context.h:
  • kjs/date_object.cpp:
  • kjs/date_object.h:
  • kjs/debugger.cpp:
  • kjs/debugger.h:
  • kjs/dtoa.h:
  • kjs/error_object.cpp:
  • kjs/error_object.h:
  • kjs/function.cpp:
  • kjs/function.h:
  • kjs/function_object.cpp:
  • kjs/function_object.h:
  • kjs/grammar.y:
  • kjs/identifier.cpp:
  • kjs/identifier.h:
  • kjs/internal.cpp:
  • kjs/internal.h:
  • kjs/interpreter.cpp:
  • kjs/interpreter.h:
  • kjs/lexer.cpp:
  • kjs/lexer.h:
  • kjs/list.cpp:
  • kjs/list.h:
  • kjs/lookup.cpp:
  • kjs/lookup.h:
  • kjs/math_object.cpp:
  • kjs/math_object.h:
  • kjs/nodes.cpp:
  • kjs/nodes.h:
  • kjs/nodes2string.cpp:
  • kjs/number_object.cpp:
  • kjs/number_object.h:
  • kjs/object.cpp:
  • kjs/object.h:
  • kjs/object_object.cpp:
  • kjs/object_object.h:
  • kjs/operations.cpp:
  • kjs/operations.h:
  • kjs/property_map.cpp:
  • kjs/property_map.h:
  • kjs/property_slot.cpp:
  • kjs/property_slot.h:
  • kjs/reference.cpp:
  • kjs/reference.h:
  • kjs/reference_list.cpp:
  • kjs/reference_list.h:
  • kjs/regexp.cpp:
  • kjs/regexp.h:
  • kjs/regexp_object.cpp:
  • kjs/regexp_object.h:
  • kjs/scope_chain.cpp:
  • kjs/scope_chain.h:
  • kjs/simple_number.h:
  • kjs/string_object.cpp:
  • kjs/string_object.h:
  • kjs/testkjs.cpp:
  • kjs/types.h:
  • kjs/ustring.cpp:
  • kjs/ustring.h:
  • kjs/value.cpp:
  • kjs/value.h:
  • kxmlcore/AlwaysInline.h:
  • kxmlcore/ListRefPtr.h:
  • kxmlcore/PassRefPtr.h:
  • kxmlcore/RefPtr.h:
  • Property svn:eol-style set to native
File size: 4.7 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2001 Harri Porten ([email protected])
5 *
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.
10 *
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.
15 *
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
19 *
20 */
21
22#include "config.h"
23#include "regexp.h"
24
25#include <assert.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30namespace KJS {
31
32RegExp::RegExp(const UString &p, int flags)
33 : _flags(flags), _numSubPatterns(0)
34{
35#ifdef HAVE_PCREPOSIX
36
37 int options = PCRE_UTF8;
38 // Note: the Global flag is already handled by RegExpProtoFunc::execute.
39 // FIXME: That last comment is dubious. Not all RegExps get run through RegExpProtoFunc::execute.
40 if (flags & IgnoreCase)
41 options |= PCRE_CASELESS;
42 if (flags & Multiline)
43 options |= PCRE_MULTILINE;
44
45 const char *errorMessage;
46 int errorOffset;
47 UString nullTerminated(p);
48 char null(0);
49 nullTerminated.append(null);
50 _regex = pcre_compile(reinterpret_cast<const uint16_t *>(nullTerminated.data()), options, &errorMessage, &errorOffset, NULL);
51 if (!_regex) {
52#ifndef NDEBUG
53 fprintf(stderr, "KJS: pcre_compile() failed with '%s'\n", errorMessage);
54#endif
55 return;
56 }
57
58#ifdef PCRE_INFO_CAPTURECOUNT
59 // Get number of subpatterns that will be returned.
60 pcre_fullinfo(_regex, NULL, PCRE_INFO_CAPTURECOUNT, &_numSubPatterns);
61#endif
62
63#else /* HAVE_PCREPOSIX */
64
65 int regflags = 0;
66#ifdef REG_EXTENDED
67 regflags |= REG_EXTENDED;
68#endif
69#ifdef REG_ICASE
70 if ( f & IgnoreCase )
71 regflags |= REG_ICASE;
72#endif
73
74 //NOTE: Multiline is not feasible with POSIX regex.
75 //if ( f & Multiline )
76 // ;
77 // Note: the Global flag is already handled by RegExpProtoFunc::execute
78
79 regcomp(&_regex, p.ascii(), regflags);
80 /* TODO check for errors */
81
82#endif
83}
84
85RegExp::~RegExp()
86{
87#ifdef HAVE_PCREPOSIX
88 pcre_free(_regex);
89#else
90 /* TODO: is this really okay after an error ? */
91 regfree(&_regex);
92#endif
93}
94
95UString RegExp::match(const UString &s, int i, int *pos, int **ovector)
96{
97 if (i < 0)
98 i = 0;
99 int dummyPos;
100 if (!pos)
101 pos = &dummyPos;
102 *pos = -1;
103 if (ovector)
104 *ovector = 0;
105
106 if (i > s.size() || s.isNull())
107 return UString::null();
108
109#ifdef HAVE_PCREPOSIX
110
111 if (!_regex)
112 return UString::null();
113
114 // Set up the offset vector for the result.
115 // First 2/3 used for result, the last third used by PCRE.
116 int *offsetVector;
117 int offsetVectorSize;
118 int fixedSizeOffsetVector[3];
119 if (!ovector) {
120 offsetVectorSize = 3;
121 offsetVector = fixedSizeOffsetVector;
122 } else {
123 offsetVectorSize = (_numSubPatterns + 1) * 3;
124 offsetVector = new int [offsetVectorSize];
125 }
126
127 const int numMatches = pcre_exec(_regex, NULL, reinterpret_cast<const uint16_t *>(s.data()), s.size(), i, 0, offsetVector, offsetVectorSize);
128
129 if (numMatches < 0) {
130#ifndef NDEBUG
131 if (numMatches != PCRE_ERROR_NOMATCH)
132 fprintf(stderr, "KJS: pcre_exec() failed with result %d\n", numMatches);
133#endif
134 if (offsetVector != fixedSizeOffsetVector)
135 delete [] offsetVector;
136 return UString::null();
137 }
138
139 *pos = offsetVector[0];
140 if (ovector)
141 *ovector = offsetVector;
142 return s.substr(offsetVector[0], offsetVector[1] - offsetVector[0]);
143
144#else
145
146 const unsigned maxMatch = 10;
147 regmatch_t rmatch[maxMatch];
148
149 char *str = strdup(s.ascii()); // TODO: why ???
150 if (regexec(&_regex, str + i, maxMatch, rmatch, 0)) {
151 free(str);
152 return UString::null();
153 }
154 free(str);
155
156 if (!ovector) {
157 *pos = rmatch[0].rm_so + i;
158 return s.substr(rmatch[0].rm_so + i, rmatch[0].rm_eo - rmatch[0].rm_so);
159 }
160
161 // map rmatch array to ovector used in PCRE case
162 _numSubPatterns = 0;
163 for(unsigned j = 1; j < maxMatch && rmatch[j].rm_so >= 0 ; j++)
164 _numSubPatterns++;
165 int ovecsize = (_numSubPatterns+1)*3; // see above
166 *ovector = new int[ovecsize];
167 for (unsigned j = 0; j < _numSubPatterns + 1; j++) {
168 if (j>maxMatch)
169 break;
170 (*ovector)[2*j] = rmatch[j].rm_so + i;
171 (*ovector)[2*j+1] = rmatch[j].rm_eo + i;
172 }
173
174 *pos = (*ovector)[0];
175 return s.substr((*ovector)[0], (*ovector)[1] - (*ovector)[0]);
176
177#endif
178}
179
180} // namespace KJS
Note: See TracBrowser for help on using the repository browser.