import source from 1.3.40
[external/swig.git] / Lib / csharp / std_map.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_map.i
6  *
7  * SWIG typemaps for std::map< K, T >
8  *
9  * The C# wrapper is made to look and feel like a C# System.Collections.Generic.IDictionary<>.
10  * 
11  * Using this wrapper is fairly simple. For example, to create a map from integers to doubles use:
12  *
13  *   %include <std_map.i>
14  *   %template(MapIntDouble) std::map<int, double>
15  *
16  * Notes:
17  * 1) For .NET 1 compatibility, define SWIG_DOTNET_1 when compiling the C# code. In this case 
18  *    the C# wrapper has only basic functionality.
19  * 2) IEnumerable<> is implemented in the proxy class which is useful for using LINQ with 
20  *    C++ std::map wrappers.
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 %{
26 #include <map>
27 #include <algorithm>
28 #include <stdexcept>
29 %}
30
31 /* K is the C++ key type, T is the C++ value type */
32 %define SWIG_STD_MAP_INTERNAL(K, T)
33
34 %typemap(csinterfaces) std::map< K, T > "IDisposable \n#if !SWIG_DOTNET_1\n    , System.Collections.Generic.IDictionary<$typemap(cstype, K), $typemap(cstype, T)>\n#endif\n";
35 %typemap(cscode) std::map<K, T > %{
36
37   public $typemap(cstype, T) this[$typemap(cstype, K) key] {
38     get {
39       return getitem(key);
40     }
41
42     set {
43       setitem(key, value);
44     }
45   }
46
47   public bool TryGetValue($typemap(cstype, K) key, out $typemap(cstype, T) value) {
48     if (this.ContainsKey(key)) {
49       value = this[key];
50       return true;
51     }
52     value = default($typemap(cstype, T));
53     return false;
54   }
55
56   public int Count {
57     get {
58       return (int)size();
59     }
60   }
61
62   public bool IsReadOnly {
63     get { 
64       return false; 
65     }
66   }
67
68 #if !SWIG_DOTNET_1
69
70   public System.Collections.Generic.ICollection<$typemap(cstype, K)> Keys {
71     get {
72       System.Collections.Generic.ICollection<$typemap(cstype, K)> keys = new System.Collections.Generic.List<$typemap(cstype, K)>();
73       IntPtr iter = create_iterator_begin();
74       try {
75         while (true) {
76           keys.Add(get_next_key(iter));
77         }
78       } catch (ArgumentOutOfRangeException) {
79       }
80       return keys;
81     }
82   }
83
84   public System.Collections.Generic.ICollection<$typemap(cstype, T)> Values {
85     get {
86       System.Collections.Generic.ICollection<$typemap(cstype, T)> vals = new System.Collections.Generic.List<$typemap(cstype, T)>();
87       foreach (System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> pair in this) {
88         vals.Add(pair.Value);
89       }
90       return vals;
91     }
92   }
93   
94   public void Add(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) {
95     Add(item.Key, item.Value);
96   }
97
98   public bool Remove(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) {
99     if (Contains(item)) {
100       return Remove(item.Key);
101     } else {
102       return false;
103     }
104   }
105
106   public bool Contains(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) {
107     if (this[item.Key] == item.Value) {
108       return true;
109     } else {
110       return false;
111     }
112   }
113
114   public void CopyTo(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>[] array) {
115     CopyTo(array, 0);
116   }
117
118   public void CopyTo(System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>[] array, int arrayIndex) {
119     if (array == null)
120       throw new ArgumentNullException("array");
121     if (arrayIndex < 0)
122       throw new ArgumentOutOfRangeException("arrayIndex", "Value is less than zero");
123     if (array.Rank > 1)
124       throw new ArgumentException("Multi dimensional array.", "array");
125     if (arrayIndex+this.Count > array.Length)
126       throw new ArgumentException("Number of elements to copy is too large.");
127
128     System.Collections.Generic.IList<$typemap(cstype, K)> keyList = new System.Collections.Generic.List<$typemap(cstype, K)>(this.Keys);
129     for (int i = 0; i < keyList.Count; i++) {
130       $typemap(cstype, K) currentKey = keyList[i];
131       array.SetValue(new System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>(currentKey, this[currentKey]), arrayIndex+i);
132     }
133   }
134
135   System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>>.GetEnumerator() {
136     return new $csclassnameEnumerator(this);
137   }
138
139   System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
140     return new $csclassnameEnumerator(this);
141   }
142
143   public $csclassnameEnumerator GetEnumerator() {
144     return new $csclassnameEnumerator(this);
145   }
146
147   // Type-safe enumerator
148   /// Note that the IEnumerator documentation requires an InvalidOperationException to be thrown
149   /// whenever the collection is modified. This has been done for changes in the size of the
150   /// collection but not when one of the elements of the collection is modified as it is a bit
151   /// tricky to detect unmanaged code that modifies the collection under our feet.
152   public sealed class $csclassnameEnumerator : System.Collections.IEnumerator, 
153       System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>>
154   {
155     private $csclassname collectionRef;
156     private System.Collections.Generic.IList<$typemap(cstype, K)> keyCollection;
157     private int currentIndex;
158     private object currentObject;
159     private int currentSize;
160
161     public $csclassnameEnumerator($csclassname collection) {
162       collectionRef = collection;
163       keyCollection = new System.Collections.Generic.List<$typemap(cstype, K)>(collection.Keys);
164       currentIndex = -1;
165       currentObject = null;
166       currentSize = collectionRef.Count;
167     }
168
169     // Type-safe iterator Current
170     public System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> Current {
171       get {
172         if (currentIndex == -1)
173           throw new InvalidOperationException("Enumeration not started.");
174         if (currentIndex > currentSize - 1)
175           throw new InvalidOperationException("Enumeration finished.");
176         if (currentObject == null)
177           throw new InvalidOperationException("Collection modified.");
178         return (System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>)currentObject;
179       }
180     }
181
182     // Type-unsafe IEnumerator.Current
183     object System.Collections.IEnumerator.Current {
184       get {
185         return Current;
186       }
187     }
188
189     public bool MoveNext() {
190       int size = collectionRef.Count;
191       bool moveOkay = (currentIndex+1 < size) && (size == currentSize);
192       if (moveOkay) {
193         currentIndex++;
194         $typemap(cstype, K) currentKey = keyCollection[currentIndex];
195         currentObject = new System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>(currentKey, collectionRef[currentKey]);
196       } else {
197         currentObject = null;
198       }
199       return moveOkay;
200     }
201
202     public void Reset() {
203       currentIndex = -1;
204       currentObject = null;
205       if (collectionRef.Count != currentSize) {
206         throw new InvalidOperationException("Collection modified.");
207       }
208     }
209
210     public void Dispose() {
211       currentIndex = -1;
212       currentObject = null;
213     }
214   }
215 #endif
216   
217 %}
218
219   public:
220     map();
221     map(const map< K, T > &other);
222
223     typedef K key_type;
224     typedef T mapped_type;
225     typedef size_t size_type;
226     size_type size() const;
227     bool empty() const;
228     %rename(Clear) clear;
229     void clear();
230     %extend {
231       const mapped_type& getitem(const key_type& key) throw (std::out_of_range) {
232         std::map< K,T >::iterator iter = $self->find(key);
233         if (iter != $self->end())
234           return iter->second;
235         else
236           throw std::out_of_range("key not found");
237       }
238
239       void setitem(const key_type& key, const mapped_type& x) {
240         (*$self)[key] = x;
241       }
242
243       bool ContainsKey(const key_type& key) {
244         std::map< K, T >::iterator iter = $self->find(key);
245         return iter != $self->end();
246       }
247
248       void Add(const key_type& key, const mapped_type& val) throw (std::out_of_range) {
249         std::map< K, T >::iterator iter = $self->find(key);
250         if (iter != $self->end())
251           throw std::out_of_range("key already exists");
252         $self->insert(std::pair< K, T >(key, val));
253       }
254
255       bool Remove(const key_type& key) {
256         std::map< K, T >::iterator iter = $self->find(key);
257         if (iter != $self->end()) {
258           $self->erase(iter);
259           return true;
260         }                
261         return false;
262       }
263
264       // create_iterator_begin() and get_next_key() work together to provide a collection of keys to C#
265       %apply void *VOID_INT_PTR { std::map< K, T >::iterator *create_iterator_begin }
266       %apply void *VOID_INT_PTR { std::map< K, T >::iterator *swigiterator }
267
268       std::map< K, T >::iterator *create_iterator_begin() {
269         return new std::map< K, T >::iterator($self->begin());
270       }
271
272       const key_type& get_next_key(std::map< K, T >::iterator *swigiterator) throw (std::out_of_range) {
273         std::map< K, T >::iterator iter = *swigiterator;
274         if (iter == $self->end()) {
275           delete swigiterator;
276           throw std::out_of_range("no more map elements");
277         }
278         (*swigiterator)++;
279         return (*iter).first;
280       }
281     }
282
283
284 %enddef
285
286 %csmethodmodifiers std::map::size "private"
287 %csmethodmodifiers std::map::getitem "private"
288 %csmethodmodifiers std::map::setitem "private"
289 %csmethodmodifiers std::map::create_iterator_begin "private"
290 %csmethodmodifiers std::map::get_next_key "private"
291
292 // Default implementation
293 namespace std {   
294   template<class K, class T> class map {    
295     SWIG_STD_MAP_INTERNAL(K, T)
296   };
297 }
298  
299
300 // Legacy macros (deprecated)
301 %define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO)
302 #warning specialize_std_map_on_key ignored - macro is deprecated and no longer necessary
303 %enddef
304
305 %define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO)
306 #warning specialize_std_map_on_value ignored - macro is deprecated and no longer necessary
307 %enddef
308
309 %define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO)
310 #warning specialize_std_map_on_both ignored - macro is deprecated and no longer necessary
311 %enddef
312