1/*
2  Sets
3*/
4
5%fragment("StdSetTraits","header",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
156%define %swig_set_methods(set...)
157
158  %swig_sequence_methods_common(%arg(set));
159
160  %fragment("RubyPairBoolOutputIterator","header",fragment=SWIG_From_frag(bool),fragment="RubySequence_Cont") {}
161
162// Redefine std::set iterator/reverse_iterator typemap
163%typemap(out,noblock=1) iterator, reverse_iterator {
164  $result = SWIG_NewPointerObj(swig::make_set_nonconst_iterator(%static_cast($1,const $type &),
165								self),
166			          swig::Iterator::descriptor(),SWIG_POINTER_OWN);
167 }
168
169// Redefine std::set std::pair<iterator, bool> typemap
170  %typemap(out,noblock=1,fragment="RubyPairBoolOutputIterator")
171  std::pair<iterator, bool> {
172    $result = rb_ary_new2(2);
173    RARRAY_PTR($result)[0] = SWIG_NewPointerObj(swig::make_set_nonconst_iterator(%static_cast($1,$type &).first),
174						swig::Iterator::descriptor(),SWIG_POINTER_OWN);
175    RARRAY_PTR($result)[1] = SWIG_From(bool)(%static_cast($1,const $type &).second);
176    RARRAY_LEN($result) = 2;
177   }
178
179  %extend  {
180    %alias push "<<";
181    value_type push(const value_type& x) {
182      self->insert(x);
183      return x;
184    }
185
186    bool __contains__(const value_type& x) {
187      return self->find(x) != self->end();
188    }
189
190    value_type __getitem__(difference_type i) const throw (std::out_of_range) {
191      return *(swig::cgetpos(self, i));
192    }
193
194  };
195%enddef
196
197
198%mixin std::set "Enumerable";
199
200
201
202%rename("delete")     std::set::__delete__;
203%rename("reject!")    std::set::reject_bang;
204%rename("map!")       std::set::map_bang;
205%rename("empty?")     std::set::empty;
206%rename("include?" )  std::set::__contains__ const;
207%rename("has_key?" )  std::set::has_key const;
208
209%alias  std::set::push          "<<";
210
211
212%include <std/std_set.i>
213
214