/trunk/Lib/d/std_vector.i
Swig | 591 lines | 486 code | 88 blank | 17 comment | 0 complexity | db4d32ef8f493efdef696cbc5f266391 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
- /* -----------------------------------------------------------------------------
- * std_vector.i
- *
- * SWIG typemaps for std::vector<T>, D implementation.
- *
- * The D wrapper is made to loosely resemble a tango.util.container.more.Vector
- * and to provide built-in array-like access.
- *
- * If T does define an operator==, then use the SWIG_STD_VECTOR_ENHANCED
- * macro to obtain enhanced functionality (none yet), for example:
- *
- * SWIG_STD_VECTOR_ENHANCED(SomeNamespace::Klass)
- * %template(VectKlass) std::vector<SomeNamespace::Klass>;
- *
- * Warning: heavy macro usage in this file. Use swig -E to get a sane view on
- * the real file contents!
- * ----------------------------------------------------------------------------- */
- // Warning: Use the typemaps here in the expectation that the macros they are in will change name.
- %include <std_common.i>
- // MACRO for use within the std::vector class body
- %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CONST_REFERENCE, CTYPE...)
- #if (SWIG_D_VERSION == 1)
- %typemap(dimports) std::vector< CTYPE > "static import tango.core.Exception;"
- %typemap(dcode) std::vector< CTYPE > %{
- public this($typemap(dtype, CTYPE)[] values) {
- this();
- append(values);
- }
- alias push_back add;
- alias push_back push;
- alias push_back opCatAssign;
- alias size length;
- alias opSlice slice;
- public $typemap(dtype, CTYPE) opIndexAssign($typemap(dtype, CTYPE) value, size_t index) {
- if (index >= size()) {
- throw new tango.core.Exception.NoSuchElementException("Tried to assign to element out of vector bounds.");
- }
- setElement(index, value);
- return value;
- }
- public $typemap(dtype, CTYPE) opIndex(size_t index) {
- if (index >= size()) {
- throw new tango.core.Exception.NoSuchElementException("Tried to read from element out of vector bounds.");
- }
- return getElement(index);
- }
- public void append($typemap(dtype, CTYPE)[] value...) {
- foreach (v; value) {
- add(v);
- }
- }
- public $typemap(dtype, CTYPE)[] opSlice() {
- $typemap(dtype, CTYPE)[] array = new $typemap(dtype, CTYPE)[size()];
- foreach (i, ref value; array) {
- value = getElement(i);
- }
- return array;
- }
- public int opApply(int delegate(ref $typemap(dtype, CTYPE) value) dg) {
- int result;
- size_t currentSize = size();
- for (size_t i = 0; i < currentSize; ++i) {
- auto value = getElement(i);
- result = dg(value);
- setElement(i, value);
- }
- return result;
- }
- public int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) {
- int result;
- size_t currentSize = size();
- for (size_t i = 0; i < currentSize; ++i) {
- auto value = getElement(i);
- // Workaround for http://d.puremagic.com/issues/show_bug.cgi?id=2443.
- auto index = i;
- result = dg(index, value);
- setElement(i, value);
- }
- return result;
- }
- public void capacity(size_t value) {
- if (value < size()) {
- throw new tango.core.Exception.IllegalArgumentException("Tried to make the capacity of a vector smaller than its size.");
- }
- reserve(value);
- }
- %}
- public:
- typedef size_t size_type;
- typedef CTYPE value_type;
- typedef CONST_REFERENCE const_reference;
- void clear();
- void push_back(CTYPE const& x);
- size_type size() const;
- size_type capacity() const;
- void reserve(size_type n) throw (std::length_error);
- vector();
- vector(const vector &other);
- %extend {
- vector(size_type capacity) throw (std::length_error) {
- std::vector< CTYPE >* pv = 0;
- pv = new std::vector< CTYPE >();
- // Might throw std::length_error.
- pv->reserve(capacity);
- return pv;
- }
- size_type unused() const {
- return $self->capacity() - $self->size();
- }
- const_reference remove() throw (std::out_of_range) {
- if ($self->empty()) {
- throw std::out_of_range("Tried to remove last element from empty vector.");
- }
- std::vector< CTYPE >::const_reference value = $self->back();
- $self->pop_back();
- return value;
- }
- const_reference remove(size_type index) throw (std::out_of_range) {
- if (index >= $self->size()) {
- throw std::out_of_range("Tried to remove element with invalid index.");
- }
- std::vector< CTYPE >::iterator it = $self->begin() + index;
- std::vector< CTYPE >::const_reference value = *it;
- $self->erase(it);
- return value;
- }
- }
- // Wrappers for setting/getting items with the possibly thrown exception
- // specified (important for SWIG wrapper generation).
- %extend {
- const_reference getElement(size_type index) throw (std::out_of_range) {
- if ((index < 0) || ($self->size() <= index)) {
- throw std::out_of_range("Tried to get value of element with invalid index.");
- }
- return (*$self)[index];
- }
- }
- // Use CTYPE const& instead of const_reference to work around SWIG code
- // generation issue when using const pointers as vector elements (like
- // std::vector< const int* >).
- %extend {
- void setElement(size_type index, CTYPE const& val) throw (std::out_of_range) {
- if ((index < 0) || ($self->size() <= index)) {
- throw std::out_of_range("Tried to set value of element with invalid index.");
- }
- (*$self)[index] = val;
- }
- }
- %dmethodmodifiers std::vector::getElement "private"
- %dmethodmodifiers std::vector::setElement "private"
- %dmethodmodifiers std::vector::reserve "private"
- #else
- %typemap(dimports) std::vector< CTYPE > %{
- static import std.algorithm;
- static import std.exception;
- static import std.range;
- static import std.traits;
- %}
- %typemap(dcode) std::vector< CTYPE > %{
- alias size_t KeyType;
- alias $typemap(dtype, CTYPE) ValueType;
- this(ValueType[] values...) {
- this();
- reserve(values.length);
- foreach (e; values) {
- this ~= e;
- }
- }
- struct Range {
- private $typemap(dtype, std::vector< CTYPE >) _outer;
- private size_t _a, _b;
- this($typemap(dtype, std::vector< CTYPE >) data, size_t a, size_t b) {
- _outer = data;
- _a = a;
- _b = b;
- }
- @property bool empty() const {
- assert((cast($typemap(dtype, std::vector< CTYPE >))_outer).length >= _b);
- return _a >= _b;
- }
- @property Range save() {
- return this;
- }
- @property ValueType front() {
- std.exception.enforce(!empty);
- return _outer[_a];
- }
- @property void front(ValueType value) {
- std.exception.enforce(!empty);
- _outer[_a] = std.algorithm.move(value);
- }
- void popFront() {
- std.exception.enforce(!empty);
- ++_a;
- }
- void opIndexAssign(ValueType value, size_t i) {
- i += _a;
- std.exception.enforce(i < _b && _b <= _outer.length);
- _outer[i] = value;
- }
- void opIndexOpAssign(string op)(ValueType value, size_t i) {
- std.exception.enforce(_outer && _a + i < _b && _b <= _outer.length);
- auto element = _outer[i];
- mixin("element "~op~"= value;");
- _outer[i] = element;
- }
- }
- // TODO: dup?
- Range opSlice() {
- return Range(this, 0, length);
- }
- Range opSlice(size_t a, size_t b) {
- std.exception.enforce(a <= b && b <= length);
- return Range(this, a, b);
- }
- size_t opDollar() const {
- return length;
- }
- @property ValueType front() {
- std.exception.enforce(!empty);
- return getElement(0);
- }
- @property void front(ValueType value) {
- std.exception.enforce(!empty);
- setElement(0, value);
- }
- @property ValueType back() {
- std.exception.enforce(!empty);
- return getElement(length - 1);
- }
- @property void back(ValueType value) {
- std.exception.enforce(!empty);
- setElement(length - 1, value);
- }
- ValueType opIndex(size_t i) {
- return getElement(i);
- }
- void opIndexAssign(ValueType value, size_t i) {
- setElement(i, value);
- }
- void opIndexOpAssign(string op)(ValueType value, size_t i) {
- auto element = this[i];
- mixin("element "~op~"= value;");
- this[i] = element;
- }
- ValueType[] opBinary(string op, Stuff)(Stuff stuff) if (op == "~") {
- ValueType[] result;
- result ~= this[];
- assert(result.length == length);
- result ~= stuff[];
- return result;
- }
- void opOpAssign(string op, Stuff)(Stuff stuff) if (op == "~") {
- static if (is(typeof(insertBack(stuff)))) {
- insertBack(stuff);
- } else if (is(typeof(insertBack(stuff[])))) {
- insertBack(stuff[]);
- } else {
- static assert(false, "Cannot append " ~ Stuff.stringof ~ " to " ~ typeof(this).stringof);
- }
- }
- alias size length;
- alias remove removeAny;
- alias removeAny stableRemoveAny;
- size_t insertBack(Stuff)(Stuff stuff)
- if (std.traits.isImplicitlyConvertible!(Stuff, ValueType)){
- push_back(stuff);
- return 1;
- }
- size_t insertBack(Stuff)(Stuff stuff)
- if (std.range.isInputRange!Stuff &&
- std.traits.isImplicitlyConvertible!(std.range.ElementType!Stuff, ValueType)) {
- size_t itemCount;
- foreach(item; stuff) {
- insertBack(item);
- ++itemCount;
- }
- return itemCount;
- }
- alias insertBack insert;
- alias pop_back removeBack;
- alias pop_back stableRemoveBack;
- size_t insertBefore(Stuff)(Range r, Stuff stuff)
- if (std.traits.isImplicitlyConvertible!(Stuff, ValueType)) {
- std.exception.enforce(r._outer.swigCPtr == swigCPtr && r._a < length);
- insertAt(r._a, stuff);
- return 1;
- }
- size_t insertBefore(Stuff)(Range r, Stuff stuff)
- if (std.range.isInputRange!Stuff && std.traits.isImplicitlyConvertible!(ElementType!Stuff, ValueType)) {
- std.exception.enforce(r._outer.swigCPtr == swigCPtr && r._a <= length);
- size_t insertCount;
- foreach(i, item; stuff) {
- insertAt(r._a + i, item);
- ++insertCount;
- }
- return insertCount;
- }
- size_t insertAfter(Stuff)(Range r, Stuff stuff) {
- // TODO: optimize
- immutable offset = r._a + r.length;
- std.exception.enforce(offset <= length);
- auto result = insertBack(stuff);
- std.algorithm.bringToFront(this[offset .. length - result],
- this[length - result .. length]);
- return result;
- }
- size_t replace(Stuff)(Range r, Stuff stuff)
- if (std.range.isInputRange!Stuff &&
- std.traits.isImplicitlyConvertible!(ElementType!Stuff, ValueType)) {
- immutable offset = r._a;
- std.exception.enforce(offset <= length);
- size_t result;
- for (; !stuff.empty; stuff.popFront()) {
- if (r.empty) {
- // append the rest
- return result + insertBack(stuff);
- }
- r.front = stuff.front;
- r.popFront();
- ++result;
- }
- // Remove remaining stuff in r
- remove(r);
- return result;
- }
- size_t replace(Stuff)(Range r, Stuff stuff)
- if (std.traits.isImplicitlyConvertible!(Stuff, ValueType))
- {
- if (r.empty)
- {
- insertBefore(r, stuff);
- }
- else
- {
- r.front = stuff;
- r.popFront();
- remove(r);
- }
- return 1;
- }
- Range linearRemove(Range r) {
- std.exception.enforce(r._a <= r._b && r._b <= length);
- immutable tailLength = length - r._b;
- linearRemove(r._a, r._b);
- return this[length - tailLength .. length];
- }
- alias remove stableLinearRemove;
- int opApply(int delegate(ref $typemap(dtype, CTYPE) value) dg) {
- int result;
- size_t currentSize = size();
- for (size_t i = 0; i < currentSize; ++i) {
- auto value = getElement(i);
- result = dg(value);
- setElement(i, value);
- }
- return result;
- }
- int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) {
- int result;
- size_t currentSize = size();
- for (size_t i = 0; i < currentSize; ++i) {
- auto value = getElement(i);
- // Workaround for http://d.puremagic.com/issues/show_bug.cgi?id=2443.
- auto index = i;
- result = dg(index, value);
- setElement(i, value);
- }
- return result;
- }
- %}
- public:
- typedef size_t size_type;
- typedef CTYPE value_type;
- typedef CONST_REFERENCE const_reference;
- bool empty() const;
- void clear();
- void push_back(CTYPE const& x);
- void pop_back();
- size_type size() const;
- size_type capacity() const;
- void reserve(size_type n) throw (std::length_error);
- vector();
- vector(const vector &other);
- %extend {
- vector(size_type capacity) throw (std::length_error) {
- std::vector< CTYPE >* pv = 0;
- pv = new std::vector< CTYPE >();
- // Might throw std::length_error.
- pv->reserve(capacity);
- return pv;
- }
- const_reference remove() throw (std::out_of_range) {
- if ($self->empty()) {
- throw std::out_of_range("Tried to remove last element from empty vector.");
- }
- std::vector< CTYPE >::const_reference value = $self->back();
- $self->pop_back();
- return value;
- }
- const_reference remove(size_type index) throw (std::out_of_range) {
- if (index >= $self->size()) {
- throw std::out_of_range("Tried to remove element with invalid index.");
- }
- std::vector< CTYPE >::iterator it = $self->begin() + index;
- std::vector< CTYPE >::const_reference value = *it;
- $self->erase(it);
- return value;
- }
- void removeBack(size_type how_many) throw (std::out_of_range) {
- std::vector< CTYPE >::iterator end = $self->end();
- std::vector< CTYPE >::iterator start = end - how_many;
- $self->erase(start, end);
- }
- void linearRemove(size_type start_index, size_type end_index) throw (std::out_of_range) {
- std::vector< CTYPE >::iterator start = $self->begin() + start_index;
- std::vector< CTYPE >::iterator end = $self->begin() + end_index;
- $self->erase(start, end);
- }
- void insertAt(size_type index, CTYPE const& x) throw (std::out_of_range) {
- std::vector< CTYPE >::iterator it = $self->begin() + index;
- $self->insert(it, x);
- }
- }
- // Wrappers for setting/getting items with the possibly thrown exception
- // specified (important for SWIG wrapper generation).
- %extend {
- const_reference getElement(size_type index) throw (std::out_of_range) {
- if ((index < 0) || ($self->size() <= index)) {
- throw std::out_of_range("Tried to get value of element with invalid index.");
- }
- return (*$self)[index];
- }
- }
- // Use CTYPE const& instead of const_reference to work around SWIG code
- // generation issue when using const pointers as vector elements (like
- // std::vector< const int* >).
- %extend {
- void setElement(size_type index, CTYPE const& val) throw (std::out_of_range) {
- if ((index < 0) || ($self->size() <= index)) {
- throw std::out_of_range("Tried to set value of element with invalid index.");
- }
- (*$self)[index] = val;
- }
- }
- %dmethodmodifiers std::vector::getElement "private"
- %dmethodmodifiers std::vector::setElement "private"
- #endif
- %enddef
- // Extra methods added to the collection class if operator== is defined for the class being wrapped
- // The class will then implement IList<>, which adds extra functionality
- %define SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE...)
- %extend {
- }
- %enddef
- // For vararg handling in macros, from swigmacros.swg
- #define %arg(X...) X
- // Macros for std::vector class specializations/enhancements
- %define SWIG_STD_VECTOR_ENHANCED(CTYPE...)
- namespace std {
- template<> class vector<CTYPE > {
- SWIG_STD_VECTOR_MINIMUM_INTERNAL(%arg(CTYPE const&), %arg(CTYPE))
- SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CTYPE)
- };
- }
- %enddef
- %{
- #include <vector>
- #include <stdexcept>
- %}
- namespace std {
- // primary (unspecialized) class template for std::vector
- // does not require operator== to be defined
- template<class T> class vector {
- SWIG_STD_VECTOR_MINIMUM_INTERNAL(T const&, T)
- };
- // specializations for pointers
- template<class T> class vector<T *> {
- SWIG_STD_VECTOR_MINIMUM_INTERNAL(T *const&, T *)
- SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(T *)
- };
- // bool is a bit different in the C++ standard - const_reference in particular
- template<> class vector<bool> {
- SWIG_STD_VECTOR_MINIMUM_INTERNAL(bool, bool)
- SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(bool)
- };
- }
- // template specializations for std::vector
- // these provide extra collections methods as operator== is defined
- SWIG_STD_VECTOR_ENHANCED(char)
- SWIG_STD_VECTOR_ENHANCED(signed char)
- SWIG_STD_VECTOR_ENHANCED(unsigned char)
- SWIG_STD_VECTOR_ENHANCED(short)
- SWIG_STD_VECTOR_ENHANCED(unsigned short)
- SWIG_STD_VECTOR_ENHANCED(int)
- SWIG_STD_VECTOR_ENHANCED(unsigned int)
- SWIG_STD_VECTOR_ENHANCED(long)
- SWIG_STD_VECTOR_ENHANCED(unsigned long)
- SWIG_STD_VECTOR_ENHANCED(long long)
- SWIG_STD_VECTOR_ENHANCED(unsigned long long)
- SWIG_STD_VECTOR_ENHANCED(float)
- SWIG_STD_VECTOR_ENHANCED(double)
- SWIG_STD_VECTOR_ENHANCED(std::string) // also requires a %include <std_string.i>