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