source: trunk/environments/g4py/source/boost/vector_indexing_suite.hpp @ 1337

Last change on this file since 1337 was 1337, checked in by garnier, 14 years ago

tag geant4.9.4 beta 1 + modifs locales

File size: 7.1 KB
Line 
1//  (C) Copyright Joel de Guzman 2003.
2//  Distributed under the Boost Software License, Version 1.0. (See
3//  accompanying file LICENSE_1_0.txt or copy at
4//  http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef VECTOR_INDEXING_SUITE_JDG20036_HPP
7# define VECTOR_INDEXING_SUITE_JDG20036_HPP
8
9# include "indexing_suite.hpp"
10# include "container_utils.hpp"
11# include <boost/python/iterator.hpp>
12
13namespace boost { namespace python {
14           
15    // Forward declaration
16    template <class Container, bool NoProxy, class DerivedPolicies>
17    class vector_indexing_suite;
18   
19    namespace detail
20    {
21        template <class Container, bool NoProxy>
22        class final_vector_derived_policies 
23            : public vector_indexing_suite<Container, 
24                NoProxy, final_vector_derived_policies<Container, NoProxy> > {};
25    }
26
27    // The vector_indexing_suite class is a predefined indexing_suite derived
28    // class for wrapping std::vector (and std::vector like) classes. It provides
29    // all the policies required by the indexing_suite (see indexing_suite).
30    // Example usage:
31    //
32    //  class X {...};
33    //
34    //  ...
35    //
36    //      class_<std::vector<X> >("XVec")
37    //          .def(vector_indexing_suite<std::vector<X> >())
38    //      ;
39    //
40    // By default indexed elements are returned by proxy. This can be
41    // disabled by supplying *true* in the NoProxy template parameter.
42    //
43    template <
44        class Container, 
45        bool NoProxy = false,
46        class DerivedPolicies 
47            = detail::final_vector_derived_policies<Container, NoProxy> >
48    class vector_indexing_suite 
49        : public indexing_suite<Container, DerivedPolicies, NoProxy>
50    {
51    public:
52   
53        typedef typename Container::value_type data_type;
54        typedef typename Container::value_type key_type;
55        typedef typename Container::size_type index_type;
56        typedef typename Container::size_type size_type;
57        typedef typename Container::difference_type difference_type;
58       
59        template <class Class>
60        static void 
61        extension_def(Class& cl)
62        {
63            cl
64                .def("append", &base_append)
65                .def("push_back", &base_append)
66                .def("extend", &base_extend)
67            ;
68        }
69       
70        static 
71        typename mpl::if_<
72            is_class<data_type>
73          , data_type&
74          , data_type
75        >::type
76        get_item(Container& container, index_type i)
77        { 
78            return container[i];
79        }
80
81        static object
82        get_slice(Container& container, index_type from, index_type to)
83        { 
84            if (from > to)
85                return object(Container());
86            return object(Container(container.begin()+from, container.begin()+to));
87        }
88
89        static void 
90        set_item(Container& container, index_type i, data_type const& v)
91        { 
92            container[i] = v;
93        }
94
95        static void 
96        set_slice(Container& container, index_type from, 
97            index_type to, data_type const& v)
98        { 
99            if (from > to) {
100                return;
101            }
102            else {
103                container.erase(container.begin()+from, container.begin()+to);
104                container.insert(container.begin()+from, v);
105            }
106        }
107
108        template <class Iter>
109        static void 
110        set_slice(Container& container, index_type from, 
111            index_type to, Iter first, Iter last)
112        { 
113            if (from > to) {
114                container.insert(container.begin()+from, first, last);
115            }
116            else {
117                container.erase(container.begin()+from, container.begin()+to);
118                container.insert(container.begin()+from, first, last);
119            }
120        }
121
122        static void 
123        delete_item(Container& container, index_type i)
124        { 
125            container.erase(container.begin()+i);
126        }
127       
128        static void 
129        delete_slice(Container& container, index_type from, index_type to)
130        { 
131            if (from > to) {
132                // A null-op.
133                return;
134            }
135            container.erase(container.begin()+from, container.begin()+to);
136        }
137       
138        static size_t
139        size(Container& container)
140        {
141            return container.size();
142        }
143       
144        static bool
145        contains(Container& container, key_type const& key)
146        {
147            return std::find(container.begin(), container.end(), key)
148                != container.end();
149        }
150       
151        static index_type
152        get_min_index(Container& container)
153        { 
154            return 0;
155        }
156
157        static index_type
158        get_max_index(Container& container)
159        { 
160            return container.size();
161        }
162     
163        static bool 
164        compare_index(Container& container, index_type a, index_type b)
165        {
166            return a < b;
167        }
168       
169        static index_type
170        convert_index(Container& container, PyObject* i_)
171        { 
172            extract<long> i(i_);
173            if (i.check())
174            {
175                long index = i();
176                if (index < 0)
177                    index += DerivedPolicies::size(container);
178                if (index >= long(container.size()) || index < 0)
179                {
180                    PyErr_SetString(PyExc_IndexError, "Index out of range");
181                    throw_error_already_set();
182                }
183                return index;
184            }
185           
186            PyErr_SetString(PyExc_TypeError, "Invalid index type");
187            throw_error_already_set();
188            return index_type();
189        }
190     
191        static void 
192        append(Container& container, data_type const& v)
193        { 
194            container.push_back(v);
195        }
196       
197        template <class Iter>
198        static void 
199        extend(Container& container, Iter first, Iter last)
200        { 
201            container.insert(container.end(), first, last);
202        }
203       
204    private:
205   
206        static void
207        base_append(Container& container, object v)
208        {
209            extract<data_type&> elem(v);
210            // try if elem is an exact Data
211            if (elem.check())
212            {
213                DerivedPolicies::append(container, elem());
214            }
215            else
216            {
217                //  try to convert elem to data_type
218                extract<data_type> elem(v);
219                if (elem.check())
220                {
221                    DerivedPolicies::append(container, elem());
222                }
223                else
224                {
225                    PyErr_SetString(PyExc_TypeError, 
226                        "Attempting to append an invalid type");
227                    throw_error_already_set();
228                }
229            }
230        }
231       
232        static void
233        base_extend(Container& container, object v)
234        {
235            std::vector<data_type> temp;
236            container_utils::extend_container(temp, v);
237            DerivedPolicies::extend(container, temp.begin(), temp.end());
238        }
239    };
240       
241}} // namespace boost::python
242
243#endif // VECTOR_INDEXING_SUITE_JDG20036_HPP
Note: See TracBrowser for help on using the repository browser.