blob: f6078690b465512511cfcd4ecf5d008b1a99125e [file] [log] [blame]
/* -----------------------------------------------------------------------------
* scicontainer.swg
*
* Scilab list <-> C++ container wrapper
*
* This wrapper, and its iterator, allows a general use (and reuse) of
* the mapping between C++ and Scilab, thanks to the C++ templates.
*
* Of course, it needs the C++ compiler to support templates, but
* since we will use this wrapper with the STL containers, that should
* be the case.
* ----------------------------------------------------------------------------- */
%{
#include <iostream>
%}
#if !defined(SWIG_NO_EXPORT_ITERATOR_METHODS)
# if !defined(SWIG_EXPORT_ITERATOR_METHODS)
# define SWIG_EXPORT_ITERATOR_METHODS SWIG_EXPORT_ITERATOR_METHODS
# endif
#endif
// #define (SWIG_SCILAB_EXTRA_NATIVE_CONTAINERS)
// if defined: sequences in return are converted from/to Scilab lists or matrices
// if not defined: sequences are passed from/to Scilab as pointers
%{
#define SWIG_STD_NOASSIGN_STL
%}
%include <sciiterators.swg>
%include <scisequence.swg>
%{
#include <stdexcept>
%}
%include <exception.i>
%include <std_except.i>
%fragment("SciSequence_Cont", "header",
fragment="StdTraits",
fragment="SwigSciIterator_T",
fragment=SWIG_Traits_Sequence_frag(ptr),
fragment=SWIG_Traits_SequenceItem_frag(ptr))
{
namespace swig
{
template <class T>
struct SciSequence_Ref
{
SciSequence_Ref(const SwigSciObject& seq, int index)
: _seq(seq), _index(index)
{
if (traits_as_sequence<T>::get(_seq, &piSeqAddr) != SWIG_OK)
{
throw std::invalid_argument("Cannot get sequence data.");
}
}
operator T () const
{
return traits_asval_sequenceitem<T>::asval(_seq, piSeqAddr, _index);
}
SciSequence_Ref& operator=(const T& v)
{
// TODO
return *this;
}
private:
SwigSciObject _seq;
int _index;
void *piSeqAddr;
};
template <class T>
struct SciSequence_ArrowProxy
{
SciSequence_ArrowProxy(const T& x): m_value(x) {}
const T* operator->() const { return &m_value; }
operator const T*() const { return &m_value; }
T m_value;
};
template <class T, class Reference >
struct SwigSciSequence_InputIterator
{
typedef SwigSciSequence_InputIterator<T, Reference > self;
typedef std::random_access_iterator_tag iterator_category;
typedef Reference reference;
typedef T value_type;
typedef T* pointer;
typedef int difference_type;
SwigSciSequence_InputIterator()
{
}
SwigSciSequence_InputIterator(const SwigSciObject& seq, int index)
: _seq(seq), _index(index)
{
}
reference operator*() const
{
return reference(_seq, _index);
}
SciSequence_ArrowProxy<T>
operator->() const {
return SciSequence_ArrowProxy<T>(operator*());
}
bool operator==(const self& ri) const
{
return (_index == ri._index);
}
bool operator!=(const self& ri) const
{
return !(operator==(ri));
}
self& operator ++ ()
{
++_index;
return *this;
}
self& operator -- ()
{
--_index;
return *this;
}
self& operator += (difference_type n)
{
_index += n;
return *this;
}
self operator +(difference_type n) const
{
return self(_seq, _index + n);
}
self& operator -= (difference_type n)
{
_index -= n;
return *this;
}
self operator -(difference_type n) const
{
return self(_seq, _index - n);
}
difference_type operator - (const self& ri) const
{
return _index - ri._index;
}
bool operator < (const self& ri) const
{
return _index < ri._index;
}
reference
operator[](difference_type n) const
{
return reference(_seq, _index + n);
}
private:
SwigSciObject _seq;
difference_type _index;
};
template <class T>
struct SciSequence_Cont
{
typedef SciSequence_Ref<T> reference;
typedef const SciSequence_Ref<T> const_reference;
typedef T value_type;
typedef T* pointer;
typedef int difference_type;
typedef int size_type;
typedef const pointer const_pointer;
typedef SwigSciSequence_InputIterator<T, reference> iterator;
typedef SwigSciSequence_InputIterator<T, const_reference> const_iterator;
SciSequence_Cont(const SwigSciObject& seq) : _seq(seq)
{
}
~SciSequence_Cont()
{
}
size_type size() const
{
int iSeqSize;
if (traits_as_sequence<value_type>::size(_seq, &iSeqSize) == SWIG_OK)
{
return iSeqSize;
}
else
{
return SWIG_ERROR;
}
}
bool empty() const
{
return size() == 0;
}
iterator begin()
{
return iterator(_seq, 0);
}
const_iterator begin() const
{
return const_iterator(_seq, 0);
}
iterator end()
{
return iterator(_seq, size());
}
const_iterator end() const
{
return const_iterator(_seq, size());
}
reference operator[](difference_type n)
{
return reference(_seq, n);
}
const_reference operator[](difference_type n) const
{
return const_reference(_seq, n);
}
private:
SwigSciObject _seq;
};
}
}
%define %swig_sequence_iterator(Sequence...)
#if defined(SWIG_EXPORT_ITERATOR_METHODS)
class iterator;
class reverse_iterator;
class const_iterator;
class const_reverse_iterator;
%typemap(out,noblock=1,fragment="SciSequence_Cont")
iterator, reverse_iterator, const_iterator, const_reverse_iterator {
%set_output(SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &)),
swig::SciSwigIterator::descriptor(),SWIG_POINTER_OWN));
}
%typemap(out,fragment="SciSequence_Cont")
std::pair<iterator, iterator>, std::pair<const_iterator, const_iterator> {
// TODO: return a Scilab list from the pair (see code for Octave)
}
%fragment("SciSwigPairBoolOutputIterator", "header",
fragment=SWIG_From_frag(bool), fragment="SciSequence_Cont") {}
%typemap(out,fragment="SciSwigPairBoolOutputIterator")
std::pair<iterator, bool>, std::pair<const_iterator, bool> {
// TODO: return a Scilab list from the pair (see code for Octave)
}
%typemap(in,noblock=1,fragment="SciSequence_Cont")
iterator(swig::SciSwigIterator *iter = 0, int res),
reverse_iterator(swig::SciSwigIterator *iter = 0, int res),
const_iterator(swig::SciSwigIterator *iter = 0, int res),
const_reverse_iterator(swig::SciSwigIterator *iter = 0, int res) {
res = SWIG_ConvertPtr((SwigSciObject)$input, %as_voidptrptr(&iter), swig::SciSwigIterator::descriptor(), 0);
if (!SWIG_IsOK(res) || !iter) {
%argument_fail(SWIG_TypeError, "$type", $symname, $argnum);
} else {
swig::SwigSciIterator_T<$type > *iter_t = dynamic_cast<swig::SwigSciIterator_T<$type > *>(iter);
if (iter_t) {
$1 = iter_t->get_current();
} else {
%argument_fail(SWIG_TypeError, "$type", $symname, $argnum);
}
}
}
%typecheck(%checkcode(ITERATOR),noblock=1,fragment="SciSequence_Cont")
iterator, reverse_iterator, const_iterator, const_reverse_iterator {
swig::SciSwigIterator *iter = 0;
int res = SWIG_ConvertPtr((SwigSciObject)$input, %as_voidptrptr(&iter), swig::SciSwigIterator::descriptor(), 0);
$1 = (SWIG_IsOK(res) && iter && (dynamic_cast<swig::SwigSciIterator_T<$type > *>(iter) != 0));
}
%fragment("SciSequence_Cont");
#endif //SWIG_EXPORT_ITERATOR_METHODS
%enddef
// The Scilab container methods
%define %swig_container_methods(Container...)
%enddef
%define %swig_sequence_methods_common(Sequence...)
%swig_sequence_iterator(%arg(Sequence))
%swig_container_methods(%arg(Sequence))
%enddef
%define %swig_sequence_methods(Sequence...)
%swig_sequence_methods_common(%arg(Sequence))
%enddef
%define %swig_sequence_methods_val(Sequence...)
%swig_sequence_methods_common(%arg(Sequence))
%enddef
//
// Common fragments
//
%fragment("StdSequenceTraits","header",
fragment="StdTraits",
fragment="SciSequence_Cont")
{
namespace swig {
template <class SciSeq, class Seq>
inline void
assign(const SciSeq& sciSeq, Seq* seq) {
%#ifdef SWIG_STD_NOASSIGN_STL
typedef typename SciSeq::value_type value_type;
typename SciSeq::const_iterator it = sciSeq.begin();
for (;it != sciSeq.end(); ++it) {
seq->insert(seq->end(),(value_type)(*it));
}
%#else
seq->assign(sciSeq.begin(), sciSeq.end());
%#endif
}
template <class Seq, class T = typename Seq::value_type >
struct traits_asptr_stdseq {
typedef Seq sequence;
typedef T value_type;
static int asptr(const SwigSciObject& obj, sequence **seq)
{
swig_type_info *typeInfo = swig::type_info<sequence>();
if (typeInfo)
{
sequence *p;
if (SWIG_ConvertPtr(obj, (void**)&p, typeInfo, 0) == SWIG_OK)
{
if (seq)
*seq = p;
return SWIG_OLDOBJ;
}
}
if (traits_as_sequence<value_type>::check(obj) == SWIG_OK)
{
try
{
SciSequence_Cont<value_type> sciSeq(obj);
if (seq)
{
*seq = new sequence();
assign(sciSeq, *seq);
return SWIG_NEWOBJ;
}
else
{
return SWIG_ERROR;
}
}
catch (std::exception& e)
{
SWIG_exception(SWIG_RuntimeError, e.what());
return SWIG_ERROR;
}
}
else
{
return SWIG_ERROR;
}
}
};
template <class Seq, class T = typename Seq::value_type >
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 SwigSciObject from(const sequence& seq)
{
%#ifdef SWIG_SCILAB_EXTRA_NATIVE_CONTAINERS
swig_type_info *typeInfo = swig::type_info<sequence>();
if (typeInfo)
{
return SWIG_NewPointerObj(new sequence(seq), typeInfo, SWIG_POINTER_OWN);
}
%#endif
try
{
void *data;
size_type size = seq.size();
if (traits_from_sequence<value_type>::create(size, &data) == SWIG_OK) {
const_iterator it;
int index = 0;
for (it = seq.begin(); it != seq.end(); ++it)
{
traits_from_sequenceitem<value_type>::from(data, index, *it);
index++;
}
return traits_from_sequence<value_type>::set(size, data);
}
return SWIG_OK;
}
catch (std::exception& e)
{
SWIG_exception(SWIG_RuntimeError, e.what());
return SWIG_ERROR;
}
}
};
}
}