JavaScriptCore:
[WebKit-https.git] / JavaScriptCore / kjs / regexp.cpp
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 1999-2001,2004 Harri Porten (porten@kde.org)
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
31 namespace KJS {
32
33 RegExp::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
46 RegExp::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
76 RegExp::~RegExp()
77 {
78   jsRegExpFree(m_regExp);
79   free(m_constructionError);
80 }
81
82 int 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