diff --git a/Examples/test-suite/ruby/li_std_set_runme.rb b/Examples/test-suite/ruby/li_std_set_runme.rb index 4acd208be..5254a5752 100755 --- a/Examples/test-suite/ruby/li_std_set_runme.rb +++ b/Examples/test-suite/ruby/li_std_set_runme.rb @@ -57,7 +57,7 @@ s = LanguageSet.new s.insert([1,2]) s.insert(1) s.insert("hello") -s.to_a == [1,'hello',[1,2]] +s.to_a == [1,[1,2],'hello'] # sort order: s.sort {|a,b| a.hash <=> b.hash} EOF diff --git a/Examples/test-suite/ruby/li_std_vector_runme.rb b/Examples/test-suite/ruby/li_std_vector_runme.rb index bf7789973..797448236 100755 --- a/Examples/test-suite/ruby/li_std_vector_runme.rb +++ b/Examples/test-suite/ruby/li_std_vector_runme.rb @@ -93,5 +93,8 @@ halve_in_place(dv) halved == dv.to_a sv = StructVector.new sv << Li_std_vector::Struct.new +sv[0].class == Li_std_vector::Struct +sv[1] = Li_std_vector::Struct.new + EOF diff --git a/Lib/ruby/rubyclasses.swg b/Lib/ruby/rubyclasses.swg index 3aa6b7c34..704edf3b7 100644 --- a/Lib/ruby/rubyclasses.swg +++ b/Lib/ruby/rubyclasses.swg @@ -135,6 +135,13 @@ namespace std { static ID cmp_id; static ID hash_id; + + static VALUE swig_protect_funcall( VALUE p ) + { + swig::GC_VALUE* args = (swig::GC_VALUE*) p; + return rb_funcall(VALUE(args[0]), cmp_id, 1, VALUE(args[1])); + } + bool operator()( const swig::GC_VALUE& v, const swig::GC_VALUE& w ) const { @@ -145,7 +152,10 @@ namespace std { // First, try to compare using the <=> operator if present if ( rb_respond_to( v, cmp_id ) == Qtrue ) { - ret = rb_funcall(VALUE(v), cmp_id, 1, VALUE(w)); + int status; + swig::GC_VALUE args[] = { v, w }; + ret = rb_protect( PROTECTFUNC(swig_protect_funcall), VALUE(args), + &status ); } bool res; diff --git a/Lib/ruby/rubycontainer.swg b/Lib/ruby/rubycontainer.swg index 670f4e69e..b8c4686ea 100644 --- a/Lib/ruby/rubycontainer.swg +++ b/Lib/ruby/rubycontainer.swg @@ -607,7 +607,7 @@ namespace swig VALUE r = Qnil; try { - r = swig::from< Sequence >( *(swig::getslice(self, i, j)) ); + r = swig::from< const Sequence* >( swig::getslice(self, i, j) ); } catch( std::out_of_range ) { @@ -744,7 +744,7 @@ namespace swig VALUE r = Qnil; try { - r = swig::from< Sequence >( *(swig::getslice(self, i, j)) ); + r = swig::from< const Sequence* >( swig::getslice(self, i, j) ); } catch( std::out_of_range ) { @@ -792,26 +792,51 @@ namespace swig if ( noend ) e -= 1; if ( e >= len ) e = len - 1; - return swig::from< Sequence >( *(swig::getslice(self, s, e+1)) ); + return swig::from< Sequence* >( swig::getslice(self, s, e+1) ); } - VALUE __setitem__(difference_type i, const value_type& x) throw (std::out_of_range) { - *(swig::getpos(self,i)) = x; - return swig::from< Sequence::value_type >( x ); - } + VALUE __setitem__(difference_type i, const value_type& x) + { + std::size_t len = $self->size(); + if ( i < 0 ) i = len - i; + else if ( i >= len ) + $self->resize( i+1, x ); + else + *(swig::getpos(self,i)) = x; + + return swig::from< Sequence::value_type >( x ); + } VALUE __setitem__(difference_type i, difference_type j, const Sequence& v) - throw (std::out_of_range, std::invalid_argument) { + throw (std::invalid_argument) { if ( j <= 0 ) return Qnil; std::size_t len = $self->size(); if ( i < 0 ) i = len - i; - j += i; if ( j >= len ) j = len-1; + j += i; + if ( j >= len ) { + $self->resize( j+1, *(v.begin()) ); + j = len-1; + } + VALUE r = Qnil; + swig::setslice(self, i, j, v); + r = swig::from< const Sequence* >( &v ); + return r; + } + + } +%enddef + +// ..I don't think %swig_sequence_methods_val are really used at all anymore... +%define %swig_sequence_methods_val(Sequence...) + %swig_sequence_methods_common(%arg(Sequence)) + %extend { + + VALUE __getitem__(difference_type i) { VALUE r = Qnil; try { - swig::setslice(self, i, j, v); - r = swig::from< const Sequence* >( &v ); + r = swig::from< Sequence::value_type >( *(swig::cgetpos(self, i)) ); } catch( std::out_of_range ) { @@ -819,19 +844,13 @@ namespace swig return r; } - } -%enddef - -%define %swig_sequence_methods_val(Sequence...) - %swig_sequence_methods_common(%arg(Sequence)) - %extend { - - value_type __getitem__(difference_type i) throw (std::out_of_range) { - return *(swig::cgetpos(self, i)); - } - - void __setitem__(difference_type i, value_type x) throw (std::out_of_range) { - *(swig::getpos(self,i)) = x; + VALUE __setitem__(difference_type i, value_type x) { + std::size_t len = $self->size(); + if ( i < 0 ) i = len - i; + else if ( i >= len ) + $self->resize( i+1, x ); + else *(swig::getpos(self,i)) = x; + return swig::from< Sequence::value_type >( x ); } } %enddef