import source from 1.3.40
[external/swig.git] / Lib / csharp / std_vector.i
1 /* -----------------------------------------------------------------------------
2  * See the LICENSE file for information on copyright, usage and redistribution
3  * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4  *
5  * std_vector.i
6  *
7  * SWIG typemaps for std::vector<T>
8  * C# implementation
9  * The C# wrapper is made to look and feel like a C# System.Collections.Generic.List<> collection.
10  * For .NET 1 compatibility, define SWIG_DOTNET_1 when compiling the C# code; then the C# wrapper is 
11  * made to look and feel like a typesafe C# System.Collections.ArrayList.
12  *
13  * Note that IEnumerable<> is implemented in the proxy class which is useful for using LINQ with 
14  * C++ std::vector wrappers. The IList<> interface is also implemented to provide enhanced functionality
15  * whenever we are confident that the required C++ operator== is available. This is the case for when 
16  * T is a primitive type or a pointer. If T does define an operator==, then use the SWIG_STD_VECTOR_ENHANCED
17  * macro to obtain this enhanced functionality, for example:
18  *
19  *   SWIG_STD_VECTOR_ENHANCED(SomeNamespace::Klass)
20  *   %template(VectKlass) std::vector<SomeNamespace::Klass>;
21  *
22  * Warning: heavy macro usage in this file. Use swig -E to get a sane view on the real file contents!
23  * ----------------------------------------------------------------------------- */
24
25 // Warning: Use the typemaps here in the expectation that the macros they are in will change name.
26
27
28 %include <std_common.i>
29
30 // MACRO for use within the std::vector class body
31 %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CSINTERFACE, CONST_REFERENCE_TYPE, CTYPE...)
32 %typemap(csinterfaces) std::vector<CTYPE > "IDisposable, System.Collections.IEnumerable\n#if !SWIG_DOTNET_1\n    , System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n#endif\n";
33 %typemap(cscode) std::vector<CTYPE > %{
34   public $csclassname(System.Collections.ICollection c) : this() {
35     if (c == null)
36       throw new ArgumentNullException("c");
37     foreach ($typemap(cstype, CTYPE) element in c) {
38       this.Add(element);
39     }
40   }
41
42   public bool IsFixedSize {
43     get {
44       return false;
45     }
46   }
47
48   public bool IsReadOnly {
49     get {
50       return false;
51     }
52   }
53
54   public $typemap(cstype, CTYPE) this[int index]  {
55     get {
56       return getitem(index);
57     }
58     set {
59       setitem(index, value);
60     }
61   }
62
63   public int Capacity {
64     get {
65       return (int)capacity();
66     }
67     set {
68       if (value < size())
69         throw new ArgumentOutOfRangeException("Capacity");
70       reserve((uint)value);
71     }
72   }
73
74   public int Count {
75     get {
76       return (int)size();
77     }
78   }
79
80   public bool IsSynchronized {
81     get {
82       return false;
83     }
84   }
85
86 #if SWIG_DOTNET_1
87   public void CopyTo(System.Array array)
88 #else
89   public void CopyTo($typemap(cstype, CTYPE)[] array)
90 #endif
91   {
92     CopyTo(0, array, 0, this.Count);
93   }
94
95 #if SWIG_DOTNET_1
96   public void CopyTo(System.Array array, int arrayIndex)
97 #else
98   public void CopyTo($typemap(cstype, CTYPE)[] array, int arrayIndex)
99 #endif
100   {
101     CopyTo(0, array, arrayIndex, this.Count);
102   }
103
104 #if SWIG_DOTNET_1
105   public void CopyTo(int index, System.Array array, int arrayIndex, int count)
106 #else
107   public void CopyTo(int index, $typemap(cstype, CTYPE)[] array, int arrayIndex, int count)
108 #endif
109   {
110     if (array == null)
111       throw new ArgumentNullException("array");
112     if (index < 0)
113       throw new ArgumentOutOfRangeException("index", "Value is less than zero");
114     if (arrayIndex < 0)
115       throw new ArgumentOutOfRangeException("arrayIndex", "Value is less than zero");
116     if (count < 0)
117       throw new ArgumentOutOfRangeException("count", "Value is less than zero");
118     if (array.Rank > 1)
119       throw new ArgumentException("Multi dimensional array.", "array");
120     if (index+count > this.Count || arrayIndex+count > array.Length)
121       throw new ArgumentException("Number of elements to copy is too large.");
122     for (int i=0; i<count; i++)
123       array.SetValue(getitemcopy(index+i), arrayIndex+i);
124   }
125
126 #if !SWIG_DOTNET_1
127   System.Collections.Generic.IEnumerator<$typemap(cstype, CTYPE)> System.Collections.Generic.IEnumerable<$typemap(cstype, CTYPE)>.GetEnumerator() {
128     return new $csclassnameEnumerator(this);
129   }
130 #endif
131
132   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
133     return new $csclassnameEnumerator(this);
134   }
135
136   public $csclassnameEnumerator GetEnumerator() {
137     return new $csclassnameEnumerator(this);
138   }
139
140   // Type-safe enumerator
141   /// Note that the IEnumerator documentation requires an InvalidOperationException to be thrown
142   /// whenever the collection is modified. This has been done for changes in the size of the
143   /// collection but not when one of the elements of the collection is modified as it is a bit
144   /// tricky to detect unmanaged code that modifies the collection under our feet.
145   public sealed class $csclassnameEnumerator : System.Collections.IEnumerator
146 #if !SWIG_DOTNET_1
147     , System.Collections.Generic.IEnumerator<$typemap(cstype, CTYPE)>
148 #endif
149   {
150     private $csclassname collectionRef;
151     private int currentIndex;
152     private object currentObject;
153     private int currentSize;
154
155     public $csclassnameEnumerator($csclassname collection) {
156       collectionRef = collection;
157       currentIndex = -1;
158       currentObject = null;
159       currentSize = collectionRef.Count;
160     }
161
162     // Type-safe iterator Current
163     public $typemap(cstype, CTYPE) Current {
164       get {
165         if (currentIndex == -1)
166           throw new InvalidOperationException("Enumeration not started.");
167         if (currentIndex > currentSize - 1)
168           throw new InvalidOperationException("Enumeration finished.");
169         if (currentObject == null)
170           throw new InvalidOperationException("Collection modified.");
171         return ($typemap(cstype, CTYPE))currentObject;
172       }
173     }
174
175     // Type-unsafe IEnumerator.Current
176     object System.Collections.IEnumerator.Current {
177       get {
178         return Current;
179       }
180     }
181
182     public bool MoveNext() {
183       int size = collectionRef.Count;
184       bool moveOkay = (currentIndex+1 < size) && (size == currentSize);
185       if (moveOkay) {
186         currentIndex++;
187         currentObject = collectionRef[currentIndex];
188       } else {
189         currentObject = null;
190       }
191       return moveOkay;
192     }
193
194     public void Reset() {
195       currentIndex = -1;
196       currentObject = null;
197       if (collectionRef.Count != currentSize) {
198         throw new InvalidOperationException("Collection modified.");
199       }
200     }
201
202 #if !SWIG_DOTNET_1
203     public void Dispose() {
204         currentIndex = -1;
205         currentObject = null;
206     }
207 #endif
208   }
209 %}
210
211   public:
212     typedef size_t size_type;
213     typedef CTYPE value_type;
214     typedef CONST_REFERENCE_TYPE const_reference;
215     %rename(Clear) clear;
216     void clear();
217     %rename(Add) push_back;
218     void push_back(const value_type& x);
219     size_type size() const;
220     size_type capacity() const;
221     void reserve(size_type n);
222     %newobject GetRange(int index, int count);
223     %newobject Repeat(const value_type& value, int count);
224     vector();
225     vector(const vector &other);
226     %extend {
227       vector(int capacity) throw (std::out_of_range) {
228         std::vector<CTYPE >* pv = 0;
229         if (capacity >= 0) {
230           pv = new std::vector<CTYPE >();
231           pv->reserve(capacity);
232        } else {
233           throw std::out_of_range("capacity");
234        }
235        return pv;
236       }
237       CTYPE getitemcopy(int index) throw (std::out_of_range) {
238         if (index>=0 && index<(int)$self->size())
239           return (*$self)[index];
240         else
241           throw std::out_of_range("index");
242       }
243       const_reference getitem(int index) throw (std::out_of_range) {
244         if (index>=0 && index<(int)$self->size())
245           return (*$self)[index];
246         else
247           throw std::out_of_range("index");
248       }
249       void setitem(int index, const value_type& val) throw (std::out_of_range) {
250         if (index>=0 && index<(int)$self->size())
251           (*$self)[index] = val;
252         else
253           throw std::out_of_range("index");
254       }
255       // Takes a deep copy of the elements unlike ArrayList.AddRange
256       void AddRange(const std::vector<CTYPE >& values) {
257         $self->insert($self->end(), values.begin(), values.end());
258       }
259       // Takes a deep copy of the elements unlike ArrayList.GetRange
260       std::vector<CTYPE > *GetRange(int index, int count) throw (std::out_of_range, std::invalid_argument) {
261         if (index < 0)
262           throw std::out_of_range("index");
263         if (count < 0)
264           throw std::out_of_range("count");
265         if (index >= (int)$self->size()+1 || index+count > (int)$self->size())
266           throw std::invalid_argument("invalid range");
267         return new std::vector<CTYPE >($self->begin()+index, $self->begin()+index+count);
268       }
269       void Insert(int index, const value_type& x) throw (std::out_of_range) {
270         if (index>=0 && index<(int)$self->size()+1)
271           $self->insert($self->begin()+index, x);
272         else
273           throw std::out_of_range("index");
274       }
275       // Takes a deep copy of the elements unlike ArrayList.InsertRange
276       void InsertRange(int index, const std::vector<CTYPE >& values) throw (std::out_of_range) {
277         if (index>=0 && index<(int)$self->size()+1)
278           $self->insert($self->begin()+index, values.begin(), values.end());
279         else
280           throw std::out_of_range("index");
281       }
282       void RemoveAt(int index) throw (std::out_of_range) {
283         if (index>=0 && index<(int)$self->size())
284           $self->erase($self->begin() + index);
285         else
286           throw std::out_of_range("index");
287       }
288       void RemoveRange(int index, int count) throw (std::out_of_range, std::invalid_argument) {
289         if (index < 0)
290           throw std::out_of_range("index");
291         if (count < 0)
292           throw std::out_of_range("count");
293         if (index >= (int)$self->size()+1 || index+count > (int)$self->size())
294           throw std::invalid_argument("invalid range");
295         $self->erase($self->begin()+index, $self->begin()+index+count);
296       }
297       static std::vector<CTYPE > *Repeat(const value_type& value, int count) throw (std::out_of_range) {
298         if (count < 0)
299           throw std::out_of_range("count");
300         return new std::vector<CTYPE >(count, value);
301       }
302       void Reverse() {
303         std::reverse($self->begin(), $self->end());
304       }
305       void Reverse(int index, int count) throw (std::out_of_range, std::invalid_argument) {
306         if (index < 0)
307           throw std::out_of_range("index");
308         if (count < 0)
309           throw std::out_of_range("count");
310         if (index >= (int)$self->size()+1 || index+count > (int)$self->size())
311           throw std::invalid_argument("invalid range");
312         std::reverse($self->begin()+index, $self->begin()+index+count);
313       }
314       // Takes a deep copy of the elements unlike ArrayList.SetRange
315       void SetRange(int index, const std::vector<CTYPE >& values) throw (std::out_of_range) {
316         if (index < 0)
317           throw std::out_of_range("index");
318         if (index+values.size() > $self->size())
319           throw std::out_of_range("index");
320         std::copy(values.begin(), values.end(), $self->begin()+index);
321       }
322     }
323 %enddef
324
325 %define SWIG_STD_VECTOR_MINIMUM(CTYPE...)
326 SWIG_STD_VECTOR_MINIMUM_INTERNAL(IEnumerable, const value_type&, CTYPE)
327 %enddef
328
329 // Extra methods added to the collection class if operator== is defined for the class being wrapped
330 // The class will then implement IList<>, which adds extra functionality
331 %define SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE...)
332     %extend {
333       bool Contains(const value_type& value) {
334         return std::find($self->begin(), $self->end(), value) != $self->end();
335       }
336       int IndexOf(const value_type& value) {
337         int index = -1;
338         std::vector<CTYPE >::iterator it = std::find($self->begin(), $self->end(), value);
339         if (it != $self->end())
340           index = (int)(it - $self->begin());
341         return index;
342       }
343       int LastIndexOf(const value_type& value) {
344         int index = -1;
345         std::vector<CTYPE >::reverse_iterator rit = std::find($self->rbegin(), $self->rend(), value);
346         if (rit != $self->rend())
347           index = (int)($self->rend() - 1 - rit);
348         return index;
349       }
350       bool Remove(const value_type& value) {
351         std::vector<CTYPE >::iterator it = std::find($self->begin(), $self->end(), value);
352         if (it != $self->end()) {
353           $self->erase(it);
354           return true;
355         }
356         return false;
357       }
358     }
359 %enddef
360
361 // Macros for std::vector class specializations/enhancements
362 %define SWIG_STD_VECTOR_ENHANCED(CTYPE...)
363 namespace std {
364   template<> class vector<CTYPE > {
365     SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, const value_type&, CTYPE)
366     SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE)
367   };
368 }
369 %enddef
370
371 // Legacy macros
372 %define SWIG_STD_VECTOR_SPECIALIZE(CSTYPE, CTYPE...)
373 #warning SWIG_STD_VECTOR_SPECIALIZE macro deprecated, please see csharp/std_vector.i and switch to SWIG_STD_VECTOR_ENHANCED
374 SWIG_STD_VECTOR_ENHANCED(CTYPE)
375 %enddef
376
377 %define SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(CSTYPE, CTYPE...)
378 #warning SWIG_STD_VECTOR_SPECIALIZE_MINIMUM macro deprecated, it is no longer required
379 %enddef
380
381 %{
382 #include <vector>
383 #include <algorithm>
384 #include <stdexcept>
385 %}
386
387 %csmethodmodifiers std::vector::getitemcopy "private"
388 %csmethodmodifiers std::vector::getitem "private"
389 %csmethodmodifiers std::vector::setitem "private"
390 %csmethodmodifiers std::vector::size "private"
391 %csmethodmodifiers std::vector::capacity "private"
392 %csmethodmodifiers std::vector::reserve "private"
393
394 namespace std {
395   // primary (unspecialized) class template for std::vector
396   // does not require operator== to be defined
397   template<class T> class vector {
398     SWIG_STD_VECTOR_MINIMUM(T)
399   };
400   // specializations for pointers
401   template<class T> class vector<T*> {
402     SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, const value_type&, T*)
403     SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(T*)
404   };
405   template<class T> class vector<const T*> {
406     SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, const value_type&, const T*)
407     SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(const T*)
408   };
409   // bool is a bit different in the C++ standard
410   template<> class vector<bool> {
411     SWIG_STD_VECTOR_MINIMUM_INTERNAL(IList, bool, bool)
412     SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(bool)
413   };
414 }
415
416 // template specializations for std::vector
417 // these provide extra collections methods as operator== is defined
418 SWIG_STD_VECTOR_ENHANCED(char)
419 SWIG_STD_VECTOR_ENHANCED(signed char)
420 SWIG_STD_VECTOR_ENHANCED(unsigned char)
421 SWIG_STD_VECTOR_ENHANCED(short)
422 SWIG_STD_VECTOR_ENHANCED(unsigned short)
423 SWIG_STD_VECTOR_ENHANCED(int)
424 SWIG_STD_VECTOR_ENHANCED(unsigned int)
425 SWIG_STD_VECTOR_ENHANCED(long)
426 SWIG_STD_VECTOR_ENHANCED(unsigned long)
427 SWIG_STD_VECTOR_ENHANCED(long long)
428 SWIG_STD_VECTOR_ENHANCED(unsigned long long)
429 SWIG_STD_VECTOR_ENHANCED(float)
430 SWIG_STD_VECTOR_ENHANCED(double)
431 SWIG_STD_VECTOR_ENHANCED(std::string) // also requires a %include <std_string.i>
432