Add std::set<> typemaps for C#
Create new Lib/csharp/std_set.i based on the existing std_map.i and run li_std_set unit test for C# as well. Notice that the set operations defined by the base ISet<> interface are not implemented yet.
This commit is contained in:
parent
54821e3af3
commit
f0067b6bbf
4 changed files with 303 additions and 3 deletions
239
Lib/csharp/std_set.i
Normal file
239
Lib/csharp/std_set.i
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* std_map.i
|
||||
*
|
||||
* SWIG typemaps for std::set<T>
|
||||
*
|
||||
* The C# wrapper is made to look and feel like a C# System.Collections.Generic.HashSet<>.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%{
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
%}
|
||||
|
||||
%csmethodmodifiers std::set::size "private"
|
||||
%csmethodmodifiers std::set::getitem "private"
|
||||
%csmethodmodifiers std::set::create_iterator_begin "private"
|
||||
%csmethodmodifiers std::set::get_next "private"
|
||||
%csmethodmodifiers std::set::destroy_iterator "private"
|
||||
|
||||
namespace std {
|
||||
|
||||
// TODO: Add support for comparator and allocator template parameters.
|
||||
template <class T>
|
||||
class set {
|
||||
|
||||
%typemap(csinterfaces) std::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(string 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 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) { throw new global::System.Exception("TODO"); }
|
||||
public void IntersectWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); }
|
||||
public bool IsProperSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); }
|
||||
public bool IsProperSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); }
|
||||
public bool IsSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); }
|
||||
public bool IsSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); }
|
||||
public bool Overlaps(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); }
|
||||
public bool SetEquals(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); }
|
||||
public void SymmetricExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); }
|
||||
public void UnionWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { throw new global::System.Exception("TODO"); }
|
||||
|
||||
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 $typemap(cstype, T) 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 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;
|
||||
|
||||
set();
|
||||
set(const 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::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::set<T>::iterator *create_iterator_begin }
|
||||
%apply void *VOID_INT_PTR { std::set<T>::iterator *swigiterator }
|
||||
|
||||
std::set<T>::iterator *create_iterator_begin() {
|
||||
return new std::set<T>::iterator($self->begin());
|
||||
}
|
||||
|
||||
const key_type& get_next(std::set<T>::iterator *swigiterator) {
|
||||
std::set<T>::iterator iter = *swigiterator;
|
||||
(*swigiterator)++;
|
||||
return *iter;
|
||||
}
|
||||
|
||||
void destroy_iterator(std::set<T>::iterator *swigiterator) {
|
||||
delete swigiterator;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue