Home | History | Annotate | Download | only in octave
      1 /* -----------------------------------------------------------------------------
      2  * octiterators.swg
      3  *
      4  * Users can derive form the OctSwigIterator to implemet their
      5  * own iterators. As an example (real one since we use it for STL/STD
      6  * containers), the template OctSwigIterator_T does the
      7  * implementation for generic C++ iterators.
      8  * ----------------------------------------------------------------------------- */
      9 
     10 %include <std_common.i>
     11 
     12 %fragment("OctSwigIterator","header",fragment="<stddef.h>") {
     13 namespace swig {
     14   struct stop_iteration {
     15   };
     16 
     17   struct OctSwigIterator {
     18   private:
     19     octave_value _seq;
     20 
     21   protected:
     22     OctSwigIterator(octave_value seq) : _seq(seq)
     23     {
     24     }
     25 
     26   public:
     27     virtual ~OctSwigIterator() {}
     28 
     29     virtual octave_value value() const = 0;
     30 
     31     virtual OctSwigIterator *incr(size_t n = 1) = 0;
     32 
     33     virtual OctSwigIterator *decr(size_t n = 1)
     34     {
     35       throw stop_iteration();
     36     }
     37 
     38     virtual ptrdiff_t distance(const OctSwigIterator &x) const
     39     {
     40       throw std::invalid_argument("operation not supported");
     41     }
     42 
     43     virtual bool equal (const OctSwigIterator &x) const
     44     {
     45       throw std::invalid_argument("operation not supported");
     46     }
     47 
     48     virtual OctSwigIterator *copy() const = 0;
     49 
     50     octave_value next()
     51     {
     52       octave_value obj = value();
     53       incr();
     54       return obj;
     55     }
     56 
     57     octave_value previous()
     58     {
     59       decr();
     60       return value();
     61     }
     62 
     63     OctSwigIterator *advance(ptrdiff_t n)
     64     {
     65       return  (n > 0) ?  incr(n) : decr(-n);
     66     }
     67 
     68     bool operator == (const OctSwigIterator& x)  const
     69     {
     70       return equal(x);
     71     }
     72 
     73     bool operator != (const OctSwigIterator& x) const
     74     {
     75       return ! operator==(x);
     76     }
     77 
     78     OctSwigIterator* operator ++ () {
     79       incr();
     80       return this;
     81     }
     82 
     83     OctSwigIterator* operator -- () {
     84       decr();
     85       return this;
     86     }
     87 
     88     OctSwigIterator* operator + (ptrdiff_t n) const
     89     {
     90       return copy()->advance(n);
     91     }
     92 
     93     OctSwigIterator* operator - (ptrdiff_t n) const
     94     {
     95       return copy()->advance(-n);
     96     }
     97 
     98     ptrdiff_t operator - (const OctSwigIterator& x) const
     99     {
    100       return x.distance(*this);
    101     }
    102 
    103     static swig_type_info* descriptor() {
    104       static int init = 0;
    105       static swig_type_info* desc = 0;
    106       if (!init) {
    107 	desc = SWIG_TypeQuery("swig::OctSwigIterator *");
    108 	init = 1;
    109       }
    110       return desc;
    111     }
    112   };
    113 }
    114 }
    115 
    116 %fragment("OctSwigIterator_T","header",fragment="<stddef.h>",fragment="OctSwigIterator",fragment="StdTraits",fragment="StdIteratorTraits") {
    117 namespace swig {
    118   template<typename OutIterator>
    119   class OctSwigIterator_T :  public OctSwigIterator
    120   {
    121   public:
    122     typedef OutIterator out_iterator;
    123     typedef typename std::iterator_traits<out_iterator>::value_type value_type;
    124     typedef OctSwigIterator_T<out_iterator> self_type;
    125 
    126     OctSwigIterator_T(out_iterator curr, octave_value seq)
    127       : OctSwigIterator(seq), current(curr)
    128     {
    129     }
    130 
    131     const out_iterator& get_current() const
    132     {
    133       return current;
    134     }
    135 
    136 
    137     bool equal (const OctSwigIterator &iter) const
    138     {
    139       const self_type *iters = dynamic_cast<const self_type *>(&iter);
    140       if (iters) {
    141 	return (current == iters->get_current());
    142       } else {
    143 	throw std::invalid_argument("bad iterator type");
    144       }
    145     }
    146 
    147     ptrdiff_t distance(const OctSwigIterator &iter) const
    148     {
    149       const self_type *iters = dynamic_cast<const self_type *>(&iter);
    150       if (iters) {
    151 	return std::distance(current, iters->get_current());
    152       } else {
    153 	throw std::invalid_argument("bad iterator type");
    154       }
    155     }
    156 
    157   protected:
    158     out_iterator current;
    159   };
    160 
    161   template <class ValueType>
    162   struct from_oper
    163   {
    164     typedef const ValueType& argument_type;
    165     typedef octave_value result_type;
    166     result_type operator()(argument_type v) const
    167     {
    168       return swig::from(v);
    169     }
    170   };
    171 
    172   template<typename OutIterator,
    173 	   typename ValueType = typename std::iterator_traits<OutIterator>::value_type,
    174 	   typename FromOper = from_oper<ValueType> >
    175   class OctSwigIteratorOpen_T :  public OctSwigIterator_T<OutIterator>
    176   {
    177   public:
    178     FromOper from;
    179     typedef OutIterator out_iterator;
    180     typedef ValueType value_type;
    181     typedef OctSwigIterator_T<out_iterator>  base;
    182     typedef OctSwigIteratorOpen_T<OutIterator, ValueType, FromOper> self_type;
    183 
    184     OctSwigIteratorOpen_T(out_iterator curr, octave_value seq)
    185       : OctSwigIterator_T<OutIterator>(curr, seq)
    186     {
    187     }
    188 
    189     octave_value value() const {
    190       return from(static_cast<const value_type&>(*(base::current)));
    191     }
    192 
    193     OctSwigIterator *copy() const
    194     {
    195       return new self_type(*this);
    196     }
    197 
    198     OctSwigIterator *incr(size_t n = 1)
    199     {
    200       while (n--) {
    201 	++base::current;
    202       }
    203       return this;
    204     }
    205 
    206     OctSwigIterator *decr(size_t n = 1)
    207     {
    208       while (n--) {
    209 	--base::current;
    210       }
    211       return this;
    212     }
    213   };
    214 
    215   template<typename OutIterator,
    216 	   typename ValueType = typename std::iterator_traits<OutIterator>::value_type,
    217 	   typename FromOper = from_oper<ValueType> >
    218   class OctSwigIteratorClosed_T :  public OctSwigIterator_T<OutIterator>
    219   {
    220   public:
    221     FromOper from;
    222     typedef OutIterator out_iterator;
    223     typedef ValueType value_type;
    224     typedef OctSwigIterator_T<out_iterator>  base;
    225     typedef OctSwigIteratorClosed_T<OutIterator, ValueType, FromOper> self_type;
    226 
    227     OctSwigIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, octave_value seq)
    228       : OctSwigIterator_T<OutIterator>(curr, seq), begin(first), end(last)
    229     {
    230     }
    231 
    232     octave_value value() const {
    233       if (base::current == end) {
    234 	throw stop_iteration();
    235       } else {
    236 	return from(static_cast<const value_type&>(*(base::current)));
    237       }
    238     }
    239 
    240     OctSwigIterator *copy() const
    241     {
    242       return new self_type(*this);
    243     }
    244 
    245     OctSwigIterator *incr(size_t n = 1)
    246     {
    247       while (n--) {
    248 	if (base::current == end) {
    249 	  throw stop_iteration();
    250 	} else {
    251 	  ++base::current;
    252 	}
    253       }
    254       return this;
    255     }
    256 
    257     OctSwigIterator *decr(size_t n = 1)
    258     {
    259       while (n--) {
    260 	if (base::current == begin) {
    261 	  throw stop_iteration();
    262 	} else {
    263 	  --base::current;
    264 	}
    265       }
    266       return this;
    267     }
    268 
    269   private:
    270     out_iterator begin;
    271     out_iterator end;
    272   };
    273 
    274   template<typename OutIter>
    275   inline OctSwigIterator*
    276   make_output_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, octave_value seq = octave_value())
    277   {
    278     return new OctSwigIteratorClosed_T<OutIter>(current, begin, end, seq);
    279   }
    280 
    281   template<typename OutIter>
    282   inline OctSwigIterator*
    283   make_output_iterator(const OutIter& current, octave_value seq = octave_value())
    284   {
    285     return new OctSwigIteratorOpen_T<OutIter>(current, seq);
    286   }
    287 }
    288 }
    289 
    290 
    291 %fragment("OctSwigIterator");
    292 namespace swig
    293 {
    294 // Throw a StopIteration exception
    295   %ignore stop_iteration;
    296   struct stop_iteration {};
    297 
    298   %typemap(throws) stop_iteration {
    299     error("stop_iteration exception");
    300     SWIG_fail;
    301   }
    302 
    303 // Mark methods that return new objects
    304   %newobject OctSwigIterator::copy;
    305   %newobject OctSwigIterator::operator + (ptrdiff_t n) const;
    306   %newobject OctSwigIterator::operator - (ptrdiff_t n) const;
    307 
    308   %nodirector OctSwigIterator;
    309 
    310   %catches(swig::stop_iteration) OctSwigIterator::value() const;
    311   %catches(swig::stop_iteration) OctSwigIterator::incr(size_t n = 1);
    312   %catches(swig::stop_iteration) OctSwigIterator::decr(size_t n = 1);
    313   %catches(std::invalid_argument) OctSwigIterator::distance(const OctSwigIterator &x) const;
    314   %catches(std::invalid_argument) OctSwigIterator::equal (const OctSwigIterator &x) const;
    315   %catches(swig::stop_iteration) OctSwigIterator::next();
    316   %catches(swig::stop_iteration) OctSwigIterator::previous();
    317   %catches(swig::stop_iteration) OctSwigIterator::advance(ptrdiff_t n);
    318   %catches(swig::stop_iteration) OctSwigIterator::operator += (ptrdiff_t n);
    319   %catches(swig::stop_iteration) OctSwigIterator::operator -= (ptrdiff_t n);
    320   %catches(swig::stop_iteration) OctSwigIterator::operator + (ptrdiff_t n) const;
    321   %catches(swig::stop_iteration) OctSwigIterator::operator - (ptrdiff_t n) const;
    322 
    323 
    324   struct OctSwigIterator
    325   {
    326   protected:
    327     OctSwigIterator(octave_value seq);
    328 
    329   public:
    330     virtual ~OctSwigIterator();
    331 
    332     virtual octave_value value() const = 0;
    333 
    334     virtual OctSwigIterator *incr(size_t n = 1) = 0;
    335 
    336     virtual OctSwigIterator *decr(size_t n = 1);
    337 
    338     virtual ptrdiff_t distance(const OctSwigIterator &x) const;
    339 
    340     virtual bool equal (const OctSwigIterator &x) const;
    341 
    342     virtual OctSwigIterator *copy() const = 0;
    343 
    344     octave_value next();
    345     octave_value previous();
    346     OctSwigIterator *advance(ptrdiff_t n);
    347 
    348     bool operator == (const OctSwigIterator& x)  const;
    349     bool operator != (const OctSwigIterator& x) const;
    350     OctSwigIterator* operator ++ ();
    351     OctSwigIterator* operator -- ();
    352     OctSwigIterator* operator + (ptrdiff_t n) const;
    353     OctSwigIterator* operator - (ptrdiff_t n) const;
    354     ptrdiff_t operator - (const OctSwigIterator& x) const;
    355   };
    356 }
    357 
    358