PageRenderTime 24ms CodeModel.GetById 14ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/Lib/csharp/std_map.i

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