swig/Lib/ruby/rubycontainer.swg
William S Fulton 6d0c495fd0 Add missing parameter names in STL container wrappers
Mostly in STL copy constructors.

Best to have parameter names as they make their way into the wrappers in
some target languages.
2019-02-13 22:45:47 +00:00

1121 lines
28 KiB
Text

/* -----------------------------------------------------------------------------
* rubycontainer.swg
*
* Ruby sequence <-> C++ container wrapper
*
* This wrapper, and its iterator, allows a general use (and reuse) of
* the mapping between C++ and Ruby, 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
%include <rubyiterators.swg>
/**** The RubySequence C++ Wrap ***/
%fragment("<stdexcept>");
%include <std_except.i>
%fragment("RubySequence_Base","header")
{
%#include <functional>
namespace swig {
template < class T >
struct yield
{
bool
operator()( const T& v ) const
{
return RTEST( rb_yield( swig::from< T >(v) ) );
}
};
inline size_t
check_index(ptrdiff_t i, size_t size, bool insert = false) {
if ( i < 0 ) {
if ((size_t) (-i) <= size)
return (size_t) (i + size);
} else if ( (size_t) i < size ) {
return (size_t) i;
} else if (insert && ((size_t) i == size)) {
return size;
}
throw std::out_of_range("index out of range");
}
inline size_t
slice_index(ptrdiff_t i, size_t size) {
if ( i < 0 ) {
if ((size_t) (-i) <= size) {
return (size_t) (i + size);
} else {
throw std::out_of_range("index out of range");
}
} else {
return ( (size_t) i < size ) ? ((size_t) i) : size;
}
}
template <class Sequence, class Difference>
inline typename Sequence::iterator
getpos(Sequence* self, Difference i) {
typename Sequence::iterator pos = self->begin();
std::advance(pos, check_index(i,self->size()));
return pos;
}
template <class Sequence, class Difference>
inline typename Sequence::const_iterator
cgetpos(const Sequence* self, Difference i) {
typename Sequence::const_iterator pos = self->begin();
std::advance(pos, check_index(i,self->size()));
return pos;
}
template <class Sequence>
inline void
resize(Sequence *seq, typename Sequence::size_type n, typename Sequence::value_type x) {
seq->resize(n, x);
}
template <class Sequence, class Difference>
inline Sequence*
getslice(const Sequence* self, Difference i, Difference j) {
typename Sequence::size_type size = self->size();
typename Sequence::size_type ii = swig::check_index(i, size, (i == size && j == size));
typename Sequence::size_type jj = swig::slice_index(j, size);
if (jj > ii) {
typename Sequence::const_iterator vb = self->begin();
typename Sequence::const_iterator ve = self->begin();
std::advance(vb,ii);
std::advance(ve,jj);
return new Sequence(vb, ve);
} else {
return new Sequence();
}
}
template <class Sequence, class Difference, class InputSeq>
inline void
setslice(Sequence* self, Difference i, Difference j, const InputSeq& v) {
typename Sequence::size_type size = self->size();
typename Sequence::size_type ii = swig::check_index(i, size, true);
typename Sequence::size_type jj = swig::slice_index(j, size);
if (jj < ii) jj = ii;
size_t ssize = jj - ii;
if (ssize <= v.size()) {
typename Sequence::iterator sb = self->begin();
typename InputSeq::const_iterator vmid = v.begin();
std::advance(sb,ii);
std::advance(vmid, jj - ii);
self->insert(std::copy(v.begin(), vmid, sb), vmid, v.end());
} else {
typename Sequence::iterator sb = self->begin();
typename Sequence::iterator se = self->begin();
std::advance(sb,ii);
std::advance(se,jj);
self->erase(sb,se);
self->insert(sb, v.begin(), v.end());
}
}
template <class Sequence, class Difference>
inline void
delslice(Sequence* self, Difference i, Difference j) {
typename Sequence::size_type size = self->size();
typename Sequence::size_type ii = swig::check_index(i, size, true);
typename Sequence::size_type jj = swig::slice_index(j, size);
if (jj > ii) {
typename Sequence::iterator sb = self->begin();
typename Sequence::iterator se = self->begin();
std::advance(sb,ii);
std::advance(se,jj);
self->erase(sb,se);
}
}
}
}
%fragment("RubySequence_Cont","header",
fragment="<stddef.h>",
fragment="StdTraits",
fragment="RubySequence_Base",
fragment="ConstIterator_T")
{
namespace swig
{
/**
* This class is a proxy class for references, used to return and set values
* of an element of a Ruby Array of stuff.
* It can be used by RubySequence_InputIterator to make it work with STL
* algorithms.
*/
template <class T>
struct RubySequence_Ref
{
RubySequence_Ref(VALUE seq, int index)
: _seq(seq), _index(index)
{
}
operator T () const
{
VALUE item = rb_ary_entry(_seq, _index );
try {
return swig::as<T>(item);
} catch (const std::invalid_argument& e) {
char msg[1024];
sprintf(msg, "in sequence element %d ", _index);
VALUE lastErr = rb_gv_get("$!");
if ( lastErr == Qnil ) {
%type_error(swig::type_name<T>());
}
VALUE str = rb_str_new2(msg);
str = rb_str_cat2( str, e.what() );
SWIG_Ruby_ExceptionType( NULL, str );
throw;
}
}
RubySequence_Ref& operator=(const T& v)
{
rb_ary_set(_seq, _index, swig::from< T >(v));
return *this;
}
private:
VALUE _seq;
int _index;
};
/**
* This class is a proxy to return a pointer to a class, usually
* RubySequence_Ref.
* It can be used by RubySequence_InputIterator to make it work with STL
* algorithms.
*/
template <class T>
struct RubySequence_ArrowProxy
{
RubySequence_ArrowProxy(const T& x): m_value(x) {}
const T* operator->() const { return &m_value; }
operator const T*() const { return &m_value; }
T m_value;
};
/**
* Input Iterator. This adapator class is a random access iterator that
* allows you to use STL algorithms with a Ruby class (a Ruby Array by default).
*/
template <class T, class Reference = RubySequence_Ref< T > >
struct RubySequence_InputIterator
{
typedef RubySequence_InputIterator<T, Reference > self;
typedef std::random_access_iterator_tag iterator_category;
typedef Reference reference;
typedef T value_type;
typedef T* pointer;
typedef ptrdiff_t difference_type;
RubySequence_InputIterator()
{
}
RubySequence_InputIterator(VALUE seq, int index)
: _seq(seq), _index(index)
{
}
reference operator*() const
{
return reference(_seq, _index);
}
RubySequence_ArrowProxy<T>
operator->() const {
return RubySequence_ArrowProxy<T>(operator*());
}
bool operator==(const self& ri) const
{
return (_index == ri._index) && (_seq == ri._seq);
}
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:
VALUE _seq;
difference_type _index;
};
/**
* This adaptor class allows you to use a Ruby Array as if it was an STL
* container, giving it begin(), end(), and iterators.
*/
template <class T>
struct RubySequence_Cont
{
typedef RubySequence_Ref<T> reference;
typedef const RubySequence_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 RubySequence_InputIterator<T, reference> iterator;
typedef RubySequence_InputIterator<T, const_reference> const_iterator;
RubySequence_Cont(VALUE seq) : _seq(0)
{
if (!rb_obj_is_kind_of(seq, rb_cArray)) {
throw std::invalid_argument("an Array is expected");
}
_seq = seq;
}
~RubySequence_Cont()
{
}
size_type size() const
{
return RARRAY_LEN(_seq);
}
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);
}
bool check(bool set_err = false) const
{
int s = (int) size();
for (int i = 0; i < s; ++i) {
VALUE item = rb_ary_entry(_seq, i );
if (!swig::check<value_type>(item)) {
if (set_err) {
char msg[1024];
sprintf(msg, "in sequence element %d", i);
SWIG_Error(SWIG_RuntimeError, msg);
}
return false;
}
}
return true;
}
private:
VALUE _seq;
};
}
}
/**
* Macros used to typemap an STL iterator -> SWIGIterator conversion.
*/
%define %swig_sequence_iterator(Sequence...)
#if defined(SWIG_EXPORT_ITERATOR_METHODS)
%typemap(out,noblock=1,fragment="RubySequence_Cont")
const_iterator, const_reverse_iterator {
$result = SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &),
self),
swig::ConstIterator::descriptor(),SWIG_POINTER_OWN);
}
%typemap(out,noblock=1,fragment="RubySequence_Cont")
iterator, reverse_iterator {
$result = SWIG_NewPointerObj(swig::make_nonconst_iterator(%static_cast($1,const $type &),
self),
swig::Iterator::descriptor(),SWIG_POINTER_OWN);
}
%typemap(out,noblock=1,fragment="RubySequence_Cont")
std::pair<const_iterator, const_iterator> {
$result = rb_ary_new2(2);
rb_ary_push($result, SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).first),
swig::ConstIterator::descriptor(),SWIG_POINTER_OWN));
rb_ary_push($result, SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).second),
swig::ConstIterator::descriptor(),SWIG_POINTER_OWN));
}
// std::map/multimap/set allow returning std::pair< iterator, iterator > from
// equal_range, but we cannot still modify the key, so the iterator is
// const.
%typemap(out,noblock=1,fragment="RubySequence_Cont")
std::pair<iterator, iterator> {
$result = rb_ary_new2(2);
rb_ary_push($result, SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).first),
swig::ConstIterator::descriptor(),SWIG_POINTER_OWN));
rb_ary_push($result, SWIG_NewPointerObj(swig::make_const_iterator(%static_cast($1,const $type &).second),
swig::ConstIterator::descriptor(),SWIG_POINTER_OWN));
}
%typemap(in,noblock=1,fragment="RubySequence_Cont")
const_iterator(swig::ConstIterator *iter = 0, int res),
const_reverse_iterator(swig::ConstIterator *iter = 0, int res) {
res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::ConstIterator::descriptor(), 0);
if (!SWIG_IsOK(res) || !iter) {
%argument_fail(SWIG_TypeError, "$type", $symname, $argnum);
} else {
swig::ConstIterator_T<$type > *iter_t = dynamic_cast<swig::ConstIterator_T<$type > *>(iter);
if (iter_t) {
$1 = iter_t->get_current();
} else {
%argument_fail(SWIG_TypeError, "$type", $symname, $argnum);
}
}
}
%typemap(in,noblock=1,fragment="RubySequence_Cont")
iterator(swig::Iterator *iter = 0, int res),
reverse_iterator(swig::Iterator *iter = 0, int res) {
res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::Iterator::descriptor(), 0);
if (!SWIG_IsOK(res) || !iter) {
%argument_fail(SWIG_TypeError, "$type", $symname, $argnum);
} else {
swig::Iterator_T<$type > *iter_t = dynamic_cast<swig::Iterator_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="RubySequence_Cont")
const_iterator, const_reverse_iterator {
swig::ConstIterator *iter = 0;
int res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::ConstIterator::descriptor(), 0);
$1 = (SWIG_IsOK(res) && iter && (dynamic_cast<swig::ConstIterator_T<$type > *>(iter) != 0));
}
%typecheck(%checkcode(ITERATOR),noblock=1,fragment="RubySequence_Cont")
iterator, reverse_iterator {
swig::ConstIterator *iter = 0;
int res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::Iterator::descriptor(), 0);
$1 = (SWIG_IsOK(res) && iter && (dynamic_cast<swig::Iterator_T<$type > *>(iter) != 0));
}
%fragment("RubySequence_Cont");
// %newobject iterator;
// %newobject const_iterator;
// %extend {
// swig::Iterator* iterator(VALUE* RUBY_SELF) {
// return swig::make_nonconst_iterator($self->begin(), $self->begin(),
// $self->end(), *RUBY_SELF);
// }
// swig::ConstIterator* const_iterator(VALUE* RUBY_SELF) {
// return swig::make_const_iterator($self->begin(), $self->begin(),
// $self->end(), *RUBY_SELF);
// }
// }
#endif //SWIG_EXPORT_ITERATOR_METHODS
%enddef
/**** The Ruby container methods ****/
%define %swig_container_methods(Container...)
%extend {
%newobject dup;
Container* dup()
{
return new Container(*$self);
}
}
%enddef
/**
* Macro used to define common Ruby printing methods for STL container
*/
%define %swig_sequence_printing_methods(Sequence...)
%extend {
VALUE inspect()
{
Sequence::const_iterator i = $self->begin();
Sequence::const_iterator e = $self->end();
const char *type_name = swig::type_name< Sequence >();
VALUE str = rb_str_new2(type_name);
str = rb_str_cat2( str, " [" );
bool comma = false;
VALUE tmp;
for ( ; i != e; ++i, comma = true )
{
if (comma) str = rb_str_cat2( str, "," );
tmp = swig::from< Sequence::value_type >( *i );
tmp = rb_inspect( tmp );
str = rb_str_buf_append( str, tmp );
}
str = rb_str_cat2( str, "]" );
return str;
}
VALUE to_a()
{
Sequence::const_iterator i = $self->begin();
Sequence::const_iterator e = $self->end();
VALUE ary = rb_ary_new2( std::distance( i, e ) );
VALUE tmp;
for ( ; i != e; ++i )
{
tmp = swig::from< Sequence::value_type >( *i );
rb_ary_push( ary, tmp );
}
return ary;
}
VALUE to_s()
{
Sequence::iterator i = $self->begin();
Sequence::iterator e = $self->end();
VALUE str = rb_str_new2( "" );
VALUE tmp;
for ( ; i != e; ++i )
{
tmp = swig::from< Sequence::value_type >( *i );
tmp = rb_obj_as_string( tmp );
str = rb_str_buf_append( str, tmp );
}
return str;
}
}
%enddef
/**
* Macro used to add common methods to all STL sequence-type containers
*/
%define %swig_sequence_methods_non_resizable_common(Sequence...)
%swig_container_methods(%arg(Sequence))
%swig_sequence_iterator(%arg(Sequence))
%swig_sequence_printing_methods(%arg(Sequence))
%fragment("RubySequence_Base");
%extend {
VALUE slice( difference_type i, difference_type length ) throw (std::invalid_argument) {
if ( length < 0 )
return Qnil;
std::size_t len = $self->size();
if ( i < 0 ) {
if ( i + static_cast<Sequence::difference_type>(len) < 0 )
return Qnil;
else
i = len + i;
}
Sequence::difference_type j = length + i;
if ( j > static_cast<Sequence::difference_type>(len) )
j = len;
VALUE r = Qnil;
try {
r = swig::from< const Sequence* >( swig::getslice(self, i, j) );
}
catch( std::out_of_range ) {
}
return r;
}
Sequence* each()
{
if ( !rb_block_given_p() )
rb_raise( rb_eArgError, "no block given");
VALUE r;
Sequence::const_iterator i = self->begin();
Sequence::const_iterator e = self->end();
for ( ; i != e; ++i )
{
r = swig::from< Sequence::value_type >(*i);
rb_yield(r);
}
return self;
}
VALUE __delete2__(const value_type& i) {
VALUE r = Qnil;
return r;
}
}
%enddef
%define %swig_sequence_methods_resizable_common(Sequence...)
%extend {
%newobject select;
Sequence* select() {
if ( !rb_block_given_p() )
rb_raise( rb_eArgError, "no block given" );
Sequence* r = new Sequence();
Sequence::const_iterator i = $self->begin();
Sequence::const_iterator e = $self->end();
for ( ; i != e; ++i )
{
VALUE v = swig::from< Sequence::value_type >(*i);
if ( RTEST( rb_yield(v) ) )
$self->insert( r->end(), *i);
}
return r;
}
VALUE delete_at(difference_type i) {
VALUE r = Qnil;
try {
Sequence::iterator at = swig::getpos(self, i);
r = swig::from< Sequence::value_type >( *(at) );
$self->erase(at);
}
catch (std::out_of_range)
{
}
return r;
}
}
%enddef
%define %swig_sequence_methods_common(Sequence...)
%swig_sequence_methods_non_resizable_common(%arg(Sequence))
%swig_sequence_methods_resizable_common(%arg(Sequence))
%enddef
/**
* Macro used to add functions for back insertion of values in
* STL sequence containers
*/
%define %swig_sequence_back_inserters( Sequence... )
%extend {
VALUE pop() {
if ($self->empty()) return Qnil;
Sequence::value_type x = self->back();
$self->pop_back();
return swig::from< Sequence::value_type >( x );
}
%alias push "<<";
const value_type push( const value_type& e ) {
$self->push_back( e );
return e;
}
%newobject reject;
Sequence* reject() {
if ( !rb_block_given_p() )
rb_raise( rb_eArgError, "no block given" );
Sequence* r = new Sequence();
std::remove_copy_if( $self->begin(), $self->end(),
std::back_inserter(*r),
swig::yield< Sequence::value_type >() );
return r;
}
}
%enddef
%define %swig_sequence_methods_extra(Sequence...)
%extend {
%alias reject_bang "delete_if";
Sequence* reject_bang() {
if ( !rb_block_given_p() )
rb_raise( rb_eArgError, "no block given" );
$self->erase( std::remove_if( $self->begin(), $self->end(),
swig::yield< Sequence::value_type >() ), $self->end() );
return $self;
}
}
%enddef
%define %swig_sequence_methods_non_resizable_accessors(Sequence...)
%extend {
VALUE at(difference_type i) const {
VALUE r = Qnil;
try {
r = swig::from< Sequence::value_type >( *(swig::cgetpos(self, i)) );
}
catch( std::out_of_range ) {
}
return r;
}
VALUE __getitem__(difference_type i, difference_type length) const throw (std::invalid_argument) {
if ( length < 0 )
return Qnil;
std::size_t len = $self->size();
if ( i < 0 ) {
if ( i + static_cast<Sequence::difference_type>(len) < 0 )
return Qnil;
else
i = len + i;
}
Sequence::difference_type j = length + i;
if ( j > static_cast<Sequence::difference_type>(len) )
j = len;
VALUE r = Qnil;
try {
r = swig::from< const Sequence* >( swig::getslice(self, i, j) );
}
catch( std::out_of_range ) {
}
return r;
}
VALUE __getitem__(difference_type i) const {
VALUE r = Qnil;
try {
r = swig::from< Sequence::value_type >( *(swig::cgetpos(self, i)) );
}
catch( std::out_of_range ) {
}
return r;
}
VALUE __getitem__(VALUE i) const throw (std::invalid_argument) {
if ( rb_obj_is_kind_of( i, rb_cRange ) == Qfalse ) {
rb_raise( rb_eTypeError, "not a valid index or range" );
}
static ID id_end = rb_intern("end");
static ID id_start = rb_intern("begin");
static ID id_noend = rb_intern("exclude_end?");
VALUE start = rb_funcall( i, id_start, 0 );
VALUE end = rb_funcall( i, id_end, 0 );
bool noend = ( rb_funcall( i, id_noend, 0 ) == Qtrue );
int len = $self->size();
int s = NUM2INT( start );
if ( s < 0 ) {
s = len + s;
if ( s < 0 )
return Qnil;
} else if ( s > len )
return Qnil;
int e = NUM2INT( end );
if ( e < 0 ) e = len + e;
if ( noend ) e -= 1;
if ( e < 0 ) e = -1;
if ( e >= len ) e = len - 1;
if ( s == len ) e = len - 1;
return swig::from< Sequence* >( swig::getslice(self, s, e+1) );
}
VALUE __setitem__(difference_type i, const value_type& x) throw (std::invalid_argument, std::out_of_range)
{
if ( i >= static_cast<Sequence::difference_type>( $self->size()) )
swig::resize( $self, i+1, x );
else
*(swig::getpos($self, i)) = x;
return swig::from< Sequence::value_type >( x );
}
VALUE __setitem__(difference_type i, difference_type length, const Sequence& v) throw (std::invalid_argument) {
if ( length < 0 )
return Qnil;
std::size_t len = $self->size();
if ( i < 0 ) {
if ( i + static_cast<Sequence::difference_type>(len) < 0 )
return Qnil;
else
i = len + i;
}
Sequence::difference_type j = length + i;
if ( j > static_cast<Sequence::difference_type>(len) ) {
swig::resize( $self, j, *(v.begin()) );
}
VALUE r = Qnil;
swig::setslice($self, i, j, v);
r = swig::from< const Sequence* >( &v );
return r;
}
}
%enddef
/**
* Macro used to add functions for non resizable sequences
*/
%define %swig_sequence_methods_non_resizable(Sequence...)
%swig_sequence_methods_non_resizable_common(%arg(Sequence))
%swig_sequence_methods_non_resizable_accessors(%arg(Sequence))
%enddef
/**
* Macro used to add functions for sequences
*/
%define %swig_sequence_methods(Sequence...)
%swig_sequence_methods_non_resizable_common(%arg(Sequence))
%swig_sequence_methods_resizable_common(%arg(Sequence))
%swig_sequence_methods_non_resizable_accessors(%arg(Sequence))
%swig_sequence_methods_extra(%arg(Sequence));
%swig_sequence_back_inserters(%arg(Sequence));
%enddef
%define %swig_sequence_methods_non_resizable_val(Sequence...)
%swig_sequence_methods_non_resizable(%arg(Sequence))
%enddef
%define %swig_sequence_methods_val(Sequence...)
%swig_sequence_methods(%arg(Sequence))
%enddef
/**
* Macro used to add functions for front insertion of
* elements in STL sequence containers that support it.
*/
%define %swig_sequence_front_inserters( Sequence... )
%extend {
VALUE shift()
{
if ($self->empty()) return Qnil;
Sequence::value_type x = self->front();
$self->erase( $self->begin() );
return swig::from< Sequence::value_type >( x );
}
%typemap(in) (int argc, VALUE* argv) {
$1 = argc - 1;
$2 = argv + 1;
}
Sequence* insert( difference_type pos, int argc, VALUE* argv, ... )
{
std::size_t len = $self->size();
std::size_t i = swig::check_index( pos, len, true );
Sequence::iterator start;
VALUE elem = argv[0];
int idx = 0;
try {
Sequence::value_type val = swig::as<Sequence::value_type>( elem );
if ( i >= len ) {
$self->resize(i-1, val);
return $self;
}
start = $self->begin();
std::advance( start, i );
$self->insert( start++, val );
for ( ++idx; idx < argc; ++idx )
{
elem = argv[idx];
val = swig::as<Sequence::value_type>( elem );
$self->insert( start++, val );
}
}
catch(const std::invalid_argument &)
{
rb_raise( rb_eArgError, "%s",
Ruby_Format_TypeError( "",
swig::type_name<Sequence::value_type>(),
__FUNCTION__, idx+2, elem ));
}
return $self;
}
%typemap(in) (int argc, VALUE* argv) {
$1 = argc;
$2 = argv;
}
Sequence* unshift( int argc, VALUE* argv, ... )
{
for ( int idx = argc-1; idx >= 0; --idx )
{
Sequence::iterator start = $self->begin();
VALUE elem = argv[idx];
try {
Sequence::value_type val = swig::as<Sequence::value_type>( elem );
$self->insert( start, val );
}
catch(const std::invalid_argument &)
{
rb_raise( rb_eArgError, "%s",
Ruby_Format_TypeError( "",
swig::type_name<Sequence::value_type>(),
__FUNCTION__, idx+2, elem ));
}
}
return $self;
}
}
%enddef
//
// Common fragments
//
%fragment("StdSequenceTraits","header",
fragment="StdTraits",
fragment="RubySequence_Cont",
fragment="GC_VALUE_definition")
{
namespace swig {
template <class RubySeq, class Seq>
inline void
assign(const RubySeq& rubyseq, Seq* seq) {
// seq->assign(rubyseq.begin(), rubyseq.end()); // not used as not always implemented
typedef typename RubySeq::value_type value_type;
typename RubySeq::const_iterator it = rubyseq.begin();
for (;it != rubyseq.end(); ++it) {
seq->insert(seq->end(),(value_type)(*it));
}
}
template <class Seq, class T = typename Seq::value_type >
struct traits_asptr_stdseq {
typedef Seq sequence;
typedef T value_type;
static int asptr(VALUE obj, sequence **seq) {
if (rb_obj_is_kind_of(obj, rb_cArray) == Qtrue) {
try {
RubySequence_Cont<value_type> rubyseq(obj);
if (seq) {
sequence *pseq = new sequence();
assign(rubyseq, pseq);
*seq = pseq;
return SWIG_NEWOBJ;
} else {
return rubyseq.check() ? SWIG_OK : SWIG_ERROR;
}
} catch (std::exception& e) {
if (seq) {
VALUE lastErr = rb_gv_get("$!");
if (lastErr == Qnil) {
rb_raise(rb_eTypeError, "%s", e.what());
}
}
return SWIG_ERROR;
}
} else {
sequence *p;
swig_type_info *descriptor = swig::type_info<sequence>();
if (descriptor && SWIG_IsOK(SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0))) {
if (seq) *seq = p;
return SWIG_OLDOBJ;
}
}
return SWIG_ERROR;
}
};
// Partial specialization for GC_VALUE's. No need to typecheck each
// element.
template< class Seq >
struct traits_asptr_stdseq< Seq, swig::GC_VALUE > {
typedef Seq sequence;
typedef swig::GC_VALUE value_type;
static int asptr(VALUE obj, sequence **seq) {
if (rb_obj_is_kind_of(obj, rb_cArray) == Qtrue) {
try {
if (seq) {
RubySequence_Cont<value_type> rubyseq(obj);
sequence *pseq = new sequence();
assign(rubyseq, pseq);
*seq = pseq;
return SWIG_NEWOBJ;
} else {
return true;
}
} catch (std::exception& e) {
if (seq) {
VALUE lastErr = rb_gv_get("$!");
if (lastErr == Qnil) {
rb_raise(rb_eTypeError, "%s", e.what());
}
}
return SWIG_ERROR;
}
} else {
sequence *p;
swig_type_info *descriptor = swig::type_info<sequence>();
if (descriptor && SWIG_IsOK(SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0))) {
if (seq) *seq = p;
return SWIG_OLDOBJ;
}
}
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 VALUE from(const sequence& seq) {
#ifdef SWIG_RUBY_EXTRA_NATIVE_CONTAINERS
swig_type_info *desc = swig::type_info<sequence>();
if (desc && desc->clientdata) {
return SWIG_NewPointerObj(new sequence(seq), desc, SWIG_POINTER_OWN);
}
#endif
size_type size = seq.size();
if (size <= (size_type)INT_MAX) {
VALUE obj = rb_ary_new2((int)size);
int i = 0;
for (const_iterator it = seq.begin();
it != seq.end(); ++it, ++i) {
rb_ary_push(obj, swig::from< value_type >(*it));
}
rb_obj_freeze(obj); // treat as immutable result
return obj;
} else {
rb_raise(rb_eRangeError,"sequence size not valid in ruby");
return Qnil;
}
}
};
}
}
%include <rubycontainer_extended.swg>