<commit_before>#ifndef ELEMEL_STRING_RANGE_HPP
#define ELEMEL_STRING_RANGE_HPP

#include <algorithm>
#include <string>

namespace elemel {
    template <class Char, class Traits = std::char_traits<Char> >
    class basic_string_range {
    public:
        typedef Char value_type;
        typedef Traits traits_type;
        typedef std::size_t size_type;
        typedef value_type const *const_pointer;
        typedef value_type const *const_iterator;

        basic_string_range() :
            first_(0),
            last_(0)
        { }

        basic_string_range(const_pointer str) :
            first_(str),
            last_(str + Traits::length(str))
        { }

        basic_string_range(const_pointer str, size_type n) :
            first_(str),
            last_(str + n)
        { }

        basic_string_range(const_pointer first, const_pointer last) :
            first_(first),
            last_(last)
        { }

        const_pointer data() const
        {
            return first_;
        }

        size_type size() const
        {
            return last_ - first_;
        }

        const_iterator begin() const
        {
            return first_;
        }

        const_iterator end() const
        {
            return last_;
        }

    private:
        const_pointer first_;
        const_pointer last_;
    };

    template <class C, class T>
    bool operator==(basic_string_range<C, T> const &left,
                    basic_string_range<C, T> const &right)
    {
        return (left.size() == right.size() &&
                std::equal(left.begin(), left.end(), right.begin(), T::eq));
    }

    template <class C, class T>
    bool operator!=(basic_string_range<C, T> const &left,
                    basic_string_range<C, T> const &right)
    {
        return !(left == right);
    }

    template <class C, class T>
    bool operator<(basic_string_range<C, T> const &left,
                   basic_string_range<C, T> const &right)
    {
        return std::lexicographical_compare(left.begin(), left.end(),
                                            right.begin(), right.end(), T::lt);<commit_msg>more member functions for string_range<commit_after>#ifndef ELEMEL_STRING_RANGE_HPP
#define ELEMEL_STRING_RANGE_HPP

#include <algorithm>
#include <stdexcept>
#include <string>

namespace elemel {
    template <class Char, class Traits = std::char_traits<Char> >
    class basic_string_range {
    public:
        typedef Char value_type;
        typedef Traits traits_type;
        typedef std::size_t size_type;
        typedef value_type const *const_pointer;
        typedef value_type const &const_reference;
        typedef value_type const *const_iterator;

        basic_string_range() :
            first_(0),
            last_(0)
        { }

        basic_string_range(const_pointer str) :
            first_(str),
            last_(str + Traits::length(str))
        { }

        basic_string_range(const_pointer str, size_type n) :
            first_(str),
            last_(str + n)
        { }

        basic_string_range(const_pointer first, const_pointer last) :
            first_(first),
            last_(last)
        { }

        const_pointer data() const
        {
            return first_;
        }

        size_type size() const
        {
            return last_ - first_;
        }

        bool empty() const
        {
            return first_ != last_;
        }

        const_iterator begin() const
        {
            return first_;
        }

        const_iterator end() const
        {
            return last_;
        }

        const_reference front() const
        {
            assert(!empty());
            return *first_;
        }

        const_reference back() const
        {
            assert(!empty());
            return *(last_ - 1);
        }

        const_reference operator[](size_type index) const
        {
            assert(index < size());
            return first_[index];
        }

        const_reference at(size_type index) const
        {
            if (index >= size()) {
                throw std::out_of_range("index out of range");
            }
            return first_[index];
        }

    private:
        const_pointer first_;
        const_pointer last_;
    };

    template <class C, class T>
    bool operator==(basic_string_range<C, T> const &left,
                    basic_string_range<C, T> const &right)
    {
        return (left.size() == right.size() &&
                std::equal(left.begin(), left.end(), right.begin(), T::eq));
    }

    template <class C, class T>
    bool operator!=(basic_string_range<C, T> const &left,
                    basic_string_range<C, T> const &right)
    {
        return !(left == right);
    }

    template <class C, class T>
    bool operator<(basic_string_range<C, T> const &left,
                   basic_string_range<C, T> const &right)
    {
        return std::lexicographical_compare(left.begin(), left.end(),
                                            right.begin(), right.end(), T::lt);
{'fraction_non_alphanumeric': 0.10041346721795628, 'fraction_numerical': 0.0009844457570387872, 'mean_word_length': 1.7136752136752136, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 31, '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': '2466804', 'n_tokens_mistral': 1438, 'n_tokens_neox': 1398, 'n_words': 332}