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

@ -1,5 +1,30 @@
Version 1.3.32 (in progress)
============================
05/05/2007: gga
[Ruby]
STL files have been upgraded to follow the new swig/python
Lib/std conventions.
This means std::vector, std::set, std::map, set::multimap,
std::multiset, std::deque and std::string are now properly
supported, including their iterators, support for containing
ruby objects (swig::GC_VALUE) and several other ruby
enhancements.
std::ios, std::iostream, std::iostreambuf and std::sstream
are now also supported.
std::wstring, std::wios, std::wiostream, std::wiostreambuf
and std::wsstream are supported verbatim with no unicode
conversion.
std_vector.i now mimics the behavior of Ruby Arrays much more
closely, supporting slicing, shifting, unshifting,
multiple indexing and proper return values on assignment.
COMPATABILITY NOTE: this changes the older api a little bit in
that improper indexing would previously (incorrectly) raise
exceptions. Now, nil is returned instead, following ruby's
standard Array behavior.
05/01/2007: gga
[Ruby]
Improved the documentation to document the new features
@ -9,10 +34,35 @@ Version 1.3.32 (in progress)
[Ruby]
Added %initstack and %ignorestack directives for director
functions. These allow you to control whether a director
function should re-init the ruby stack.
function should re-init the Ruby stack.
This is sometimes needed for an embedded Ruby where the
director method is used as a C++ callback and not called
by the user from ruby code.
Explanation:
Ruby's GC needs to be aware of the running OS stack in order to
mark any VALUE (Ruby objects) it finds there to avoid collection
of them. This allows the ruby API to be very simple and allows
you to write code like "VALUE a = sth" anywhere without needing
to do things like refcounting like python.
By default, the start of the stack is set when ruby_init() is
called. If ruby is inited within main(), as it usually is the
case with the main ruby executable, ruby will be able to calculate
its stack properly. However, when this is not possible, as when
ruby is embedded as a plugin to an application where main is not
available, ruby_init() will be called in the wrong place, and
ruby will be incorrectly tracking the stack from the function
that called ruby_init() forwards only, which can lead to
all sorts of weird crashes or to ruby thinking it has run out of
stack space incorrectly.
To avoid this, director (callback) functions can now be tagged
to try to reset the ruby stack, which will solve the issues.
NOTE: ruby1.8.6 still contains a bug in it in that its function
to reset the stack will not always do so. This bug is triggered
very rarely, when ruby is called from two very distinct places
in memory, like a branch of main() and another dso. This bug
has now been reported to ruby-core and is pending further
investigation.
(bug #1700535 and patch #1702907)
04/30/2007: wsfulton
Fix #1707582 - Restore building from read-only source directories.
@ -24,28 +74,15 @@ Version 1.3.32 (in progress)
argument passed.
(feature request #1699670)
04/30/2007: gga
[Ruby]
STL files have been upgraded to follow the new swig/python
Lib/std conventions.
std_vector.i now mimics the behavior of Ruby Arrays much more
closely, supporting slicing, shifting, unshifting,
multiple indexing and proper return values on assignment.
COMPATABILITY NOTE: this changes the older api a little bit in
that improper indexing would previously (incorrectly) raise
exceptions. Now, nil is returned instead, following ruby's
standard Array behavior.
04/30/2007: gga
[Ruby]
Ruby no longer creates the free_Class function if the class
containes its own user defined free function (%freefunc).
contains its own user defined free function (%freefunc).
(bug #1702882)
04/30/2007: gga
[Ruby]
Made directors raise a ruby expection for incorrect argout
Made directors raise a ruby exception for incorrect argout
returned values if RUBY_EMBEDDED is set, instead of throwing
an actual SwigDirector exception.
This will prevent crashes when ruby is embedded and unaware
@ -91,7 +128,7 @@ Version 1.3.32 (in progress)
%feature("numoutputs","0") added.
This feature allows you to ignore the output of a function so
that it is not added to a list of outpus values
that it is not added to a list of output values
( ie. argouts ).
This should also become a feature of %typemap(directorout)
as "numoutputs"=0, just like "numinputs"=0 exists.
@ -101,15 +138,15 @@ Version 1.3.32 (in progress)
%include <typemaps.i>
%feature("numoutputs","0") { Class::member_function1 };
%typemap(out) MStatus { // some code, like ignore mstatus
// and raise exception };
%typemap(out) MStatus { // some code, like check mstatus
// and raise exception if wrong };
%inline %{
typedef int MStatus;
class Class {
// one argument returned, but director out code added
// MStatus is discarded.
// MStatus is discarded as a return (out) parameter.
virtual MStatus member_function1( int& OUTPUT );
// two arguments returned, director out code added
@ -118,35 +155,6 @@ Version 1.3.32 (in progress)
};
%}
04/29/2007: gga
[Ruby]
Directors will now try to reset the ruby stack on the first call
to them if the developer sets the define RUBY_EMBEDDED.
Explanation:
Ruby's GC needs to be aware of the running OS stack in order to
mark any VALUE (Ruby objects) it finds there to avoid collection
of them. This allows the ruby API to be very simple and allows
you to write code like "VALUE a = sth" anywhere without needing
to do things like refcounting like python.
By default, the start of the stack is set when ruby_init() is
called. If ruby is inited within main(), as it usually is
with the main ruby executable, ruby will be able to calculate
its stack properly. However, when this is not possible, as when
ruby is embedded as a plugin to an application where main is not
available, ruby_init() will be called in the wrong place, and
ruby will be incorrectly tracking the stack from the function
that called ruby_init() only, which can lead to
all sorts of weird crashes or to ruby thinking it has run out of
stack space incorrectly.
To avoid this, director (callback) functions can now be tagged
to try to reset the ruby stack, which will solve the issues.
NOTE: ruby1.8.6 still contains a bug in it in that its function
to reset the stack will not always do so. This bug is triggered
very rarely, when ruby is called from two very distinct places
in memory, like a branch of main() and another dso. This bug
has now been reported to ruby-core and is pending further
investigation.
(bug #1700535 and patch #1702907)
04/21/2007: olly
Fix parsing of float constants with an exponent (e.g. 1e-02f)

View file

@ -40,7 +40,7 @@ m["foo"] = "hello"
pm = Li_std_map::LanguageMap.new
m.each_key { |k| pm[k] = m[k] }
m.each_key { |k| swig_assert("#{pm[k].inspect} == #{m[k].inspect}") }
m.each_key { |k| swig_assert_equal("pm[#{k.inspect}]", "m[#{k.inspect}]", binding) }
m = Li_std_map::MmapA.new
m[0] = a1
@ -49,7 +49,7 @@ m[0].size == 2
m.respond_to?(:each) == true
m.respond_to?(:each_key) == true
m.respond_to?(:each_value) == true
m.values_at(0)[0] == m[0]
EOF
mii = Li_std_map::Mapii.new

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() )