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:
parent
8564ff90c0
commit
a6fa331dae
5 changed files with 161 additions and 73 deletions
106
CHANGES.current
106
CHANGES.current
|
|
@ -1,5 +1,30 @@
|
||||||
Version 1.3.32 (in progress)
|
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
|
05/01/2007: gga
|
||||||
[Ruby]
|
[Ruby]
|
||||||
Improved the documentation to document the new features
|
Improved the documentation to document the new features
|
||||||
|
|
@ -9,10 +34,35 @@ Version 1.3.32 (in progress)
|
||||||
[Ruby]
|
[Ruby]
|
||||||
Added %initstack and %ignorestack directives for director
|
Added %initstack and %ignorestack directives for director
|
||||||
functions. These allow you to control whether a 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
|
This is sometimes needed for an embedded Ruby where the
|
||||||
director method is used as a C++ callback and not called
|
director method is used as a C++ callback and not called
|
||||||
by the user from ruby code.
|
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
|
04/30/2007: wsfulton
|
||||||
Fix #1707582 - Restore building from read-only source directories.
|
Fix #1707582 - Restore building from read-only source directories.
|
||||||
|
|
@ -24,28 +74,15 @@ Version 1.3.32 (in progress)
|
||||||
argument passed.
|
argument passed.
|
||||||
(feature request #1699670)
|
(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
|
04/30/2007: gga
|
||||||
[Ruby]
|
[Ruby]
|
||||||
Ruby no longer creates the free_Class function if the class
|
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)
|
(bug #1702882)
|
||||||
|
|
||||||
04/30/2007: gga
|
04/30/2007: gga
|
||||||
[Ruby]
|
[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
|
returned values if RUBY_EMBEDDED is set, instead of throwing
|
||||||
an actual SwigDirector exception.
|
an actual SwigDirector exception.
|
||||||
This will prevent crashes when ruby is embedded and unaware
|
This will prevent crashes when ruby is embedded and unaware
|
||||||
|
|
@ -91,7 +128,7 @@ Version 1.3.32 (in progress)
|
||||||
%feature("numoutputs","0") added.
|
%feature("numoutputs","0") added.
|
||||||
|
|
||||||
This feature allows you to ignore the output of a function so
|
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 ).
|
( ie. argouts ).
|
||||||
This should also become a feature of %typemap(directorout)
|
This should also become a feature of %typemap(directorout)
|
||||||
as "numoutputs"=0, just like "numinputs"=0 exists.
|
as "numoutputs"=0, just like "numinputs"=0 exists.
|
||||||
|
|
@ -101,15 +138,15 @@ Version 1.3.32 (in progress)
|
||||||
%include <typemaps.i>
|
%include <typemaps.i>
|
||||||
|
|
||||||
%feature("numoutputs","0") { Class::member_function1 };
|
%feature("numoutputs","0") { Class::member_function1 };
|
||||||
%typemap(out) MStatus { // some code, like ignore mstatus
|
%typemap(out) MStatus { // some code, like check mstatus
|
||||||
// and raise exception };
|
// and raise exception if wrong };
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
typedef int MStatus;
|
typedef int MStatus;
|
||||||
class Class {
|
class Class {
|
||||||
|
|
||||||
// one argument returned, but director out code added
|
// 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 );
|
virtual MStatus member_function1( int& OUTPUT );
|
||||||
|
|
||||||
// two arguments returned, director out code added
|
// 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
|
04/21/2007: olly
|
||||||
Fix parsing of float constants with an exponent (e.g. 1e-02f)
|
Fix parsing of float constants with an exponent (e.g. 1e-02f)
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ m["foo"] = "hello"
|
||||||
|
|
||||||
pm = Li_std_map::LanguageMap.new
|
pm = Li_std_map::LanguageMap.new
|
||||||
m.each_key { |k| pm[k] = m[k] }
|
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 = Li_std_map::MmapA.new
|
||||||
m[0] = a1
|
m[0] = a1
|
||||||
|
|
@ -49,7 +49,7 @@ m[0].size == 2
|
||||||
m.respond_to?(:each) == true
|
m.respond_to?(:each) == true
|
||||||
m.respond_to?(:each_key) == true
|
m.respond_to?(:each_key) == true
|
||||||
m.respond_to?(:each_value) == true
|
m.respond_to?(:each_value) == true
|
||||||
|
m.values_at(0)[0] == m[0]
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
mii = Li_std_map::Mapii.new
|
mii = Li_std_map::Mapii.new
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,48 @@ namespace swig {
|
||||||
|
|
||||||
typedef GC_VALUE LANGUAGE_OBJ;
|
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");
|
||||||
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,26 +71,6 @@ namespace swig {
|
||||||
{
|
{
|
||||||
%#include <functional>
|
%#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 {
|
namespace swig {
|
||||||
template < class T >
|
template < class T >
|
||||||
|
|
@ -652,6 +632,24 @@ namespace swig
|
||||||
return self;
|
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;
|
%rename("reject!") reject_bang;
|
||||||
%alias reject_bang "delete_if";
|
%alias reject_bang "delete_if";
|
||||||
|
|
@ -659,12 +657,11 @@ namespace swig
|
||||||
if ( !rb_block_given_p() )
|
if ( !rb_block_given_p() )
|
||||||
rb_raise( rb_eArgError, "no block given" );
|
rb_raise( rb_eArgError, "no block given" );
|
||||||
|
|
||||||
VALUE r;
|
|
||||||
Sequence::iterator i = self->begin();
|
Sequence::iterator i = self->begin();
|
||||||
Sequence::iterator e = self->end();
|
Sequence::iterator e = self->end();
|
||||||
for ( ; i != e; )
|
for ( ; i != e; )
|
||||||
{
|
{
|
||||||
r = swig::from<Sequence::value_type>(*i);
|
VALUE r = swig::from<Sequence::value_type>(*i);
|
||||||
if ( RTEST( rb_yield(r) ) )
|
if ( RTEST( rb_yield(r) ) )
|
||||||
$self->erase(i++);
|
$self->erase(i++);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,47 @@
|
||||||
return self;
|
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()
|
Map* each_key()
|
||||||
{
|
{
|
||||||
if ( !rb_block_given_p() )
|
if ( !rb_block_given_p() )
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue