summaryrefslogtreecommitdiff
path: root/src/inc/iterator.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/iterator.h')
-rw-r--r--src/inc/iterator.h639
1 files changed, 639 insertions, 0 deletions
diff --git a/src/inc/iterator.h b/src/inc/iterator.h
new file mode 100644
index 0000000000..98cf6185e0
--- /dev/null
+++ b/src/inc/iterator.h
@@ -0,0 +1,639 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ---------------------------------------------------------------------------
+// Iterator.h
+// ---------------------------------------------------------------------------
+
+// ================================================================================
+// Iterator pattern:
+//
+// This pattern is similar to the STL iterator pattern. It basically consists of
+// wrapping an "iteration variable" in an object, and providing pointer-like operators
+// on the iterator. Example usage:
+//
+// for (Iterator start = foo->Begin(), end = foo->End(); start != end; start++)
+// {
+// // use foo, start
+// }
+//
+// There are 3 levels of iterator functionality
+// 1. Enumerator (STL forward) - only go forward one at a time
+// Enumerators have the following operations:
+// operator * : access current element as ref
+// operator -> : access current element as ptr
+// operator++ : go to the next element
+// operator==, operator!= : compare to another enumerator
+//
+//
+// 2. Scanner (STL bidirectional) - backward or forward one at a time
+// Scanners have all the functionality of enumerators, plus:
+// operator-- : go backward one element
+//
+// 3. Indexer (STL random access) - skip around arbitrarily
+// Indexers have all the functionality of scanners, plus:
+// operator[] : access the element at index from iterator as ref
+// operator+= : advance iterator by index
+// operator+ : return new iterator at index from iterator
+// operator-= : rewind iterator by index
+// operator- : return new iterator at index back from iterator
+// operator <, operator <=, operator >, operator>= :
+// range comparison on two indexers
+//
+// The object being iterated should define the following methods:
+// Begin() return an iterator starting at the first element
+// End() return an iterator just past the last element
+//
+// Iterator types are normally defined as member types named "Iterator", no matter
+// what their functionality level is.
+// ================================================================================
+
+
+#ifndef ITERATOR_H_
+#define ITERATOR_H_
+
+#include "contract.h"
+
+namespace HIDDEN {
+// These prototypes are not for direct use - they are only here to illustrate the
+// iterator pattern
+
+template <typename CONTAINER, typename ELEMENT>
+class ScannerPrototype
+{
+ public:
+
+ typedef ScannerPrototype<CONTAINER, ELEMENT> Iterator;
+
+ ELEMENT &operator*();
+ ELEMENT *operator->();
+
+ Iterator &operator++();
+ Iterator operator++(int);
+ Iterator &operator--();
+ Iterator operator--(int);
+
+ bool operator==(const Iterator &i);
+ bool operator!=(const Iterator &i);
+};
+
+template <typename CONTAINER, typename ELEMENT>
+class EnumeratorPrototype
+{
+ public:
+
+ typedef EnumeratorPrototype<CONTAINER, ELEMENT> Iterator;
+
+ ELEMENT &operator*();
+ ELEMENT *operator->();
+
+ Iterator &operator++();
+ Iterator operator++(int);
+
+ bool operator==(const Iterator &i);
+ bool operator!=(const Iterator &i);
+};
+
+template <typename CONTAINER, typename ELEMENT>
+class IndexerPrototype
+{
+ public:
+ typedef IndexerPrototype<CONTAINER, ELEMENT> Iterator;
+
+ ELEMENT &operator*();
+ ELEMENT *operator->();
+ ELEMENT &operator[](int index);
+
+ Iterator &operator++();
+ Iterator operator++(int);
+ Iterator &operator--();
+ Iterator operator--(int);
+
+ Iterator &operator+=(SCOUNT_T index);
+ Iterator &operator-=(SCOUNT_T index);
+
+ Iterator operator+(SCOUNT_T index);
+ Iterator operator-(SCOUNT_T index);
+
+ SCOUNT_T operator-(Iterator &i);
+
+ bool operator==(const Iterator &i);
+ bool operator!=(const Iterator &i);
+ bool operator<(const Iterator &i);
+ bool operator<=(const Iterator &i);
+ bool operator>(const Iterator &i);
+ bool operator>=(const Iterator &i);
+};
+
+template <typename ELEMENT>
+class EnumerablePrototype
+{
+ typedef EnumeratorPrototype<EnumerablePrototype, ELEMENT> Iterator;
+
+ Iterator Begin();
+ Iterator End();
+};
+
+template <typename ELEMENT>
+class ScannablePrototype
+{
+ typedef ScannerPrototype<ScannablePrototype, ELEMENT> Iterator;
+
+ Iterator Begin();
+ Iterator End();
+};
+
+template <typename ELEMENT>
+class IndexablePrototype
+{
+ typedef IndexerPrototype<IndexablePrototype, ELEMENT> Iterator;
+
+ Iterator Begin();
+ Iterator End();
+};
+
+};
+
+// --------------------------------------------------------------------------------
+// EnumeratorBase, ScannerBase, and IndexerBase are abstract classes
+// describing basic operations for iterator functionality at the different levels.
+//
+// You
+// 1. Use the classes as a pattern (don't derive from them), and plug in your own
+// class into the Enumerator/Scanner/Indexer templates below.
+// 2. Subclass the AbstractEnumerator/AbstractScanner/AbstractIndexer classes
+// --------------------------------------------------------------------------------
+
+namespace HIDDEN
+{
+// These prototypes are not for direct use - they are only here to illustrate the
+// pattern of the BASE class for the Iterator templates
+
+template <typename ELEMENT, typename CONTAINER>
+class EnumeratorBasePrototype
+{
+ protected:
+ EnumeratorBasePrototype(CONTAINER *container, BOOL begin);
+ ELEMENT &Get() const;
+ void Next();
+ BOOL Equal(const EnumeratorBasePrototype &i) const;
+ CHECK DoCheck() const;
+};
+
+template <typename ELEMENT, typename CONTAINER>
+class ScannerBasePrototype
+{
+ protected:
+ ScannerBasePrototype(CONTAINER *container, BOOL begin);
+ ELEMENT &Get() const;
+ void Next();
+ void Previous();
+ BOOL Equal(const ScannerBasePrototype &i) const;
+ CHECK DoCheck() const;
+};
+
+template <typename ELEMENT, typename CONTAINER>
+class IndexerBasePrototype
+{
+ protected:
+ IndexerBasePrototype(CONTAINER *container, SCOUNT_T delta);
+ ELEMENT &GetAt(SCOUNT_T delta) const;
+ void Skip(SCOUNT_T delta);
+ SCOUNT_T Subtract(const IndexerBasePrototype &i) const;
+ CHECK DoCheck(SCOUNT_T delta) const;
+};
+
+};
+
+
+template <typename CONTAINER>
+class CheckedIteratorBase
+{
+ protected:
+#if defined(_DEBUG)
+ const CONTAINER *m_container;
+ int m_revision;
+#endif
+
+ CHECK CheckRevision() const
+ {
+ LIMITED_METHOD_CONTRACT;
+ SUPPORTS_DAC;
+#if defined(_DEBUG)
+ __if_exists(CONTAINER::m_revision)
+ {
+ CHECK_MSG(m_revision == m_container->m_revision,
+ "Use of Iterator after container has been modified");
+ }
+#endif
+ CHECK_OK;
+ }
+
+ CheckedIteratorBase()
+ {
+ LIMITED_METHOD_DAC_CONTRACT;
+#if defined(_DEBUG)
+ m_container = NULL;
+#endif
+ }
+
+ CheckedIteratorBase(const CONTAINER *container)
+ {
+ LIMITED_METHOD_CONTRACT;
+#if defined(_DEBUG)
+ m_container = container;
+ __if_exists(CONTAINER::m_revision)
+ {
+ m_revision = m_container->m_revision;
+ }
+#endif
+ }
+
+ void Resync(const CONTAINER *container)
+ {
+ LIMITED_METHOD_DAC_CONTRACT;
+
+#if defined(_DEBUG)
+ __if_exists(CONTAINER::m_revision)
+ {
+ m_revision = m_container->m_revision;
+ }
+#endif
+ }
+
+#if defined(_DEBUG)
+ const CONTAINER *GetContainerDebug() const
+ {
+ LIMITED_METHOD_CONTRACT;
+ return m_container;
+ }
+#endif
+
+ public:
+ CHECK Check() const
+ {
+ WRAPPER_NO_CONTRACT;
+ SUPPORTS_DAC;
+ CHECK(CheckRevision());
+ CHECK_OK;
+ }
+
+ CHECK CheckContainer(const CONTAINER *container) const
+ {
+ WRAPPER_NO_CONTRACT;
+#if defined(_DEBUG)
+ CHECK(container == m_container);
+#endif
+ CHECK_OK;
+ }
+
+};
+
+
+// --------------------------------------------------------------------------------
+// Enumerator, Scanner, and Indexer provide a template to produce an iterator
+// on an existing class with a single iteration variable.
+//
+// The template takes 3 type parameters:
+// CONTAINER - type of object being interated on
+// ELEMENT - type of iteration
+// BASE - base type of the iteration. This type must follow the pattern described
+// by the above Prototypes
+// --------------------------------------------------------------------------------
+
+template <typename ELEMENT, typename SUBTYPE>
+class Enumerator
+{
+ private:
+ const SUBTYPE *This() const
+ {
+ return (const SUBTYPE *) this;
+ }
+
+ SUBTYPE *This()
+ {
+ return (SUBTYPE *)this;
+ }
+
+ public:
+
+ Enumerator()
+ {
+ }
+
+ CHECK CheckIndex() const
+ {
+#if defined(_DEBUG)
+ CHECK(This()->DoCheck());
+#endif
+ CHECK_OK;
+ }
+
+ ELEMENT &operator*() const
+ {
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(This()->CheckIndex());
+
+ return This()->Get();
+ }
+ ELEMENT *operator->() const
+ {
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(This()->CheckIndex());
+
+ return &(This()->Get());
+ }
+ SUBTYPE &operator++()
+ {
+ PRECONDITION(CheckPointer(This()));
+
+ This()->Next();
+ return *This();
+ }
+ SUBTYPE operator++(int)
+ {
+ PRECONDITION(CheckPointer(This()));
+
+ SUBTYPE i = *This();
+ This()->Next();
+ return i;
+ }
+ bool operator==(const SUBTYPE &i) const
+ {
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+
+ return This()->Equal(i);
+ }
+ bool operator!=(const SUBTYPE &i) const
+ {
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+
+ return !This()->Equal(i);
+ }
+};
+
+template <typename ELEMENT, typename SUBTYPE>
+class Scanner
+{
+ private:
+ const SUBTYPE *This() const
+ {
+ return (const SUBTYPE *)this;
+ }
+
+ SUBTYPE *This()
+ {
+ return (SUBTYPE *)this;
+ }
+
+ public:
+
+ Scanner()
+ {
+ }
+
+ CHECK CheckIndex() const
+ {
+#if defined(_DEBUG)
+ CHECK(This()->DoCheck());
+#endif
+ CHECK_OK;
+ }
+
+ ELEMENT &operator*() const
+ {
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(This()->CheckIndex());
+
+ return This()->Get();
+ }
+ ELEMENT *operator->() const
+ {
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(This()->CheckIndex());
+
+ return &This()->Get();
+ }
+ SUBTYPE &operator++()
+ {
+ PRECONDITION(CheckPointer(This()));
+
+ This()->Next();
+ return *This();
+ }
+ SUBTYPE operator++(int)
+ {
+ PRECONDITION(CheckPointer(This()));
+
+ SUBTYPE i = *This();
+ This()->Next();
+ return i;
+ }
+ SUBTYPE &operator--()
+ {
+ PRECONDITION(CheckPointer(This()));
+
+ This()->Previous();
+ return *This();
+ }
+ SUBTYPE operator--(int)
+ {
+ PRECONDITION(CheckPointer(this));
+
+ SUBTYPE i = *This();
+ This()->Previous();
+ return i;
+ }
+ bool operator==(const SUBTYPE &i) const
+ {
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+
+ return This()->Equal(i);
+ }
+ bool operator!=(const SUBTYPE &i) const
+ {
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+
+ return !This()->Equal(i);
+ }
+};
+
+template <typename ELEMENT, typename SUBTYPE>
+class Indexer
+{
+ private:
+ const SUBTYPE *This() const
+ {
+ return (const SUBTYPE *)this;
+ }
+
+ SUBTYPE *This()
+ {
+ return (SUBTYPE *)this;
+ }
+
+ public:
+
+ Indexer()
+ {
+ LIMITED_METHOD_DAC_CONTRACT;
+ }
+
+ CHECK CheckIndex() const
+ {
+#if defined(_DEBUG)
+ CHECK(This()->DoCheck(0));
+#endif
+ CHECK_OK;
+ }
+
+ CHECK CheckIndex(int index) const
+ {
+#if defined(_DEBUG)
+ CHECK(This()->DoCheck(index));
+#endif
+ CHECK_OK;
+ }
+
+ ELEMENT &operator*() const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(This()->CheckIndex(0));
+
+ return *(ELEMENT*)&This()->GetAt(0);
+ }
+ ELEMENT *operator->() const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(This()->CheckIndex(0));
+
+ return &This()->GetAt(0);
+ }
+ ELEMENT &operator[](int index) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(This()->CheckIndex(index));
+ return *(ELEMENT*)&This()->GetAt(index);
+ }
+ SUBTYPE &operator++()
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ This()->Skip(1);
+ return *This();
+ }
+ SUBTYPE operator++(int)
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ SUBTYPE i = *This();
+ This()->Skip(1);
+ return i;
+ }
+ SUBTYPE &operator--()
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ This()->Skip(-1);
+ return *This();
+ }
+ SUBTYPE operator--(int)
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ SUBTYPE i = *This();
+ This()->Skip(-1);
+ return i;
+ }
+ SUBTYPE &operator+=(SCOUNT_T index)
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ This()->Skip(index);
+ return *This();
+ }
+ SUBTYPE operator+(SCOUNT_T index) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ SUBTYPE i = *This();
+ i.Skip(index);
+ return i;
+ }
+ SUBTYPE &operator-=(SCOUNT_T index)
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ This()->Skip(-index);
+ return *This();
+ }
+ SUBTYPE operator-(SCOUNT_T index) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ SUBTYPE i = *This();
+ i.Skip(-index);
+ return i;
+ }
+ SCOUNT_T operator-(const SUBTYPE &i) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+
+ return This()->Subtract(i);
+ }
+ bool operator==(const SUBTYPE &i) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+
+ return This()->Subtract(i) == 0;
+ }
+ bool operator!=(const SUBTYPE &i) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+
+ return This()->Subtract(i) != 0;
+ }
+ bool operator<(const SUBTYPE &i) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+ return This()->Subtract(i) < 0;
+ }
+ bool operator<=(const SUBTYPE &i) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+ return This()->Subtract(i) <= 0;
+ }
+ bool operator>(const SUBTYPE &i) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+ return This()->Subtract(i) > 0;
+ }
+ bool operator>=(const SUBTYPE &i) const
+ {
+ WRAPPER_NO_CONTRACT;
+ PRECONDITION(CheckPointer(This()));
+ PRECONDITION(i.Check());
+ return This()->Subtract(i) >= 0;
+ }
+};
+
+#endif // ITERATOR_H_