# HG changeset patch # User Lukas Heinrich <lukas.heinrich@gmail.com> # Date 1430606843 14400 # Node ID 325f89b7b72922e9add9ca9dd0f7ca4a6c83bf00 # Parent e4fd953257e0d38511f2177de7ffaef662358af2 add incoming/outgoing generators for GenVertex diff --git a/hepmc/generators.i b/hepmc/generators.i new file mode 100644 --- /dev/null +++ b/hepmc/generators.i @@ -0,0 +1,171 @@ +/*! + * \file generators.i + * \author Seth R. Johnson + * \brief Define generator/iterator for any type + +Example: +\code + SETUP_GENERATOR( std::vector<Cell>::const_iterator ) + ADD_GENERATOR( Mesh, cells, + std::vector<Cell>::const_iterator, Cell, beginCells, endCells) +\endcode +would be a method to add a \c cells generator method method to the Python class +\c Mesh, when the C++ class \c Mesh has a \c std::vector<Cell> accessed through +methods \c beginCells and \c endCells. + +The macro \c ADD_GENERATOR_P would be if the underlying storage were \c +std::vector<Cell*> instead. + +Alternatively, for containers of regular objects that provide \c begin(), \c end(), and \c const_iterator, you can use the \c ADD_CONTAINER_ITERATOR macro: +\code +ADD_CONTAINER_ITERATOR( QuadratureSet ) +\endcode + +\section License + +Copyright (c) 2010, Seth R. Johnson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the this project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This material is based upon work supported under a National Science + Foundation Graduate Research Fellowship. Any opinions, findings, conclusions + or recommendations expressed in this publication are those of the author + and do not necessarily reflect the views of the National Science + Foundation. +*/ +#ifndef tools_SWIG_generators_i +#define tools_SWIG_generators_i +/*----------------------------------------------------------------------------*/ + +// Add a Python class to provide iterator objects +%insert("python") %{ +class GenericIterator: + def __init__(self, begin_iter_method, deref_method, incr_method): + self.it = begin_iter_method() + self.incr = incr_method + self.deref = deref_method + + def __iter__(self): + return self + + def next(self): + obj = self.deref( self.it ) + if obj is not None: + self.incr( self.it ) + return obj + else: + raise StopIteration +%} + +//============== GENERIC GENERATOR/ITERATOR WRAPPER SUPPORT ============ +//! Thin wrapper for incrementing a certain type of iterator +// only need to define once per iterator type, and we can use the same name +// thanks to overloading (even though this may decrease efficiency) +%define SETUP_GENERATOR( ITERATOR... ) +%inline %{ +void _iter_incr( ITERATOR* iter ) +{ + ++(*iter); +} +%} +%enddef + +/*----------------------------------------------------------------------------*/ +// Internal method for adding common parts of the generator +%define PYTRT_BASE_ADD_GENERATOR( CLASS, PYMETHOD, ITERATOR, CBEGIN ) + %extend CLASS { +%insert("python") %{ + def PYMETHOD(self): + "Returns an iterator for PYMETHOD." + return GenericIterator( + self._begin_ ## PYMETHOD, + self._deref_ ## PYMETHOD, + _iter_incr + ) +%} +// get the first element in the vector +ITERATOR* _begin_ ## PYMETHOD() +{ + return new ITERATOR( ($self)->CBEGIN() ); +} + } +%enddef +/*----------------------------------------------------------------------------*/ +// If the dereferenced iterator is an object +%define ADD_GENERATOR( CLASS, PYMETHOD, ITERATOR, RVALUE, CBEGIN, CEND ) + +// add the python and begin method +PYTRT_BASE_ADD_GENERATOR( CLASS, PYMETHOD, ITERATOR, CBEGIN ) + + %extend CLASS { +//! Dereference the iterator; return NULL if at the end +const RVALUE* _deref_ ## PYMETHOD ## ( const ITERATOR* iter ) +{ + // if at the end, return NULL + if (*iter == ($self)->CEND() ) { + return NULL; + } + // otherwise, return the POINTER to the dereferenced iterator + return &(**iter); +} + } +%enddef +/*----------------------------------------------------------------------------*/ +// If the dereferenced iterator is a pointer +%define ADD_GENERATOR_P( CLASS, PYMETHOD, ITERATOR, RVALUE, CBEGIN, CEND ) + +// add the python and begin method +PYTRT_BASE_ADD_GENERATOR( CLASS, PYMETHOD, ITERATOR, CBEGIN ) + + %extend CLASS { +//! Dereference the iterator; return NULL if at the end +const RVALUE* _deref_ ## PYMETHOD ## ( const ITERATOR* iter ) +{ + // if at the end, return NULL + if (*iter == ($self)->CEND() ) { + return NULL; + } + // otherwise, return the dereferenced iterator (a pointer) + return **iter; +} + } +%enddef +/*----------------------------------------------------------------------------*/ +//! For a regular container with "begin" and "end" and "size" +%define ADD_CONTAINER_ITERATOR( CLASS ) + SETUP_GENERATOR( CLASS::const_iterator ); + ADD_GENERATOR( CLASS, __iter__, + CLASS ## ::const_iterator, CLASS ## ::value_type, + begin, end) + %extend CLASS { + %insert("python") %{ + def __len__(self): + return self.size() + %} + } +%enddef + +/*============================================================================*/ +#endif + diff --git a/hepmc/hepmcwrap.i b/hepmc/hepmcwrap.i --- a/hepmc/hepmcwrap.i +++ b/hepmc/hepmcwrap.i @@ -1,5 +1,7 @@ %module hepmcwrap +%include generators.i + %{ #include "HepMC/GenEvent.h" #include "HepMC/GenVertex.h" @@ -251,3 +253,9 @@ return ss.str(); } } + +SETUP_GENERATOR( std::vector< HepMC::GenParticle* >::const_iterator ) +ADD_GENERATOR_P( HepMC::GenVertex, incoming, +std::vector< HepMC::GenParticle* >::const_iterator, HepMC::GenParticle, particles_in_const_begin, particles_in_const_end) +ADD_GENERATOR_P( HepMC::GenVertex, outgoing, +std::vector< HepMC::GenParticle* >::const_iterator, HepMC::GenParticle, particles_out_const_begin, particles_out_const_end)