197 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			197 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
 | ||
|  | 
 | ||
|  | #if !defined(CPPLINQ_LINQ_ITERATORS_HPP)
 | ||
|  | #define CPPLINQ_LINQ_ITERATORS_HPP
 | ||
|  | #pragma once
 | ||
|  | 
 | ||
|  | #include <cstddef>
 | ||
|  | 
 | ||
|  | namespace cpplinq { | ||
|  | 
 | ||
|  |     // if a member, provides the straightforward implementation of various redundant operators. For example,
 | ||
|  |     //   providing -> for any iterator providing *, and so forth.
 | ||
|  |     struct use_default_iterator_operators {}; | ||
|  | 
 | ||
|  |     #define CPPLINQ_USE_DEFAULT_ITERATOR_OPERATORS \
 | ||
|  |     operator ::cpplinq::use_default_iterator_operators() const { return ::cpplinq::use_default_iterator_operators(); } | ||
|  | 
 | ||
|  |     template <class Iter> | ||
|  |     typename std::enable_if< | ||
|  |         std::is_convertible<Iter, use_default_iterator_operators>::value, | ||
|  |         Iter | ||
|  |         >::type | ||
|  |     operator+(const Iter& it, typename std::iterator_traits<Iter>::distance_type n) { | ||
|  |         return it += n; | ||
|  |     } | ||
|  |     template <class Iter> | ||
|  |     typename std::enable_if< | ||
|  |         std::is_convertible<Iter, use_default_iterator_operators>::value, | ||
|  |         Iter | ||
|  |         >::type | ||
|  |     operator-(const Iter& it, typename std::iterator_traits<Iter>::distance_type n) { | ||
|  |         return it -= n; | ||
|  |     } | ||
|  |     template <class Iter> | ||
|  |     typename std::enable_if< | ||
|  |         std::is_convertible<Iter, use_default_iterator_operators>::value, | ||
|  |         Iter | ||
|  |         >::type | ||
|  |     operator-=(const Iter& it, typename std::iterator_traits<Iter>::distance_type n) { | ||
|  |         return it += (-n); | ||
|  |     } | ||
|  | 
 | ||
|  |     template <class Iter> | ||
|  |     typename std::enable_if< | ||
|  |         std::is_convertible<Iter, use_default_iterator_operators>::value, | ||
|  |         bool | ||
|  |         >::type | ||
|  |     operator!=(const Iter& it, const Iter& it2) { | ||
|  |         return !(it == it2); | ||
|  |     } | ||
|  |     template <class Iter> | ||
|  |     typename std::enable_if< | ||
|  |         std::is_convertible<Iter, use_default_iterator_operators>::value, | ||
|  |         bool | ||
|  |         >::type | ||
|  |     operator>(const Iter& it, const Iter& it2) { | ||
|  |         return it2 < it; | ||
|  |     } | ||
|  |     template <class Iter> | ||
|  |     typename std::enable_if< | ||
|  |         std::is_convertible<Iter, use_default_iterator_operators>::value, | ||
|  |         bool | ||
|  |         >::type | ||
|  |     operator<=(const Iter& it, const Iter& it2) { | ||
|  |         return !(it2 < it); | ||
|  |     } | ||
|  |     template <class Iter> | ||
|  |     typename std::enable_if< | ||
|  |         std::is_convertible<Iter, use_default_iterator_operators>::value, | ||
|  |         bool | ||
|  |         >::type | ||
|  |     operator>=(const Iter& it, const Iter& it2) { | ||
|  |         return !(it < it2); | ||
|  |     }    | ||
|  |      | ||
|  |     namespace util { | ||
|  |         template <class Iter, class T> | ||
|  |         typename std::iterator_traits<Iter>::pointer deref_iterator(const Iter& it) { | ||
|  |             return deref_iterator(it, util::identity<typename std::iterator_traits<Iter>::reference>()); | ||
|  |         } | ||
|  | 
 | ||
|  |         template <class Iter, class T> | ||
|  |         T* deref_iterator(const Iter& it, util::identity<T&>) { | ||
|  |             return &*it; | ||
|  |         } | ||
|  | 
 | ||
|  |         template <class Iter, class T> | ||
|  |         util::value_ptr<T> deref_iterator(const Iter& it, util::identity<T>) { | ||
|  |             return util::value_ptr<T>(*it); | ||
|  |         } | ||
|  |     }  | ||
|  |      | ||
|  |      | ||
|  |     template <class Iter> | ||
|  |     class iter_range | ||
|  |     { | ||
|  |         Iter start, finish; | ||
|  |     public: | ||
|  | 
 | ||
|  |         CPPLINQ_USE_DEFAULT_ITERATOR_OPERATORS | ||
|  | 
 | ||
|  |         typedef Iter iterator; | ||
|  |         typedef typename iterator::value_type value_type; | ||
|  | 
 | ||
|  |         explicit iter_range(Iter start, Iter finish) : start(start), finish(finish) {} | ||
|  |         iterator begin() const { return start; } | ||
|  |         iterator end() const { return finish; } | ||
|  |     }; | ||
|  |     template <class Iter> | ||
|  |     iter_range<Iter> make_range(Iter start, Iter finish) { | ||
|  |         return iter_range<Iter>(start, finish); | ||
|  |     } | ||
|  | 
 | ||
|  |     // decays into a onepass/forward iterator
 | ||
|  |     template <class Cursor> | ||
|  |     class cursor_iterator  | ||
|  |         : public std::iterator<std::forward_iterator_tag,  | ||
|  |                 typename Cursor::element_type, | ||
|  |                 std::ptrdiff_t, | ||
|  |                 typename std::conditional<std::is_reference<typename Cursor::reference_type>::value, | ||
|  |                                           typename std::add_pointer<typename Cursor::element_type>::type, | ||
|  |                                           util::value_ptr<typename Cursor::element_type>>::type, | ||
|  |                 typename Cursor::reference_type> | ||
|  |     { | ||
|  |     public: | ||
|  |         CPPLINQ_USE_DEFAULT_ITERATOR_OPERATORS; | ||
|  | 
 | ||
|  |         cursor_iterator(Cursor cur) : cur(cur) { | ||
|  |         } | ||
|  | 
 | ||
|  |         cursor_iterator() : cur() { | ||
|  |         } | ||
|  | 
 | ||
|  |         bool operator==(const cursor_iterator& other) const { | ||
|  |             return !cur && !other.cur; | ||
|  |         } | ||
|  | 
 | ||
|  |         typename Cursor::reference_type operator*() const { | ||
|  |             return cur->get(); | ||
|  |         } | ||
|  | 
 | ||
|  |         typename cursor_iterator::pointer operator->() const { | ||
|  |             auto& v = **this; | ||
|  |             return &v; | ||
|  |         } | ||
|  |          | ||
|  |         cursor_iterator& operator++() { | ||
|  |             cur->inc(); | ||
|  | 
 | ||
|  |             if (cur->empty()) { cur.reset(); } | ||
|  |             return *this; | ||
|  |         } | ||
|  | 
 | ||
|  |         cursor_iterator& operator+=(std::ptrdiff_t n) { | ||
|  |             cur->skip(n); | ||
|  | 
 | ||
|  |             if (cur->empty()) { cur.reset(); } | ||
|  |             return *this; | ||
|  |         } | ||
|  | 
 | ||
|  | 
 | ||
|  |          | ||
|  |     private: | ||
|  |         bool empty() const { | ||
|  |             !cur || cur->empty(); | ||
|  |         } | ||
|  | 
 | ||
|  |         util::maybe<Cursor> cur; | ||
|  |     }; | ||
|  | 
 | ||
|  |     template <class Container> | ||
|  |     class container_range | ||
|  |     { | ||
|  |         Container c; | ||
|  | 
 | ||
|  |     public: | ||
|  |         typedef cursor_iterator<typename Container::cursor> iterator; | ||
|  | 
 | ||
|  |         container_range(Container c) : c(c)  | ||
|  |         { | ||
|  |         } | ||
|  | 
 | ||
|  |         iterator begin() const | ||
|  |         { | ||
|  |             return iterator(c.get_cursor()); | ||
|  |         } | ||
|  | 
 | ||
|  |         iterator end() const | ||
|  |         { | ||
|  |             return iterator(); | ||
|  |         } | ||
|  |     }; | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 |