~yade-dev/yade/0.80

1 by Anton Gladky
0.80.0
1
// Copyright (c) 2003 Raoul M. Gough
2
//
3
// Use, modification and distribution is subject to the Boost Software
4
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
5
// at http://www.boost.org/LICENSE_1_0.txt)
6
//
7
// Header file int_slice_helper.hpp
8
//
9
// History
10
// =======
11
// 2003/10/13   rmg     File creation
12
// 2008/12/08   Roman   Change indexing suite layout
13
//
14
// $Id: int_slice_helper.hpp,v 1.1.2.10 2004/02/08 18:57:42 raoulgough Exp $
15
//
16
17
#ifndef BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP
18
#define BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP
19
20
# include <boost/python/errors.hpp>
21
# include <indexing_suite/workaround.hpp>
22
23
namespace boost { namespace python { namespace indexing {
24
  template<typename Algorithms, typename SliceType>
25
  struct int_slice_helper
26
  {
27
    // Works with a SliceType that provides an int-like index_type
28
    // that is convertible to the algorithm's index_param
29
30
    typedef Algorithms algorithms_type;
31
    typedef SliceType slice_type;
32
33
    typedef typename algorithms_type::container container;
34
    typedef typename algorithms_type::reference reference;
35
    typedef typename algorithms_type::value_param value_param;
36
    typedef typename algorithms_type::container_traits container_traits;
37
    typedef typename slice_type::index_type index_type;
38
39
    int_slice_helper (container &c, slice_type const &);
40
41
    bool next();
42
43
    reference current () const;
44
    void write (value_param val);
45
    void erase_remaining () const;
46
47
  private:
48
    void assign (value_param val) const;
49
    void insert (value_param val);
50
51
  private:
52
    slice_type m_slice;
53
    container *m_ptr;
54
    index_type m_pos;
55
  };
56
57
  template<typename Algorithms, typename SliceType>
58
  int_slice_helper<Algorithms, SliceType>
59
  ::int_slice_helper (container &c, slice_type const &sl)
60
    : m_slice (sl),
61
    m_ptr (&c),
62
    m_pos (-1)
63
  {
64
  }
65
66
  template<typename Algorithms, typename SliceType>
67
  bool
68
  int_slice_helper<Algorithms, SliceType>::next()
69
  {
70
    bool result = false; // Assume the worst
71
72
    if (m_pos == -1)
73
      {
74
        // First time call - get to start of the slice (if any)
75
        m_pos = m_slice.start();
76
        result = m_slice.in_range (m_pos);
77
      }
78
79
    else if (m_slice.in_range (m_pos))
80
      {
81
        // Subsequent calls - advance by the slice's stride
82
        m_pos += m_slice.step();
83
        result = m_slice.in_range (m_pos);
84
      }
85
86
    return result;
87
  }
88
89
  template<typename Algorithms, typename SliceType>
90
  typename int_slice_helper<Algorithms, SliceType>::reference
91
  int_slice_helper<Algorithms, SliceType>::current () const
92
  {
93
    return algorithms_type::get (*m_ptr, m_pos);
94
  }
95
96
  template<typename Algorithms, typename SliceType>
97
  void int_slice_helper<Algorithms, SliceType>::write (value_param val)
98
  {
99
    if (next())
100
      {
101
        assign (val);
102
      }
103
104
    else
105
      {
106
        insert (val);
107
      }
108
  }
109
110
  template<typename Algorithms, typename SliceType>
111
  void int_slice_helper<Algorithms, SliceType>::assign (value_param val) const
112
  {
113
    algorithms_type::assign (*m_ptr, m_pos, val);
114
  }
115
116
  namespace detail {
117
    template<bool doit> struct maybe_insert {
118
119
      // NOTE: use the name "apply_" instead of "apply" to avoid
120
      // weirdo compiler crash in mpl/aux_/apply.hpp on MSVC7. Don't
121
      // even ask how I arrived at this fix :-)
122
123
      template<class Algorithms>
124
      static void apply_(
125
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
126
        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
127
          // Can't explicitly instantiate member function - must let
128
          // the compiler deduce the argument type from a dummy
129
          // parameter. Same applies throughout
130
          Algorithms *,
131
# endif
132
          typename Algorithms::container &,
133
          typename Algorithms::index_param,
134
          typename Algorithms::value_param)
135
      {
136
        PyErr_SetString(
137
            PyExc_TypeError,
138
            "container does not support insertion into slice");
139
140
        boost::python::throw_error_already_set ();
141
      }
142
    };
143
144
    template<> struct maybe_insert<true> {
145
      template<class Algorithms>
146
      static void apply_(
147
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
148
        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
149
          Algorithms *,
150
# endif
151
          typename Algorithms::container &c,
152
          typename Algorithms::index_param i,
153
          typename Algorithms::value_param v)
154
      {
155
        Algorithms::insert (c, i, v);
156
      }
157
    };
158
  }
159
160
  template<typename Algorithms, typename SliceType>
161
  void int_slice_helper<Algorithms, SliceType>::insert (value_param val)
162
  {
163
    if (m_slice.step() != 1)
164
      {
165
        PyErr_SetString(
166
            PyExc_ValueError, "attempt to insert via extended slice");
167
168
        boost::python::throw_error_already_set ();
169
      }
170
171
    else
172
      {
173
        detail::maybe_insert<
174
          detail::is_member<
175
            container_traits::supported_methods, method_insert>::value>::
176
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
177
  && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
178
          apply_ (static_cast<Algorithms *>(0),
179
# else
180
          BOOST_NESTED_TEMPLATE apply_ <Algorithms>(
181
# endif
182
              *m_ptr, m_pos, val);
183
184
        ++m_pos;  // Advance for any subsequent inserts
185
      }
186
  }
187
188
  namespace detail {
189
    template<bool doit> struct maybe_erase {
190
      template<class Algorithms>
191
      static void apply_(
192
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
193
        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
194
          Algorithms *,
195
# endif
196
          typename Algorithms::container &,
197
          typename Algorithms::index_param,
198
          typename Algorithms::index_param)
199
      {
200
        PyErr_SetString(
201
            PyExc_TypeError, "container does not support item deletion");
202
203
        boost::python::throw_error_already_set ();
204
      }
205
    };
206
207
    template<> struct maybe_erase<true> {
208
      template<class Algorithms>
209
      static void apply_(
210
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
211
        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
212
          Algorithms *,
213
# endif
214
          typename Algorithms::container &c,
215
          typename Algorithms::index_param from,
216
          typename Algorithms::index_param to)
217
      {
218
        Algorithms::erase_range (c, from, to);
219
      }
220
    };
221
  }
222
223
  template<typename Algorithms, typename SliceType>
224
  void int_slice_helper<Algorithms, SliceType>::erase_remaining () const
225
  {
226
    if (m_slice.step() != 1)
227
      {
228
        PyErr_SetString(
229
            PyExc_ValueError, "attempt to delete via extended slice");
230
231
        boost::python::throw_error_already_set ();
232
      }
233
234
    else
235
      {
236
        detail::maybe_erase<
237
          detail::is_member<
238
            container_traits::supported_methods, method_delitem>::value>::
239
240
# if defined (BOOST_NO_MEMBER_TEMPLATES) \
241
  && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
242
          apply_ (static_cast<Algorithms *>(0),
243
# else
244
          BOOST_NESTED_TEMPLATE apply_ <Algorithms>(
245
# endif
246
              *m_ptr, m_pos, m_slice.stop());
247
      }
248
  }
249
250
} } }
251
252
#endif // BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP