From 4b853865b95b5d4968967e5c4f4a513daaf0495d Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Fri, 11 Dec 2015 11:54:27 +0100 Subject: [PATCH] python: initial work on wrapping twa_graph::out(n) * spot/twa/twagraph.hh (out): Do not hide from SWIG. * spot/graph/graph.hh: Hide stuff that SWIG do not understand. * wrap/python/spot_impl.i: Add some typemaps and fragment to iterate over the result of twa_graph::out(). --- spot/graph/graph.hh | 52 +++++++++++++++++----- spot/twa/twagraph.hh | 17 ++++++-- wrap/python/spot_impl.i | 95 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 148 insertions(+), 16 deletions(-) diff --git a/spot/graph/graph.hh b/spot/graph/graph.hh index 5e24665a7..2e948e8b6 100644 --- a/spot/graph/graph.hh +++ b/spot/graph/graph.hh @@ -36,6 +36,7 @@ namespace spot namespace internal { +#ifndef SWIG template struct first_is_base_of { @@ -48,7 +49,7 @@ namespace spot static const bool value = std::is_base_of::type>::value; }; - +#endif // The boxed_label class stores Data as an attribute called // "label" if boxed is true. It is an empty class if Data is @@ -62,6 +63,7 @@ namespace spot typedef Data data_t; Data label; +#ifndef SWIG template ::value>::type> @@ -70,6 +72,7 @@ namespace spot : label{std::forward(args)...} { } +#endif // if Data is a POD type, G++ 4.8.2 wants default values for all // label fields unless we define this default constructor here. @@ -115,6 +118,7 @@ namespace spot { typedef Data data_t; +#ifndef SWIG template ::value>::type> @@ -123,6 +127,7 @@ namespace spot : Data{std::forward(args)...} { } +#endif // if Data is a POD type, G++ 4.8.2 wants default values for all // label fields unless we define this default constructor here. @@ -155,7 +160,7 @@ namespace spot Edge succ = 0; // First outgoing edge (used when iterating) Edge succ_tail = 0; // Last outgoing edge (used for // appending new edges) - +#ifndef SWIG template ::value>::type> @@ -164,6 +169,7 @@ namespace spot : State_Data{std::forward(args)...} { } +#endif }; ////////////////////////////////////////////////// @@ -189,6 +195,7 @@ namespace spot { } +#ifndef SWIG template edge_storage(StateOut dst, Edge next_succ, StateIn src, Args&&... args) @@ -199,6 +206,7 @@ namespace spot dst(dst), next_succ(next_succ), src(src) { } +#endif bool operator<(const edge_storage& other) const { @@ -231,12 +239,12 @@ namespace spot // of that list. template - class SPOT_API edge_iterator: - std::iterator::value, - const typename Graph::edge_storage_t, - typename Graph::edge_storage_t>::type> + class SPOT_API edge_iterator: public + std::iterator::value, + const typename Graph::edge_storage_t, + typename Graph::edge_storage_t>::type> { typedef std::iteratoredge_storage(t_); } + const typename super::reference + operator*() const + { + return g_->edge_storage(t_); + } + typename super::pointer operator->() { return &g_->edge_storage(t_); } + const typename super::pointer + operator->() const + { + return &g_->edge_storage(t_); + } + edge_iterator operator++() { t_ = operator*().next_succ; @@ -412,7 +432,7 @@ namespace spot ////////////////////////////////////////////////// template - class SPOT_API all_edge_iterator: + class SPOT_API all_edge_iterator: public std::iterator::value, @@ -484,11 +504,23 @@ namespace spot return tv_[t_]; } - typename super::pointer + const typename super::reference + operator*() const + { + return tv_[t_]; + } + + const typename super::pointer operator->() { return &tv_[t_]; } + + typename super::pointer + operator->() const + { + return &tv_[t_]; + } }; diff --git a/spot/twa/twagraph.hh b/spot/twa/twagraph.hh index cd21a62b4..a00705be6 100644 --- a/spot/twa/twagraph.hh +++ b/spot/twa/twagraph.hh @@ -387,11 +387,20 @@ namespace spot } #ifndef SWIG - auto out(unsigned src) const - SPOT_RETURN(g_.out(src)); - auto out(unsigned src) - SPOT_RETURN(g_.out(src)); + internal::state_out + out(unsigned src) const + { + return g_.out(src); + } +#endif + internal::state_out + out(unsigned src) + { + return g_.out(src); + } + +#ifndef SWIG auto states() const SPOT_RETURN(g_.states()); auto states() diff --git a/wrap/python/spot_impl.i b/wrap/python/spot_impl.i index b676798d0..cbf9b72d1 100644 --- a/wrap/python/spot_impl.i +++ b/wrap/python/spot_impl.i @@ -109,8 +109,8 @@ #include #include -#include #include +#include #include #include #include @@ -153,6 +153,71 @@ using namespace spot; %} +// Swig come with iterators that implement a decrement method. +// This is not supported in our "successor" iterators. +%fragment("ForwardIterator_T","header",fragment="SwigPyIterator_T") { +namespace swig +{ + template::value_type, + typename FromOper = from_oper > + class ForwardIterator_T : public SwigPyIterator_T + { + public: + FromOper from; + typedef OutIterator out_iterator; + typedef ValueType value_type; + typedef SwigPyIterator_T base; + typedef ForwardIterator_T self_type; + + ForwardIterator_T(out_iterator curr, out_iterator first, + out_iterator last, PyObject *seq) + : SwigPyIterator_T(curr, seq), begin(first), end(last) + { + } + + PyObject *value() const { + if (base::current == end) { + throw stop_iteration(); + } else { + return from(static_cast(*(base::current))); + } + } + + SwigPyIterator *copy() const + { + return new self_type(*this); + } + + SwigPyIterator *incr(size_t n = 1) + { + while (n--) { + if (base::current == end) { + throw stop_iteration(); + } else { + ++base::current; + } + } + return this; + } + + private: + out_iterator begin; + out_iterator end; + }; + + template + inline SwigPyIterator* + make_forward_iterator(const OutIter& current, + const OutIter& begin, + const OutIter& end, PyObject *seq = 0) + { + return new ForwardIterator_T(current, begin, end, seq); + } +} +} +%fragment("ForwardIterator_T"); // For spot::emptiness_check_instantiator::construct and any other // function that return errors via a "char **err" argument. @@ -284,8 +349,25 @@ namespace std { %include %include + +%include +%nodefaultctor spot::digraph; +%nodefaultctor spot::internal::state_out; +%traits_swigtype(spot::internal::edge_storage >); +%fragment(SWIG_Traits_frag(spot::internal::edge_storage >)); + +%typemap(out, optimal="1") spot::internal::state_out> { + $result = SWIG_NewPointerObj(new $1_ltype($1), $&1_descriptor, + SWIG_POINTER_OWN); +} + +%noexception spot::twa_graph::out; %include +%template(twa_graph_state_out) spot::internal::state_out>; +%template(twa_graph_edge_boxed_data) spot::internal::boxed_label; +%template(twa_graph_edge_storage) spot::internal::edge_storage >; + // Should come after the definition of twa_graph %include @@ -303,8 +385,8 @@ namespace std { %include %include %include -%include %include +%include %include %include %include @@ -369,6 +451,15 @@ namespace std { } } + +%extend spot::internal::state_out> { + swig::SwigPyIterator* __iter__(PyObject **PYTHON_SELF) + { + return swig::make_forward_iterator(self->begin(), self->begin(), + self->end(), *PYTHON_SELF); + } +} + %extend spot::acc_cond::acc_code { std::string __repr__() { -- GitLab