~yade-dev/yade/0.80

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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
// Copyright (c) 2003 Raoul M. Gough
//
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
// at http://www.boost.org/LICENSE_1_0.txt)
//
// Header file int_slice_helper.hpp
//
// History
// =======
// 2003/10/13   rmg     File creation
// 2008/12/08   Roman   Change indexing suite layout
//
// $Id: int_slice_helper.hpp,v 1.1.2.10 2004/02/08 18:57:42 raoulgough Exp $
//

#ifndef BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP
#define BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP

# include <boost/python/errors.hpp>
# include <indexing_suite/workaround.hpp>

namespace boost { namespace python { namespace indexing {
  template<typename Algorithms, typename SliceType>
  struct int_slice_helper
  {
    // Works with a SliceType that provides an int-like index_type
    // that is convertible to the algorithm's index_param

    typedef Algorithms algorithms_type;
    typedef SliceType slice_type;

    typedef typename algorithms_type::container container;
    typedef typename algorithms_type::reference reference;
    typedef typename algorithms_type::value_param value_param;
    typedef typename algorithms_type::container_traits container_traits;
    typedef typename slice_type::index_type index_type;

    int_slice_helper (container &c, slice_type const &);

    bool next();

    reference current () const;
    void write (value_param val);
    void erase_remaining () const;

  private:
    void assign (value_param val) const;
    void insert (value_param val);

  private:
    slice_type m_slice;
    container *m_ptr;
    index_type m_pos;
  };

  template<typename Algorithms, typename SliceType>
  int_slice_helper<Algorithms, SliceType>
  ::int_slice_helper (container &c, slice_type const &sl)
    : m_slice (sl),
    m_ptr (&c),
    m_pos (-1)
  {
  }

  template<typename Algorithms, typename SliceType>
  bool
  int_slice_helper<Algorithms, SliceType>::next()
  {
    bool result = false; // Assume the worst

    if (m_pos == -1)
      {
        // First time call - get to start of the slice (if any)
        m_pos = m_slice.start();
        result = m_slice.in_range (m_pos);
      }

    else if (m_slice.in_range (m_pos))
      {
        // Subsequent calls - advance by the slice's stride
        m_pos += m_slice.step();
        result = m_slice.in_range (m_pos);
      }

    return result;
  }

  template<typename Algorithms, typename SliceType>
  typename int_slice_helper<Algorithms, SliceType>::reference
  int_slice_helper<Algorithms, SliceType>::current () const
  {
    return algorithms_type::get (*m_ptr, m_pos);
  }

  template<typename Algorithms, typename SliceType>
  void int_slice_helper<Algorithms, SliceType>::write (value_param val)
  {
    if (next())
      {
        assign (val);
      }

    else
      {
        insert (val);
      }
  }

  template<typename Algorithms, typename SliceType>
  void int_slice_helper<Algorithms, SliceType>::assign (value_param val) const
  {
    algorithms_type::assign (*m_ptr, m_pos, val);
  }

  namespace detail {
    template<bool doit> struct maybe_insert {

      // NOTE: use the name "apply_" instead of "apply" to avoid
      // weirdo compiler crash in mpl/aux_/apply.hpp on MSVC7. Don't
      // even ask how I arrived at this fix :-)

      template<class Algorithms>
      static void apply_(
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
          // Can't explicitly instantiate member function - must let
          // the compiler deduce the argument type from a dummy
          // parameter. Same applies throughout
          Algorithms *,
# endif
          typename Algorithms::container &,
          typename Algorithms::index_param,
          typename Algorithms::value_param)
      {
        PyErr_SetString(
            PyExc_TypeError,
            "container does not support insertion into slice");

        boost::python::throw_error_already_set ();
      }
    };

    template<> struct maybe_insert<true> {
      template<class Algorithms>
      static void apply_(
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
          Algorithms *,
# endif
          typename Algorithms::container &c,
          typename Algorithms::index_param i,
          typename Algorithms::value_param v)
      {
        Algorithms::insert (c, i, v);
      }
    };
  }

  template<typename Algorithms, typename SliceType>
  void int_slice_helper<Algorithms, SliceType>::insert (value_param val)
  {
    if (m_slice.step() != 1)
      {
        PyErr_SetString(
            PyExc_ValueError, "attempt to insert via extended slice");

        boost::python::throw_error_already_set ();
      }

    else
      {
        detail::maybe_insert<
          detail::is_member<
            container_traits::supported_methods, method_insert>::value>::
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
  && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
          apply_ (static_cast<Algorithms *>(0),
# else
          BOOST_NESTED_TEMPLATE apply_ <Algorithms>(
# endif
              *m_ptr, m_pos, val);

        ++m_pos;  // Advance for any subsequent inserts
      }
  }

  namespace detail {
    template<bool doit> struct maybe_erase {
      template<class Algorithms>
      static void apply_(
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
          Algorithms *,
# endif
          typename Algorithms::container &,
          typename Algorithms::index_param,
          typename Algorithms::index_param)
      {
        PyErr_SetString(
            PyExc_TypeError, "container does not support item deletion");

        boost::python::throw_error_already_set ();
      }
    };

    template<> struct maybe_erase<true> {
      template<class Algorithms>
      static void apply_(
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
          Algorithms *,
# endif
          typename Algorithms::container &c,
          typename Algorithms::index_param from,
          typename Algorithms::index_param to)
      {
        Algorithms::erase_range (c, from, to);
      }
    };
  }

  template<typename Algorithms, typename SliceType>
  void int_slice_helper<Algorithms, SliceType>::erase_remaining () const
  {
    if (m_slice.step() != 1)
      {
        PyErr_SetString(
            PyExc_ValueError, "attempt to delete via extended slice");

        boost::python::throw_error_already_set ();
      }

    else
      {
        detail::maybe_erase<
          detail::is_member<
            container_traits::supported_methods, method_delitem>::value>::

# if defined (BOOST_NO_MEMBER_TEMPLATES) \
  && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
          apply_ (static_cast<Algorithms *>(0),
# else
          BOOST_NESTED_TEMPLATE apply_ <Algorithms>(
# endif
              *m_ptr, m_pos, m_slice.stop());
      }
  }

} } }

#endif // BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP