<commit_before>#ifndef regex_hh_INCLUDED
#define regex_hh_INCLUDED

#include "string.hh"
#include "exception.hh"
#include "utf8_iterator.hh"

#include <boost/regex.hpp>

namespace Kakoune
{

struct regex_error : runtime_error
{
    regex_error(StringView desc)
        : runtime_error{format("regex error: '{}'", desc)}
    {}
};

using RegexBase = boost::basic_regex<wchar_t, boost::c_regex_traits<wchar_t>>;

// Regex that keeps track of its string representation
class Regex : public RegexBase
{
public:
    Regex() = default;

    explicit Regex(StringView re, flag_type flags = ECMAScript);
    bool empty() const { return m_str.empty(); }
    bool operator==(const Regex& other) const { return m_str == other.m_str; }
    bool operator!=(const Regex& other) const { return m_str != other.m_str; }

    const String& str() const { return m_str; }

    static constexpr const char* option_type_name = "regex";

private:
    String m_str;
};

template<typename It>
using RegexUtf8It = utf8::iterator<It, wchar_t, ssize_t>;

template<typename It>
using RegexIteratorBase = boost::regex_iterator<RegexUtf8It<It>, wchar_t,
                                                boost::c_regex_traits<wchar_t>>;

namespace RegexConstant = boost::regex_constants;

template<typename Iterator>
struct MatchResults : boost::match_results<RegexUtf8It<Iterator>>
{
    using ParentType = boost::match_results<RegexUtf8It<Iterator>>;
    struct SubMatch : std::pair<Iterator, Iterator>
    {
        SubMatch() = default;
        SubMatch(const boost::sub_match<RegexUtf8It<Iterator>>& m)
            : std::pair<Iterator, Iterator>{m.first.base(), m.second.base()},
              matched{m.matched}
        {}

        bool matched = false;
    };

    struct iterator : boost::match_results<RegexUtf8It<Iterator>>::iterator
    {
        using ParentType = typename boost::match_results<RegexUtf8It<Iterator>>::iterator;
        iterator(const ParentType& it) : ParentType(it) {}

        SubMatch operator*() const { return {ParentType::operator*()}; }
    };

    iterator begin() const { return {ParentType::begin()}; }
    iterator cbegin() const { return {ParentType::cbegin()}; }
    iterator end() const { return {ParentType::end()}; }
    iterator cend() const { return {ParentType::cend()}; }

    SubMatch operator[](size_t s) const { return {ParentType::operator[](s)}; }
};

template<typename Iterator>
struct RegexIterator : RegexIteratorBase<Iterator>
{
    using Utf8It = RegexUtf8It<Iterator>;
    using ValueType = MatchResults<Iterator>;

    RegexIterator() = default;
    RegexIterator(Iterator begin, Iterator end, const Regex& re,
                  RegexConstant::match_flag_type flags = RegexConstant::match_default)
        : RegexIteratorBase<Iterator>{Utf8It{begin, begin, end}, Utf8It{end, begin, end}, re, flags} {}

    const ValueType& operator*() const { return *reinterpret_cast<const ValueType*>(&RegexIteratorBase<Iterator>::operator*()); }
    const ValueType* operator->() const { return reinterpret_cast<const ValueType*>(RegexIteratorBase<Iterator>::operator->()); }
};

inline RegexConstant::match_flag_type match_flags(bool bol, bool eol, bool bow, bool eow)
{
    return (bol ? RegexConstant::match_default : RegexConstant::match_not_bol) |
           (eol ? RegexConstant::match_default : RegexConstant::match_not_eol) |
           (bow ? RegexConstant::match_default : RegexConstant::match_not_bow) |
           (eow ? RegexConstant::match_default : RegexConstant::match_not_eow);
}

template<typename It>
bool regex_match(It begin, It end, const Regex& re)
{
    using Utf8It = RegexUtf8It<It>;
    try
    {
        return boost::regex_match(Utf8It{begin, begin, end}, Utf8It{end, begin, end}, re);
    }
    catch (std::runtime_error& err)
    {
        throw runtime_error{format("Regex matching error: {}", err.what())};
    }
}

template<typename It>
bool regex_match(It begin, It end, MatchResults<It>& res, const Regex& re)
{
    using Utf8It = RegexUtf8It<It>;
    try
    {
        return boost::regex_match(Utf8It{begin, begin, end}, Utf8It{end, begin, end}, res, re);
    }
    catch (std::runtime_error& err)
    {
        throw runtime_error{format("Regex matching error: {}", err.what())};
    }
}

template<typename It>
bool regex_search(It begin, It end, const Regex& re,
                  RegexConstant::match_flag_type flags = RegexConstant::match_default)
{
    using Utf8It = RegexUtf8It<It>;
    try
    {
        return boost::regex_search(Utf8It{begin, begin, end}, Utf8It{end, begin, end}, re, flags);
    }
    catch (std::runtime_error& err)
    {
        throw runtime_error{format("Regex searching error: {}", err.what())};
    }
}

template<typename It>
bool regex_search(It begin, It end, MatchResults<It>& res, const Regex& re,
                  RegexConstant::match_flag_type flags = RegexConstant::match_default)
{
    using Utf8It = RegexUtf8It<It>;
    try
    {
        return boost::regex_search(Utf8It{begin, begin, end}, Utf8It{end, begin, end}, res, re, flags);
    }
    catch (std::runtime_error& err)
    {
        throw runtime_error{format("Regex searching error: {}", err.what())};
    }
}

String option_to_string(const Regex& re);
void option_from_string(StringView str, Regex& re);

}

#endif // regex_hh_INCLUDED
<commit_msg>Style tweak for regex code<commit_after>#ifndef regex_hh_INCLUDED
#define regex_hh_INCLUDED

#include "string.hh"
#include "exception.hh"
#include "utf8_iterator.hh"

#include <boost/regex.hpp>

namespace Kakoune
{

struct regex_error : runtime_error
{
    regex_error(StringView desc)
        : runtime_error{format("regex error: '{}'", desc)}
    {}
};

using RegexBase = boost::basic_regex<wchar_t, boost::c_regex_traits<wchar_t>>;

// Regex that keeps track of its string representation
class Regex : public RegexBase
{
public:
    Regex() = default;

    explicit Regex(StringView re, flag_type flags = ECMAScript);
    bool empty() const { return m_str.empty(); }
    bool operator==(const Regex& other) const { return m_str == other.m_str; }
    bool operator!=(const Regex& other) const { return m_str != other.m_str; }

    const String& str() const { return m_str; }

    static constexpr const char* option_type_name = "regex";

private:
    String m_str;
};

template<typename It>
using RegexUtf8It = utf8::iterator<It, wchar_t, ssize_t>;

template<typename It>
using RegexIteratorBase = boost::regex_iterator<RegexUtf8It<It>, wchar_t,
                                                boost::c_regex_traits<wchar_t>>;

namespace RegexConstant = boost::regex_constants;

template<typename Iterator>
struct MatchResults : boost::match_results<RegexUtf8It<Iterator>>
{
    using ParentType = boost::match_results<RegexUtf8It<Iterator>>;
    struct SubMatch : std::pair<Iterator, Iterator>
    {
        SubMatch() = default;
        SubMatch(const boost::sub_match<RegexUtf8It<Iterator>>& m)
            : std::pair<Iterator, Iterator>{m.first.base(), m.second.base()},
              matched{m.matched}
        {}

        bool matched = false;
    };

    struct iterator : boost::match_results<RegexUtf8It<Iterator>>::iterator
    {
        using ParentType = typename boost::match_results<RegexUtf8It<Iterator>>::iterator;
        iterator(const ParentType& it) : ParentType(it) {}

        SubMatch operator*() const { return {ParentType::operator*()}; }
    };

    iterator begin() const { return {ParentType::begin()}; }
    iterator cbegin() const { return {ParentType::cbegin()}; }
    iterator end() const { return {ParentType::end()}; }
    iterator cend() const { return {ParentType::cend()}; }

    SubMatch operator[](size_t s) const { return {ParentType::operator[](s)}; }
};

template<typename Iterator>
struct RegexIterator : RegexIteratorBase<Iterator>
{
    using Utf8It = RegexUtf8It<Iterator>;
    using ValueType = MatchResults<Iterator>;

    RegexIterator() = default;
    RegexIterator(Iterator begin, Iterator end, const Regex& re,
                  RegexConstant::match_flag_type flags = RegexConstant::match_default)
        : RegexIteratorBase<Iterator>{Utf8It{begin, begin, end}, Utf8It{end, begin, end}, re, flags} {}

    const ValueType& operator*() const { return *reinterpret_cast<const ValueType*>(&RegexIteratorBase<Iterator>::operator*()); }
    const ValueType* operator->() const { return reinterpret_cast<const ValueType*>(RegexIteratorBase<Iterator>::operator->()); }
};

inline RegexConstant::match_flag_type match_flags(bool bol, bool eol, bool bow, bool eow)
{
    return (bol ? RegexConstant::match_default : RegexConstant::match_not_bol) |
           (eol ? RegexConstant::match_default : RegexConstant::match_not_eol) |
           (bow ? RegexConstant::match_default : RegexConstant::match_not_bow) |
           (eow ? RegexConstant::match_default : RegexConstant::match_not_eow);
}

template<typename It>
bool regex_match(It begin, It end, const Regex& re)
{
    try
    {
        return boost::regex_match<RegexUtf8It<It>>({begin, begin, end}, {end, begin, end}, re);
    }
    catch (std::runtime_error& err)
    {
        throw runtime_error{format("Regex matching error: {}", err.what())};
    }
}

template<typename It>
bool regex_match(It begin, It end, MatchResults<It>& res, const Regex& re)
{
    try
    {
        return boost::regex_match<RegexUtf8It<It>>({begin, begin, end}, {end, begin, end}, res, re);
    }
    catch (std::runtime_error& err)
    {
        throw runtime_error{format("Regex matching error: {}", err.what())};
    }
}

template<typename It>
bool regex_search(It begin, It end, const Regex& re,
                  RegexConstant::match_flag_type flags = RegexConstant::match_default)
{
    try
    {
        return boost::regex_search<RegexUtf8It<It>>({begin, begin, end}, {end, begin, end}, re, flags);
    }
    catch (std::runtime_error& err)
    {
        throw runtime_error{format("Regex searching error: {}", err.what())};
    }
}

template<typename It>
bool regex_search(It begin, It end, MatchResults<It>& res, const Regex& re,
                  RegexConstant::match_flag_type flags = RegexConstant::match_default)
{
    try
    {
        return boost::regex_search<RegexUtf8It<It>>({begin, begin, end}, {end, begin, end}, res, re, flags);
    }
    catch (std::runtime_error& err)
    {
        throw runtime_error{format("Regex searching error: {}", err.what())};
    }
}

String option_to_string(const Regex& re);
void option_from_string(StringView str, Regex& re);

}

#endif // regex_hh_INCLUDED

{'fraction_non_alphanumeric': 0.13139103113396172, 'fraction_numerical': 0.004379701037798724, 'mean_word_length': 3.943058823529412, 'pattern_counts': {'":': 0, '<': 89, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5951983', 'n_tokens_mistral': 3344, 'n_tokens_neox': 3318, 'n_words': 750}