Home | History | Annotate | Download | only in ruby
      1 /*
      2   Sets
      3 */
      4 
      5 %fragment("StdSetTraits","header",fragment="<stddef.h>",fragment="StdSequenceTraits")
      6 %{
      7   namespace swig {
      8     template <class RubySeq, class T>
      9     inline void
     10     assign(const RubySeq& rubyseq, std::set<T>* seq) {
     11       // seq->insert(rubyseq.begin(), rubyseq.end()); // not used as not always implemented
     12       typedef typename RubySeq::value_type value_type;
     13       typename RubySeq::const_iterator it = rubyseq.begin();
     14       for (;it != rubyseq.end(); ++it) {
     15 	seq->insert(seq->end(),(value_type)(*it));
     16       }
     17     }
     18 
     19     template <class T>
     20     struct traits_asptr<std::set<T> >  {
     21       static int asptr(VALUE obj, std::set<T> **s) {
     22 	return traits_asptr_stdseq<std::set<T> >::asptr(obj, s);
     23       }
     24     };
     25 
     26     template <class T>
     27     struct traits_from<std::set<T> > {
     28       static VALUE from(const std::set<T>& vec) {
     29 	return traits_from_stdseq<std::set<T> >::from(vec);
     30       }
     31     };
     32 
     33 
     34     /**
     35      * Set Iterator class for an iterator with no end() boundaries.
     36      *
     37      */
     38     template<typename InOutIterator,
     39 	     typename ValueType = typename std::iterator_traits<InOutIterator>::value_type,
     40 	     typename FromOper = from_oper<ValueType>,
     41 	     typename AsvalOper = asval_oper<ValueType> >
     42       class SetIteratorOpen_T :  public Iterator_T<InOutIterator>
     43     {
     44     public:
     45       FromOper  from;
     46       AsvalOper asval;
     47       typedef InOutIterator nonconst_iter;
     48       typedef ValueType value_type;
     49       typedef Iterator_T<nonconst_iter>  base;
     50       typedef SetIteratorOpen_T<InOutIterator, ValueType, FromOper, AsvalOper> self_type;
     51 
     52     public:
     53       SetIteratorOpen_T(nonconst_iter curr, VALUE seq = Qnil)
     54 	: Iterator_T<InOutIterator>(curr, seq)
     55       {
     56       }
     57 
     58       virtual VALUE value() const {
     59 	return from(static_cast<const value_type&>(*(base::current)));
     60       }
     61 
     62       // no setValue allowed
     63 
     64       Iterator *dup() const
     65       {
     66 	return new self_type(*this);
     67       }
     68     };
     69 
     70 
     71     /**
     72      * Set Iterator class for a iterator where begin() and end() boundaries
     73        are known.
     74      *
     75      */
     76     template<typename InOutIterator,
     77 	     typename ValueType = typename std::iterator_traits<InOutIterator>::value_type,
     78 	     typename FromOper = from_oper<ValueType>,
     79 	     typename AsvalOper = asval_oper<ValueType> >
     80     class SetIteratorClosed_T :  public Iterator_T<InOutIterator>
     81     {
     82     public:
     83       FromOper   from;
     84       AsvalOper asval;
     85       typedef InOutIterator nonconst_iter;
     86       typedef ValueType value_type;
     87       typedef Iterator_T<nonconst_iter>  base;
     88       typedef SetIteratorClosed_T<InOutIterator, ValueType, FromOper, AsvalOper> self_type;
     89 
     90     protected:
     91       virtual Iterator* advance(ptrdiff_t n)
     92       {
     93 	std::advance( base::current, n );
     94 	if ( base::current == end )
     95 	  throw stop_iteration();
     96 	return this;
     97       }
     98 
     99     public:
    100       SetIteratorClosed_T(nonconst_iter curr, nonconst_iter first,
    101 		       nonconst_iter last, VALUE seq = Qnil)
    102 	: Iterator_T<InOutIterator>(curr, seq), begin(first), end(last)
    103       {
    104       }
    105 
    106       virtual VALUE value() const {
    107 	if (base::current == end) {
    108 	  throw stop_iteration();
    109 	} else {
    110 	  return from(static_cast<const value_type&>(*(base::current)));
    111 	}
    112       }
    113 
    114       // no setValue allowed
    115 
    116 
    117       Iterator *dup() const
    118       {
    119 	return new self_type(*this);
    120       }
    121 
    122     private:
    123       nonconst_iter begin;
    124       nonconst_iter end;
    125     };
    126 
    127     // Template specialization to construct a closed iterator for sets
    128     // this turns a nonconst iterator into a const one for ruby to avoid
    129     // allowing the user to change the value
    130     template< typename InOutIter >
    131     inline Iterator*
    132     make_set_nonconst_iterator(const InOutIter& current,
    133 			       const InOutIter& begin,
    134 			       const InOutIter& end,
    135 			       VALUE seq = Qnil)
    136     {
    137       return new SetIteratorClosed_T< InOutIter >(current,
    138 						  begin, end, seq);
    139     }
    140 
    141     // Template specialization to construct an open iterator for sets
    142     // this turns a nonconst iterator into a const one for ruby to avoid
    143     // allowing the user to change the value
    144     template< typename InOutIter >
    145     inline Iterator*
    146     make_set_nonconst_iterator(const InOutIter& current,
    147 			       VALUE seq = Qnil)
    148     {
    149       return new SetIteratorOpen_T< InOutIter >(current, seq);
    150     }
    151 
    152   }
    153 %}
    154 
    155 %define %swig_sequence_methods_extra_set(Sequence...)
    156   %extend {
    157     %alias reject_bang "delete_if";
    158     Sequence* reject_bang() {
    159       if ( !rb_block_given_p() )
    160 	rb_raise( rb_eArgError, "no block given" );
    161 
    162       for ( Sequence::iterator i = $self->begin(); i != $self->end(); ) {
    163         VALUE r = swig::from< Sequence::value_type >(*i);
    164         Sequence::iterator current = i++;
    165         if ( RTEST( rb_yield(r) ) )
    166           $self->erase(current);
    167       }
    168 
    169       return self;
    170     }
    171   }
    172 %enddef
    173 
    174 %define %swig_set_methods(set...)
    175 
    176   %swig_sequence_methods_common(%arg(set));
    177   %swig_sequence_methods_extra_set(%arg(set));
    178 
    179   %fragment("RubyPairBoolOutputIterator","header",fragment=SWIG_From_frag(bool),fragment="RubySequence_Cont") {}
    180 
    181 // Redefine std::set iterator/reverse_iterator typemap
    182 %typemap(out,noblock=1) iterator, reverse_iterator {
    183   $result = SWIG_NewPointerObj(swig::make_set_nonconst_iterator(%static_cast($1,const $type &),
    184 								self),
    185 			          swig::Iterator::descriptor(),SWIG_POINTER_OWN);
    186  }
    187 
    188 // Redefine std::set std::pair<iterator, bool> typemap
    189   %typemap(out,noblock=1,fragment="RubyPairBoolOutputIterator")
    190   std::pair<iterator, bool> {
    191     $result = rb_ary_new2(2);
    192     rb_ary_push($result, SWIG_NewPointerObj(swig::make_set_nonconst_iterator(%static_cast($1,$type &).first),
    193                                             swig::Iterator::descriptor(),SWIG_POINTER_OWN));
    194     rb_ary_push($result, SWIG_From(bool)(%static_cast($1,const $type &).second));
    195    }
    196 
    197   %extend  {
    198     %alias push "<<";
    199     value_type push(const value_type& x) {
    200       self->insert(x);
    201       return x;
    202     }
    203 
    204     bool __contains__(const value_type& x) {
    205       return self->find(x) != self->end();
    206     }
    207 
    208     value_type __getitem__(difference_type i) const throw (std::out_of_range) {
    209       return *(swig::cgetpos(self, i));
    210     }
    211 
    212   };
    213 %enddef
    214 
    215 
    216 %mixin std::set "Enumerable";
    217 
    218 
    219 
    220 %rename("delete")     std::set::__delete__;
    221 %rename("reject!")    std::set::reject_bang;
    222 %rename("map!")       std::set::map_bang;
    223 %rename("empty?")     std::set::empty;
    224 %rename("include?" )  std::set::__contains__ const;
    225 %rename("has_key?" )  std::set::has_key const;
    226 
    227 %alias  std::set::push          "<<";
    228 
    229 
    230 %include <std/std_set.i>
    231 
    232