2024-12-25 02:11:27 +01:00

125 lines
2.5 KiB
C++

#ifndef code__unicode__iterator_hxx_
#define code__unicode__iterator_hxx_
#include <code/unicode/decoding.hxx>
#include <cstdint>
namespace code::unicode
{
template<typename Decoder, typename IteratorType>
class Unicode_input_iterator
{
public:
using decoder_type = Decoder;
using iterator_type = IteratorType;
using value_type = std::uint32_t;
// TODO standard member types
Unicode_input_iterator()
{}
explicit Unicode_input_iterator(iterator_type it) : it_{ std::move(it) }
{
decode();
}
Unicode_input_iterator(iterator_type it, iterator_type end)
: it_{ std::move(it) }, end_{ std::move(end) }
{
decode();
}
Unicode_input_iterator(decoder_type decoder, iterator_type it)
: decoder_{ std::move(decoder) }, it_{ std::move(it) }
{
decode();
}
Unicode_input_iterator(decoder_type decoder,
iterator_type it,
iterator_type end)
: decoder_{ std::move(decoder) },
it_{ std::move(it) },
end_{ std::move(end) }
{
decode();
}
value_type operator*() const
{
return unicode_;
}
Unicode_input_iterator&
operator++()
{
decode();
return *this;
}
struct Proxy
{
value_type unicode_;
value_type operator*() const
{
return unicode_;
}
};
Proxy
operator++(int)
{
auto unicode = unicode_;
decode();
return Proxy{unicode};
}
bool
equal(iterator_type const& other) const
{
return it_ == other;
}
private:
void
decode()
{
if (it_ != end_)
unicode_ = decoder_.decode(it_, end_);
}
decoder_type decoder_;
iterator_type it_;
iterator_type end_;
std::uint32_t unicode_{};
};
template<typename InputIterator >
using Utf8_input_iterator = Unicode_input_iterator<Utf8_decoder, InputIterator>;
template<typename Decoder, typename IteratorType>
bool
operator==(
Unicode_input_iterator<Decoder, IteratorType> const& lhs,
typename Unicode_input_iterator<Decoder, IteratorType>::iterator_type const& rhs)
{
return lhs.equal(rhs);
}
template<typename Decoder, typename IteratorType>
bool
operator!=(
Unicode_input_iterator<Decoder, IteratorType> const& lhs,
typename Unicode_input_iterator< Decoder, IteratorType >::iterator_type const& rhs)
{
return !lhs.equal(rhs);
}
} // namespace code::unicode
#endif