Home | History | Annotate | Download | only in r
      1 
      2 //
      3 // Common fragments
      4 //
      5 
      6 
      7 /**** The python container methods  ****/
      8 
      9 
     10 
     11 %fragment("StdSequenceTraits","header",fragment="<stddef.h>")
     12 {
     13 %#include <functional>
     14 namespace swig {
     15   inline size_t
     16   check_index(ptrdiff_t i, size_t size, bool insert = false) {
     17     if ( i < 0 ) {
     18       if ((size_t) (-i) <= size)
     19 	return (size_t) (i + size);
     20     } else if ( (size_t) i < size ) {
     21       return (size_t) i;
     22     } else if (insert && ((size_t) i == size)) {
     23       return size;
     24     }
     25     
     26     throw std::out_of_range("index out of range");
     27   }
     28 
     29   inline size_t
     30   slice_index(ptrdiff_t i, size_t size) {
     31     if ( i < 0 ) {
     32       if ((size_t) (-i) <= size) {
     33 	return (size_t) (i + size);
     34       } else {
     35 	throw std::out_of_range("index out of range");
     36       }
     37     } else {
     38       return ( (size_t) i < size ) ? ((size_t) i) : size;
     39     }
     40   }
     41 
     42   template <class Sequence, class Difference>
     43   inline typename Sequence::iterator
     44   getpos(Sequence* self, Difference i)  {
     45     typename Sequence::iterator pos = self->begin();
     46     std::advance(pos, check_index(i,self->size()));
     47     return pos;
     48   }
     49 
     50   template <class Sequence, class Difference>
     51   inline typename Sequence::const_iterator
     52   cgetpos(const Sequence* self, Difference i)  {
     53     typename Sequence::const_iterator pos = self->begin();
     54     std::advance(pos, check_index(i,self->size()));
     55     return pos;
     56   }
     57 
     58   template <class Sequence, class Difference>
     59   inline Sequence*
     60   getslice(const Sequence* self, Difference i, Difference j) {
     61     typename Sequence::size_type size = self->size();
     62     typename Sequence::size_type ii = swig::check_index(i, size);
     63     typename Sequence::size_type jj = swig::slice_index(j, size);
     64 
     65     if (jj > ii) {
     66       typename Sequence::const_iterator vb = self->begin();
     67       typename Sequence::const_iterator ve = self->begin();
     68       std::advance(vb,ii);
     69       std::advance(ve,jj);
     70       return new Sequence(vb, ve);
     71     } else {
     72       return new Sequence();
     73     }
     74   }
     75 
     76   template <class Sequence, class Difference, class InputSeq>
     77   inline void
     78   setslice(Sequence* self, Difference i, Difference j, const InputSeq& v) {
     79     typename Sequence::size_type size = self->size();
     80     typename Sequence::size_type ii = swig::check_index(i, size, true);
     81     typename Sequence::size_type jj = swig::slice_index(j, size);
     82     if (jj < ii) jj = ii;
     83     size_t ssize = jj - ii;
     84     if (ssize <= v.size()) {
     85       typename Sequence::iterator sb = self->begin();
     86       typename InputSeq::const_iterator vmid = v.begin();
     87       std::advance(sb,ii);
     88       std::advance(vmid, jj - ii);
     89       self->insert(std::copy(v.begin(), vmid, sb), vmid, v.end());
     90     } else {
     91       typename Sequence::iterator sb = self->begin();
     92       typename Sequence::iterator se = self->begin();
     93       std::advance(sb,ii);
     94       std::advance(se,jj);
     95       self->erase(sb,se);
     96       self->insert(sb, v.begin(), v.end());
     97     }
     98   }
     99 
    100   template <class Sequence, class Difference>
    101   inline void
    102   delslice(Sequence* self, Difference i, Difference j) {
    103     typename Sequence::size_type size = self->size();
    104     typename Sequence::size_type ii = swig::check_index(i, size, true);
    105     typename Sequence::size_type jj = swig::slice_index(j, size);
    106     if (jj > ii) {
    107       typename Sequence::iterator sb = self->begin();
    108       typename Sequence::iterator se = self->begin();
    109       std::advance(sb,ii);
    110       std::advance(se,jj);
    111       self->erase(sb,se);
    112     }
    113   }
    114 }
    115 }
    116 
    117 %define %swig_container_methods(Container...)
    118 
    119   %newobject __getslice__;
    120 
    121   %extend {
    122     bool __nonzero__() const {
    123       return !(self->empty());
    124     }
    125 
    126     size_type __len__() const {
    127       return self->size();
    128     }
    129   }
    130 %enddef
    131 
    132 %define %swig_sequence_methods_common(Sequence...)
    133 //  %swig_sequence_iterator(%arg(Sequence))
    134   %swig_container_methods(%arg(Sequence))
    135 
    136   %fragment("StdSequenceTraits");
    137 
    138   %extend {
    139     value_type pop() throw (std::out_of_range) {
    140       if (self->size() == 0)
    141 	throw std::out_of_range("pop from empty container");
    142       Sequence::value_type x = self->back();
    143       self->pop_back();
    144       return x;
    145     }
    146 
    147     Sequence* __getslice__(difference_type i, difference_type j) throw (std::out_of_range) {
    148       return swig::getslice(self, i, j);
    149     }
    150 
    151     void __setslice__(difference_type i, difference_type j, const Sequence& v) 
    152       throw (std::out_of_range, std::invalid_argument) {
    153       swig::setslice(self, i, j, v);
    154     }
    155 
    156     void __delslice__(difference_type i, difference_type j) throw (std::out_of_range) {
    157       swig::delslice(self, i, j);
    158     }
    159 
    160     void __delitem__(difference_type i) throw (std::out_of_range) {
    161       self->erase(swig::getpos(self,i));
    162     }
    163   }
    164 %enddef
    165 
    166 %define %swig_sequence_methods(Sequence...)
    167   %swig_sequence_methods_common(%arg(Sequence))
    168   %extend {
    169     const value_type& __getitem__(difference_type i) const throw (std::out_of_range) {
    170       return *(swig::cgetpos(self, i));
    171     }
    172 
    173     void __setitem__(difference_type i, const value_type& x) throw (std::out_of_range) {
    174       *(swig::getpos(self,i)) = x;
    175     }
    176 
    177     void append(const value_type& x) {
    178       self->push_back(x);
    179     }
    180  }
    181 %enddef
    182 
    183 %define %swig_sequence_methods_val(Sequence...)
    184   %swig_sequence_methods_common(%arg(Sequence))
    185   %extend {
    186     value_type __getitem__(difference_type i) throw (std::out_of_range) {
    187       return *(swig::cgetpos(self, i));
    188     }
    189 
    190     void __setitem__(difference_type i, value_type x) throw (std::out_of_range) {
    191       *(swig::getpos(self,i)) = x;
    192     }
    193 
    194     void append(value_type x) {
    195       self->push_back(x);
    196     }
    197  }
    198 %enddef
    199