Fixed VALUE less compare function to be a good GC_VALUE

less compare function.  This is used for hashing.
Moved the functor over to rubyclasses to avoid bloat
when GC_VALUE is not used.
Updated std::map test to check for equivalence.
Updated CHANGES.current a tad to move the STL
stuff as last and merge two feature updates as one.




git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9740 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Gonzalo Garramuno 2007-05-01 09:55:44 +00:00
commit a6fa331dae
5 changed files with 161 additions and 73 deletions

View file

@ -125,6 +125,48 @@ namespace swig {
typedef GC_VALUE LANGUAGE_OBJ;
}
namespace std {
template <>
struct less< swig::GC_VALUE >: public binary_function< swig::GC_VALUE,
swig::GC_VALUE, bool >
{
static ID cmp_id;
static ID hash_id;
bool
operator()( const swig::GC_VALUE& v, const swig::GC_VALUE& w ) const
{
// SWIG_RUBY_THREAD_BEGIN_BLOCK;
VALUE ret = Qnil;
// 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));
}
bool res;
// If that fails, try to use the two object's hash function to compare.
if ( ret == Qnil ) {
VALUE a = rb_funcall( VALUE(v), hash_id, 0 );
VALUE b = rb_funcall( VALUE(w), hash_id, 0 );
res = a < b; // as shifted integers
}
else
{
res = NUM2INT( ret ) < 0;
}
// SWIG_RUBY_THREAD_END_BLOCK;
return res;
}
};
ID less< swig::GC_VALUE >::cmp_id = rb_intern("<=>");
ID less< swig::GC_VALUE >::hash_id = rb_intern("hash");
}
%}

View file

@ -71,26 +71,6 @@ namespace swig {
{
%#include <functional>
namespace std {
template <>
struct less< VALUE >: public binary_function< VALUE, VALUE, bool >
{
static ID id;
bool
operator()( VALUE v, VALUE w ) const
{
// SWIG_RUBY_THREAD_BEGIN_BLOCK;
bool res = NUM2INT( rb_funcall(v, id, 1, w) ) < 0;
// SWIG_RUBY_THREAD_END_BLOCK;
return res;
}
};
ID less< VALUE >::id = rb_intern("<=>");
}
namespace swig {
template < class T >
@ -652,6 +632,24 @@ namespace swig
return self;
}
%newobject select
Sequence* select() {
if ( !rb_block_given_p() )
rb_raise( rb_eArgError, "no block given" );
Sequence* r = new Sequence;
Sequence::iterator i = self->begin();
Sequence::iterator e = self->end();
for ( ; i != e; ++i )
{
VALUE v = swig::from<Sequence::value_type>(*i);
if ( RTEST( rb_yield(v) ) )
$self->push_back(*i);
}
return r;
}
%rename("reject!") reject_bang;
%alias reject_bang "delete_if";
@ -659,12 +657,11 @@ namespace swig
if ( !rb_block_given_p() )
rb_raise( rb_eArgError, "no block given" );
VALUE r;
Sequence::iterator i = self->begin();
Sequence::iterator e = self->end();
for ( ; i != e; )
{
r = swig::from<Sequence::value_type>(*i);
VALUE r = swig::from<Sequence::value_type>(*i);
if ( RTEST( rb_yield(r) ) )
$self->erase(i++);
else

View file

@ -194,6 +194,47 @@
return self;
}
%newobject select;
Map* select() {
if ( !rb_block_given_p() )
rb_raise( rb_eArgError, "no block given" );
Map* r = new Map;
Map::iterator i = $self->begin();
Map::iterator e = $self->end();
for ( ; i != e; ++i )
{
VALUE k = swig::from<Map::key_type>(i->first);
VALUE v = swig::from<Map::mapped_type>(i->second);
if ( RTEST( rb_yield_values(2, k, v) ) )
$self->insert(r->end(), *i);
}
return r;
}
%typemap(in) (int argc, VALUE* argv) {
$1 = argc;
$2 = argv;
}
VALUE values_at(int argc, VALUE* argv, ...) {
VALUE r = rb_ary_new();
ID id = rb_intern("[]");
swig_type_info* type = swig::type_info< Map >();
VALUE me = SWIG_NewPointerObj( $self, type, 0 );
for ( int i = 0; i < argc; ++i )
{
VALUE key = argv[i];
VALUE tmp = rb_funcall( me, id, 1, key );
rb_ary_push( r, tmp );
}
return r;
}
Map* each_key()
{
if ( !rb_block_given_p() )