1
#ifndef CHILON_ITERATOR_RANGE_HPP
2
#define CHILON_ITERATOR_RANGE_HPP
3
4
#include <chilon/meta/return.hpp>
5
6
// allow boost to hash these ranges
7
#include <boost/functional/hash/hash.hpp>
8
9
#include <iostream>
10
#include <iterator>
11
#include <string>
12
13
namespace chilon {
14
15
template <class T>
16
static inline auto begin(T&& t) CHILON_RETURN(std::forward<T>(t).begin())
17
18
template <class T>
19
static inline auto end(T&& t) CHILON_RETURN(std::forward<T>(t).end())
20
21
static inline char const * const begin(char const *str) {
22
    return str;
23
}
24
25
static inline char const * end(char const *str) {
26
    while ('\0' != *str) ++str;
27
    return str;
28
}
29
30
static inline char * end(char *str) {
31
    while ('\0' != *str) ++str;
32
    return str;
33
}
34
35
/**
36
 * @brief This class represents an iterator_range much like boost::iterator_range.
37
 * @detailed This iterator_range provides all of the functionality of boost::iterator_range
38
 *           but in addition allows easier modification of the range through
39
 *           references for begin/end in addition to .assign
40
 * @tparam   Iterator type for iterators to begin/end of range.
41
 */
42
template <class Iterator>
43
struct iterator_range {
44
    typedef typename std::iterator_traits<Iterator>::value_type          value_type;
45
    typedef typename std::iterator_traits<Iterator>::reference           reference;
46
    typedef typename std::iterator_traits<Iterator>::difference_type     difference_type;
47
    typedef typename std::iterator_traits<Iterator>::pointer             pointer;
48
    typedef typename std::iterator_traits<Iterator>::iterator_category   iterator_category;
49
    typedef Iterator    iterator;
50
    typedef Iterator    const_iterator;
51
52
    void assign(iterator const& begin, iterator const& end) {
53
        begin_ = begin;
54
        end_ = end;
55
    }
56
57
    std::size_t size()  const { return end_ - begin_; }
58
    bool        empty() const { return begin_ >= end_; }
59
    void        advance()               { ++begin_; }
60
    void        advance(int const size) { begin_ += size; }
61
    bool        same(char const * const ptr) const { return begin_ = ptr; }
62
    bool        end(iterator const candidate) const { return candidate == end_; }
63
64
    iterator    begin() const { return begin_; }
65
    iterator    end()   const { return end_; }
66
    iterator&   begin()       { return begin_; }
67
    iterator&   end()         { return end_; }
68
    reference   front() const { return *begin_; }
69
    reference   back()  const { return *(end_ - 1); }
70
71
    template <class T>
72
    friend std::ostream& operator<<(std::ostream &os, iterator_range<T> const& self);
73
74
    template <class T>
75
    bool operator==(T const& rhs) const {
76
        return size() == rhs.size() && std::equal(begin_, end_, rhs.begin());
77
    }
78
79
    bool operator==(char const * const str) const {
80
        return std::equal(begin_, end_, str) && str[end_ - begin_] == '\0';
81
    }
82
83
    bool operator==(std::string const &str) const {
84
        return size() == str.size() && std::equal(begin_, end_, str.begin());
85
    }
86
87
    template <class T>
88
    bool operator<(T const& rhs) const {
89
        auto it = begin();
90
        auto rhs_it = chilon::begin(rhs);
91
        auto rhs_end = chilon::end(rhs);
92
93
        for (;;) {
94
            if (*it < *rhs_it) return true;
95
            else if (*it != *rhs_it) return false;
96
            else if (++rhs_it == rhs_end) return false;
97
            else if (++it == end()) return true;
98
        }
99
    }
100
101
    template <class T>
102
    bool operator!=(T const& rhs) const {
103
        return ! (*this == rhs);
104
    }
105
106
    template <class T>
107
    void operator=(T const& rhs) {
108
        begin_ = rhs.begin();
109
        end_ = rhs.end();
110
    }
111
112
    reference operator[](difference_type const idx) const {
113
        return begin_[idx];
114
    }
115
116
    // iterator_range can be converted into a string
117
    operator std::string() const {
118
        return std::string(begin_, end_);
119
    }
120
121
    iterator_range(iterator const& begin, iterator const& end) : begin_(begin), end_(end) {}
122
    iterator_range(iterator const& end) : begin_(end), end_(end) {}
123
    iterator_range(std::string const& str) : begin_(str.begin()), end_(str.end()) {}
124
    // TODO: find default null type
125
    iterator_range() : begin_(0), end_(0) {}
126
  protected:
127
    iterator  begin_;
128
    iterator  end_;
129
};
130
131
template <class T>
132
std::ostream& operator<<(std::ostream &os, iterator_range<T> const& self) {
133
    std::copy(self.begin_, self.end_,
134
              std::ostream_iterator<typename iterator_range<T>::value_type>(os));
135
    return os;
136
}
137
138
template <class T>
139
bool operator==(std::string const &str, iterator_range<T> const& self) {
140
    return ! str.compare(0, str.size(), self.begin(), 0, self.size());
141
}
142
143
////////////////////////////////////////////////////////////////////////////////
144
typedef iterator_range<char const *>                range;
145
typedef iterator_range<std::string::const_iterator> string_range;
146
typedef iterator_range<std::string::iterator>       mutable_string_range;
147
148
static inline range to_range(char const * const str) {
149
    return range(str, end(str));
150
    return str;
151
}
152
153
template <class T>
154
std::size_t inline hash_value(chilon::iterator_range<T> const& arg) {
155
    return boost::hash_range(arg.begin(), arg.end());
156
}
157
158
}
159
160
namespace std {
161
    template <class T>
162
    struct hash<chilon::iterator_range<T>> {
163
        std::size_t operator()(chilon::iterator_range<T> const& arg) const {
164
            return chilon::hash_value(arg);
165
        }
166
    };
167
}
168
169
#endif