aboutsummaryrefslogtreecommitdiff
path: root/Lib/csharp/std_unordered_set.i
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/csharp/std_unordered_set.i')
-rw-r--r--Lib/csharp/std_unordered_set.i320
1 files changed, 320 insertions, 0 deletions
diff --git a/Lib/csharp/std_unordered_set.i b/Lib/csharp/std_unordered_set.i
new file mode 100644
index 000000000..d6f6a18f3
--- /dev/null
+++ b/Lib/csharp/std_unordered_set.i
@@ -0,0 +1,320 @@
+/* -----------------------------------------------------------------------------
+ * std_unordered_set.i
+ *
+ * SWIG typemaps for std::unordered_set<T>.
+ *
+ * Note that ISet<> used here requires .NET 4 or later.
+ *
+ * The C# wrapper implements ISet<> interface and is similar in
+ * characteristics to the C# System.Collections.Generic.HashSet<> class, but
+ * doesn't provide quite all of its methods.
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <unordered_set>
+#include <algorithm>
+#include <stdexcept>
+%}
+
+%csmethodmodifiers std::unordered_set::empty "private"
+%csmethodmodifiers std::unordered_set::size "private"
+%csmethodmodifiers std::unordered_set::getitem "private"
+%csmethodmodifiers std::unordered_set::create_iterator_begin "private"
+%csmethodmodifiers std::unordered_set::get_next "private"
+%csmethodmodifiers std::unordered_set::destroy_iterator "private"
+
+namespace std {
+
+// TODO: Add support for comparator and allocator template parameters.
+template <class T>
+class unordered_set {
+
+%typemap(csinterfaces) std::unordered_set<T> "global::System.IDisposable, global::System.Collections.Generic.ISet<$typemap(cstype, T)>\n"
+%proxycode %{
+ void global::System.Collections.Generic.ICollection<$typemap(cstype, T)>.Add($typemap(cstype, T) item) {
+ ((global::System.Collections.Generic.ISet<$typemap(cstype, T)>)this).Add(item);
+ }
+
+ public bool TryGetValue($typemap(cstype, T) equalValue, out $typemap(cstype, T) actualValue) {
+ try {
+ actualValue = getitem(equalValue);
+ return true;
+ } catch {
+ actualValue = default($typemap(cstype, T));
+ return false;
+ }
+ }
+
+ public bool IsEmpty {
+ get {
+ return empty();
+ }
+ }
+
+ public int Count {
+ get {
+ return (int)size();
+ }
+ }
+
+ public bool IsReadOnly {
+ get {
+ return false;
+ }
+ }
+
+ public void CopyTo($typemap(cstype, T)[] array) {
+ CopyTo(array, 0);
+ }
+
+ public void CopyTo($typemap(cstype, T)[] array, int arrayIndex) {
+ if (array == null)
+ throw new global::System.ArgumentNullException("array");
+ if (arrayIndex < 0)
+ throw new global::System.ArgumentOutOfRangeException("arrayIndex", "Value is less than zero");
+ if (array.Rank > 1)
+ throw new global::System.ArgumentException("Multi dimensional array.", "array");
+ if (arrayIndex+this.Count > array.Length)
+ throw new global::System.ArgumentException("Number of elements to copy is too large.");
+
+ foreach ($typemap(cstype, T) item in this) {
+ array.SetValue(item, arrayIndex++);
+ }
+ }
+
+ public void ExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ foreach ($typemap(cstype, T) item in other) {
+ Remove(item);
+ }
+ }
+
+ public void IntersectWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ $csclassname old = new $csclassname(this);
+
+ Clear();
+ foreach ($typemap(cstype, T) item in other) {
+ if (old.Contains(item))
+ Add(item);
+ }
+ }
+
+ private static int count_enum(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ int count = 0;
+ foreach ($typemap(cstype, T) item in other) {
+ count++;
+ }
+
+ return count;
+ }
+
+ public bool IsProperSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ return IsSubsetOf(other) && Count < count_enum(other);
+ }
+
+ public bool IsProperSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ return IsSupersetOf(other) && Count > count_enum(other);
+ }
+
+ public bool IsSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ int countContained = 0;
+
+ foreach ($typemap(cstype, T) item in other) {
+ if (Contains(item))
+ countContained++;
+ }
+
+ return countContained == Count;
+ }
+
+ public bool IsSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ foreach ($typemap(cstype, T) item in other) {
+ if (!Contains(item))
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool Overlaps(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ foreach ($typemap(cstype, T) item in other) {
+ if (Contains(item))
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool SetEquals(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ return IsSupersetOf(other) && Count == count_enum(other);
+ }
+
+ public void SymmetricExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ foreach ($typemap(cstype, T) item in other) {
+ if (!Remove(item))
+ Add(item);
+ }
+ }
+
+ public void UnionWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) {
+ foreach ($typemap(cstype, T) item in other) {
+ Add(item);
+ }
+ }
+
+ private global::System.Collections.Generic.ICollection<$typemap(cstype, T)> Items {
+ get {
+ global::System.Collections.Generic.ICollection<$typemap(cstype, T)> items = new global::System.Collections.Generic.List<$typemap(cstype, T)>();
+ int size = this.Count;
+ if (size > 0) {
+ global::System.IntPtr iter = create_iterator_begin();
+ for (int i = 0; i < size; i++) {
+ items.Add(get_next(iter));
+ }
+ destroy_iterator(iter);
+ }
+ return items;
+ }
+ }
+
+ global::System.Collections.Generic.IEnumerator<$typemap(cstype, T)> global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)>.GetEnumerator() {
+ return new $csclassnameEnumerator(this);
+ }
+
+ global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() {
+ return new $csclassnameEnumerator(this);
+ }
+
+ public $csclassnameEnumerator GetEnumerator() {
+ return new $csclassnameEnumerator(this);
+ }
+
+ // Type-safe enumerator
+ /// Note that the IEnumerator documentation requires an InvalidOperationException to be thrown
+ /// whenever the collection is modified. This has been done for changes in the size of the
+ /// collection but not when one of the elements of the collection is modified as it is a bit
+ /// tricky to detect unmanaged code that modifies the collection under our feet.
+ public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator,
+ global::System.Collections.Generic.IEnumerator<$typemap(cstype, T)>
+ {
+ private $csclassname collectionRef;
+ private global::System.Collections.Generic.IList<$typemap(cstype, T)> ItemsCollection;
+ private int currentIndex;
+ private object currentObject;
+ private int currentSize;
+
+ public $csclassnameEnumerator($csclassname collection) {
+ collectionRef = collection;
+ ItemsCollection = new global::System.Collections.Generic.List<$typemap(cstype, T)>(collection.Items);
+ currentIndex = -1;
+ currentObject = null;
+ currentSize = collectionRef.Count;
+ }
+
+ // Type-safe iterator Current
+ public $typemap(cstype, T) Current {
+ get {
+ if (currentIndex == -1)
+ throw new global::System.InvalidOperationException("Enumeration not started.");
+ if (currentIndex > currentSize - 1)
+ throw new global::System.InvalidOperationException("Enumeration finished.");
+ if (currentObject == null)
+ throw new global::System.InvalidOperationException("Collection modified.");
+ return ($typemap(cstype, T))currentObject;
+ }
+ }
+
+ // Type-unsafe IEnumerator.Current
+ object global::System.Collections.IEnumerator.Current {
+ get {
+ return Current;
+ }
+ }
+
+ public bool MoveNext() {
+ int size = collectionRef.Count;
+ bool moveOkay = (currentIndex+1 < size) && (size == currentSize);
+ if (moveOkay) {
+ currentIndex++;
+ currentObject = ItemsCollection[currentIndex];
+ } else {
+ currentObject = null;
+ }
+ return moveOkay;
+ }
+
+ public void Reset() {
+ currentIndex = -1;
+ currentObject = null;
+ if (collectionRef.Count != currentSize) {
+ throw new global::System.InvalidOperationException("Collection modified.");
+ }
+ }
+
+ public void Dispose() {
+ currentIndex = -1;
+ currentObject = null;
+ }
+ }
+
+%}
+
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T key_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ unordered_set();
+ unordered_set(const unordered_set& other);
+ size_type size() const;
+ bool empty() const;
+ %rename(Clear) clear;
+ void clear();
+ %extend {
+ bool Add(const value_type& item) {
+ return $self->insert(item).second;
+ }
+
+ bool Contains(const value_type& item) {
+ return $self->count(item) != 0;
+ }
+
+ bool Remove(const value_type& item) {
+ return $self->erase(item) != 0;
+ }
+
+ const value_type& getitem(const value_type& item) throw (std::out_of_range) {
+ std::unordered_set<T>::iterator iter = $self->find(item);
+ if (iter == $self->end())
+ throw std::out_of_range("item not found");
+
+ return *iter;
+ }
+
+ // create_iterator_begin(), get_next() and destroy_iterator work together to provide a collection of items to C#
+ %apply void *VOID_INT_PTR { std::unordered_set<T>::iterator *create_iterator_begin }
+ %apply void *VOID_INT_PTR { std::unordered_set<T>::iterator *swigiterator }
+
+ std::unordered_set<T>::iterator *create_iterator_begin() {
+ return new std::unordered_set<T>::iterator($self->begin());
+ }
+
+ const key_type& get_next(std::unordered_set<T>::iterator *swigiterator) {
+ (void)$self;
+ std::unordered_set<T>::iterator iter = *swigiterator;
+ (*swigiterator)++;
+ return *iter;
+ }
+
+ void destroy_iterator(std::unordered_set<T>::iterator *swigiterator) {
+ (void)$self;
+ delete swigiterator;
+ }
+ }
+};
+
+}