I've created 2 helpers for std::regex
.
The first helper match
fills the given std::vector<std::pair<std::string, std::size_t>>
with the first match with all subgroup matches and their positions. match_all
builds on match
and sets the given std::vector<std::vector<std::pair<std::string, std::size_t>>>
to all the matches in the text.
I would like to maybe in the future use CTRE instead of std::regex
but for now this is what I have:
using match_result = std::vector<std::pair<std::string, std::size_t>>;
using match_all_result = std::vector<match_result>;
std::size_t match(const std::regex& regex, const std::string& input, match_result* result) {
std::size_t total{ 0 };
std::smatch m;
if (std::regex_search(input, m, regex)) {
total = m.size();
if (result != nullptr) {
std::size_t startPos{};
std::string original{};
for (size_t i = 0; i < m.size(); i++) {
const std::string dataMatch{ m[i] };
std::size_t pos{};
if (i == 0) { //full match
startPos = pos = m.position();
original = dataMatch;
}
else {
pos = startPos;
if (dataMatch != original)
pos += original.find(dataMatch);
}
result->emplace_back(dataMatch, pos);
}
}
}
return total;
}
std::size_t match_all(const std::regex& regex, std::string input, match_all_result* result) {
match_result m{};
std::size_t positionFix{};
auto first{ true };
std::size_t total{};
while (const auto t = match(regex, input, &m)) {
total += t;
const auto sumLP = m[0].first.size() + m[0].second;
if (first) {
positionFix = sumLP;
first = false;
}
else {
if (result) {
for (auto& [m1, p1] : m) {
p1 += positionFix;
}
}
positionFix += sumLP;
}
//input = input.c_str() + (sumLP);
input = input.substr(sumLP);
if (result) {
result->push_back(m);
m.clear();
}
}
return total;
}
You can see the code running here: https://gcc.godbolt.org/z/wHRZET
NOTE: fixed the description as what I had described what my code did previously. It now does not return a vector but expects a pointer to a vector to be passed.