the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1// Copyright David Abrahams 2002.
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#ifndef CLASS_DWA200216_HPP
6# define CLASS_DWA200216_HPP
7
8# include <boost/python/detail/prefix.hpp>
9
10# include <boost/noncopyable.hpp>
11
12# include <boost/python/class_fwd.hpp>
13# include <boost/python/object/class.hpp>
14
15# include <boost/python/object.hpp>
16# include <boost/python/type_id.hpp>
17# include <boost/python/data_members.hpp>
18# include <boost/python/make_function.hpp>
19# include <boost/python/signature.hpp>
20# include <boost/python/init.hpp>
21# include <boost/python/args_fwd.hpp>
22
23# include <boost/python/object/class_metadata.hpp>
24# include <boost/python/object/pickle_support.hpp>
25# include <boost/python/object/add_to_namespace.hpp>
26
27# include <boost/python/detail/overloads_fwd.hpp>
28# include <boost/python/detail/operator_id.hpp>
29# include <boost/python/detail/def_helper.hpp>
30# include <boost/python/detail/force_instantiate.hpp>
31# include <boost/python/detail/unwrap_type_id.hpp>
32# include <boost/python/detail/unwrap_wrapper.hpp>
33
34# include <boost/type_traits/is_same.hpp>
35# include <boost/type_traits/is_member_function_pointer.hpp>
36# include <boost/type_traits/is_polymorphic.hpp>
37
38# include <boost/mpl/size.hpp>
39# include <boost/mpl/for_each.hpp>
40# include <boost/mpl/bool.hpp>
41# include <boost/mpl/not.hpp>
42
43# include <boost/detail/workaround.hpp>
44
45# if BOOST_WORKAROUND(__MWERKS__, <= 0x3004) \
46 /* pro9 reintroduced the bug */ \
47 || (BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
48 && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) \
49 || BOOST_WORKAROUND(__GNUC__, < 3)
50
51# define BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING 1
52
53# endif
54
55# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
56# include <boost/mpl/and.hpp>
57# include <boost/type_traits/is_member_pointer.hpp>
58# endif
59
60namespace boost { namespace python {
61
62template <class DerivedVisitor> class def_visitor;
63
64enum no_init_t { no_init };
65
66namespace detail
67{
68 // This function object is used with mpl::for_each to write the id
69 // of the type a pointer to which is passed as its 2nd compile-time
70 // argument. into the iterator pointed to by its runtime argument
71 struct write_type_id
72 {
73 write_type_id(type_info**p) : p(p) {}
74
75 // Here's the runtime behavior
76 template <class T>
77 void operator()(T*) const
78 {
79 *(*p)++ = type_id<T>();
80 }
81
82 type_info** p;
83 };
84
85 template <class T>
86 struct is_data_member_pointer
87 : mpl::and_<
88 is_member_pointer<T>
89 , mpl::not_<is_member_function_pointer<T> >
90 >
91 {};
92
93# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
94# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , detail::is_data_member_pointer<D>()
95# define BOOST_PYTHON_YES_DATA_MEMBER , mpl::true_
96# define BOOST_PYTHON_NO_DATA_MEMBER , mpl::false_
97# elif defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
98# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , 0
99# define BOOST_PYTHON_YES_DATA_MEMBER , int
100# define BOOST_PYTHON_NO_DATA_MEMBER , ...
101# else
102# define BOOST_PYTHON_DATA_MEMBER_HELPER(D)
103# define BOOST_PYTHON_YES_DATA_MEMBER
104# define BOOST_PYTHON_NO_DATA_MEMBER
105# endif
106
107 namespace error
108 {
109 //
110 // A meta-assertion mechanism which prints nice error messages and
111 // backtraces on lots of compilers. Usage:
112 //
113 // assertion<C>::failed
114 //
115 // where C is an MPL metafunction class
116 //
117
118 template <class C> struct assertion_failed { };
119 template <class C> struct assertion_ok { typedef C failed; };
120
121 template <class C>
122 struct assertion
123 : mpl::if_<C, assertion_ok<C>, assertion_failed<C> >::type
124 {};
125
126 //
127 // Checks for validity of arguments used to define virtual
128 // functions with default implementations.
129 //
130
131 template <class Default>
132 void not_a_derived_class_member(Default) {}
133
134 template <class T, class Fn>
135 struct virtual_function_default
136 {
137 template <class Default>
138 static void
139 must_be_derived_class_member(Default const&)
140 {
141 // https://svn.boost.org/trac/boost/ticket/5803
142 //typedef typename assertion<mpl::not_<is_same<Default,Fn> > >::failed test0;
143# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
144 typedef typename assertion<is_polymorphic<T> >::failed test1;
145# endif
146 typedef typename assertion<is_member_function_pointer<Fn> >::failed test2;
147 not_a_derived_class_member<Default>(Fn());
148 }
149 };
150 }
151}
152
153// This is the primary mechanism through which users will expose
154// C++ classes to Python.
155template <
156 class W // class being wrapped
157 , class X1 // = detail::not_specified
158 , class X2 // = detail::not_specified
159 , class X3 // = detail::not_specified
160 >
161class class_ : public objects::class_base
162{
163 public: // types
164 typedef objects::class_base base;
165 typedef class_<W,X1,X2,X3> self;
166 typedef typename objects::class_metadata<W,X1,X2,X3> metadata;
167 typedef W wrapped_type;
168
169 private: // types
170
171 // A helper class which will contain an array of id objects to be
172 // passed to the base class constructor
173 struct id_vector
174 {
175 typedef typename metadata::bases bases;
176
177 id_vector()
178 {
179 // Stick the derived class id into the first element of the array
180 ids[0] = detail::unwrap_type_id((W*)0, (W*)0);
181
182 // Write the rest of the elements into succeeding positions.
183 type_info* p = ids + 1;
184 mpl::for_each(detail::write_type_id(&p), (bases*)0, (add_pointer<mpl::_>*)0);
185 }
186
187 BOOST_STATIC_CONSTANT(
188 std::size_t, size = mpl::size<bases>::value + 1);
189 type_info ids[size];
190 };
191 friend struct id_vector;
192
193 public: // constructors
194
195 // Construct with the class name, with or without docstring, and default __init__() function
196 class_(char const* name, char const* doc = 0);
197
198 // Construct with class name, no docstring, and an uncallable __init__ function
199 class_(char const* name, no_init_t);
200
201 // Construct with class name, docstring, and an uncallable __init__ function
202 class_(char const* name, char const* doc, no_init_t);
203
204 // Construct with class name and init<> function
205 template <class DerivedT>
206 inline class_(char const* name, init_base<DerivedT> const& i)
207 : base(name, id_vector::size, id_vector().ids)
208 {
209 this->initialize(i);
210 }
211
212 // Construct with class name, docstring and init<> function
213 template <class DerivedT>
214 inline class_(char const* name, char const* doc, init_base<DerivedT> const& i)
215 : base(name, id_vector::size, id_vector().ids, doc)
216 {
217 this->initialize(i);
218 }
219
220 public: // member functions
221
222 // Generic visitation
223 template <class Derived>
224 self& def(def_visitor<Derived> const& visitor)
225 {
226 visitor.visit(*this);
227 return *this;
228 }
229
230 // Wrap a member function or a non-member function which can take
231 // a T, T cv&, or T cv* as its first parameter, a callable
232 // python object, or a generic visitor.
233 template <class F>
234 self& def(char const* name, F f)
235 {
236 this->def_impl(
237 detail::unwrap_wrapper((W*)0)
238 , name, f, detail::def_helper<char const*>(0), &f);
239 return *this;
240 }
241
242 template <class A1, class A2>
243 self& def(char const* name, A1 a1, A2 const& a2)
244 {
245 this->def_maybe_overloads(name, a1, a2, &a2);
246 return *this;
247 }
248
249 template <class Fn, class A1, class A2>
250 self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2)
251 {
252 // The arguments are definitely:
253 // def(name, function, policy, doc_string)
254 // def(name, function, doc_string, policy)
255
256 this->def_impl(
257 detail::unwrap_wrapper((W*)0)
258 , name, fn
259 , detail::def_helper<A1,A2>(a1,a2)
260 , &fn);
261
262 return *this;
263 }
264
265 template <class Fn, class A1, class A2, class A3>
266 self& def(char const* name, Fn fn, A1 const& a1, A2 const& a2, A3 const& a3)
267 {
268 this->def_impl(
269 detail::unwrap_wrapper((W*)0)
270 , name, fn
271 , detail::def_helper<A1,A2,A3>(a1,a2,a3)
272 , &fn);
273
274 return *this;
275 }
276
277 //
278 // Data member access
279 //
280 template <class D>
281 self& def_readonly(char const* name, D const& d, char const* doc=0)
282 {
283 return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
284 }
285
286 template <class D>
287 self& def_readwrite(char const* name, D const& d, char const* doc=0)
288 {
289 return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
290 }
291
292 template <class D>
293 self& def_readonly(char const* name, D& d, char const* doc=0)
294 {
295 return this->def_readonly_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
296 }
297
298 template <class D>
299 self& def_readwrite(char const* name, D& d, char const* doc=0)
300 {
301 return this->def_readwrite_impl(name, d, doc BOOST_PYTHON_DATA_MEMBER_HELPER(D));
302 }
303
304 // Property creation
305# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
306 template <class Get>
307 self& add_property(char const* name, Get fget, char const* docstr = 0)
308 {
309 base::add_property(name, this->make_getter(fget), docstr);
310 return *this;
311 }
312
313 template <class Get, class Set>
314 self& add_property(char const* name, Get fget, Set fset, char const* docstr = 0)
315 {
316 base::add_property(
317 name, this->make_getter(fget), this->make_setter(fset), docstr);
318 return *this;
319 }
320# else
321 private:
322 template <class Get>
323 self& add_property_impl(char const* name, Get fget, char const* docstr, int)
324 {
325 base::add_property(name, this->make_getter(fget), docstr);
326 return *this;
327 }
328
329 template <class Get, class Set>
330 self& add_property_impl(char const* name, Get fget, Set fset, ...)
331 {
332 base::add_property(
333 name, this->make_getter(fget), this->make_setter(fset), 0);
334 return *this;
335 }
336
337 public:
338 template <class Get>
339 self& add_property(char const* name, Get fget)
340 {
341 base::add_property(name, this->make_getter(fget), 0);
342 return *this;
343 }
344
345 template <class Get, class DocStrOrSet>
346 self& add_property(char const* name, Get fget, DocStrOrSet docstr_or_set)
347 {
348 this->add_property_impl(name, this->make_getter(fget), docstr_or_set, 0);
349 return *this;
350 }
351
352 template <class Get, class Set>
353 self&
354 add_property(char const* name, Get fget, Set fset, char const* docstr)
355 {
356 base::add_property(
357 name, this->make_getter(fget), this->make_setter(fset), docstr);
358 return *this;
359 }
360# endif
361
362 template <class Get>
363 self& add_static_property(char const* name, Get fget)
364 {
365 base::add_static_property(name, object(fget));
366 return *this;
367 }
368
369 template <class Get, class Set>
370 self& add_static_property(char const* name, Get fget, Set fset)
371 {
372 base::add_static_property(name, object(fget), object(fset));
373 return *this;
374 }
375
376 template <class U>
377 self& setattr(char const* name, U const& x)
378 {
379 this->base::setattr(name, object(x));
380 return *this;
381 }
382
383 // Pickle support
384 template <typename PickleSuiteType>
385 self& def_pickle(PickleSuiteType const& x)
386 {
387 error_messages::must_be_derived_from_pickle_suite(x);
388 detail::pickle_suite_finalize<PickleSuiteType>::register_(
389 *this,
390 &PickleSuiteType::getinitargs,
391 &PickleSuiteType::getstate,
392 &PickleSuiteType::setstate,
393 PickleSuiteType::getstate_manages_dict());
394 return *this;
395 }
396
397 self& enable_pickling()
398 {
399 this->base::enable_pickling_(false);
400 return *this;
401 }
402
403 self& staticmethod(char const* name)
404 {
405 this->make_method_static(name);
406 return *this;
407 }
408 private: // helper functions
409
410 // Builds a method for this class around the given [member]
411 // function pointer or object, appropriately adjusting the type of
412 // the first signature argument so that if f is a member of a
413 // (possibly not wrapped) base class of T, an lvalue argument of
414 // type T will be required.
415 //
416 // @group PropertyHelpers {
417 template <class F>
418 object make_getter(F f)
419 {
420 typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
421
422 return this->make_fn_impl(
423 detail::unwrap_wrapper((W*)0)
424 , f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
425 );
426 }
427
428 template <class F>
429 object make_setter(F f)
430 {
431 typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
432
433 return this->make_fn_impl(
434 detail::unwrap_wrapper((W*)0)
435 , f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
436 );
437 }
438
439 template <class T, class F>
440 object make_fn_impl(T*, F const& f, mpl::false_, void*, mpl::false_)
441 {
442 return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
443 }
444
445 template <class T, class D, class B>
446 object make_fn_impl(T*, D B::*pm_, mpl::false_, char*, mpl::true_)
447 {
448 D T::*pm = pm_;
449 return python::make_getter(pm);
450 }
451
452 template <class T, class D, class B>
453 object make_fn_impl(T*, D B::*pm_, mpl::false_, int*, mpl::true_)
454 {
455 D T::*pm = pm_;
456 return python::make_setter(pm);
457 }
458
459 template <class T, class F>
460 object make_fn_impl(T*, F const& x, mpl::true_, void*, mpl::false_)
461 {
462 return x;
463 }
464 // }
465
466 template <class D, class B>
467 self& def_readonly_impl(
468 char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
469 {
470 return this->add_property(name, pm_, doc);
471 }
472
473 template <class D, class B>
474 self& def_readwrite_impl(
475 char const* name, D B::*pm_, char const* doc BOOST_PYTHON_YES_DATA_MEMBER)
476 {
477 return this->add_property(name, pm_, pm_, doc);
478 }
479
480 template <class D>
481 self& def_readonly_impl(
482 char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
483 {
484 return this->add_static_property(name, python::make_getter(d));
485 }
486
487 template <class D>
488 self& def_readwrite_impl(
489 char const* name, D& d, char const* BOOST_PYTHON_NO_DATA_MEMBER)
490 {
491 return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
492 }
493
494 template <class DefVisitor>
495 inline void initialize(DefVisitor const& i)
496 {
497 metadata::register_(); // set up runtime metadata/conversions
498
499 typedef typename metadata::holder holder;
500 this->set_instance_size( objects::additional_instance_size<holder>::value );
501
502 this->def(i);
503 }
504
505 inline void initialize(no_init_t)
506 {
507 metadata::register_(); // set up runtime metadata/conversions
508 this->def_no_init();
509 }
510
511 //
512 // These two overloads discriminate between def() as applied to a
513 // generic visitor and everything else.
514 //
515 // @group def_impl {
516 template <class T, class Helper, class LeafVisitor, class Visitor>
517 inline void def_impl(
518 T*
519 , char const* name
520 , LeafVisitor
521 , Helper const& helper
522 , def_visitor<Visitor> const* v
523 )
524 {
525 v->visit(*this, name, helper);
526 }
527
528 template <class T, class Fn, class Helper>
529 inline void def_impl(
530 T*
531 , char const* name
532 , Fn fn
533 , Helper const& helper
534 , ...
535 )
536 {
537 objects::add_to_namespace(
538 *this
539 , name
540 , make_function(
541 fn
542 , helper.policies()
543 , helper.keywords()
544 , detail::get_signature(fn, (T*)0)
545 )
546 , helper.doc()
547 );
548
549 this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>());
550 }
551 // }
552
553 //
554 // These two overloads handle the definition of default
555 // implementation overloads for virtual functions. The second one
556 // handles the case where no default implementation was specified.
557 //
558 // @group def_default {
559 template <class Fn, class Helper>
560 inline void def_default(
561 char const* name
562 , Fn
563 , Helper const& helper
564 , mpl::bool_<true>)
565 {
566 detail::error::virtual_function_default<W,Fn>::must_be_derived_class_member(
567 helper.default_implementation());
568
569 objects::add_to_namespace(
570 *this, name,
571 make_function(
572 helper.default_implementation(), helper.policies(), helper.keywords())
573 );
574 }
575
576 template <class Fn, class Helper>
577 inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
578 { }
579 // }
580
581 //
582 // These two overloads discriminate between def() as applied to
583 // regular functions and def() as applied to the result of
584 // BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
585 // discriminate.
586 //
587 // @group def_maybe_overloads {
588 template <class OverloadsT, class SigT>
589 void def_maybe_overloads(
590 char const* name
591 , SigT sig
592 , OverloadsT const& overloads
593 , detail::overloads_base const*)
594
595 {
596 // convert sig to a type_list (see detail::get_signature in signature.hpp)
597 // before calling detail::define_with_defaults.
598 detail::define_with_defaults(
599 name, overloads, *this, detail::get_signature(sig));
600 }
601
602 template <class Fn, class A1>
603 void def_maybe_overloads(
604 char const* name
605 , Fn fn
606 , A1 const& a1
607 , ...)
608 {
609 this->def_impl(
610 detail::unwrap_wrapper((W*)0)
611 , name
612 , fn
613 , detail::def_helper<A1>(a1)
614 , &fn
615 );
616
617 }
618 // }
619};
620
621
622//
623// implementations
624//
625
626template <class W, class X1, class X2, class X3>
627inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc)
628 : base(name, id_vector::size, id_vector().ids, doc)
629{
630 this->initialize(init<>());
631// select_holder::assert_default_constructible();
632}
633
634template <class W, class X1, class X2, class X3>
635inline class_<W,X1,X2,X3>::class_(char const* name, no_init_t)
636 : base(name, id_vector::size, id_vector().ids)
637{
638 this->initialize(no_init);
639}
640
641template <class W, class X1, class X2, class X3>
642inline class_<W,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t)
643 : base(name, id_vector::size, id_vector().ids, doc)
644{
645 this->initialize(no_init);
646}
647
648}} // namespace boost::python
649
650# undef BOOST_PYTHON_DATA_MEMBER_HELPER
651# undef BOOST_PYTHON_YES_DATA_MEMBER
652# undef BOOST_PYTHON_NO_DATA_MEMBER
653# undef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
654
655#endif // CLASS_DWA200216_HPP