diff --git a/Examples/test-suite/python/li_std_carray.i b/Examples/test-suite/python/li_std_carray.i new file mode 100644 index 000000000..b38e0e441 --- /dev/null +++ b/Examples/test-suite/python/li_std_carray.i @@ -0,0 +1,8 @@ +%module li_std_carray + +%include + +%template(Vector3) std::carray; + +%template(Matrix3) std::carray, 3>; + diff --git a/Examples/test-suite/python/li_std_carray_runme.py b/Examples/test-suite/python/li_std_carray_runme.py new file mode 100644 index 000000000..45a39ae41 --- /dev/null +++ b/Examples/test-suite/python/li_std_carray_runme.py @@ -0,0 +1,47 @@ +from li_std_carray import * + + +v3 = Vector3() + +da = Vector3((1,2,3)) +print da + +for i in range(0,len(v3)): + v3[i] = i + +i = 0 +for d in v3: + if d != i: + raise RuntimeError + i += 1 + + +m3 = Matrix3() + +for i in range(0,len(m3)): + v3 = m3[i] + print v3 + for j in range(0,len(v3)): + v3[j] = i + j + +i = 0 +for v3 in m3: + j = 0 + for d in v3: + if d != i + j: + raise RuntimeError + j += 1 + pass + i += 1 + pass + +for i in range(0,len(m3)): + for j in range(0,len(m3)): + if m3[i][j] != i + j: + raise RuntimeError + + +print m3 +print m3[0] + +da = Vector3((1,2,3)) diff --git a/Lib/python/pyclasses.swg b/Lib/python/pyclasses.swg index 03f828fbb..f625ca17c 100644 --- a/Lib/python/pyclasses.swg +++ b/Lib/python/pyclasses.swg @@ -114,22 +114,19 @@ namespace swig { } %{ - namespace swig { - struct PyObject_var : PyObject_ptr { - PyObject_var(PyObject* obj = 0) : PyObject_ptr(obj, false) { } - - PyObject_var & operator = (PyObject* obj) - { - Py_XDECREF(_obj); - _obj = obj; - return *this; - } - }; - } +namespace swig { + struct PyObject_var : PyObject_ptr { + PyObject_var(PyObject* obj = 0) : PyObject_ptr(obj, false) { } + + PyObject_var & operator = (PyObject* obj) + { + Py_XDECREF(_obj); + _obj = obj; + return *this; + } + }; +} %} - - - #endif diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg index 8c835389b..daaed85f3 100644 --- a/Lib/python/pycontainer.swg +++ b/Lib/python/pycontainer.swg @@ -14,6 +14,16 @@ %} +#if !defined(SWIG_NO_EXPORT_ITERATOR_METHODS) +# if !defined(SWIG_EXPORT_ITERATOR_METHODS) +# define SWIG_EXPORT_ITERATOR_METHODS SWIG_EXPORT_ITERATOR_METHODS +# endif +#endif + +#if defined(SWIG_EXPORT_ITERATOR_METHODS) +%include +#endif + /**** The PySequence C++ Wrap ***/ %insert(header) %{ @@ -25,8 +35,6 @@ %include - - %fragment(SWIG_Traits_frag(swig::PyObject_ptr),"header",fragment="StdTraits") { namespace swig { template <> struct traits { @@ -60,7 +68,6 @@ namespace swig { } } - %fragment(SWIG_Traits_frag(swig::PyObject_var),"header",fragment="StdTraits") { namespace swig { template <> struct traits { @@ -94,11 +101,8 @@ namespace swig { } } - - %fragment("PySequence_Base","header") { - namespace std { template <> struct less : public binary_function @@ -167,9 +171,7 @@ namespace swig { } - namespace swig { - inline size_t check_index(ptrdiff_t i, size_t size, bool insert = false) { if ( i < 0 ) { @@ -262,227 +264,13 @@ namespace swig { } } - -#define SWIG_EXPORT_ITERATOR_METHODS SWIG_EXPORT_ITERATOR_METHODS - -#if defined(SWIG_EXPORT_ITERATOR_METHODS) -/* - Throw a StopIteration exception -*/ -namespace swig -{ - %ignore stop_iteration; - %typemap(throws) stop_iteration { - SWIG_SetErrorObj(PyExc_StopIteration, SWIG_Py_Void()); - SWIG_fail; - } -} - - - -namespace swig { - %newobject PySequence_OutputIterator::operator +; - %newobject PySequence_OutputIterator::operator - (ptrdiff_t n) const; - %newobject PySequence_OutputIterator::copy; -} - -%inline { - namespace swig { - struct stop_iteration - { - }; - - struct PySequence_OutputIterator - { - private: - PyObject_ptr _seq; - - protected: - PySequence_OutputIterator(PyObject *seq) : _seq(seq) - { - } - - public: - virtual ~PySequence_OutputIterator() {} - - virtual PyObject *value() const throw (stop_iteration) = 0; - virtual PySequence_OutputIterator *incr(size_t n = 1) throw (stop_iteration) = 0; - virtual PySequence_OutputIterator *decr(size_t n = 1) throw (stop_iteration) = 0; - virtual PySequence_OutputIterator *copy() const = 0; - virtual ptrdiff_t distance(const PySequence_OutputIterator &x) const = 0; - virtual bool equal (const PySequence_OutputIterator &x) const = 0; - - PyObject *next() throw (stop_iteration) - { - PyObject *obj = value(); - incr(); - return obj; - } - - PyObject *previous() throw (stop_iteration) - { - decr(); - return value(); - } - - PySequence_OutputIterator *advance(ptrdiff_t n) throw (stop_iteration) - { - return (n > 0) ? incr(n) : decr(-n); - } - - public: - - bool operator == (const PySequence_OutputIterator& x) const - { - return equal(x); - } - - bool operator != (const PySequence_OutputIterator& x) const - { - return ! operator==(x); - } - - PySequence_OutputIterator& operator += (ptrdiff_t n) throw (stop_iteration) - { - return *advance(n); - } - - PySequence_OutputIterator& operator -= (ptrdiff_t n) throw (stop_iteration) - { - return *advance(-n); - } - - PySequence_OutputIterator* operator + (ptrdiff_t n) const throw (stop_iteration) - { - return copy()->advance(n); - } - - PySequence_OutputIterator* operator - (ptrdiff_t n) const throw (stop_iteration) - { - return copy()->advance(-n); - } - - ptrdiff_t operator - (const PySequence_OutputIterator& x) const - { - return x.distance(*this); - } - - static swig_type_info* descriptor() { - static int init = 0; - static swig_type_info* desc = 0; - if (!init) { - desc = SWIG_TypeQuery("swig::PySequence_OutputIterator *"); - init = 1; - } - return desc; - } - }; - } -} -#endif //SWIG_EXPORT_ITERATOR_METHODS - %fragment("PySequence_Cont","header", fragment="StdTraits", - fragment="PySequence_Base") + fragment="PySequence_Base", + fragment="PySwigIterator_T") { -#include - namespace swig { -#if defined(SWIG_EXPORT_ITERATOR_METHODS) - template - class PySequence_OutputIterator_T : public PySequence_OutputIterator - { - public: - typedef OutIterator out_iterator; - typedef typename std::iterator_traits::value_type value_type; - - typedef PySequence_OutputIterator_T self_type; - - PySequence_OutputIterator_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) - : PySequence_OutputIterator(seq), current(curr), begin(first), end(last) - { - } - - PyObject *value() const throw (stop_iteration) { - if (current == end) { - throw stop_iteration(); - } else { - return swig::from((const value_type&)*(current)); - } - } - - - PySequence_OutputIterator_T *copy() const - { - return new self_type(*this); - } - - PySequence_OutputIterator_T *incr(size_t n = 1) throw (stop_iteration) - { - while (n--) { - if (current == end) { - throw stop_iteration(); - } else { - ++current; - } - } - return this; - } - - PySequence_OutputIterator_T *decr(size_t n = 1) throw (stop_iteration) - { - while (n--) { - if (current == begin) { - throw stop_iteration(); - } else { - --current; - } - } - return this; - } - - - bool equal (const PySequence_OutputIterator &iter) const throw (std::invalid_argument) - { - const self_type *iters = dynamic_cast(&iter); - if (iters) { - return (current == iters->get_current()); - } else { - throw std::invalid_argument("bad iterator type"); - } - } - - ptrdiff_t distance(const PySequence_OutputIterator &iter) const throw (std::invalid_argument) - { - const self_type *iters = dynamic_cast(&iter); - if (iters) { - return std::distance(current, iters->get_current()); - } else { - throw std::invalid_argument("bad iterator type"); - } - } - - const out_iterator& get_current() const - { - return current; - } - - private: - out_iterator current; - out_iterator begin; - out_iterator end; - }; - - template - inline PySequence_OutputIterator* - make_output_iterator(const OutIter& current, const OutIter& begin = OutIter(), - const OutIter& end = OutIter(), PyObject *seq = 0) - { - return new PySequence_OutputIterator_T(current, begin, end, seq); - } -#endif //SWIG_EXPORT_ITERATOR_METHODS - template struct PySequence_Ref { @@ -719,15 +507,15 @@ namespace swig %typemap(out,noblock=1,fragment="PySequence_Cont") iterator, reverse_iterator, const_iterator, const_reverse_iterator { $result = SWIG_NewPointerObj(swig::make_output_iterator((const $type &)$1), - swig::PySequence_OutputIterator::descriptor(),SWIG_POINTER_OWN); + swig::PySwigIterator::descriptor(),SWIG_POINTER_OWN); } %typemap(out,noblock=1,fragment="PySequence_Cont") std::pair, std::pair { $result = PyTuple_New(2); PyTuple_SetItem($result,0,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), - swig::PySequence_OutputIterator::descriptor(),SWIG_POINTER_OWN)); + swig::PySwigIterator::descriptor(),SWIG_POINTER_OWN)); PyTuple_SetItem($result,1,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).second), - swig::PySequence_OutputIterator::descriptor(),SWIG_POINTER_OWN)); + swig::PySwigIterator::descriptor(),SWIG_POINTER_OWN)); } %fragment("PyPairBoolOutputIterator","header",fragment=SWIG_From_frag(bool),fragment="PySequence_Cont") {} @@ -736,21 +524,21 @@ namespace swig std::pair, std::pair { $result = PyTuple_New(2); PyTuple_SetItem($result,0,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), - swig::PySequence_OutputIterator::descriptor(),SWIG_POINTER_OWN)); + swig::PySwigIterator::descriptor(),SWIG_POINTER_OWN)); PyTuple_SetItem($result,1,SWIG_From(bool)(%static_cast($1,const $type &).second)); } %typemap(in,noblock=1,fragment="PySequence_Cont") - iterator(swig::PySequence_OutputIterator *iter), - reverse_iterator(swig::PySequence_OutputIterator *iter), - const_iterator(swig::PySequence_OutputIterator *iter), - const_reverse_iterator(swig::PySequence_OutputIterator *iter) { - if (SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::PySequence_OutputIterator::descriptor(), 0) != SWIG_OK) { + iterator(swig::PySwigIterator *iter), + reverse_iterator(swig::PySwigIterator *iter), + const_iterator(swig::PySwigIterator *iter), + const_reverse_iterator(swig::PySwigIterator *iter) { + if (SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::PySwigIterator::descriptor(), 0) != SWIG_OK) { %argument_fail(SWIG_TypeError, "$type", $argnum); } if (iter) { - swig::PySequence_OutputIterator_T<$type > *iter_t - = dynamic_cast *>(iter); + swig::PySwigIterator_T<$type > *iter_t + = dynamic_cast *>(iter); $1 = iter_t->get_current(); } else { %argument_fail(SWIG_TypeError, "$type", $argnum); @@ -759,18 +547,18 @@ namespace swig %typecheck(%checkcode(ITERATOR),noblock=1,fragment="PySequence_Cont") iterator, reverse_iterator, const_iterator, const_reverse_iterator { - swig::PySequence_OutputIterator *iter = 0; + swig::PySwigIterator *iter = 0; $1 = ((SWIG_ConvertPtr($input, %as_voidptrptr(&iter), - swig::PySequence_OutputIterator::descriptor(), 0) == SWIG_OK) + swig::PySwigIterator::descriptor(), 0) == SWIG_OK) && iter - && (dynamic_cast *>(iter) != 0)); + && (dynamic_cast *>(iter) != 0)); } %fragment("PySequence_Cont"); %newobject iterator(PyObject **PYTHON_SELF); %extend { - swig::PySequence_OutputIterator* iterator(PyObject **PYTHON_SELF) { + swig::PySwigIterator* iterator(PyObject **PYTHON_SELF) { return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } @@ -871,7 +659,6 @@ namespace swig - // // Common fragments // @@ -880,85 +667,85 @@ namespace swig fragment="StdTraits", fragment="PySequence_Cont") { - namespace swig { - template - inline void - assign(const PySeq& pyseq, Seq* seq) { +namespace swig { + template + inline void + assign(const PySeq& pyseq, Seq* seq) { %#ifdef SWIG_STD_NOASSIGN_STL - typedef typename PySeq::value_type value_type; - typename PySeq::const_iterator it = pyseq.begin(); - for (;it != pyseq.end(); ++it) { - seq->insert(seq->end(),(value_type)(*it)); - } -%#else - seq->assign(pyseq.begin(), pyseq.end()); -%#endif + typedef typename PySeq::value_type value_type; + typename PySeq::const_iterator it = pyseq.begin(); + for (;it != pyseq.end(); ++it) { + seq->insert(seq->end(),(value_type)(*it)); } - - template - struct traits_asptr_stdseq { - typedef Seq sequence; - typedef T value_type; - - static int asptr(PyObject *obj, sequence **seq) { - if (PySequence_Check(obj)) { - try { - PySequence_Cont pyseq(obj); - if (seq) { - sequence *pseq = new sequence(); - assign(pyseq, pseq); - *seq = pseq; - return SWIG_NEWOBJ; - } else { - return pyseq.check(); - } - } catch (std::exception& e) { - if (seq) { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, e.what()); - } - } - return 0; - } - } else { - sequence *p; - if (SWIG_ConvertPtr(obj,(void**)&p, - swig::type_info(),0) == SWIG_OK) { - if (seq) *seq = p; - return SWIG_OLDOBJ; - } - } - if (seq) { - PyErr_Format(PyExc_TypeError, "a %s is expected", - swig::type_name()); - } - return 0; - } - }; - - template - struct traits_from_stdseq { - typedef Seq sequence; - typedef T value_type; - typedef typename Seq::size_type size_type; - typedef typename sequence::const_iterator const_iterator; - - static PyObject *from(const sequence& seq) { - size_type size = seq.size(); - if (size <= (size_type)INT_MAX) { - PyObject *obj = PyTuple_New((int)size); - int i = 0; - for (const_iterator it = seq.begin(); - it != seq.end(); ++it, ++i) { - PyTuple_SetItem(obj,i,swig::from(*it)); - } - return obj; - } else { - PyErr_SetString(PyExc_OverflowError, - "sequence size not valid in python"); - return NULL; - } - } - }; +%#else + seq->assign(pyseq.begin(), pyseq.end()); +%#endif } + + template + struct traits_asptr_stdseq { + typedef Seq sequence; + typedef T value_type; + + static int asptr(PyObject *obj, sequence **seq) { + if (PySequence_Check(obj)) { + try { + PySequence_Cont pyseq(obj); + if (seq) { + sequence *pseq = new sequence(); + assign(pyseq, pseq); + *seq = pseq; + return SWIG_NEWOBJ; + } else { + return pyseq.check(); + } + } catch (std::exception& e) { + if (seq) { + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, e.what()); + } + } + return 0; + } + } else { + sequence *p; + if (SWIG_ConvertPtr(obj,(void**)&p, + swig::type_info(),0) == SWIG_OK) { + if (seq) *seq = p; + return SWIG_OLDOBJ; + } + } + if (seq) { + PyErr_Format(PyExc_TypeError, "a %s is expected", + swig::type_name()); + } + return 0; + } + }; + + template + struct traits_from_stdseq { + typedef Seq sequence; + typedef T value_type; + typedef typename Seq::size_type size_type; + typedef typename sequence::const_iterator const_iterator; + + static PyObject *from(const sequence& seq) { + size_type size = seq.size(); + if (size <= (size_type)INT_MAX) { + PyObject *obj = PyTuple_New((int)size); + int i = 0; + for (const_iterator it = seq.begin(); + it != seq.end(); ++it, ++i) { + PyTuple_SetItem(obj,i,swig::from(*it)); + } + return obj; + } else { + PyErr_SetString(PyExc_OverflowError, + "sequence size not valid in python"); + return NULL; + } + } + }; +} } diff --git a/Lib/python/pyiterators.swg b/Lib/python/pyiterators.swg new file mode 100644 index 000000000..2c4be9fd4 --- /dev/null +++ b/Lib/python/pyiterators.swg @@ -0,0 +1,239 @@ +// +// Implemet a python 'output' iterator for Python 2.2 or higher. +// +// Users can derive form the PySwigIterator to implemet their +// own iterators. As an example (real one since we use it for STL/STD +// containers), the template PySwigIterator_T does the +// implementation for genereic C++ iterators. +// +%include + + + +namespace swig +{ + /* + Throw a StopIteration exception + */ + %ignore stop_iteration; + %typemap(throws) stop_iteration { + SWIG_SetErrorObj(PyExc_StopIteration, SWIG_Py_Void()); + SWIG_fail; + } + + /* + Mark methods that return new objects + */ + %newobject PySwigIterator::copy; + %newobject PySwigIterator::operator + (ptrdiff_t n) const; + %newobject PySwigIterator::operator - (ptrdiff_t n) const; +} + +%inline { +namespace swig { + struct stop_iteration + { + }; + + struct PySwigIterator + { + private: + PyObject_ptr _seq; + + protected: + PySwigIterator(PyObject *seq) : _seq(seq) + { + } + + public: + virtual ~PySwigIterator() {} + + // Access iterator method, required by Python + virtual PyObject *value() const throw (stop_iteration) = 0; + + // Forward iterator method, required by Python + virtual PySwigIterator *incr(size_t n = 1) throw (stop_iteration) = 0; + + // Backward iterator method, very common in C++, but not required in Python + virtual PySwigIterator *decr(size_t n = 1) throw (stop_iteration) + { + throw stop_iteration(); + } + + // Random access iterator methods, but not required in Python + virtual ptrdiff_t distance(const PySwigIterator &x) const throw (std::invalid_argument) + { + throw std::invalid_argument("operation not supported"); + } + + virtual bool equal (const PySwigIterator &x) const throw (std::invalid_argument) + { + throw std::invalid_argument("operation not supported"); + } + + // C++ common/needed methods + virtual PySwigIterator *copy() const = 0; + + public: + + PyObject *next() throw (stop_iteration) + { + PyObject *obj = value(); + incr(); + return obj; + } + + PyObject *previous() throw (stop_iteration) + { + decr(); + return value(); + } + + PySwigIterator *advance(ptrdiff_t n) throw (stop_iteration) + { + return (n > 0) ? incr(n) : decr(-n); + } + + bool operator == (const PySwigIterator& x) const + { + return equal(x); + } + + bool operator != (const PySwigIterator& x) const + { + return ! operator==(x); + } + + PySwigIterator& operator += (ptrdiff_t n) throw (stop_iteration) + { + return *advance(n); + } + + PySwigIterator& operator -= (ptrdiff_t n) throw (stop_iteration) + { + return *advance(-n); + } + + PySwigIterator* operator + (ptrdiff_t n) const throw (stop_iteration) + { + return copy()->advance(n); + } + + PySwigIterator* operator - (ptrdiff_t n) const throw (stop_iteration) + { + return copy()->advance(-n); + } + + ptrdiff_t operator - (const PySwigIterator& x) const + { + return x.distance(*this); + } + + static swig_type_info* descriptor() { + static int init = 0; + static swig_type_info* desc = 0; + if (!init) { + desc = SWIG_TypeQuery("swig::PySwigIterator *"); + init = 1; + } + return desc; + } + }; +} +} + +%fragment("PySwigIterator_T","header",fragment="StdTraits") { +#include +namespace swig { + template + class PySwigIterator_T : public PySwigIterator + { + public: + typedef OutIterator out_iterator; + typedef typename std::iterator_traits::value_type value_type; + + typedef PySwigIterator_T self_type; + + PySwigIterator_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) + : PySwigIterator(seq), current(curr), begin(first), end(last) + { + } + + PyObject *value() const throw (stop_iteration) { + if (current == end) { + throw stop_iteration(); + } else { + return swig::from((const value_type&)*(current)); + } + } + + PySwigIterator *copy() const + { + return new self_type(*this); + } + + PySwigIterator *incr(size_t n = 1) throw (stop_iteration) + { + while (n--) { + if (current == end) { + throw stop_iteration(); + } else { + ++current; + } + } + return this; + } + + PySwigIterator *decr(size_t n = 1) throw (stop_iteration) + { + while (n--) { + if (current == begin) { + throw stop_iteration(); + } else { + --current; + } + } + return this; + } + + bool equal (const PySwigIterator &iter) const throw (std::invalid_argument) + { + const self_type *iters = dynamic_cast(&iter); + if (iters) { + return (current == iters->get_current()); + } else { + throw std::invalid_argument("bad iterator type"); + } + } + + ptrdiff_t distance(const PySwigIterator &iter) const throw (std::invalid_argument) + { + const self_type *iters = dynamic_cast(&iter); + if (iters) { + return std::distance(current, iters->get_current()); + } else { + throw std::invalid_argument("bad iterator type"); + } + } + + const out_iterator& get_current() const + { + return current; + } + + private: + out_iterator current; + out_iterator begin; + out_iterator end; + }; + + template + inline PySwigIterator* + make_output_iterator(const OutIter& current, const OutIter& begin = OutIter(), + const OutIter& end = OutIter(), PyObject *seq = 0) + { + return new PySwigIterator_T(current, begin, end, seq); + } +} +} + diff --git a/Lib/python/std_carray.i b/Lib/python/std_carray.i new file mode 100644 index 000000000..a12c52fe6 --- /dev/null +++ b/Lib/python/std_carray.i @@ -0,0 +1,54 @@ +%include + + +%fragment("StdCarrayTraits","header",fragment="StdSequenceTraits") +{ +namespace swig { + template + struct traits_asptr > { + static int asptr(PyObject *obj, std::carray **array) { + return traits_asptr_stdseq >::asptr(obj, array); + } + }; +} +} + +%warnfilter(389) std::carray::operator[]; + +%extend std::carray { + %fragment(SWIG_Traits_frag(std::carray<_Type, _Size >), "header", + fragment="PySwigIterator_T", + fragment=SWIG_Traits_frag(_Type), + fragment="StdCarrayTraits") { + namespace swig { + template <> struct traits > { + typedef pointer_category category; + static const char* type_name() { + return "std::carray<" #_Type "," #_Size " >"; + } + }; + } + } + + %typemaps_asptr(SWIG_TYPECHECK_VECTOR, swig::asptr, + SWIG_Traits_frag(std::carray<_Type, _Size >), + std::carray<_Type, _Size >); + + %typemap(out,noblock=1) iterator, const_iterator { + $result = SWIG_NewPointerObj(swig::make_output_iterator((const $type &)$1), + swig::PySwigIterator::descriptor(),SWIG_POINTER_OWN); + } + + inline size_t __len__() const { return self->size(); } + + inline const _Type& __getitem__(size_t i) const { return (*self)[i]; } + + inline void __setitem__(size_t i, const _Type& v) { (*self)[i] = v; } + + + swig::PySwigIterator* __iter__(PyObject **PYTHON_SELF) { + return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + } +} + +%include diff --git a/Lib/std/std_carray.swg b/Lib/std/std_carray.swg new file mode 100644 index 000000000..ebb20ce6a --- /dev/null +++ b/Lib/std/std_carray.swg @@ -0,0 +1,64 @@ +%{ +#include +%} + +// +// std::carray - is really an extension to the 'std' namespace. +// +// A simple fix C array wrapper, more or less as presented in +// +// "The C++ Standarf Library", by Nicolai M. Josuttis +// +// which is also derived from the example in +// +// "The C++ Programming Language", by Bjarne Stroustup. +// + +%inline %{ +namespace std { + template + class carray + { + public: + typedef _Type value_type; + typedef size_t size_type; + + typedef _Type * iterator; + typedef const _Type * const_iterator; + + carray() { } + + carray(const carray& c) { + std::copy(c.v, c.v + size(), v); + } + + template + carray(_Iterator first, _Iterator last) { + assign(first, last); + } + + iterator begin() { return v; } + iterator end() { return v + _Size; } + + const_iterator begin() const { return v; } + const_iterator end() const { return v + _Size; } + + _Type& operator[](size_t i) { return v[i]; } + const _Type& operator[](size_t i) const { return v[i]; } + + static size_t size() { return _Size; } + + template + void assign(_Iterator first, _Iterator last) { + if (std::distance(first,last) == size()) { + std::copy(first, last, v); + } else { + throw std::length_error("bad range length"); + } + } + + private: + _Type v[_Size]; + }; +} +%}