Add std::array container wrappers for Python
These work much like any of the other STL containers except Python slicing is somewhat limited because the array is a fixed size. Only slices of the full size are supported.
This commit is contained in:
parent
4e8ea4e853
commit
55bbf68512
8 changed files with 500 additions and 57 deletions
|
|
@ -531,6 +531,7 @@ CPP11_TEST_CASES = \
|
||||||
cpp11_initializer_list \
|
cpp11_initializer_list \
|
||||||
cpp11_initializer_list_extend \
|
cpp11_initializer_list_extend \
|
||||||
cpp11_lambda_functions \
|
cpp11_lambda_functions \
|
||||||
|
cpp11_li_std_array \
|
||||||
cpp11_noexcept \
|
cpp11_noexcept \
|
||||||
cpp11_null_pointer_constant \
|
cpp11_null_pointer_constant \
|
||||||
cpp11_raw_string_literals \
|
cpp11_raw_string_literals \
|
||||||
|
|
|
||||||
53
Examples/test-suite/cpp11_li_std_array.i
Normal file
53
Examples/test-suite/cpp11_li_std_array.i
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
%module cpp11_li_std_array
|
||||||
|
|
||||||
|
#if defined(SWIGPYTHON)
|
||||||
|
|
||||||
|
%include <std_array.i>
|
||||||
|
|
||||||
|
%template(ArrayInt6) std::array<int, 6>;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
std::array<int, 6> arrayOutVal() {
|
||||||
|
return { -2, -1, 0, 0, 1, 2 };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<int, 6> & arrayOutRef() {
|
||||||
|
static std::array<int, 6> a = { -2, -1, 0, 0, 1, 2 };
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<int, 6> * arrayOutPtr() {
|
||||||
|
static std::array<int, 6> a = { -2, -1, 0, 0, 1, 2 };
|
||||||
|
return &a;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<int, 6> arrayInVal(std::array<int, 6> myarray) {
|
||||||
|
std::array<int, 6> a = myarray;
|
||||||
|
for (auto& val : a) {
|
||||||
|
val *= 10;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::array<int, 6> & arrayInConstRef(const std::array<int, 6> & myarray) {
|
||||||
|
static std::array<int, 6> a = myarray;
|
||||||
|
for (auto& val : a) {
|
||||||
|
val *= 10;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arrayInRef(std::array<int, 6> & myarray) {
|
||||||
|
for (auto& val : myarray) {
|
||||||
|
val *= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void arrayInPtr(std::array<int, 6> * myarray) {
|
||||||
|
for (auto& val : *myarray) {
|
||||||
|
val *= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
#endif
|
||||||
160
Examples/test-suite/python/cpp11_li_std_array_runme.py
Normal file
160
Examples/test-suite/python/cpp11_li_std_array_runme.py
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
from cpp11_li_std_array import *
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def failed(a, b, msg):
|
||||||
|
raise RuntimeError, msg + " " + str(list(a)) + " " + str(list(b))
|
||||||
|
|
||||||
|
|
||||||
|
def compare_sequences(a, b):
|
||||||
|
if len(a) != len(b):
|
||||||
|
failed(a, b, "different sizes")
|
||||||
|
for i in range(len(a)):
|
||||||
|
if a[i] != b[i]:
|
||||||
|
failed(a, b, "elements are different")
|
||||||
|
|
||||||
|
def compare_containers(pythonlist, swigarray):
|
||||||
|
compare_sequences(pythonlist, swigarray)
|
||||||
|
|
||||||
|
def steps_exception(swigarray, i, j, step):
|
||||||
|
try:
|
||||||
|
if i == None and j == None:
|
||||||
|
a = swigarray[::step]
|
||||||
|
elif i == None:
|
||||||
|
a = swigarray[:j:step]
|
||||||
|
elif j == None:
|
||||||
|
a = swigarray[i::step]
|
||||||
|
else:
|
||||||
|
a = swigarray[i:j:step]
|
||||||
|
raise RuntimeError, "swigarray[" + str(i) + ":" + str(j) + ":" + str(step) + "] missed steps exception for " + str(list(swigarray))
|
||||||
|
except ValueError, e:
|
||||||
|
# print("exception: {}".format(e))
|
||||||
|
pass
|
||||||
|
|
||||||
|
def del_exception(swigarray, i, j, step):
|
||||||
|
try:
|
||||||
|
if i == None and j == None:
|
||||||
|
del swigarray[::step]
|
||||||
|
elif j == None and step == None:
|
||||||
|
del swigarray[i]
|
||||||
|
elif i == None:
|
||||||
|
del swigarray[:j:step]
|
||||||
|
elif j == None:
|
||||||
|
del swigarray[i::step]
|
||||||
|
else:
|
||||||
|
del swigarray[i:j:step]
|
||||||
|
raise RuntimeError, "swigarray[" + str(i) + ":" + str(j) + ":" + str(step) + "] missed del exception for " + str(list(swigarray))
|
||||||
|
except ValueError, e:
|
||||||
|
# print("exception: {}".format(e))
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setslice_exception(swigarray, newval):
|
||||||
|
try:
|
||||||
|
swigarray[::] = newval
|
||||||
|
raise RuntimeError, "swigarray[::] = " + str(newval) + " missed set exception for swigarray:" + str(list(swigarray))
|
||||||
|
except TypeError, e:
|
||||||
|
# print("exception: {}".format(e))
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Check std::array has similar behaviour to a Python list
|
||||||
|
# except it is not resizable
|
||||||
|
|
||||||
|
ps = [0, 1, 2, 3, 4, 5]
|
||||||
|
|
||||||
|
ai = ArrayInt6(ps)
|
||||||
|
|
||||||
|
# slices
|
||||||
|
compare_containers(ps[0:6], ai[0:6])
|
||||||
|
compare_containers(ps[0:10], ai[0:10])
|
||||||
|
compare_containers(ps[-10:6], ai[-10:6])
|
||||||
|
compare_containers(ps[-10:10], ai[-10:10])
|
||||||
|
|
||||||
|
compare_containers(ps[0:6:1], ai[0:6:1])
|
||||||
|
compare_containers(ps[::], ai[::])
|
||||||
|
compare_containers(ps[::1], ai[::1])
|
||||||
|
|
||||||
|
compare_containers([x for x in ps], [x for x in ai])
|
||||||
|
|
||||||
|
# Reverse
|
||||||
|
compare_containers(ps[::-1], ai[::-1])
|
||||||
|
compare_containers(ps[5::-1], ai[5::-1])
|
||||||
|
compare_containers(ps[10::-1], ai[10::-1])
|
||||||
|
|
||||||
|
# Steps other than +1 and -1 not supported
|
||||||
|
steps_exception(ai, 0, 6, 3)
|
||||||
|
steps_exception(ai, None, None, 0)
|
||||||
|
steps_exception(ai, None, None, 2)
|
||||||
|
steps_exception(ai, None, None, -2)
|
||||||
|
steps_exception(ai, 1, 3, 1)
|
||||||
|
steps_exception(ai, 3, 1, -1)
|
||||||
|
|
||||||
|
# Modify content
|
||||||
|
for i in range(len(ps)):
|
||||||
|
ps[i] = (ps[i] + 1) * 10
|
||||||
|
ai[i] = (ai[i] + 1) * 10
|
||||||
|
compare_containers(ps, ai)
|
||||||
|
|
||||||
|
# Delete
|
||||||
|
del_exception(ai, 0, 6, 3)
|
||||||
|
del_exception(ai, None, None, 0)
|
||||||
|
del_exception(ai, None, None, 2)
|
||||||
|
del_exception(ai, None, None, -2)
|
||||||
|
del_exception(ai, 1, 3, 1)
|
||||||
|
del_exception(ai, 3, 1, -1)
|
||||||
|
|
||||||
|
del_exception(ai, 0, None, None)
|
||||||
|
del_exception(ai, 5, None, None)
|
||||||
|
|
||||||
|
# Empty
|
||||||
|
ai = ArrayInt6()
|
||||||
|
compare_containers([0, 0, 0, 0, 0, 0], ai)
|
||||||
|
|
||||||
|
# Set slice
|
||||||
|
newvals = [10, 20, 30, 40, 50, 60]
|
||||||
|
ai[::] = newvals
|
||||||
|
compare_containers(ai, newvals)
|
||||||
|
|
||||||
|
newvals = [100, 200, 300, 400, 500, 600]
|
||||||
|
ai[0:6:1] = newvals
|
||||||
|
compare_containers(ai, newvals)
|
||||||
|
|
||||||
|
newvals = [1000, 2000, 3000, 4000, 5000, 6000]
|
||||||
|
ai[::-1] = newvals
|
||||||
|
compare_containers(ai, newvals[::-1])
|
||||||
|
|
||||||
|
newvals = [10000, 20000, 30000, 40000, 50000, 60000]
|
||||||
|
ai[-10:100:1] = newvals
|
||||||
|
compare_containers(ai, newvals[-10:100:1])
|
||||||
|
|
||||||
|
setslice_exception(ai, [1, 2, 3, 4, 5, 6, 7])
|
||||||
|
setslice_exception(ai, [1, 2, 3, 4, 5])
|
||||||
|
setslice_exception(ai, [1, 2, 3, 4])
|
||||||
|
setslice_exception(ai, [1, 2, 3])
|
||||||
|
setslice_exception(ai, [1, 2])
|
||||||
|
setslice_exception(ai, [1])
|
||||||
|
setslice_exception(ai, [])
|
||||||
|
|
||||||
|
# Check return
|
||||||
|
compare_containers(arrayOutVal(), [-2, -1, 0, 0, 1, 2])
|
||||||
|
compare_containers(arrayOutRef(), [-2, -1, 0, 0, 1, 2])
|
||||||
|
compare_containers(arrayOutPtr(), [-2, -1, 0, 0, 1, 2])
|
||||||
|
|
||||||
|
# Check passing arguments
|
||||||
|
ai = arrayInVal([9, 8, 7, 6, 5, 4])
|
||||||
|
compare_containers(ai, [90, 80, 70, 60, 50, 40])
|
||||||
|
|
||||||
|
ai = arrayInConstRef([9, 8, 7, 6, 5, 4])
|
||||||
|
compare_containers(ai, [90, 80, 70, 60, 50, 40])
|
||||||
|
|
||||||
|
ai = ArrayInt6([9, 8, 7, 6, 5, 4])
|
||||||
|
arrayInRef(ai)
|
||||||
|
compare_containers(ai, [90, 80, 70, 60, 50, 40])
|
||||||
|
|
||||||
|
ai = ArrayInt6([9, 8, 7, 6, 5, 4])
|
||||||
|
arrayInPtr(ai)
|
||||||
|
compare_containers(ai, [90, 80, 70, 60, 50, 40])
|
||||||
|
|
||||||
|
# fill
|
||||||
|
ai.fill(111)
|
||||||
|
compare_containers(ai, [111, 111, 111, 111, 111, 111])
|
||||||
|
|
@ -252,6 +252,12 @@ namespace swig {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
inline void
|
||||||
|
erase(Sequence* seq, const typename Sequence::iterator& position) {
|
||||||
|
seq->erase(position);
|
||||||
|
}
|
||||||
|
|
||||||
template <class Sequence, class Difference>
|
template <class Sequence, class Difference>
|
||||||
inline Sequence*
|
inline Sequence*
|
||||||
getslice(const Sequence* self, Difference i, Difference j, Py_ssize_t step) {
|
getslice(const Sequence* self, Difference i, Difference j, Py_ssize_t step) {
|
||||||
|
|
@ -552,6 +558,7 @@ namespace swig
|
||||||
difference_type _index;
|
difference_type _index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// STL container wrapper around a Python sequence
|
||||||
template <class T>
|
template <class T>
|
||||||
struct SwigPySequence_Cont
|
struct SwigPySequence_Cont
|
||||||
{
|
{
|
||||||
|
|
@ -748,7 +755,6 @@ namespace swig
|
||||||
return self->size();
|
return self->size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -756,7 +762,7 @@ namespace swig
|
||||||
%define %swig_sequence_methods_common(Sequence...)
|
%define %swig_sequence_methods_common(Sequence...)
|
||||||
%swig_sequence_iterator(%arg(Sequence))
|
%swig_sequence_iterator(%arg(Sequence))
|
||||||
%swig_container_methods(%arg(Sequence))
|
%swig_container_methods(%arg(Sequence))
|
||||||
|
|
||||||
%fragment("SwigPySequence_Base");
|
%fragment("SwigPySequence_Base");
|
||||||
|
|
||||||
#if defined(SWIGPYTHON_BUILTIN)
|
#if defined(SWIGPYTHON_BUILTIN)
|
||||||
|
|
@ -769,14 +775,6 @@ namespace swig
|
||||||
#endif // SWIGPYTHON_BUILTIN
|
#endif // SWIGPYTHON_BUILTIN
|
||||||
|
|
||||||
%extend {
|
%extend {
|
||||||
value_type pop() throw (std::out_of_range) {
|
|
||||||
if (self->size() == 0)
|
|
||||||
throw std::out_of_range("pop from empty container");
|
|
||||||
Sequence::value_type x = self->back();
|
|
||||||
self->pop_back();
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* typemap for slice object support */
|
/* typemap for slice object support */
|
||||||
%typemap(in) PySliceObject* {
|
%typemap(in) PySliceObject* {
|
||||||
if (!PySlice_Check($input)) {
|
if (!PySlice_Check($input)) {
|
||||||
|
|
@ -794,7 +792,11 @@ namespace swig
|
||||||
return swig::getslice(self, i, j, 1);
|
return swig::getslice(self, i, j, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __setslice__(difference_type i, difference_type j, const Sequence& v = Sequence()) throw (std::out_of_range, std::invalid_argument) {
|
void __setslice__(difference_type i, difference_type j) throw (std::out_of_range, std::invalid_argument) {
|
||||||
|
swig::setslice(self, i, j, 1, Sequence());
|
||||||
|
}
|
||||||
|
|
||||||
|
void __setslice__(difference_type i, difference_type j, const Sequence& v) throw (std::out_of_range, std::invalid_argument) {
|
||||||
swig::setslice(self, i, j, 1, v);
|
swig::setslice(self, i, j, 1, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -803,11 +805,10 @@ namespace swig
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __delitem__(difference_type i) throw (std::out_of_range) {
|
void __delitem__(difference_type i) throw (std::out_of_range, std::invalid_argument) {
|
||||||
self->erase(swig::getpos(self,i));
|
swig::erase(self, swig::getpos(self, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Overloaded methods for Python 3 compatibility
|
/* Overloaded methods for Python 3 compatibility
|
||||||
* (Also useful in Python 2.x)
|
* (Also useful in Python 2.x)
|
||||||
*/
|
*/
|
||||||
|
|
@ -858,12 +859,11 @@ namespace swig
|
||||||
Sequence::difference_type jd = j;
|
Sequence::difference_type jd = j;
|
||||||
swig::delslice(self, id, jd, step);
|
swig::delslice(self, id, jd, step);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
%define %swig_sequence_methods(Sequence...)
|
%define %swig_sequence_methods_non_resizable(Sequence...)
|
||||||
%swig_sequence_methods_common(%arg(Sequence))
|
%swig_sequence_methods_common(%arg(Sequence))
|
||||||
%extend {
|
%extend {
|
||||||
const value_type& __getitem__(difference_type i) const throw (std::out_of_range) {
|
const value_type& __getitem__(difference_type i) const throw (std::out_of_range) {
|
||||||
|
|
@ -876,19 +876,32 @@ namespace swig
|
||||||
|
|
||||||
#if defined(SWIGPYTHON_BUILTIN)
|
#if defined(SWIGPYTHON_BUILTIN)
|
||||||
// This will be called through the mp_ass_subscript slot to delete an entry.
|
// This will be called through the mp_ass_subscript slot to delete an entry.
|
||||||
void __setitem__(difference_type i) throw (std::out_of_range) {
|
void __setitem__(difference_type i) throw (std::out_of_range, std::invalid_argument) {
|
||||||
self->erase(swig::getpos(self,i));
|
swig::erase(self, swig::getpos(self, i));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
%enddef
|
||||||
|
|
||||||
|
%define %swig_sequence_methods(Sequence...)
|
||||||
|
%swig_sequence_methods_non_resizable(%arg(Sequence))
|
||||||
|
%extend {
|
||||||
|
value_type pop() throw (std::out_of_range) {
|
||||||
|
if (self->size() == 0)
|
||||||
|
throw std::out_of_range("pop from empty container");
|
||||||
|
Sequence::value_type x = self->back();
|
||||||
|
self->pop_back();
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
void append(const value_type& x) {
|
void append(const value_type& x) {
|
||||||
self->push_back(x);
|
self->push_back(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
%define %swig_sequence_methods_val(Sequence...)
|
%define %swig_sequence_methods_non_resizable_val(Sequence...)
|
||||||
%swig_sequence_methods_common(%arg(Sequence))
|
%swig_sequence_methods_common(%arg(Sequence))
|
||||||
%extend {
|
%extend {
|
||||||
value_type __getitem__(difference_type i) throw (std::out_of_range) {
|
value_type __getitem__(difference_type i) throw (std::out_of_range) {
|
||||||
|
|
@ -901,16 +914,28 @@ namespace swig
|
||||||
|
|
||||||
#if defined(SWIGPYTHON_BUILTIN)
|
#if defined(SWIGPYTHON_BUILTIN)
|
||||||
// This will be called through the mp_ass_subscript slot to delete an entry.
|
// This will be called through the mp_ass_subscript slot to delete an entry.
|
||||||
void __setitem__(difference_type i) throw (std::out_of_range) {
|
void __setitem__(difference_type i) throw (std::out_of_range, std::invalid_argument) {
|
||||||
self->erase(swig::getpos(self,i));
|
swig::erase(self, swig::getpos(self, i));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
%enddef
|
||||||
|
|
||||||
|
%define %swig_sequence_methods_val(Sequence...)
|
||||||
|
%swig_sequence_methods_non_resizable_val(%arg(Sequence))
|
||||||
|
%extend {
|
||||||
|
value_type pop() throw (std::out_of_range) {
|
||||||
|
if (self->size() == 0)
|
||||||
|
throw std::out_of_range("pop from empty container");
|
||||||
|
Sequence::value_type x = self->back();
|
||||||
|
self->pop_back();
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
void append(value_type x) {
|
void append(value_type x) {
|
||||||
self->push_back(x);
|
self->push_back(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
91
Lib/python/std_array.i
Normal file
91
Lib/python/std_array.i
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
std::array
|
||||||
|
*/
|
||||||
|
|
||||||
|
%fragment("StdArrayTraits","header",fragment="StdSequenceTraits")
|
||||||
|
%{
|
||||||
|
namespace swig {
|
||||||
|
template <class T, size_t N>
|
||||||
|
struct traits_asptr<std::array<T, N> > {
|
||||||
|
static int asptr(PyObject *obj, std::array<T, N> **vec) {
|
||||||
|
return traits_asptr_stdseq<std::array<T, N> >::asptr(obj, vec);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, size_t N>
|
||||||
|
struct traits_from<std::array<T, N> > {
|
||||||
|
static PyObject *from(const std::array<T, N>& vec) {
|
||||||
|
return traits_from_stdseq<std::array<T, N> >::from(vec);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class SwigPySeq, class T, size_t N>
|
||||||
|
inline void
|
||||||
|
assign(const SwigPySeq& swigpyseq, std::array<T, N>* seq) {
|
||||||
|
if (swigpyseq.size() < seq->size())
|
||||||
|
throw std::invalid_argument("std::array cannot be expanded in size");
|
||||||
|
else if (swigpyseq.size() > seq->size())
|
||||||
|
throw std::invalid_argument("std::array cannot be reduced in size");
|
||||||
|
std::copy(swigpyseq.begin(), swigpyseq.end(), seq->begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, size_t N>
|
||||||
|
inline void
|
||||||
|
erase(std::array<T, N>* seq, const typename std::array<T, N>::iterator& position) {
|
||||||
|
throw std::invalid_argument("std::array object does not support item deletion");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only limited slicing is supported as std::array is fixed in size
|
||||||
|
template <class T, size_t N, class Difference>
|
||||||
|
inline std::array<T, N>*
|
||||||
|
getslice(const std::array<T, N>* self, Difference i, Difference j, Py_ssize_t step) {
|
||||||
|
using Sequence = std::array<T, N>;
|
||||||
|
typename Sequence::size_type size = self->size();
|
||||||
|
Difference ii = 0;
|
||||||
|
Difference jj = 0;
|
||||||
|
swig::slice_adjust(i, j, step, size, ii, jj);
|
||||||
|
|
||||||
|
if (step == 1 && ii == 0 && jj == size) {
|
||||||
|
Sequence *sequence = new Sequence();
|
||||||
|
std::copy(self->begin(), self->end(), sequence->begin());
|
||||||
|
return sequence;
|
||||||
|
} else if (step == -1 && ii == (size - 1) && jj == -1) {
|
||||||
|
Sequence *sequence = new Sequence();
|
||||||
|
std::copy(self->rbegin(), self->rend(), sequence->begin());
|
||||||
|
return sequence;
|
||||||
|
} else {
|
||||||
|
throw std::invalid_argument("std::array object only supports getting a slice that is the size of the array");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, size_t N, class Difference, class InputSeq>
|
||||||
|
inline void
|
||||||
|
setslice(std::array<T, N>* self, Difference i, Difference j, Py_ssize_t step, const InputSeq& is = InputSeq()) {
|
||||||
|
using Sequence = std::array<T, N>;
|
||||||
|
typename Sequence::size_type size = self->size();
|
||||||
|
Difference ii = 0;
|
||||||
|
Difference jj = 0;
|
||||||
|
swig::slice_adjust(i, j, step, size, ii, jj, true);
|
||||||
|
|
||||||
|
if (step == 1 && ii == 0 && jj == size) {
|
||||||
|
std::copy(is.begin(), is.end(), self->begin());
|
||||||
|
} else if (step == -1 && ii == (size - 1) && jj == -1) {
|
||||||
|
std::copy(is.rbegin(), is.rend(), self->begin());
|
||||||
|
} else {
|
||||||
|
throw std::invalid_argument("std::array object only supports setting a slice that is the size of the array");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, size_t N, class Difference>
|
||||||
|
inline void
|
||||||
|
delslice(std::array<T, N>* self, Difference i, Difference j, Py_ssize_t step) {
|
||||||
|
throw std::invalid_argument("std::array object does not support item deletion");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
#define %swig_array_methods(Type...) %swig_sequence_methods_non_resizable(Type)
|
||||||
|
#define %swig_array_methods_val(Type...) %swig_sequence_methods_non_resizable_val(Type);
|
||||||
|
|
||||||
|
%include <std/std_array.i>
|
||||||
|
|
||||||
88
Lib/std/std_array.i
Normal file
88
Lib/std/std_array.i
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
//
|
||||||
|
// std::array
|
||||||
|
//
|
||||||
|
|
||||||
|
%include <std_container.i>
|
||||||
|
|
||||||
|
%define %std_array_methods(array...)
|
||||||
|
%std_sequence_methods_non_resizable(array)
|
||||||
|
void fill(const value_type& u);
|
||||||
|
%enddef
|
||||||
|
|
||||||
|
|
||||||
|
%define %std_array_methods_val(array...)
|
||||||
|
%std_sequence_methods_non_resizable_val(array)
|
||||||
|
void fill(const value_type& u);
|
||||||
|
%enddef
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// std::array
|
||||||
|
//
|
||||||
|
// The aim of all that follows would be to integrate std::array with
|
||||||
|
// as much as possible, namely, to allow the user to pass and
|
||||||
|
// be returned tuples or lists.
|
||||||
|
// const declarations are used to guess the intent of the function being
|
||||||
|
// exported; therefore, the following rationale is applied:
|
||||||
|
//
|
||||||
|
// -- f(std::array<T, N>), f(const std::array<T, N>&):
|
||||||
|
// the parameter being read-only, either a sequence or a
|
||||||
|
// previously wrapped std::array<T, N> can be passed.
|
||||||
|
// -- f(std::array<T, N>&), f(std::array<T, N>*):
|
||||||
|
// the parameter may be modified; therefore, only a wrapped std::array
|
||||||
|
// can be passed.
|
||||||
|
// -- std::array<T, N> f(), const std::array<T, N>& f():
|
||||||
|
// the array is returned by copy; therefore, a sequence of T:s
|
||||||
|
// is returned which is most easily used in other functions
|
||||||
|
// -- std::array<T, N>& f(), std::array<T, N>* f():
|
||||||
|
// the array is returned by reference; therefore, a wrapped std::array
|
||||||
|
// is returned
|
||||||
|
// -- const std::array<T, N>* f(), f(const std::array<T, N>*):
|
||||||
|
// for consistency, they expect and return a plain array pointer.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <array>
|
||||||
|
%}
|
||||||
|
|
||||||
|
// exported classes
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
template<class _Tp, size_t _Nm >
|
||||||
|
class array {
|
||||||
|
public:
|
||||||
|
typedef size_t size_type;
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
typedef _Tp value_type;
|
||||||
|
typedef value_type* pointer;
|
||||||
|
typedef const value_type* const_pointer;
|
||||||
|
typedef _Tp& reference;
|
||||||
|
typedef const _Tp& const_reference;
|
||||||
|
|
||||||
|
%traits_swigtype(_Tp);
|
||||||
|
%traits_enum(_Tp);
|
||||||
|
|
||||||
|
%fragment(SWIG_Traits_frag(std::array<_Tp, _Nm >), "header",
|
||||||
|
fragment=SWIG_Traits_frag(_Tp),
|
||||||
|
fragment="StdArrayTraits") {
|
||||||
|
namespace swig {
|
||||||
|
template <> struct traits<std::array<_Tp, _Nm > > {
|
||||||
|
typedef pointer_category category;
|
||||||
|
static const char* type_name() {
|
||||||
|
return "std::array<" #_Tp "," #_Nm " >";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap_traits_ptr(SWIG_TYPECHECK_STDARRAY, std::array<_Tp, _Nm >);
|
||||||
|
|
||||||
|
#ifdef %swig_array_methods
|
||||||
|
// Add swig/language extra methods
|
||||||
|
%swig_array_methods(std::array<_Tp, _Nm >);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%std_array_methods(array);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -6,20 +6,17 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// Common container methods
|
// Common non-resizable container methods
|
||||||
|
|
||||||
|
%define %std_container_methods_non_resizable(container...)
|
||||||
|
|
||||||
%define %std_container_methods(container...)
|
|
||||||
container();
|
container();
|
||||||
container(const container&);
|
container(const container&);
|
||||||
|
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
size_type size() const;
|
size_type size() const;
|
||||||
void clear();
|
|
||||||
|
|
||||||
void swap(container& v);
|
void swap(container& v);
|
||||||
|
|
||||||
allocator_type get_allocator() const;
|
|
||||||
|
|
||||||
#ifdef SWIG_EXPORT_ITERATOR_METHODS
|
#ifdef SWIG_EXPORT_ITERATOR_METHODS
|
||||||
class iterator;
|
class iterator;
|
||||||
class reverse_iterator;
|
class reverse_iterator;
|
||||||
|
|
@ -34,17 +31,27 @@
|
||||||
|
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
// Common container methods
|
||||||
|
|
||||||
|
%define %std_container_methods(container...)
|
||||||
|
%std_container_methods_non_resizable(%arg(container))
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
allocator_type get_allocator() const;
|
||||||
|
|
||||||
|
%enddef
|
||||||
|
|
||||||
// Common sequence
|
// Common sequence
|
||||||
|
|
||||||
%define %std_sequence_methods_common(sequence)
|
%define %std_sequence_methods_common(sequence)
|
||||||
|
|
||||||
%std_container_methods(%arg(sequence));
|
%std_container_methods(%arg(sequence));
|
||||||
|
|
||||||
sequence(size_type size);
|
sequence(size_type size);
|
||||||
void pop_back();
|
void pop_back();
|
||||||
|
|
||||||
void resize(size_type new_size);
|
void resize(size_type new_size);
|
||||||
|
|
||||||
#ifdef SWIG_EXPORT_ITERATOR_METHODS
|
#ifdef SWIG_EXPORT_ITERATOR_METHODS
|
||||||
%extend {
|
%extend {
|
||||||
// %extend wrapper used for differing definitions of these methods introduced in C++11
|
// %extend wrapper used for differing definitions of these methods introduced in C++11
|
||||||
|
|
@ -52,24 +59,31 @@
|
||||||
iterator erase(iterator first, iterator last) { return $self->erase(first, last); }
|
iterator erase(iterator first, iterator last) { return $self->erase(first, last); }
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
%define %std_sequence_methods_non_resizable(sequence)
|
||||||
|
|
||||||
%define %std_sequence_methods(sequence)
|
%std_container_methods_non_resizable(%arg(sequence))
|
||||||
|
|
||||||
%std_sequence_methods_common(%arg(sequence));
|
|
||||||
|
|
||||||
sequence(size_type size, const value_type& value);
|
|
||||||
void push_back(const value_type& x);
|
|
||||||
|
|
||||||
const value_type& front() const;
|
const value_type& front() const;
|
||||||
const value_type& back() const;
|
const value_type& back() const;
|
||||||
|
|
||||||
void assign(size_type n, const value_type& x);
|
|
||||||
|
|
||||||
|
%enddef
|
||||||
|
|
||||||
|
%define %std_sequence_methods(sequence)
|
||||||
|
|
||||||
|
%std_sequence_methods_common(%arg(sequence));
|
||||||
|
|
||||||
|
sequence(size_type size, const value_type& value);
|
||||||
|
void push_back(const value_type& x);
|
||||||
|
|
||||||
|
const value_type& front() const;
|
||||||
|
const value_type& back() const;
|
||||||
|
|
||||||
|
void assign(size_type n, const value_type& x);
|
||||||
void resize(size_type new_size, const value_type& x);
|
void resize(size_type new_size, const value_type& x);
|
||||||
|
|
||||||
#ifdef SWIG_EXPORT_ITERATOR_METHODS
|
#ifdef SWIG_EXPORT_ITERATOR_METHODS
|
||||||
%extend {
|
%extend {
|
||||||
// %extend wrapper used for differing definitions of these methods introduced in C++11
|
// %extend wrapper used for differing definitions of these methods introduced in C++11
|
||||||
|
|
@ -77,23 +91,33 @@
|
||||||
void insert(iterator pos, size_type n, const value_type& x) { $self->insert(pos, n, x); }
|
void insert(iterator pos, size_type n, const value_type& x) { $self->insert(pos, n, x); }
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
%define %std_sequence_methods_val(sequence...)
|
%define %std_sequence_methods_non_resizable_val(sequence...)
|
||||||
|
|
||||||
%std_sequence_methods_common(%arg(sequence));
|
%std_container_methods_non_resizable(%arg(sequence))
|
||||||
|
|
||||||
sequence(size_type size, value_type value);
|
|
||||||
void push_back(value_type x);
|
|
||||||
|
|
||||||
value_type front() const;
|
value_type front() const;
|
||||||
value_type back() const;
|
value_type back() const;
|
||||||
|
|
||||||
void assign(size_type n, value_type x);
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%enddef
|
||||||
|
|
||||||
|
%define %std_sequence_methods_val(sequence...)
|
||||||
|
|
||||||
|
%std_sequence_methods_common(%arg(sequence));
|
||||||
|
|
||||||
|
sequence(size_type size, value_type value);
|
||||||
|
void push_back(value_type x);
|
||||||
|
|
||||||
|
value_type front() const;
|
||||||
|
value_type back() const;
|
||||||
|
|
||||||
|
void assign(size_type n, value_type x);
|
||||||
void resize(size_type new_size, value_type x);
|
void resize(size_type new_size, value_type x);
|
||||||
|
|
||||||
#ifdef SWIG_EXPORT_ITERATOR_METHODS
|
#ifdef SWIG_EXPORT_ITERATOR_METHODS
|
||||||
%extend {
|
%extend {
|
||||||
// %extend wrapper used for differing definitions of these methods introduced in C++11
|
// %extend wrapper used for differing definitions of these methods introduced in C++11
|
||||||
|
|
@ -101,7 +125,7 @@
|
||||||
void insert(iterator pos, size_type n, value_type x) { $self->insert(pos, n, x); }
|
void insert(iterator pos, size_type n, value_type x) { $self->insert(pos, n, x); }
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,7 @@ static int NAME(TYPE x) {
|
||||||
%define SWIG_TYPECHECK_STDSTRING 135 %enddef
|
%define SWIG_TYPECHECK_STDSTRING 135 %enddef
|
||||||
%define SWIG_TYPECHECK_STRING 140 %enddef
|
%define SWIG_TYPECHECK_STRING 140 %enddef
|
||||||
%define SWIG_TYPECHECK_PAIR 150 %enddef
|
%define SWIG_TYPECHECK_PAIR 150 %enddef
|
||||||
|
%define SWIG_TYPECHECK_STDARRAY 155 %enddef
|
||||||
%define SWIG_TYPECHECK_VECTOR 160 %enddef
|
%define SWIG_TYPECHECK_VECTOR 160 %enddef
|
||||||
%define SWIG_TYPECHECK_DEQUE 170 %enddef
|
%define SWIG_TYPECHECK_DEQUE 170 %enddef
|
||||||
%define SWIG_TYPECHECK_LIST 180 %enddef
|
%define SWIG_TYPECHECK_LIST 180 %enddef
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue