2
* Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
2
* Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
3
3
* Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>
5
5
* This program is free software; you can redistribute it and/or modify
36
Pattern::Pattern(const std::string& pattern, const std::string& options) :
36
Pattern::Pattern(const std::string& pattern, bool matchGlobally) :
43
optionsDescription_(options)
46
offset_[0] = offset_[1] = 0;
48
for (unsigned int i = 0; i < options.length(); i++) {
49
switch (options.at(i)) {
51
options_ |= PCRE_CASELESS;
55
options_ |= PCRE_MULTILINE;
59
options_ |= PCRE_DOTALL;
63
options_ |= PCRE_EXTENDED;
68
// Compile the pattern.
78
void Pattern::compile()
43
matchGlobally_(matchGlobally)
80
45
// Compile the pattern
103
68
ovector_.resize((captureCount + 1) * 3);
106
unsigned int Pattern::getCaptureGroupCount()
108
int captureCount = 0;
109
pcre_fullinfo(re_, NULL, PCRE_INFO_CAPTURECOUNT, &captureCount);
113
std::vector<std::string> Pattern::groups()
115
const char ** stringList;
117
pcre_get_substring_list(subject_.c_str(), &ovector_[0], count_, &stringList);
118
std::vector<std::string> matchedSubstrings;
119
for (int i = 1; stringList[i] != NULL; i++)
120
matchedSubstrings.push_back(stringList[i]);
122
pcre_free_substring_list(stringList);
124
return matchedSubstrings;
127
std::string Pattern::group(int groupNumber)
129
const char * stringPtr;
130
int rc = pcre_get_substring(subject_.substr(offset_[0]).c_str(), &ovector_[0],
131
count_, groupNumber, &stringPtr);
135
case PCRE_ERROR_NOSUBSTRING:
136
throw std::out_of_range("Invalid group reference.");
138
case PCRE_ERROR_NOMEMORY:
139
throw MatchError("Memory exhausted.");
142
throw MatchError("Failed to get named substring.");
145
std::string matchedStr(stringPtr);
147
pcre_free_substring(stringPtr);
152
std::string Pattern::group(const std::string& groupName)
78
std::string Pattern::group(const char *groupName)
154
80
const char * stringPtr = NULL;
155
81
int rc = pcre_get_named_substring(re_, subject_.substr(offset_[0]).c_str(),
156
&ovector_[0], count_, groupName.c_str(),
82
&ovector_[0], count_, groupName,
176
102
return matchedStr;
179
void Pattern::start(const std::string& groupName) const
181
int index = pcre_get_stringnumber(re_, groupName.c_str());
185
size_t Pattern::start(unsigned int groupNumber) const
187
if (groupNumber <= (unsigned int) count_)
188
return ovector_[(groupNumber + 1) * 2];
190
throw std::out_of_range("Invalid group reference.");
194
105
size_t Pattern::start() const
196
107
return ovector_[0] + offset_[0];
199
void Pattern::end(const std::string& groupName) const
201
int index = pcre_get_stringnumber(re_, groupName.c_str());
205
size_t Pattern::end(unsigned int groupNumber) const
207
if (groupNumber <= (unsigned int) count_)
208
return ovector_[((groupNumber + 1) * 2) + 1 ] - 1;
210
throw std::out_of_range("Invalid group reference.");
214
110
size_t Pattern::end() const
216
112
return (ovector_[1] - 1) + offset_[0];
219
115
bool Pattern::matches()
221
return matches(subject_);
225
bool Pattern::matches(const std::string& subject)
227
117
// Try to find a match for this pattern
228
int rc = pcre_exec(re_, NULL, subject.substr(offset_[1]).c_str(),
229
subject.length() - offset_[1], 0, options_, &ovector_[0],
118
int rc = pcre_exec(re_, NULL, subject_.substr(offset_[1]).c_str(),
119
subject_.length() - offset_[1], 0, 0, &ovector_[0],
230
120
ovector_.size());
232
122
// Matching failed.
238
128
// Handle the case if matching should be done globally
239
if (optionsDescription_.find("g") != std::string::npos) {
129
if (matchGlobally_) {
240
130
offset_[0] = offset_[1];
241
131
// New offset is old offset + end of relative offset
242
132
offset_[1] = ovector_[1] + offset_[0];