]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/parameter/python.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / parameter / python.hpp
CommitLineData
7c673cae
FG
1// Copyright Daniel Wallin 2006. Use, modification and distribution is
2// subject to the Boost Software License, Version 1.0. (See accompanying
3// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5#ifndef BOOST_PARAMETER_PYTHON_060209_HPP
6# define BOOST_PARAMETER_PYTHON_060209_HPP
7
8# include <boost/mpl/vector.hpp>
9# include <boost/mpl/fold.hpp>
10# include <boost/mpl/prior.hpp>
11# include <boost/mpl/shift_right.hpp>
12# include <boost/mpl/shift_left.hpp>
13# include <boost/mpl/bitand.hpp>
14# include <boost/mpl/pair.hpp>
15# include <boost/mpl/size.hpp>
16# include <boost/mpl/push_back.hpp>
17# include <boost/mpl/or.hpp>
18# include <boost/mpl/count_if.hpp>
19# include <boost/mpl/transform.hpp>
20# include <boost/mpl/front.hpp>
21# include <boost/mpl/iterator_range.hpp>
22# include <boost/mpl/next.hpp>
23# include <boost/mpl/begin_end.hpp>
24# include <boost/mpl/not.hpp>
25# include <boost/mpl/empty.hpp>
26# include <boost/python/def.hpp>
27# include <boost/python/make_constructor.hpp>
28# include <boost/python/init.hpp>
29# include <boost/python/to_python_converter.hpp>
30# include <boost/parameter/aux_/maybe.hpp>
31# include <boost/parameter/aux_/python/invoker.hpp>
32
33namespace boost { namespace parameter { namespace python
34{
35 namespace python_ = boost::python;
36}}}
37
38namespace boost { namespace parameter { namespace python { namespace aux
39{
40
41 inline PyObject* unspecified_type()
42 {
43 static PyTypeObject unspecified = {
92f5a8d4 44 PyVarObject_HEAD_INIT(NULL,0)
7c673cae
FG
45 "Boost.Parameter.Unspecified", /* tp_name */
46 PyType_Type.tp_basicsize, /* tp_basicsize */
47 0, /* tp_itemsize */
48 0, /* tp_dealloc */
49 0, /* tp_print */
50 0, /* tp_getattr */
51 0, /* tp_setattr */
52 0, /* tp_compare */
53 0, /* tp_repr */
54 0, /* tp_as_number */
55 0, /* tp_as_sequence */
56 0, /* tp_as_mapping */
57 0, /* tp_hash */
58 0, /* tp_call */
59 0, /* tp_str */
60 0, /* tp_getattro */
61 0, /* tp_setattro */
62 0, /* tp_as_buffer */
63 Py_TPFLAGS_DEFAULT, /* tp_flags */
64 0, /* tp_doc */
65 };
92f5a8d4
TL
66
67 if (Py_TYPE(&unspecified) == 0)
7c673cae 68 {
92f5a8d4 69 Py_TYPE(&unspecified) = &PyType_Type;
7c673cae
FG
70 PyType_Ready(&unspecified);
71 }
92f5a8d4 72
7c673cae
FG
73 return (PyObject*)&unspecified;
74 }
75
76 struct empty_tag {};
77
78 struct empty_tag_to_python
79 {
80 static PyObject* convert(empty_tag)
81 {
82 return python_::xincref(unspecified_type());
83 }
84 };
85
86}}}} // namespace boost::parameter::python::aux
87
88namespace boost { namespace python
89{
90
91 // Converts a Python value to a maybe<T>
92 template <class T>
93 struct arg_from_python<parameter::aux::maybe<T> >
94 : arg_from_python<T>
95 {
96 arg_from_python(PyObject* p)
97 : arg_from_python<T>(p)
98 , empty(parameter::python::aux::unspecified_type() == p)
99 {}
100
101 bool convertible() const
102 {
103 return empty || arg_from_python<T>::convertible();
104 }
105
106 parameter::aux::maybe<T> operator()()
107 {
108 if (empty)
109 {
110 return parameter::aux::maybe<T>();
111 }
112 else
113 {
114 return parameter::aux::maybe<T>(
115 arg_from_python<T>::operator()()
116 );
117 }
118 }
119
120 bool empty;
121 };
122
123}} // namespace boost::python
124
125namespace boost { namespace parameter { namespace python {
126
127namespace aux
128{
129
130 template <class K>
131 struct is_optional
132 : mpl::not_<
133 mpl::or_<typename K::required, typename K::optimized_default>
134 >
135 {};
136
137 template <class K, class Required, class Optimized, class T>
138 struct arg_spec
139 {
140 typedef K keyword;
141 typedef Required required;
142 typedef T type;
143 typedef Optimized optimized_default;
144 };
145
146 template <class K, class T, class Optimized = mpl::false_>
147 struct make_arg_spec_impl
148 {
149 typedef arg_spec<
150 typename K::first, typename K::second, Optimized, T
151 > type;
152 };
153
154 template <class K, class T>
155 struct make_arg_spec_impl<K, T, typename K::third>
156 {
157 typedef arg_spec<
158 typename K::first, typename K::second, typename K::third, T
159 > type;
160 };
161
162 template <class K, class T>
163 struct make_arg_spec
164 : make_arg_spec_impl<K, T>
165 {
166 };
167
168 template <class Spec, class State>
169 struct combinations_op
170 {
171 typedef typename State::second bits;
172 typedef typename State::first result0;
173
174 typedef typename mpl::if_<
175 mpl::or_<
176 typename Spec::required
177 , typename Spec::optimized_default
178 , mpl::bitand_<bits, mpl::long_<1> >
179 >
180 , typename mpl::push_back<result0, Spec>::type
181 , result0
182 >::type result;
183
184 typedef typename mpl::if_<
185 mpl::or_<
186 typename Spec::required
187 , typename Spec::optimized_default
188 >
189 , bits
190 , typename mpl::shift_right<bits, mpl::long_<1> >::type
191 >::type next_bits;
192
193 typedef mpl::pair<
194 result
195 , next_bits
196 > type;
197 };
198
199 // Used as start value in the recursive arg() composition below.
200 struct no_keywords
201 {
202 template <class T>
203 T const& operator,(T const& x) const
204 {
205 return x;
206 }
207 };
208
209 template <class Def, class F, class Iter, class End, class Keywords>
210 void def_combination_aux0(
211 Def def, F f, Iter, End, Keywords const& keywords, mpl::false_)
212 {
213 typedef typename mpl::deref<Iter>::type spec;
214 typedef typename spec::keyword kw;
215
216 def_combination_aux(
217 def, f, typename mpl::next<Iter>::type(), End()
218 , (
219 keywords, boost::python::arg(kw::keyword_name())
220 )
221 );
222 }
223
224 template <class Def, class F, class Iter, class End, class Keywords>
225 void def_combination_aux0(
226 Def def, F f, Iter, End, Keywords const& keywords, mpl::true_)
227 {
228 typedef typename mpl::deref<Iter>::type spec;
229 typedef typename spec::keyword kw;
230
231 def_combination_aux(
232 def, f, typename mpl::next<Iter>::type(), End()
233 , (
234 keywords, boost::python::arg(kw::keyword_name()) = empty_tag()
235 )
236 );
237 }
238
239 inline void initialize_converter()
240 {
241 static python_::to_python_converter<empty_tag, empty_tag_to_python> x;
242 }
243
244 template <class Def, class F, class Iter, class End, class Keywords>
245 void def_combination_aux(
246 Def def, F f, Iter, End, Keywords const& keywords)
247 {
248 typedef typename mpl::deref<Iter>::type spec;
249
250 typedef typename mpl::and_<
251 typename spec::optimized_default
252 , mpl::not_<typename spec::required>
253 >::type optimized_default;
254
255 def_combination_aux0(
256 def, f, Iter(), End(), keywords, optimized_default()
257 );
258 }
259
260 template <class Def, class F, class End, class Keywords>
261 void def_combination_aux(
262 Def def, F f, End, End, Keywords const& keywords)
263 {
264 def(f, keywords);
265 }
266
267 template <class Def, class F, class End>
268 void def_combination_aux(
269 Def def, F f, End, End, no_keywords const&)
270 {
271 def(f);
272 }
273
274 template <
275 class Def, class Specs, class Bits, class Invoker
276 >
277 void def_combination(
278 Def def, Specs*, Bits, Invoker*)
279 {
280 typedef typename mpl::fold<
281 Specs
282 , mpl::pair<mpl::vector0<>, Bits>
283 , combinations_op<mpl::_2, mpl::_1>
284 >::type combination0;
285
286 typedef typename combination0::first combination;
287
288 typedef typename mpl::apply_wrap1<
289 Invoker, combination
290 >::type invoker;
291
292 def_combination_aux(
293 def
294 , &invoker::execute
295 , typename mpl::begin<combination>::type()
296 , typename mpl::end<combination>::type()
297 , no_keywords()
298 );
299 }
300
301 template <
302 class Def, class Specs, class Bits, class End, class Invoker
303 >
304 void def_combinations(
305 Def def, Specs*, Bits, End, Invoker*)
306 {
307 initialize_converter();
308
309 def_combination(def, (Specs*)0, Bits(), (Invoker*)0);
310
311 def_combinations(
312 def
313 , (Specs*)0
314 , mpl::long_<Bits::value + 1>()
315 , End()
316 , (Invoker*)0
317 );
318 }
319
320 template <
321 class Def, class Specs, class End, class Invoker
322 >
323 void def_combinations(
324 Def, Specs*, End, End, Invoker*)
325 {}
326
327 struct not_specified {};
328
329 template <class CallPolicies>
330 struct call_policies_as_options
331 {
332 call_policies_as_options(CallPolicies const& call_policies)
333 : call_policies(call_policies)
334 {}
335
336 CallPolicies const& policies() const
337 {
338 return call_policies;
339 }
340
341 char const* doc() const
342 {
343 return 0;
344 }
345
346 CallPolicies call_policies;
347 };
348
349 template <class Class, class Options = not_specified>
350 struct def_class
351 {
352 def_class(Class& cl, char const* name, Options options = Options())
353 : cl(cl)
354 , name(name)
355 , options(options)
356 {}
357
358 template <class F>
359 void def(F f, not_specified const*) const
360 {
361 cl.def(name, f);
362 }
363
364 template <class F>
365 void def(F f, void const*) const
366 {
367 cl.def(name, f, options.doc(), options.policies());
368 }
369
370 template <class F>
371 void operator()(F f) const
372 {
373 this->def(f, &options);
374 }
375
376 template <class F, class Keywords>
377 void def(F f, Keywords const& keywords, not_specified const*) const
378 {
379 cl.def(name, f, keywords);
380 }
381
382 template <class F, class Keywords>
383 void def(F f, Keywords const& keywords, void const*) const
384 {
385 cl.def(name, f, keywords, options.doc(), options.policies());
386 }
387
388 template <class F, class Keywords>
389 void operator()(F f, Keywords const& keywords) const
390 {
391 this->def(f, keywords, &options);
392 }
393
394 Class& cl;
395 char const* name;
396 Options options;
397 };
398
399 template <class Class, class CallPolicies = boost::python::default_call_policies>
400 struct def_init
401 {
402 def_init(Class& cl, CallPolicies call_policies = CallPolicies())
403 : cl(cl)
404 , call_policies(call_policies)
405 {}
406
407 template <class F>
408 void operator()(F f) const
409 {
410 cl.def(
411 "__init__"
412 , boost::python::make_constructor(f, call_policies)
413 );
414 }
415
416 template <class F, class Keywords>
417 void operator()(F f, Keywords const& keywords) const
418 {
419 cl.def(
420 "__init__"
421 , boost::python::make_constructor(f, call_policies, keywords)
422 );
423 }
424
425 Class& cl;
426 CallPolicies call_policies;
427 };
428
429 struct def_function
430 {
431 def_function(char const* name)
432 : name(name)
433 {}
434
435 template <class F>
436 void operator()(F f) const
437 {
438 boost::python::def(name, f);
439 }
440
441 template <class F, class Keywords>
442 void operator()(F f, Keywords const& keywords) const
443 {
444 boost::python::def(name, f, keywords);
445 }
446
447 char const* name;
448 };
449
450} // namespace aux
451
452template <class M, class Signature>
453void def(char const* name, Signature)
454{
455 typedef mpl::iterator_range<
456 typename mpl::next<
457 typename mpl::begin<Signature>::type
458 >::type
459 , typename mpl::end<Signature>::type
460 > arg_types;
461
462 typedef typename mpl::transform<
463 typename M::keywords
464 , arg_types
465 , aux::make_arg_spec<mpl::_1, mpl::_2>
466 , mpl::back_inserter<mpl::vector0<> >
467 >::type arg_specs;
468
469 typedef typename mpl::count_if<
470 arg_specs
471 , aux::is_optional<mpl::_1>
472 >::type optional_arity;
473
474 typedef typename mpl::front<Signature>::type result_type;
475 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
476
477 aux::def_combinations(
478 aux::def_function(name)
479 , (arg_specs*)0
480 , mpl::long_<0>()
481 , mpl::long_<upper::value>()
482 , (aux::make_invoker<M, result_type>*)0
483 );
484}
485
486template <class M, class Class, class Signature>
487void def(Class& cl, char const* name, Signature)
488{
489 typedef mpl::iterator_range<
490 typename mpl::next<
491 typename mpl::begin<Signature>::type
492 >::type
493 , typename mpl::end<Signature>::type
494 > arg_types;
495
496 typedef typename mpl::transform<
497 typename M::keywords
498 , arg_types
499 , aux::make_arg_spec<mpl::_1, mpl::_2>
500 , mpl::back_inserter<mpl::vector0<> >
501 >::type arg_specs;
502
503 typedef typename mpl::count_if<
504 arg_specs
505 , aux::is_optional<mpl::_1>
506 >::type optional_arity;
507
508 typedef typename mpl::front<Signature>::type result_type;
509 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
510
511 aux::def_combinations(
512 aux::def_class<Class>(cl, name)
513 , (arg_specs*)0
514 , mpl::long_<0>()
515 , mpl::long_<upper::value>()
516 , (aux::make_invoker<M, result_type>*)0
517 );
518}
519
520namespace aux
521{
522
523 template <class K>
524 struct keyword
525 {
526 typedef K type;
527 };
528
529 template <class K>
530 struct keyword<K*>
531 {
532 typedef K type;
533 };
534
535 template <class K>
536 struct keyword<K**>
537 {
538 typedef K type;
539 };
540
541 template <class K>
542 struct required
543 {
544 typedef mpl::true_ type;
545 };
546
547 template <class K>
548 struct required<K*>
549 {
550 typedef mpl::false_ type;
551 };
552
553 template <class K>
554 struct optimized
555 {
556 typedef mpl::true_ type;
557 };
558
559 template <class K>
560 struct optimized<K**>
561 {
562 typedef mpl::false_ type;
563 };
564
565 template <class T>
566 struct make_kw_spec;
567
568 template <class K, class T>
569 struct make_kw_spec<K(T)>
570 {
571 typedef arg_spec<
572 typename keyword<K>::type
573 , typename required<K>::type
574 , typename optimized<K>::type
575 , T
576 > type;
577 };
578
579} // namespace aux
580
581template <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies>
582struct init
583 : boost::python::def_visitor<init<ParameterSpecs, CallPolicies> >
584{
585 init(CallPolicies call_policies = CallPolicies())
586 : call_policies(call_policies)
587 {}
588
589 template <class CallPolicies1>
590 init<ParameterSpecs, CallPolicies1>
591 operator[](CallPolicies1 const& call_policies) const
592 {
593 return init<ParameterSpecs, CallPolicies1>(call_policies);
594 }
595
596 template <class Class>
597 void visit_aux(Class& cl, mpl::true_) const
598 {
599 cl.def(boost::python::init<>()[call_policies]);
600 }
601
602 template <class Class>
603 void visit_aux(Class& cl, mpl::false_) const
604 {
605 typedef typename mpl::transform<
606 ParameterSpecs
607 , aux::make_kw_spec<mpl::_>
608 , mpl::back_inserter<mpl::vector0<> >
609 >::type arg_specs;
610
611 typedef typename mpl::count_if<
612 arg_specs
613 , aux::is_optional<mpl::_>
614 >::type optional_arity;
615
616 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
617
618 aux::def_combinations(
619 aux::def_init<Class, CallPolicies>(cl, call_policies)
620 , (arg_specs*)0
621 , mpl::long_<0>()
622 , mpl::long_<upper::value>()
623 , (aux::make_init_invoker<typename Class::wrapped_type>*)0
624 );
625 }
626
627 template <class Class>
628 void visit(Class& cl) const
629 {
630 visit_aux(cl, mpl::empty<ParameterSpecs>());
631 }
632
633 CallPolicies call_policies;
634};
635
636template <class ParameterSpecs, class CallPolicies = boost::python::default_call_policies>
637struct call
638 : boost::python::def_visitor<call<ParameterSpecs, CallPolicies> >
639{
640 call(CallPolicies const& call_policies = CallPolicies())
641 : call_policies(call_policies)
642 {}
643
644 template <class CallPolicies1>
645 call<ParameterSpecs, CallPolicies1>
646 operator[](CallPolicies1 const& call_policies) const
647 {
648 return call<ParameterSpecs, CallPolicies1>(call_policies);
649 }
650
651 template <class Class>
652 void visit(Class& cl) const
653 {
654 typedef mpl::iterator_range<
655 typename mpl::next<
656 typename mpl::begin<ParameterSpecs>::type
657 >::type
658 , typename mpl::end<ParameterSpecs>::type
659 > arg_types;
660
661 typedef typename mpl::front<ParameterSpecs>::type result_type;
662
663 typedef typename mpl::transform<
664 arg_types
665 , aux::make_kw_spec<mpl::_>
666 , mpl::back_inserter<mpl::vector0<> >
667 >::type arg_specs;
668
669 typedef typename mpl::count_if<
670 arg_specs
671 , aux::is_optional<mpl::_>
672 >::type optional_arity;
673
674 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
675
676 typedef aux::call_policies_as_options<CallPolicies> options;
677
678 aux::def_combinations(
679 aux::def_class<Class, options>(cl, "__call__", options(call_policies))
680 , (arg_specs*)0
681 , mpl::long_<0>()
682 , mpl::long_<upper::value>()
683 , (aux::make_call_invoker<typename Class::wrapped_type, result_type>*)0
684 );
685 }
686
687 CallPolicies call_policies;
688};
689
690template <class Fwd, class ParameterSpecs>
691struct function
692 : boost::python::def_visitor<function<Fwd, ParameterSpecs> >
693{
694 template <class Class, class Options>
695 void visit(Class& cl, char const* name, Options const& options) const
696 {
697 typedef mpl::iterator_range<
698 typename mpl::next<
699 typename mpl::begin<ParameterSpecs>::type
700 >::type
701 , typename mpl::end<ParameterSpecs>::type
702 > arg_types;
703
704 typedef typename mpl::front<ParameterSpecs>::type result_type;
705
706 typedef typename mpl::transform<
707 arg_types
708 , aux::make_kw_spec<mpl::_>
709 , mpl::back_inserter<mpl::vector0<> >
710 >::type arg_specs;
711
712 typedef typename mpl::count_if<
713 arg_specs
714 , aux::is_optional<mpl::_>
715 >::type optional_arity;
716
717 typedef typename mpl::shift_left<mpl::long_<1>, optional_arity>::type upper;
718
719 aux::def_combinations(
720 aux::def_class<Class, Options>(cl, name, options)
721 , (arg_specs*)0
722 , mpl::long_<0>()
723 , mpl::long_<upper::value>()
724 , (aux::make_member_invoker<
725 Fwd, result_type, typename Class::wrapped_type
726 >*)0
727 );
728 }
729};
730
731}}} // namespace boost::parameter::python
732
733#endif // BOOST_PARAMETER_PYTHON_060209_HPP
734