aboutsummaryrefslogtreecommitdiff
path: root/include/EASTL/internal/generic_iterator.h
blob: b32998a8c28df351229b1ecab70b200ae00cc32d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/////////////////////////////////////////////////////////////////////////////
// Copyright (c) Electronic Arts Inc. All rights reserved.
/////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Implements a generic iterator from a given iteratable type, such as a pointer.
// We cannot put this file into our own iterator.h file because we need to 
// still be able to use this file when we have our iterator.h disabled.
//
///////////////////////////////////////////////////////////////////////////////


#ifndef EASTL_INTERNAL_GENERIC_ITERATOR_H
#define EASTL_INTERNAL_GENERIC_ITERATOR_H


#include <EABase/eabase.h>
#if defined(EA_PRAGMA_ONCE_SUPPORTED)
	#pragma once
#endif

#include <EASTL/internal/config.h>
#include <EASTL/iterator.h>
#include <EASTL/type_traits.h>

// There is no warning number 'number'.
// Member template functions cannot be used for copy-assignment or copy-construction.
EA_DISABLE_VC_WARNING(4619 4217);


namespace eastl
{

	/// generic_iterator
	///
	/// Converts something which can be iterated into a formal iterator.
	/// While this class' primary purpose is to allow the conversion of 
	/// a pointer to an iterator, you can convert anything else to an 
	/// iterator by defining an iterator_traits<> specialization for that
	/// object type. See EASTL iterator.h for this.
	///
	/// Example usage:
	///     typedef generic_iterator<int*>       IntArrayIterator;
	///     typedef generic_iterator<int*, char> IntArrayIteratorOther;
	///
	template <typename Iterator, typename Container = void>
	class generic_iterator
	{
	protected:
		Iterator mIterator;

	public:
		typedef typename eastl::iterator_traits<Iterator>::iterator_category iterator_category;
		typedef typename eastl::iterator_traits<Iterator>::value_type        value_type;
		typedef typename eastl::iterator_traits<Iterator>::difference_type   difference_type;
		typedef typename eastl::iterator_traits<Iterator>::reference         reference;
		typedef typename eastl::iterator_traits<Iterator>::pointer           pointer;
		typedef Iterator                                                     iterator_type;
		typedef iterator_type                                                wrapped_iterator_type;   // This is not in the C++ Standard; it's used by use to identify it as a wrapping iterator type.
		typedef Container                                                    container_type;
		typedef generic_iterator<Iterator, Container>                        this_type;

		generic_iterator()
			: mIterator(iterator_type()) { }

		explicit generic_iterator(const iterator_type& x)
			: mIterator(x) { }

		this_type& operator=(const iterator_type& x)
			{ mIterator = x; return *this; }

		template <typename Iterator2>
		generic_iterator(const generic_iterator<Iterator2, Container>& x)
			: mIterator(x.base()) { }

		reference operator*() const
			{ return *mIterator; }

		pointer operator->() const
			{ return mIterator; }

		this_type& operator++()
			{ ++mIterator; return *this; }

		this_type operator++(int)
			{ return this_type(mIterator++); }

		this_type& operator--()
			{ --mIterator; return *this; }

		this_type operator--(int)
			{ return this_type(mIterator--); }

		reference operator[](const difference_type& n) const
			{ return mIterator[n]; }

		this_type& operator+=(const difference_type& n)
			{ mIterator += n; return *this; }

		this_type operator+(const difference_type& n) const
			{ return this_type(mIterator + n); }

		this_type& operator-=(const difference_type& n)
			{ mIterator -= n; return *this; }

		this_type operator-(const difference_type& n) const
			{ return this_type(mIterator - n); }

		const iterator_type& base() const
			{ return mIterator; }

	}; // class generic_iterator


	template <typename IteratorL, typename IteratorR, typename Container>
	inline bool operator==(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
		{ return lhs.base() == rhs.base(); }

	template <typename Iterator, typename Container>
	inline bool operator==(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
		{ return lhs.base() == rhs.base(); }

	template <typename IteratorL, typename IteratorR, typename Container>
	inline bool operator!=(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
		{ return lhs.base() != rhs.base(); }

	template <typename Iterator, typename Container>
	inline bool operator!=(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
		{ return lhs.base() != rhs.base(); }

	template <typename IteratorL, typename IteratorR, typename Container>
	inline bool operator<(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
		{ return lhs.base() < rhs.base(); }

	template <typename Iterator, typename Container>
	inline bool operator<(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
		{ return lhs.base() < rhs.base(); }

	template <typename IteratorL, typename IteratorR, typename Container>
	inline bool operator>(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
		{ return lhs.base() > rhs.base(); }

	template <typename Iterator, typename Container>
	inline bool operator>(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
		{ return lhs.base() > rhs.base(); }

	template <typename IteratorL, typename IteratorR, typename Container>
	inline bool operator<=(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
		{ return lhs.base() <= rhs.base(); }

	template <typename Iterator, typename Container>
	inline bool operator<=(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
		{ return lhs.base() <= rhs.base(); }

	template <typename IteratorL, typename IteratorR, typename Container>
	inline bool operator>=(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
		{ return lhs.base() >= rhs.base(); }

	template <typename Iterator, typename Container>
	inline bool operator>=(const generic_iterator<Iterator, Container>& lhs, const generic_iterator<Iterator, Container>& rhs)
		{ return lhs.base() >= rhs.base(); }

	template <typename IteratorL, typename IteratorR, typename Container>
	inline typename generic_iterator<IteratorL, Container>::difference_type
	operator-(const generic_iterator<IteratorL, Container>& lhs, const generic_iterator<IteratorR, Container>& rhs)
		{ return lhs.base() - rhs.base(); }

	template <typename Iterator, typename Container>
	inline generic_iterator<Iterator, Container>
	operator+(typename generic_iterator<Iterator, Container>::difference_type n, const generic_iterator<Iterator, Container>& x)
		{ return generic_iterator<Iterator, Container>(x.base() + n); }



	/// is_generic_iterator
	///
	/// Tells if an iterator is one of these generic_iterators. This is useful if you want to 
	/// write code that uses miscellaneous iterators but wants to tell if they are generic_iterators.
	/// A primary reason to do so is that you can get at the pointer within the generic_iterator.
	///
	template <typename Iterator>
	struct is_generic_iterator : public false_type { };

	template <typename Iterator, typename Container>
	struct is_generic_iterator<generic_iterator<Iterator, Container> > : public true_type { };


	/// unwrap_generic_iterator
	///
	/// Returns Iterator::get_base() if it's a generic_iterator, else returns Iterator as-is.
	///
	/// Example usage:
	///      vector<int> intVector;
	///      eastl::generic_iterator<vector<int>::iterator> genericIterator(intVector.begin());
	///      vector<int>::iterator it = unwrap_generic_iterator(genericIterator);
	///
	template <typename Iterator>
	inline typename eastl::is_iterator_wrapper_helper<Iterator, eastl::is_generic_iterator<Iterator>::value>::iterator_type unwrap_generic_iterator(Iterator it)
		{ return eastl::is_iterator_wrapper_helper<Iterator, eastl::is_generic_iterator<Iterator>::value>::get_base(it); }


} // namespace eastl


EA_RESTORE_VC_WARNING();


#endif // Header include guard