kakoune/src/utf8_iterator.hh

148 lines
4.0 KiB
C++
Raw Normal View History

#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 CodepointType = Codepoint,
typename DifferenceType = CharCount,
typename InvalidPolicy = utf8::InvalidPolicy::Pass>
class iterator : public std::iterator<std::bidirectional_iterator_tag,
CodepointType, DifferenceType,
CodepointType*, CodepointType>
{
public:
iterator() = default;
2017-06-07 11:58:49 +02:00
constexpr static bool noexcept_policy = noexcept(InvalidPolicy{}(0));
2017-06-07 11:58:49 +02:00
iterator(BaseIt it, BaseIt begin, BaseIt end) noexcept
: m_it{std::move(it)}, m_begin{std::move(begin)}, m_end{std::move(end)}
{}
template<typename Container>
2017-06-07 11:58:49 +02:00
iterator(BaseIt it, const Container& c) noexcept
: m_it{std::move(it)}, m_begin{std::begin(c)}, m_end{std::end(c)}
{}
2017-06-07 11:58:49 +02:00
iterator& operator++() noexcept
{
utf8::to_next(m_it, m_end);
invalidate_value();
return *this;
}
2017-06-07 11:58:49 +02:00
iterator operator++(int) noexcept
{
iterator save = *this;
++*this;
return save;
}
2017-06-07 11:58:49 +02:00
iterator& operator--() noexcept
{
utf8::to_previous(m_it, m_begin);
invalidate_value();
return *this;
}
2017-06-07 11:58:49 +02:00
iterator operator--(int) noexcept
{
iterator save = *this;
--*this;
return save;
}
2017-06-07 11:58:49 +02:00
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;
}
2017-06-07 11:58:49 +02:00
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;
}
2017-06-07 11:58:49 +02:00
bool operator==(const iterator& other) const noexcept { return m_it == other.m_it; }
bool operator!=(const iterator& other) const noexcept { return m_it != other.m_it; }
2017-06-07 11:58:49 +02:00
bool operator< (const iterator& other) const noexcept { return m_it < other.m_it; }
bool operator<= (const iterator& other) const noexcept { return m_it <= other.m_it; }
2017-06-07 11:58:49 +02:00
bool operator> (const iterator& other) const noexcept { return m_it > other.m_it; }
bool operator>= (const iterator& other) const noexcept { return m_it >= other.m_it; }
bool operator==(const BaseIt& other) const noexcept { return m_it == other; }
bool operator!=(const BaseIt& other) const noexcept { return m_it != other; }
2017-06-07 11:58:49 +02:00
bool operator< (const BaseIt& other) const noexcept { return m_it < other; }
bool operator<= (const BaseIt& other) const noexcept { return m_it <= other; }
2017-06-07 11:58:49 +02:00
bool operator> (const BaseIt& other) const noexcept { return m_it > other; }
bool operator>= (const BaseIt& other) const noexcept { return m_it >= other; }
2017-06-07 11:58:49 +02:00
DifferenceType operator-(const iterator& other) const noexcept(noexcept_policy)
{
2017-06-07 11:58:49 +02:00
return (DifferenceType)utf8::distance<InvalidPolicy>(other.m_it, m_it);
}
2017-06-07 11:58:49 +02:00
CodepointType operator*() const noexcept(noexcept_policy)
{
return get_value();
}
2017-06-07 11:58:49 +02:00
const BaseIt& base() const noexcept(noexcept_policy) { return m_it; }
private:
2017-06-07 11:58:49 +02:00
void invalidate_value() noexcept { m_value = -1; }
CodepointType get_value() const noexcept(noexcept_policy)
{
2016-05-19 21:20:42 +02:00
if (m_value == (CodepointType)-1)
m_value = (CodepointType)utf8::codepoint<InvalidPolicy>(m_it, m_end);
return m_value;
}
BaseIt m_it;
BaseIt m_begin;
BaseIt m_end;
mutable CodepointType m_value = -1;
};
}
}
#endif // utf8_iterator_hh_INCLUDED