#ifndef code__unicode__iterator_hxx_ #define code__unicode__iterator_hxx_ #include #include namespace code::unicode { template 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 using Utf8_input_iterator = Unicode_input_iterator; template bool operator==( Unicode_input_iterator const& lhs, typename Unicode_input_iterator::iterator_type const& rhs) { return lhs.equal(rhs); } template bool operator!=( Unicode_input_iterator const& lhs, typename Unicode_input_iterator< Decoder, IteratorType >::iterator_type const& rhs) { return !lhs.equal(rhs); } } // namespace code::unicode #endif