2012-10-08 14:25:58 +02:00
|
|
|
#ifndef utf8_iterator_hh_INCLUDED
|
|
|
|
#define utf8_iterator_hh_INCLUDED
|
|
|
|
|
|
|
|
#include "utf8.hh"
|
|
|
|
|
2015-03-27 14:18:52 +01:00
|
|
|
#include <iterator>
|
|
|
|
|
2012-10-08 14:25:58 +02:00
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace utf8
|
|
|
|
{
|
|
|
|
|
|
|
|
// adapter for an iterator on bytes which permits to iterate
|
|
|
|
// on unicode codepoints instead.
|
2017-02-23 01:30:59 +01:00
|
|
|
template<typename BaseIt,
|
2018-10-31 09:41:12 +01:00
|
|
|
typename Sentinel = BaseIt,
|
2016-05-09 22:56:08 +02:00
|
|
|
typename CodepointType = Codepoint,
|
|
|
|
typename DifferenceType = CharCount,
|
2014-10-13 20:54:40 +02:00
|
|
|
typename InvalidPolicy = utf8::InvalidPolicy::Pass>
|
2016-04-22 21:43:29 +02:00
|
|
|
class iterator : public std::iterator<std::bidirectional_iterator_tag,
|
2017-10-07 09:55:57 +02:00
|
|
|
CodepointType, DifferenceType,
|
|
|
|
CodepointType*, CodepointType>
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
|
|
|
public:
|
2016-04-22 21:43:29 +02:00
|
|
|
iterator() = default;
|
2017-06-07 11:58:49 +02:00
|
|
|
constexpr static bool noexcept_policy = noexcept(InvalidPolicy{}(0));
|
2016-04-22 21:43:29 +02:00
|
|
|
|
2018-10-31 09:41:12 +01:00
|
|
|
iterator(BaseIt it, Sentinel begin, Sentinel end) noexcept
|
2015-09-23 20:39:21 +02:00
|
|
|
: 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
|
2015-10-30 14:57:46 +01:00
|
|
|
: m_it{std::move(it)}, m_begin{std::begin(c)}, m_end{std::end(c)}
|
2015-09-23 20:39:21 +02:00
|
|
|
{}
|
2012-10-08 14:25:58 +02:00
|
|
|
|
2017-06-07 11:58:49 +02:00
|
|
|
iterator& operator++() noexcept
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
2016-07-27 22:36:32 +02:00
|
|
|
utf8::to_next(m_it, m_end);
|
2012-10-08 14:25:58 +02:00
|
|
|
invalidate_value();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2017-06-07 11:58:49 +02:00
|
|
|
iterator operator++(int) noexcept
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
2014-06-24 20:10:57 +02:00
|
|
|
iterator save = *this;
|
2012-10-08 14:25:58 +02:00
|
|
|
++*this;
|
|
|
|
return save;
|
|
|
|
}
|
|
|
|
|
2017-06-07 11:58:49 +02:00
|
|
|
iterator& operator--() noexcept
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
2016-07-27 22:36:32 +02:00
|
|
|
utf8::to_previous(m_it, m_begin);
|
2012-10-08 14:25:58 +02:00
|
|
|
invalidate_value();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2017-06-07 11:58:49 +02:00
|
|
|
iterator operator--(int) noexcept
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
2014-06-24 20:10:57 +02:00
|
|
|
iterator save = *this;
|
2012-10-08 14:25:58 +02:00
|
|
|
--*this;
|
|
|
|
return save;
|
|
|
|
}
|
|
|
|
|
2017-06-07 11:58:49 +02:00
|
|
|
iterator operator+(DifferenceType count) const noexcept
|
2017-09-25 15:23:50 +02:00
|
|
|
{
|
|
|
|
iterator res = *this;
|
|
|
|
res += count;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator& operator+=(DifferenceType count) noexcept
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
|
|
|
if (count < 0)
|
2017-09-25 15:23:50 +02:00
|
|
|
return operator-=(-count);
|
2012-10-08 14:25:58 +02:00
|
|
|
|
|
|
|
while (count--)
|
2017-09-25 15:23:50 +02:00
|
|
|
operator++();
|
|
|
|
return *this;
|
2012-10-08 14:25:58 +02:00
|
|
|
}
|
|
|
|
|
2017-06-07 11:58:49 +02:00
|
|
|
iterator operator-(DifferenceType count) const noexcept
|
2017-09-25 15:23:50 +02:00
|
|
|
{
|
|
|
|
iterator res = *this;
|
|
|
|
res -= count;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
iterator& operator-=(DifferenceType count) noexcept
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
|
|
|
if (count < 0)
|
2017-09-25 15:23:50 +02:00
|
|
|
return operator+=(-count);
|
2012-10-08 14:25:58 +02:00
|
|
|
|
|
|
|
while (count--)
|
2017-09-25 15:23:50 +02:00
|
|
|
operator--();
|
|
|
|
return *this;
|
2012-10-08 14:25:58 +02:00
|
|
|
}
|
|
|
|
|
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; }
|
2012-10-08 14:25:58 +02:00
|
|
|
|
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; }
|
2012-10-08 14:25:58 +02:00
|
|
|
|
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; }
|
2012-10-08 14:25:58 +02:00
|
|
|
|
2018-10-31 09:41:12 +01:00
|
|
|
template<typename T>
|
|
|
|
std::enable_if_t<std::is_same<T, BaseIt>::value or std::is_same<T, Sentinel>::value, bool>
|
|
|
|
operator==(const T& other) const noexcept { return m_it == other; }
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
std::enable_if_t<std::is_same<T, BaseIt>::value or std::is_same<T, Sentinel>::value, bool>
|
|
|
|
operator!=(const T& other) const noexcept { return m_it != other; }
|
2012-10-08 14:25:58 +02:00
|
|
|
|
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; }
|
2015-09-23 20:39:21 +02:00
|
|
|
|
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; }
|
2012-10-08 14:25:58 +02:00
|
|
|
|
2017-06-07 11:58:49 +02:00
|
|
|
DifferenceType operator-(const iterator& other) const noexcept(noexcept_policy)
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
2017-06-07 11:58:49 +02:00
|
|
|
return (DifferenceType)utf8::distance<InvalidPolicy>(other.m_it, m_it);
|
2012-10-08 14:25:58 +02:00
|
|
|
}
|
|
|
|
|
2017-06-07 11:58:49 +02:00
|
|
|
CodepointType operator*() const noexcept(noexcept_policy)
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
|
|
|
return get_value();
|
|
|
|
}
|
|
|
|
|
2018-10-31 11:13:14 +01:00
|
|
|
CodepointType read() noexcept(noexcept_policy)
|
|
|
|
{
|
|
|
|
return (CodepointType)utf8::read_codepoint<InvalidPolicy>(m_it, m_end);
|
|
|
|
}
|
|
|
|
|
2017-06-07 11:58:49 +02:00
|
|
|
const BaseIt& base() const noexcept(noexcept_policy) { return m_it; }
|
2012-10-08 14:25:58 +02:00
|
|
|
|
|
|
|
private:
|
2017-06-07 11:58:49 +02:00
|
|
|
void invalidate_value() noexcept { m_value = -1; }
|
|
|
|
CodepointType get_value() const noexcept(noexcept_policy)
|
2012-10-08 14:25:58 +02:00
|
|
|
{
|
2016-05-19 21:20:42 +02:00
|
|
|
if (m_value == (CodepointType)-1)
|
2016-05-09 22:56:08 +02:00
|
|
|
m_value = (CodepointType)utf8::codepoint<InvalidPolicy>(m_it, m_end);
|
2012-10-08 14:25:58 +02:00
|
|
|
return m_value;
|
|
|
|
}
|
|
|
|
|
2017-02-23 01:30:59 +01:00
|
|
|
BaseIt m_it;
|
2018-10-31 09:41:12 +01:00
|
|
|
Sentinel m_begin;
|
|
|
|
Sentinel m_end;
|
2016-05-09 22:56:08 +02:00
|
|
|
mutable CodepointType m_value = -1;
|
2012-10-08 14:25:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-06-05 19:19:49 +02:00
|
|
|
}
|
2012-10-08 14:25:58 +02:00
|
|
|
#endif // utf8_iterator_hh_INCLUDED
|