1 /*
2    Copyright (C) 2017-2018 by the Battle for Wesnoth Project https://www.wesnoth.org/
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY.
10 
11    See the COPYING file for more details.
12 */
13 
14 #pragma once
15 
16 #include <iterator>  //input_iterator_tag
17 #include <utility>   //pair
18 #include <cstddef>   //ptrdiff_t
19 #include <cassert>   //assert
20 
21 #include "unicode_types.hpp"
22 
23 namespace ucs4
24 {
25 	template<typename string_type, typename update_implementation>
26 	class iterator_base
27 	{
28 	public:
29 		typedef std::input_iterator_tag iterator_category;
30 		typedef ucs4::char_t value_type;
31 		typedef ptrdiff_t difference_type;
32 		typedef ucs4::char_t* pointer;
33 		typedef ucs4::char_t& reference;
34 
iterator_base(const string_type & str)35 		iterator_base(const string_type& str)
36 			: current_char(0)
37 			, string_end(str.end())
38 			, current_substr(std::make_pair(str.begin(), str.begin()))
39 		{
40 			update();
41 		}
42 
iterator_base(typename string_type::const_iterator const & begin,typename string_type::const_iterator const & end)43 		iterator_base(typename string_type::const_iterator const& begin, typename string_type::const_iterator const& end)
44 			: current_char(0)
45 			, string_end(end)
46 			, current_substr(std::make_pair(begin, begin))
47 		{
48 			update();
49 		}
50 
begin(const string_type & str)51 		static iterator_base begin(const string_type& str)
52 		{
53 			return iterator_base(str.begin(), str.end());
54 		}
55 
end(const string_type & str)56 		static iterator_base end(const string_type& str)
57 		{
58 			return iterator_base(str.end(), str.end());
59 		}
60 
operator ==(const iterator_base & a) const61 		bool operator==(const iterator_base& a) const
62 		{
63 			return current_substr.first == a.current_substr.first;
64 		}
65 
operator !=(const iterator_base & a) const66 		bool operator!=(const iterator_base& a) const
67 		{
68 			return ! (*this == a);
69 		}
70 
operator ++()71 		iterator_base& operator++()
72 		{
73 			current_substr.first = current_substr.second;
74 			update();
75 			return *this;
76 		}
77 
operator *() const78 		ucs4::char_t operator*() const
79 		{
80 			return current_char;
81 		}
82 
next_is_end() const83 		bool next_is_end() const
84 		{
85 			if(current_substr.second == string_end)
86 				return true;
87 			return false;
88 		}
89 
substr() const90 		const std::pair<typename string_type::const_iterator, typename string_type::const_iterator>& substr() const
91 		{
92 			return current_substr;
93 		}
94 	private:
update()95 		void update()
96 		{
97 			assert(current_substr.first == current_substr.second);
98 			if(current_substr.first == string_end)
99 				return;
100 			current_char = update_implementation::read(current_substr.second, string_end);
101 		}
102 
103 		ucs4::char_t current_char;
104 		typename string_type::const_iterator string_end;
105 		std::pair<typename string_type::const_iterator, typename string_type::const_iterator> current_substr;
106 	};
107 
108 }
109