-
Notifications
You must be signed in to change notification settings - Fork 715
/
utf8_iterator.hh
136 lines (109 loc) · 3.29 KB
/
utf8_iterator.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#ifndef utf8_iterator_hh_INCLUDED
#define utf8_iterator_hh_INCLUDED
#include "utf8.hh"
#include <iterator>
namespace Kakoune
{
namespace utf8
{
// adapter for an iterator on bytes which permits to iterate
// on unicode codepoints instead.
template<typename BaseIt,
typename Sentinel = BaseIt,
typename CodepointType = Codepoint,
typename DifferenceType = CharCount,
typename InvalidPolicy = utf8::InvalidPolicy::Pass>
class iterator
{
public:
using value_type = CodepointType;
using difference_type = DifferenceType;
using pointer = CodepointType*;
using reference = CodepointType&;
using iterator_category = std::bidirectional_iterator_tag;
iterator() = default;
constexpr static bool noexcept_policy = noexcept(InvalidPolicy{}(0));
iterator(BaseIt it, Sentinel begin, Sentinel end) noexcept
: m_it{std::move(it)}, m_begin{std::move(begin)}, m_end{std::move(end)}
{}
template<typename Container>
iterator(BaseIt it, const Container& c) noexcept
: m_it{std::move(it)}, m_begin{std::begin(c)}, m_end{std::end(c)}
{}
iterator& operator++() noexcept
{
utf8::to_next(m_it, m_end);
return *this;
}
iterator operator++(int) noexcept
{
iterator save = *this;
++*this;
return save;
}
iterator& operator--() noexcept
{
utf8::to_previous(m_it, m_begin);
return *this;
}
iterator operator--(int) noexcept
{
iterator save = *this;
--*this;
return save;
}
iterator operator+(DifferenceType count) const noexcept
{
iterator res = *this;
res += count;
return res;
}
iterator& operator+=(DifferenceType count) noexcept
{
if (count < 0)
return operator-=(-count);
while (count--)
operator++();
return *this;
}
iterator operator-(DifferenceType count) const noexcept
{
iterator res = *this;
res -= count;
return res;
}
iterator& operator-=(DifferenceType count) noexcept
{
if (count < 0)
return operator+=(-count);
while (count--)
operator--();
return *this;
}
bool operator==(const iterator& other) const noexcept { return m_it == other.m_it; }
auto operator<=>(const iterator& other) const noexcept { return m_it <=> other.m_it; }
template<typename T>
requires std::is_same_v<T, BaseIt> or std::is_same_v<T, Sentinel>
bool operator==(const T& other) const noexcept { return m_it == other; }
auto operator<=>(const BaseIt& other) const noexcept { return m_it <=> other; }
DifferenceType operator-(const iterator& other) const noexcept(noexcept_policy)
{
return (DifferenceType)utf8::distance<InvalidPolicy>(other.m_it, m_it);
}
CodepointType operator*() const noexcept(noexcept_policy)
{
return (CodepointType)utf8::codepoint<InvalidPolicy>(m_it, m_end);
}
CodepointType read() noexcept(noexcept_policy)
{
return (CodepointType)utf8::read_codepoint<InvalidPolicy>(m_it, m_end);
}
const BaseIt& base() const noexcept { return m_it; }
private:
BaseIt m_it;
Sentinel m_begin;
Sentinel m_end;
};
}
}
#endif // utf8_iterator_hh_INCLUDED