diff options
Diffstat (limited to 'Ix/CPP/src/cpplinq/linq_iterators.hpp')
-rw-r--r-- | Ix/CPP/src/cpplinq/linq_iterators.hpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/Ix/CPP/src/cpplinq/linq_iterators.hpp b/Ix/CPP/src/cpplinq/linq_iterators.hpp new file mode 100644 index 0000000..ed267ec --- /dev/null +++ b/Ix/CPP/src/cpplinq/linq_iterators.hpp @@ -0,0 +1,194 @@ +// 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 + +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 detail::deref_iterator(it, std::identity<typename std::iterator_traits<Iter>::reference>()); + } + + template <class Iter, class T> + T* deref_iterator(const Iter& it, std::identity<T&>) { + return &*it; + } + + template <class Iter, class T> + util::value_ptr<T> deref_iterator(const Iter& it, std::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, + 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(); + } + + pointer operator->() const { + auto& v = **this; + return &v; + } + + cursor_iterator& operator++() { + cur->inc(); + + if (cur->empty()) { cur.reset(); } + return *this; + } + + cursor_iterator& operator+=(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 |