/* ----------------------------------------------------------------------------- * sciiterators.swg * * Users can derive form the SciSwigIterator to implement their * own iterators. As an example (real one since we use it for STL/STD * containers), the template SwigSciIterator_T does the * implementation for generic C++ iterators. * ----------------------------------------------------------------------------- */ %include %fragment("SciSwigIterator","header",fragment="") { namespace swig { struct stop_iteration { }; struct SciSwigIterator { private: SwigSciObject _seq; protected: SciSwigIterator(SwigSciObject seq) : _seq(seq) { } public: virtual ~SciSwigIterator() {} virtual SwigSciObject value() const = 0; virtual SciSwigIterator *incr(size_t n = 1) = 0; virtual SciSwigIterator *decr(size_t n = 1) { throw stop_iteration(); } virtual ptrdiff_t distance(const SciSwigIterator &x) const { throw std::invalid_argument("operation not supported"); } virtual bool equal (const SciSwigIterator &x) const { throw std::invalid_argument("operation not supported"); } virtual SciSwigIterator *copy() const = 0; SwigSciObject next() { SwigSciObject obj = value(); incr(); return obj; } SwigSciObject previous() { decr(); return value(); } SciSwigIterator *advance(ptrdiff_t n) { return (n > 0) ? incr(n) : decr(-n); } bool operator == (const SciSwigIterator& x) const { return equal(x); } bool operator != (const SciSwigIterator& x) const { return ! operator==(x); } SciSwigIterator* operator ++ () { incr(); return this; } SciSwigIterator* operator -- () { decr(); return this; } SciSwigIterator* operator + (ptrdiff_t n) const { return copy()->advance(n); } SciSwigIterator* operator - (ptrdiff_t n) const { return copy()->advance(-n); } ptrdiff_t operator - (const SciSwigIterator& x) const { return x.distance(*this); } static swig_type_info* descriptor() { static int init = 0; static swig_type_info* desc = 0; if (!init) { desc = SWIG_TypeQuery("swig::SciSwigIterator *"); init = 1; } return desc; } }; } } %fragment("SwigSciIterator_T","header",fragment="",fragment="SciSwigIterator",fragment="StdTraits",fragment="StdIteratorTraits") { namespace swig { template class SwigSciIterator_T : public SciSwigIterator { public: typedef OutIterator out_iterator; typedef typename std::iterator_traits::value_type value_type; typedef SwigSciIterator_T self_type; SwigSciIterator_T(out_iterator curr, SwigSciObject seq) : SciSwigIterator(seq), current(curr) { } const out_iterator& get_current() const { return current; } bool equal (const SciSwigIterator &iter) const { const self_type *iters = dynamic_cast(&iter); if (iters) { return (current == iters->get_current()); } else { throw std::invalid_argument("bad iterator type"); } } ptrdiff_t distance(const SciSwigIterator &iter) const { const self_type *iters = dynamic_cast(&iter); if (iters) { return std::distance(current, iters->get_current()); } else { throw std::invalid_argument("bad iterator type"); } } protected: out_iterator current; }; template struct from_oper { typedef const ValueType& argument_type; typedef SwigSciObject result_type; result_type operator()(argument_type v) const { return swig::from(v); } }; template::value_type, typename FromOper = from_oper > class SciSwigIteratorOpen_T : public SwigSciIterator_T { public: FromOper from; typedef OutIterator out_iterator; typedef ValueType value_type; typedef SwigSciIterator_T base; typedef SciSwigIteratorOpen_T self_type; SciSwigIteratorOpen_T(out_iterator curr, SwigSciObject seq) : SwigSciIterator_T(curr, seq) { } SwigSciObject value() const { return from(static_cast(*(base::current))); } SciSwigIterator *copy() const { return new self_type(*this); } SciSwigIterator *incr(size_t n = 1) { while (n--) { ++base::current; } return this; } SciSwigIterator *decr(size_t n = 1) { while (n--) { --base::current; } return this; } }; template::value_type, typename FromOper = from_oper > class SciSwigIteratorClosed_T : public SwigSciIterator_T { public: FromOper from; typedef OutIterator out_iterator; typedef ValueType value_type; typedef SwigSciIterator_T base; typedef SciSwigIteratorClosed_T self_type; SciSwigIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, SwigSciObject seq) : SwigSciIterator_T(curr, seq), begin(first), end(last) { } SwigSciObject value() const { if (base::current == end) { throw stop_iteration(); } else { return from(static_cast(*(base::current))); } } SciSwigIterator *copy() const { return new self_type(*this); } SciSwigIterator *incr(size_t n = 1) { while (n--) { if (base::current == end) { throw stop_iteration(); } else { ++base::current; } } return this; } SciSwigIterator *decr(size_t n = 1) { while (n--) { if (base::current == begin) { throw stop_iteration(); } else { --base::current; } } return this; } private: out_iterator begin; out_iterator end; }; template inline SciSwigIterator* make_output_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, SwigSciObject seq = SwigSciObject()) { return new SciSwigIteratorClosed_T(current, begin, end, seq); } template inline SciSwigIterator* make_output_iterator(const OutIter& current, SwigSciObject seq = SwigSciObject()) { return new SciSwigIteratorOpen_T(current, seq); } } } %fragment("SciSwigIterator"); namespace swig { // Throw a StopIteration exception %ignore stop_iteration; struct stop_iteration {}; %typemap(throws, noblock=1) stop_iteration { SWIG_Scilab_Raise(0, "stop_iteration", NULL); return SWIG_ERROR; } // Mark methods that return new objects %newobject SciSwigIterator::copy; %newobject SciSwigIterator::operator + (ptrdiff_t n) const; %newobject SciSwigIterator::operator - (ptrdiff_t n) const; %nodirector SciSwigIterator; %catches(swig::stop_iteration) SciSwigIterator::value() const; %catches(swig::stop_iteration) SciSwigIterator::incr(size_t n = 1); %catches(swig::stop_iteration) SciSwigIterator::decr(size_t n = 1); %catches(std::invalid_argument) SciSwigIterator::distance(const SciSwigIterator &x) const; %catches(std::invalid_argument) SciSwigIterator::equal (const SciSwigIterator &x) const; %catches(swig::stop_iteration) SciSwigIterator::next(); %catches(swig::stop_iteration) SciSwigIterator::previous(); %catches(swig::stop_iteration) SciSwigIterator::advance(ptrdiff_t n); %catches(swig::stop_iteration) SciSwigIterator::operator += (ptrdiff_t n); %catches(swig::stop_iteration) SciSwigIterator::operator -= (ptrdiff_t n); %catches(swig::stop_iteration) SciSwigIterator::operator + (ptrdiff_t n) const; %catches(swig::stop_iteration) SciSwigIterator::operator - (ptrdiff_t n) const; %ignore SciSwigIterator::operator==; %ignore SciSwigIterator::operator!=; %ignore SciSwigIterator::operator++; %ignore SciSwigIterator::operator--; %ignore SciSwigIterator::operator+; %ignore SciSwigIterator::operator-; struct SciSwigIterator { protected: SciSwigIterator(SwigSciObject seq); public: virtual ~SciSwigIterator(); virtual SwigSciObject value() const = 0; virtual SciSwigIterator *incr(size_t n = 1) = 0; virtual SciSwigIterator *decr(size_t n = 1); virtual ptrdiff_t distance(const SciSwigIterator &x) const; virtual bool equal (const SciSwigIterator &x) const; virtual SciSwigIterator *copy() const = 0; SwigSciObject next(); SwigSciObject previous(); SciSwigIterator *advance(ptrdiff_t n); bool operator == (const SciSwigIterator& x) const; bool operator != (const SciSwigIterator& x) const; SciSwigIterator* operator ++ (); SciSwigIterator* operator -- (); SciSwigIterator* operator + (ptrdiff_t n) const; SciSwigIterator* operator - (ptrdiff_t n) const; ptrdiff_t operator - (const SciSwigIterator& x) const; }; }