• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 MAP_INDEXING_SUITE_JDG20038_HPP
7 # define MAP_INDEXING_SUITE_JDG20038_HPP
8 
9 # include <boost/python/suite/indexing/indexing_suite.hpp>
10 # include <boost/python/iterator.hpp>
11 # include <boost/python/call_method.hpp>
12 # include <boost/python/tuple.hpp>
13 
14 namespace boost { namespace python {
15 
16     // Forward declaration
17     template <class Container, bool NoProxy, class DerivedPolicies>
18     class map_indexing_suite;
19 
20     namespace detail
21     {
22         template <class Container, bool NoProxy>
23         class final_map_derived_policies
24             : public map_indexing_suite<Container,
25                 NoProxy, final_map_derived_policies<Container, NoProxy> > {};
26     }
27 
28     // The map_indexing_suite class is a predefined indexing_suite derived
29     // class for wrapping std::map (and std::map like) classes. It provides
30     // all the policies required by the indexing_suite (see indexing_suite).
31     // Example usage:
32     //
33     //  class X {...};
34     //
35     //  ...
36     //
37     //      class_<std::map<std::string, X> >("XMap")
38     //          .def(map_indexing_suite<std::map<std::string, X> >())
39     //      ;
40     //
41     // By default indexed elements are returned by proxy. This can be
42     // disabled by supplying *true* in the NoProxy template parameter.
43     //
44     template <
45         class Container,
46         bool NoProxy = false,
47         class DerivedPolicies
48             = detail::final_map_derived_policies<Container, NoProxy> >
49     class map_indexing_suite
50         : public indexing_suite<
51             Container
52           , DerivedPolicies
53           , NoProxy
54           , true
55           , typename Container::value_type::second_type
56           , typename Container::key_type
57           , typename Container::key_type
58         >
59     {
60     public:
61 
62         typedef typename Container::value_type value_type;
63         typedef typename Container::value_type::second_type data_type;
64         typedef typename Container::key_type key_type;
65         typedef typename Container::key_type index_type;
66         typedef typename Container::size_type size_type;
67         typedef typename Container::difference_type difference_type;
68 
69         template <class Class>
70         static void
extension_def(Class & cl)71         extension_def(Class& cl)
72         {
73             //  Wrap the map's element (value_type)
74             std::string elem_name = "map_indexing_suite_";
75             object class_name(cl.attr("__name__"));
76             extract<std::string> class_name_extractor(class_name);
77             elem_name += class_name_extractor();
78             elem_name += "_entry";
79 
80             typedef typename mpl::if_<
81                 mpl::and_<is_class<data_type>, mpl::bool_<!NoProxy> >
82               , return_internal_reference<>
83               , default_call_policies
84             >::type get_data_return_policy;
85 
86             class_<value_type>(elem_name.c_str())
87                 .def("__repr__", &DerivedPolicies::print_elem)
88                 .def("data", &DerivedPolicies::get_data, get_data_return_policy())
89                 .def("key", &DerivedPolicies::get_key)
90             ;
91         }
92 
93         static object
print_elem(typename Container::value_type const & e)94         print_elem(typename Container::value_type const& e)
95         {
96             return "(%s, %s)" % python::make_tuple(e.first, e.second);
97         }
98 
99         static
100         typename mpl::if_<
101             mpl::and_<is_class<data_type>, mpl::bool_<!NoProxy> >
102           , data_type&
103           , data_type
104         >::type
get_data(typename Container::value_type & e)105         get_data(typename Container::value_type& e)
106         {
107             return e.second;
108         }
109 
110         static typename Container::key_type
get_key(typename Container::value_type & e)111         get_key(typename Container::value_type& e)
112         {
113             return e.first;
114         }
115 
116         static data_type&
get_item(Container & container,index_type i_)117         get_item(Container& container, index_type i_)
118         {
119             typename Container::iterator i = container.find(i_);
120             if (i == container.end())
121             {
122                 PyErr_SetString(PyExc_KeyError, "Invalid key");
123                 throw_error_already_set();
124             }
125             return i->second;
126         }
127 
128         static void
set_item(Container & container,index_type i,data_type const & v)129         set_item(Container& container, index_type i, data_type const& v)
130         {
131             container[i] = v;
132         }
133 
134         static void
delete_item(Container & container,index_type i)135         delete_item(Container& container, index_type i)
136         {
137             container.erase(i);
138         }
139 
140         static size_t
size(Container & container)141         size(Container& container)
142         {
143             return container.size();
144         }
145 
146         static bool
contains(Container & container,key_type const & key)147         contains(Container& container, key_type const& key)
148         {
149             return container.find(key) != container.end();
150         }
151 
152         static bool
compare_index(Container & container,index_type a,index_type b)153         compare_index(Container& container, index_type a, index_type b)
154         {
155             return container.key_comp()(a, b);
156         }
157 
158         static index_type
convert_index(Container &,PyObject * i_)159         convert_index(Container& /*container*/, PyObject* i_)
160         {
161             extract<key_type const&> i(i_);
162             if (i.check())
163             {
164                 return i();
165             }
166             else
167             {
168                 extract<key_type> i(i_);
169                 if (i.check())
170                     return i();
171             }
172 
173             PyErr_SetString(PyExc_TypeError, "Invalid index type");
174             throw_error_already_set();
175             return index_type();
176         }
177     };
178 
179 }} // namespace boost::python
180 
181 #endif // MAP_INDEXING_SUITE_JDG20038_HPP
182