File: iterator.hh

package info (click to toggle)
dune-istl 2.11.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,504 kB
  • sloc: cpp: 34,844; python: 182; sh: 3; makefile: 3
file content (143 lines) | stat: -rw-r--r-- 5,666 bytes parent folder | download | duplicates (2)
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
// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#ifndef DUNE_PYTHON_ISTL_ITERATOR_HH
#define DUNE_PYTHON_ISTL_ITERATOR_HH

#include <tuple>

#include <dune/common/visibility.hh>

#include <dune/python/pybind11/extensions.h>
#include <dune/python/pybind11/pybind11.h>

namespace Dune
{

  namespace Python
  {

    namespace detail
    {

      template< class  T>
      struct DUNE_PRIVATE ISTLEnumerateState
      {
        T *obj;
        pybind11::object pyObj;
      };

      template< class T >
      struct DUNE_PRIVATE ISTLIteratorState
      {
        typename T::iterator it, end;
      };

      template< class T >
      struct DUNE_PRIVATE ISTLReverseIteratorState
      {
        typename T::iterator it, end;
      };

      template< class T >
      struct DUNE_PRIVATE ISTLEnumerateIteratorState
      {
        typename T::iterator it, end;
      };

      template< class T >
      struct DUNE_PRIVATE ISTLReverseEnumerateIteratorState
      {
        typename T::iterator it, end;
      };



      // registerISTLIterator
      // --------------------

      template< class T, class... options >
      inline static void registerISTLIterators ( pybind11::class_< T, options... > cls )
      {
        if( !pybind11::already_registered< ISTLIteratorState< T > >() )
        {
          pybind11::class_< ISTLIteratorState< T > > cls( pybind11::handle(), "iterator", pybind11::module_local() );
          cls.def( "__iter__", [] ( pybind11::object self ) { return self; } );
          cls.def( "__next__", [] ( ISTLIteratorState< T > &state ) -> decltype( *state.it ) {
              if( state.it == state.end )
                throw pybind11::stop_iteration();
              decltype( *state.it ) result = *state.it;
              ++state.it;
              return result;
            }, pybind11::keep_alive< 0, 1 >() );
        }

        cls.def( "__iter__", [] ( T &self ) { return ISTLIteratorState< T >{ self.begin(), self.end() }; }, pybind11::keep_alive< 0, 1 >() );

        if( !pybind11::already_registered< ISTLReverseIteratorState< T > >() )
        {
          pybind11::class_< ISTLReverseIteratorState< T > > cls( pybind11::handle(), "iterator", pybind11::module_local() );
          cls.def( "__iter__", [] ( pybind11::object self ) { return self; } );
          cls.def( "__next__", [] ( ISTLReverseIteratorState< T > &state ) -> decltype( *state.it ) {
              if( state.it == state.end )
                throw pybind11::stop_iteration();
              decltype( *state.it ) result = *state.it;
              --state.it;
              return result;
            }, pybind11::keep_alive< 0, 1 >() );
        }

        cls.def( "__reversed__", [] ( T &self ) { return ISTLReverseIteratorState< T >{ self.beforeEnd(), self.beforeBegin() }; }, pybind11::keep_alive< 0, 1 >() );

        if( !pybind11::already_registered< ISTLEnumerateState< T > >() )
        {
          if( !pybind11::already_registered< ISTLEnumerateIteratorState< T > >() )
          {
            pybind11::class_< ISTLEnumerateIteratorState< T > > cls( pybind11::handle(), "iterator", pybind11::module_local() );
            cls.def( "__iter__", [] ( pybind11::object self ) { return self; } );
            cls.def( "__next__", [] ( pybind11::object self ) {
                auto &state = pybind11::cast< ISTLEnumerateIteratorState< T > & >( self );
                if( state.it == state.end )
                  throw pybind11::stop_iteration();
                std::tuple< decltype( state.it.index() ), pybind11::object > result( state.it.index(), pybind11::cast( *state.it ) );
                pybind11::detail::keep_alive_impl( self, std::get< 1 >( result ) );
                ++state.it;
                return result;
              } );
          }

          if( !pybind11::already_registered< ISTLReverseEnumerateIteratorState< T > >() )
          {
            pybind11::class_< ISTLReverseEnumerateIteratorState< T > > cls( pybind11::handle(), "iterator", pybind11::module_local() );
            cls.def( "__iter__", [] ( pybind11::object self ) { return self; } );
            cls.def( "__next__", [] ( pybind11::object self ) {
                auto &state = pybind11::cast< ISTLReverseEnumerateIteratorState< T > & >( self );
                if( state.it == state.end )
                  throw pybind11::stop_iteration();
                std::tuple< decltype( state.it.index() ), pybind11::object > result( state.it.index(), pybind11::cast( *state.it ) );
                pybind11::detail::keep_alive_impl( self, std::get< 1 >( result ) );
                --state.it;
                return result;
              } );
          }

          pybind11::class_< ISTLEnumerateState< T > > cls( pybind11::handle(), "enumerate", pybind11::module_local() );
          cls.def( "__iter__", [] ( ISTLEnumerateState< T > &self ) {
              return ISTLEnumerateIteratorState< T >{ self.obj->begin(), self.obj->end() };
            }, pybind11::keep_alive< 0, 1 >() );
          cls.def( "__reversed__", [] ( ISTLEnumerateState< T > &self ) {
              return ISTLReverseEnumerateIteratorState< T >{ self.obj->beforeEnd(), self.obj->beforeBegin() };
            }, pybind11::keep_alive< 0, 1 >() );
        }

        cls.def_property_readonly( "enumerate", [] ( pybind11::object self ) {
            return ISTLEnumerateState< T >{ &pybind11::cast< T & >( self ), self };
          } );
      }

    } // namespace detail

  } // namespace Python

} // namespace Dune

#endif // #ifndef DUNE_PYTHON_ISTL_ITERATOR_HH