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

Last change on this file since 27571 was 27571, checked in by [email protected], 18 years ago

JavaScriptCore:

Reviewed by Darin Adler.


Fixed part of http://bugs.webkit.org/show_bug.cgi?id=15861
15% of string-validate-input.js is spent compiling the same regular expression.

Put RegExpImp properties into a static hashtable to avoid a slew of
PropertyMap churn when creating a RegExpImp.


Factored important bits of regular expression implementation out of
RegExpImp (the JS object) and into RegExp (the PCRE wrapper class),
making RegExp a ref-counted class. (This will help later.)

Removed PCRE_POSIX support because I didn't quite know how to test it
and keep it working with these changes.


1.1% SunSpider speedup. 5.8% speedup on string-validate-input.js.

  • kjs/regexp.h: A few interface changes:
  1. Renamed "subpatterns()" => "numSubpatterns()"
  2. Made flag enumeration private and replaced it with public getters for specific flags.
  3. Made RegExp ref-counted so RegExps can be shared by RegExpImps.
  4. Made RegExp take a string of flags instead of an int, eliminating duplicated flag parsing code elsewhere.
  • kjs/regexp_object.cpp: (KJS::RegExpProtoFunc::callAsFunction): For RegExp.compile:
  • Fixed a bug where compile(undefined) would throw an exception.
  • Removed some now-redundant code.
  • Used RegExp sharing to eliminate an allocation and a bunch of PropertyMap thrash. (Not a big win since compile is a deprecated function. I mainly did this to test the plubming.)

LayoutTests:

Reviewed by Darin Adler.


Beefed up the RegExp.compile testcase to cover a mistake in the
original check-in and a mistake I made while developing my new patch.

  • fast/js/resources/regexp-compile.js:
  • Property svn:eol-style set to native
File size: 3.5 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2001,2004 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 "lexer.h"
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <wtf/Assertions.h>
30
31namespace KJS {
32
33RegExp::RegExp(const UString& pattern)
34 : m_refCount(0)
35 , m_pattern(pattern)
36 , m_flags(0)
37 , m_constructionError(0)
38 , m_numSubpatterns(0)
39{
40 const char* errorMessage;
41 m_regExp = jsRegExpCompile(reinterpret_cast<const JSRegExpChar*>(m_pattern.data()), m_pattern.size(), 0, &m_numSubpatterns, &errorMessage);
42 if (!m_regExp)
43 m_constructionError = strdup(errorMessage);
44}
45
46RegExp::RegExp(const UString& pattern, const UString& flags)
47 : m_refCount(0)
48 , m_pattern(pattern)
49 , m_flags(0)
50 , m_constructionError(0)
51 , m_numSubpatterns(0)
52{
53 // NOTE: The global flag is handled on a case-by-case basis by functions like
54 // String::match and RegExpImp::match.
55 if (flags.find('g') != -1)
56 m_flags |= Global;
57
58 // FIXME: Eliminate duplication by adding a way ask a JSRegExp what its flags are.
59 int options = 0;
60 if (flags.find('i') != -1) {
61 m_flags |= IgnoreCase;
62 options |= JS_REGEXP_CASELESS;
63 }
64
65 if (flags.find('m') != -1) {
66 m_flags |= Multiline;
67 options |= JS_REGEXP_MULTILINE;
68 }
69
70 const char* errorMessage;
71 m_regExp = jsRegExpCompile(reinterpret_cast<const JSRegExpChar*>(m_pattern.data()), m_pattern.size(), options, &m_numSubpatterns, &errorMessage);
72 if (!m_regExp)
73 m_constructionError = strdup(errorMessage);
74}
75
76RegExp::~RegExp()
77{
78 jsRegExpFree(m_regExp);
79 free(m_constructionError);
80}
81
82int RegExp::match(const UString& s, int i, OwnArrayPtr<int>* ovector)
83{
84 if (i < 0)
85 i = 0;
86 if (ovector)
87 ovector->clear();
88
89 if (i > s.size() || s.isNull())
90 return -1;
91
92 if (!m_regExp)
93 return -1;
94
95 // Set up the offset vector for the result.
96 // First 2/3 used for result, the last third used by PCRE.
97 int* offsetVector;
98 int offsetVectorSize;
99 int fixedSizeOffsetVector[3];
100 if (!ovector) {
101 offsetVectorSize = 3;
102 offsetVector = fixedSizeOffsetVector;
103 } else {
104 offsetVectorSize = (m_numSubpatterns + 1) * 3;
105 offsetVector = new int [offsetVectorSize];
106 ovector->set(offsetVector);
107 }
108
109 int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const JSRegExpChar*>(s.data()), s.size(), i, offsetVector, offsetVectorSize);
110
111 if (numMatches < 0) {
112#ifndef NDEBUG
113 if (numMatches != JS_REGEXP_ERROR_NOMATCH)
114 fprintf(stderr, "KJS: pcre_exec() failed with result %d\n", numMatches);
115#endif
116 if (ovector)
117 ovector->clear();
118 return -1;
119 }
120
121 return offsetVector[0];
122}
123
124} // namespace KJS
Note: See TracBrowser for help on using the repository browser.