2
* Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
3
* Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 3 of the License, or
8
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
* Additional permission under GNU GPL version 3 section 7:
20
* If you modify this program, or any covered work, by linking or
21
* combining it with the OpenSSL project's OpenSSL library (or a
22
* modified version of that library), containing parts covered by the
23
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
24
* grants you additional permission to convey the resulting work.
25
* Corresponding Source for a non-source form of such a combination
26
* shall include the source code for the parts of OpenSSL used as well
27
* as that of the covered work.
36
Pattern::Pattern(const std::string& pattern, const std::string& options) :
44
optionsDescription_(options)
47
offset_[0] = offset_[1] = 0;
49
for (unsigned int i = 0; i < options.length(); i++) {
50
switch (options.at(i)) {
52
options_ |= PCRE_CASELESS;
56
options_ |= PCRE_MULTILINE;
60
options_ |= PCRE_DOTALL;
64
options_ |= PCRE_EXTENDED;
69
// Compile the pattern.
81
void Pattern::compile()
83
// Compile the pattern
87
re_ = pcre_compile(pattern_.c_str(), 0, &error, &offset, NULL);
90
std::string offsetStr;
95
std::string msg("PCRE compiling failed at offset " + offsetStr);
97
throw CompileError(msg);
100
// Allocate an appropriate amount
101
// of memory for the output vector.
104
pcre_fullinfo(re_, NULL, PCRE_INFO_CAPTURECOUNT, &captureCount);
108
ovector_ = new int[(captureCount + 1) * 3];
110
ovectorSize_ = (captureCount + 1) * 3;
113
unsigned int Pattern::getCaptureGroupCount()
116
pcre_fullinfo(re_, NULL, PCRE_INFO_CAPTURECOUNT, &captureCount);
120
std::vector<std::string> Pattern::groups()
122
const char ** stringList;
124
pcre_get_substring_list(subject_.c_str(),
129
std::vector<std::string> matchedSubstrings;
131
for (int i = 1; stringList[i] != NULL; i++)
132
matchedSubstrings.push_back(stringList[i]);
134
pcre_free_substring_list(stringList);
136
return matchedSubstrings;
139
std::string Pattern::group(int groupNumber)
141
const char * stringPtr;
143
int rc = pcre_get_substring(subject_.substr(offset_[0]).c_str(), ovector_,
144
count_, groupNumber, &stringPtr);
148
case PCRE_ERROR_NOSUBSTRING:
149
throw std::out_of_range("Invalid group reference.");
151
case PCRE_ERROR_NOMEMORY:
152
throw MatchError("Memory exhausted.");
155
throw MatchError("Failed to get named substring.");
159
std::string matchedStr(stringPtr);
161
pcre_free_substring(stringPtr);
166
std::string Pattern::group(const std::string& groupName)
168
const char * stringPtr = NULL;
169
int rc = pcre_get_named_substring(re_, subject_.substr(offset_[0]).c_str(),
170
ovector_, count_, groupName.c_str(),
175
case PCRE_ERROR_NOSUBSTRING:
178
case PCRE_ERROR_NOMEMORY:
179
throw MatchError("Memory exhausted.");
182
throw MatchError("Failed to get named substring.");
186
std::string matchedStr;
189
matchedStr = stringPtr;
190
pcre_free_substring(stringPtr);
196
void Pattern::start(const std::string& groupName) const
198
int index = pcre_get_stringnumber(re_, groupName.c_str());
202
size_t Pattern::start(unsigned int groupNumber) const
204
if (groupNumber <= (unsigned int) count_)
205
return ovector_[(groupNumber + 1) * 2];
207
throw std::out_of_range("Invalid group reference.");
210
size_t Pattern::start() const
212
return ovector_[0] + offset_[0];
215
void Pattern::end(const std::string& groupName) const
217
int index = pcre_get_stringnumber(re_, groupName.c_str());
221
size_t Pattern::end(unsigned int groupNumber) const
223
if (groupNumber <= (unsigned int) count_)
224
return ovector_[((groupNumber + 1) * 2) + 1 ] - 1;
226
throw std::out_of_range("Invalid group reference.");
229
size_t Pattern::end() const
231
return (ovector_[1] - 1) + offset_[0];
234
bool Pattern::matches()
236
return matches(subject_);
239
bool Pattern::matches(const std::string& subject)
241
// Try to find a match for this pattern
242
int rc = pcre_exec(re_, NULL, subject.substr(offset_[1]).c_str(),
243
subject.length() - offset_[1], 0, options_, ovector_,
248
offset_[0] = offset_[1] = 0;
252
// Handle the case if matching should be done globally
253
if (optionsDescription_.find("g") != std::string::npos) {
254
offset_[0] = offset_[1];
255
// New offset is old offset + end of relative offset
256
offset_[1] = ovector_[1] + offset_[0];
259
// Matching succeded but not enough space.
260
// @TODO figure out something more clever to do in this case.
262
throw MatchError("No space to store all substrings.");
264
// Matching succeeded. Keep the number of substrings for
265
// subsequent calls to group().
271
std::vector<std::string> Pattern::split()
273
size_t tokenEnd = -1;
274
size_t tokenStart = 0;
276
std::vector<std::string> substringSplitted;
279
tokenStart = start();
280
substringSplitted.push_back(subject_.substr(tokenEnd + 1,
281
tokenStart - tokenEnd - 1));
285
substringSplitted.push_back(subject_.substr(tokenEnd + 1,
286
tokenStart - tokenEnd - 1));
287
return substringSplitted;