2
\$\begingroup\$

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.

\$\endgroup\$
0

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.