Fixes to std_map and multimap. There's still a problem

of const correctness in the std swig STL library.  
Need to bring it up in the swig-devel list.

Added new functions to swig_assert.
Changed some tests to reflect these changes.



git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9730 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Gonzalo Garramuno 2007-05-01 01:08:17 +00:00
commit a100f16bbd
22 changed files with 366 additions and 135 deletions

View file

@ -3,7 +3,8 @@
%include "std_pair.i"
namespace std {
%template(IntPair) pair<int, int>;
%template(IntPair) pair<int, int>;
%template(ValuePair) pair< swig::LANGUAGE_OBJ, swig::LANGUAGE_OBJ >;
}
%inline %{

View file

@ -1,11 +1,16 @@
%module li_std_wstring
%include <std_basic_string.i>
%include <std_wstring.i>
%inline %{
#include <string>
typedef std::wstring A;
struct A : std::wstring
{
A(const std::wstring& s) : std::wstring(s)
{
}
};
struct B
{
@ -16,18 +21,10 @@ struct B
char *cname;
std::wstring name;
A a;
A typedefmethod(A a) {
return a;
}
};
A globala;
wchar_t test_wcvalue_w() {
return L'W';
}
wchar_t test_wcvalue(wchar_t x) {
return x;
}

View file

@ -15,19 +15,19 @@ include Abstract_access
begin
a = A.new
rescue TypeError
swig_assert(true, 'A.new')
swig_assert(true, binding, 'A.new')
end
begin
b = B.new
rescue TypeError
swig_assert(true, 'B.new')
swig_assert(true, binding, 'B.new')
end
begin
c = C.new
rescue TypeError
swig_assert(true, 'C.new')
swig_assert(true, binding, 'C.new')
end
swig_assert( 'D.new' )

View file

@ -28,7 +28,7 @@ rescue TypeError
# TypeError: allocator undefined for Abstract_inherit_ok::Foo
exceptionRaised = true
ensure
swig_assert( exceptionRaised, "for !exceptionRaised" )
swig_assert( "exceptionRaised", binding )
end
#
@ -43,6 +43,6 @@ begin
rescue NameError
exceptionRaised = true
ensure
swig_assert( !exceptionRaised, "for exceptionRaised" )
swig_assert( "!exceptionRaised", binding )
end

View file

@ -29,7 +29,7 @@ rescue TypeError
# TypeError: allocator undefined for Abstract_inherit::Foo
exceptionRaised = true
ensure
swig_assert( exceptionRaised, "exceptionRaised")
swig_assert( "exceptionRaised", binding )
end
exceptionRaised = false
@ -42,7 +42,7 @@ rescue TypeError
# TypeError: allocator undefined for Abstract_inherit::Bar
exceptionRaised = true
ensure
swig_assert( exceptionRaised, "exceptionRaised")
swig_assert( "exceptionRaised", binding )
end
exceptionRaised = false
@ -55,7 +55,7 @@ rescue TypeError
# TypeError: allocator undefined for Abstract_inherit::Spam
exceptionRaised = true
ensure
swig_assert( exceptionRaised, "exceptionRaised")
swig_assert( "exceptionRaised", binding )
end

View file

@ -33,7 +33,7 @@ rescue TypeError
# TypeError: allocator undefined for Abstract_signature::Abstract_foo
exceptionRaised = true
ensure
swig_assert( exceptionRaised, "for exceptionRaised")
swig_assert( "exceptionRaised", binding)
end
#
@ -57,6 +57,6 @@ rescue TypeError
# TypeError: allocator undefined for Abstract_signature::Abstract_bar
exceptionRaised = true
ensure
swig_assert( exceptionRaised, "for exceptionRaised")
swig_assert( "exceptionRaised", binding)
end

View file

@ -13,8 +13,11 @@ require 'abstract_typedef'
include Abstract_typedef
swig_assert_each_line(<<'EOF', binding)
e = Engine.new
a = A.new
a.write(e)
swig_assert( a.write(e), 'for a.write(e)' )
EOF

View file

@ -21,7 +21,7 @@ foo = Foo.new
'seq' => 3 }.each do |m, v|
foo.send("#{m}=", v)
val = foo.send(m)
swig_assert(val == v, " for foo.#{m} == #{v}, was #{val}")
swig_assert("val == v", binding)
end
{'x' => (1 << 4),
@ -31,5 +31,5 @@ end
'seq' => (1 << (4*8-6)) }.each do |m, v|
foo.send("#{m}=", v)
val = foo.send(m)
swig_assert(val != v, " for foo.#{m} != #{v}, was #{val}")
swig_assert("val != v", binding)
end

View file

@ -16,7 +16,7 @@ include Apply_signed_char
['CharValFunction', 'CCharValFunction', 'CCharRefFunction'].each do |m|
[ 3, -3 ].each do |v|
val = send( m, v )
swig_assert( v == val, "for #{m} #{val} == #{v} ")
swig_assert( "v == val", binding, "for #{m}")
end
end
@ -24,7 +24,7 @@ end
'globalconstchar' => -110,
}.each do |k,v|
val = Apply_signed_char.send( k )
swig_assert( v == val, "for #{k} #{val} == #{v} ")
swig_assert( "v == val", binding, "for #{k}")
end
@ -33,7 +33,7 @@ a = DirectorTest.new
['CharValFunction', 'CCharValFunction', 'CCharRefFunction'].each do |m|
[ 3, -3 ].each do |v|
val = a.send( m, v )
swig_assert( v == val, "for DirectorTest.#{m} #{val} == #{v} ")
swig_assert( "v == val", binding, "for DirectorTest.#{m}")
end
end
@ -41,5 +41,5 @@ end
'memberconstchar' => -112,
}.each do |k,v|
val = a.send( k )
swig_assert( v == val, "for #{k} #{val} == #{v} ")
swig_assert( "v == val", binding, "for #{k}")
end

View file

@ -22,14 +22,14 @@ ptr = 'a'
['UCharFunction', 'SCharFunction', 'CUCharFunction',
'CSCharFunction'].each do |m|
val = Apply_strings.send(m, ptr)
swig_assert( val == ptr, "Apply_strings.#{m} #{val} == #{ptr}" )
swig_assert( "val == ptr", binding )
end
['CharFunction', 'CCharFunction'].each do |m|
begin
val = Apply_strings.send(m, ptr)
swig_assert( false, "Apply_strings.#{m} should raise TypeError" )
swig_assert( false, nil, "Apply_strings.#{m} should raise TypeError" )
rescue TypeError
end
end
@ -39,14 +39,14 @@ foo = DirectorTest.new
['UCharFunction', 'SCharFunction', 'CUCharFunction',
'CSCharFunction'].each do |m|
val = foo.send(m, ptr)
swig_assert( val == ptr, "DirectorTest.#{m} #{val} == #{ptr}" )
swig_assert( "val == ptr", binding, "DirectorTest.#{m}" )
end
['CharFunction', 'CCharFunction'].each do |m|
begin
val = foo.send(m, ptr)
swig_assert( false, "DirectorTest.#{m} should raise TypeError" )
swig_assert( false, nil, "DirectorTest.#{m} should raise TypeError" )
rescue TypeError
end
end

View file

@ -12,27 +12,29 @@ require 'argout'
include Argout
swig_assert_each_line(<<'EOF', binding)
t = new_intp
intp_assign(t, 5)
v = incp(t)
swig_assert( v == 5, "incp - v == 5 was #{v}")
val = intp_value(t)
swig_assert( val == 6, "incp - intp_value(t) == 6 was #{val}")
val == 6
t = new_intp
intp_assign(t, 5)
v = incr(t)
swig_assert( v == 5, "incr - v == 5 was #{v}")
v == 5
val = intp_value(t)
swig_assert( val == 6, "incr - intp_value(t) == 6 was #{val}")
val == 6
t = new_intp
intp_assign(t, 5)
v = inctr(t)
swig_assert( v == 5, "inctr - v == 5 was #{v}")
v == 5
val = intp_value(t)
swig_assert( val == 6, "inctr - intp_value(t) == 6 was #{val}")
val == 6
EOF
#
# @todo: how to use voidhandle and handle?

View file

@ -12,45 +12,50 @@ require 'swig_assert'
require 'li_std_pair'
include Li_std_pair
swig_assert_each_line(<<'EOF', binding)
#
# Because of template specializations for pair<int, int>, these should return
# an Array of size 2, where both elements are Fixnums.
#
intPair = makeIntPair(7, 6)
raise RuntimeError unless intPair.instance_of?(Array)
raise RuntimeError unless intPair.size == 2
raise RuntimeError unless intPair[0] == 7 && intPair[1] == 6
intPair.instance_of?(Array)
intPair.size == 2
intPair[0] == 7 && intPair[1] == 6
intPairConstRef = makeIntPairConstRef(7, 6)
raise RuntimeError unless intPairConstRef.instance_of?(Array)
raise RuntimeError unless intPairConstRef[0] == 7 && intPairConstRef[1] == 6
intPairConstRef.instance_of?(Array)
intPairConstRef[0] == 7 && intPairConstRef[1] == 6
#
# Each of these should return a reference to a wrapped
# std::pair<int, int> object (i.e. an IntPair instance).
#
intPairPtr = makeIntPairPtr(7, 6)
raise RuntimeError unless intPairPtr.instance_of?(IntPair)
raise RuntimeError unless intPairPtr[0] == 7 && intPairPtr[1] == 6
intPairPtr.instance_of?(IntPair)
intPairPtr[0] == 7 && intPairPtr[1] == 6
intPairRef = makeIntPairRef(7, 6)
raise RuntimeError unless intPairRef.instance_of?(IntPair)
raise RuntimeError unless intPairRef[0] == 7 && intPairRef[1] == 6
intPairRef.instance_of?(IntPair)
intPairRef[0] == 7 && intPairRef[1] == 6
#
# Now test various input typemaps. Each of the wrapped C++ functions
# (product1, product2 and product3) is expecting an argument of a
# different type (see li_std_pair.i). Typemaps should be in place to
# convert this Array into the expected argument type.
#
raise RuntimeError unless product1(intPair) == 42
raise RuntimeError unless product2(intPair) == 42
raise RuntimeError unless product3(intPair) == 42
product1(intPair) == 42
product2(intPair) == 42
product3(intPair) == 42
#
# Similarly, each of the input typemaps should know what to do
# with an IntPair instance.
#
raise RuntimeError unless product1(intPairPtr) == 42
raise RuntimeError unless product2(intPairPtr) == 42
raise RuntimeError unless product3(intPairPtr) == 42
product1(intPairPtr) == 42
product2(intPairPtr) == 42
product3(intPairPtr) == 42
val = ValuePair.new
val.first = 'sd'
val.second = [5,4,3]
EOF

View file

@ -13,76 +13,78 @@ require 'li_std_vector'
include Li_std_vector
@iv = IntVector.new(4)
iv = IntVector.new(4)
swig_assert( "@iv.respond_to? :each" )
swig_assert( "iv.respond_to? :each", binding )
begin
@iv.each
swig_assert( false, "@iv.each worked with no block!")
iv.each
swig_assert( false, nil, "iv.each worked with no block!")
rescue ArgumentError
end
@iv.each_with_index { |e,i| swig_assert("#{e} == 0", "for @iv[#{i}] == 0") }
iv.each_with_index { |e,i|
swig_assert("#{e} == 0", binding, "for iv[#{i}] == 0")
}
0.upto(3) { |i| @iv[i] = i }
0.upto(3) { |i| iv[i] = i }
{ "@iv[-1]" => 3,
"@iv.slice(0,2).to_s" => "01",
"@iv.slice(1,2).to_s" => "12",
"@iv[0,-2]" => nil,
"@iv[0,3].to_s" => "012",
"@iv[0,10].to_s" => "012",
"@iv[1..2].to_s" => '12',
"@iv[1..3].to_s" => '123',
"@iv[1..4].to_s" => '123',
"@iv[1..-2].to_s" => '12',
"@iv[2..-3]" => nil,
{ "iv[-1]" => 3,
"iv.slice(0,2).to_s" => "01",
"iv.slice(1,2).to_s" => "12",
"iv[0,-2]" => nil,
"iv[0,3].to_s" => "012",
"iv[0,10].to_s" => "012",
"iv[1..2].to_s" => '12',
"iv[1..3].to_s" => '123',
"iv[1..4].to_s" => '123',
"iv[1..-2].to_s" => '12',
"iv[2..-3]" => nil,
}.each do |k,v|
swig_assert( "#{k} == #{v.inspect}" )
swig_assert( "#{k} == #{v.inspect}", binding )
end
swig_assert_each_line(<<'EOF')
@iv << 5
@iv.push 5
@iv.pop == 5
@iv.unshift(7)
@iv.shift == 7
@iv.unshift(7, 3)
@iv.insert(1,5)
@iv.insert(0, 3)
@iv.unshift(2,3,4)
x = average(@iv)
swig_assert_each_line(<<'EOF', binding)
iv << 5
iv.push 5
iv.pop == 5
iv.unshift(7)
iv.shift == 7
iv.unshift(7, 3)
iv.insert(1,5)
iv.insert(0, 3)
iv.unshift(2,3,4)
x = average(iv)
y = average([1, 2, 3, 4])
half([10, 10.5, 11, 11.5])
EOF
@dv = DoubleVector.new(10)
dv = DoubleVector.new(10)
swig_assert( "@dv.respond_to? :each_with_index" )
swig_assert( "dv.respond_to? :each_with_index", binding )
@dv.each_with_index { |e,i| swig_assert("@dv[#{i}] == 0.0") }
dv.each_with_index { |e,i| swig_assert("dv[#{i}] == 0.0", binding) }
0.upto(9) { |i| @dv[i] = i/2.0 }
0.upto(9) { |i| dv[i] = i/2.0 }
{ "@dv[-1]" => 4.5,
"@dv.slice(0,2).to_s" => "0.00.5",
"@dv[0,-2]" => nil,
"@dv[0,3].to_s" => "0.00.51.0",
"@dv[3,3].to_s" => "1.52.02.5",
{ "dv[-1]" => 4.5,
"dv.slice(0,2).to_s" => "0.00.5",
"dv[0,-2]" => nil,
"dv[0,3].to_s" => "0.00.51.0",
"dv[3,3].to_s" => "1.52.02.5",
}.each do |k,v|
swig_assert( "#{k} == #{v.inspect}" )
swig_assert( "#{k} == #{v.inspect}", binding )
end
swig_assert_each_line(<<'EOF')
@dv.delete_at(2)
@dv.delete_if() { |x| x == 2.0 }
@dv.include? 3.0
@dv.find {|x| x==3.0 }
halve_in_place(@dv) == nil
@dv = [0.0,0.25,0.75,1.25,1.5,1.75,2.0,2.25]
@sv = StructVector.new
@sv << Li_std_vector::Struct.new
swig_assert_each_line(<<'EOF', binding)
dv.delete_at(2)
dv.delete_if() { |x| x == 2.0 }
dv.include? 3.0
dv.find {|x| x==3.0 }
halve_in_place(dv) == nil
dv = [0.0,0.25,0.75,1.25,1.5,1.75,2.0,2.25]
sv = StructVector.new
sv << Li_std_vector::Struct.new
EOF

View file

@ -27,7 +27,7 @@ GC.track_class = Foo
GC.start
100.times { foo1 = Foo.makeFoo; foo2 = foo1.makeMore }
GC.stats
swig_assert( 'Foo.fooCount == 200', "but is #{Foo.fooCount}" )
swig_assert( 'Foo.fooCount == 200', binding, "but is #{Foo.fooCount}" )
GC.start
swig_assert( 'Foo.fooCount <= 2', "but is #{Foo.fooCount}" )
swig_assert( 'Foo.fooCount <= 2', binding, "but is #{Foo.fooCount}" )

View file

@ -21,7 +21,7 @@ GC.track_class = Foo
GC.stats
100.times { foo1 = makeFoo }
GC.stats
swig_assert( 'fooCount == 100', "but is #{fooCount}" )
swig_assert( 'fooCount == 100', nil, "but is #{fooCount}" )
GC.start
swig_assert( 'fooCount <= 1', "but is #{fooCount}" )
swig_assert( 'fooCount <= 1', nil, "but is #{fooCount}" )

View file

@ -15,19 +15,20 @@ class SwigAssertError < StandardError
end
def swig_assert( condition, *args )
def swig_assert_equal( a, b, scope = nil, msg = nil )
begin
ok = eval(condition.to_s)
check = "#{a} == #{b}"
ok = eval(check, scope)
rescue => e
raise SwigAssertError.new("Wrong assert: #{condition.to_s} - #{e}")
raise SwigAssertError.new("Wrong assert: #{check} - #{e}")
end
unless ok
raise SwigRubyError.new("FAILED CHECK: #{condition} was #{ok.inspect} #{args.join(' ')}")
raise SwigRubyError.new("FAILED CHECK: #{check} was #{eval(a)} #{msg}")
end
if $VERBOSE
$stdout.puts "\tPASSED #{condition} #{args.join(' ')}"
$stdout.puts "\tPASSED #{check} #{msg}"
end
return ok
@ -41,8 +42,37 @@ rescue => e
end
def swig_assert_each_line( lines )
def swig_assert( condition, scope = nil, msg = nil )
begin
if scope.kind_of? Binding
eval(condition.to_s, scope)
else
eval(condition.to_s)
msg = scope
end
rescue => e
raise SwigAssertError.new("Wrong assert: #{condition.to_s} - #{e}")
end
if $VERBOSE
$stdout.puts "\tPASSED #{condition} #{msg}"
end
rescue => e
trace = e.backtrace[1..-1]
$stderr.puts "#{trace[0,1]}: #{e}"
if trace.size > 1
$stderr.puts "\tfrom #{trace[1..-1].join("\n\t ")}"
end
exit(1)
end
def swig_assert_each_line( lines, scope = nil, msg = nil )
lines.split("\n").each do |line|
swig_assert(line)
next if line.empty? or line =~ /^\s*#.*/
if line =~ /(.*)\s*==\s*(.*)/
swig_assert_equal($1, $2, scope, msg)
else
swig_assert(line, scope, msg)
end
end
end

View file

@ -42,10 +42,9 @@ namespace swig {
};
%apply VALUE {GC_VALUE};
%apply VALUE const& {GC_VALUE const&};
/* For input */
%typemap(in,noblock=1) GC_VALUE* (GC_VALUE r) {
%typemap(in,noblock=1) GC_VALUE* (GC_VALUE r), GC_VALUE& (GC_VALUE r) {
r = $input; $1 = &r;
}

View file

@ -519,15 +519,14 @@ namespace swig
/**** The Ruby container methods ****/
%define %swig_container_methods(Container...)
%define %swig_container_printing_methods(Container...)
%extend {
VALUE inspect()
{
Container::iterator i = $self->begin();
Container::iterator e = $self->end();
Container::const_iterator i = $self->begin();
Container::const_iterator e = $self->end();
VALUE str = rb_str_new2( swig::type_name< Container >() );
str = rb_str_cat2( str, " [" );
bool comma = false;
@ -535,7 +534,7 @@ namespace swig
for ( ; i != e; ++i, comma = true )
{
if (comma) str = rb_str_cat2( str, "," );
tmp = swig::from<Container::value_type>( *i );
tmp = swig::from( *i );
tmp = rb_obj_as_string( tmp );
str = rb_str_buf_append( str, tmp );
}
@ -545,13 +544,13 @@ namespace swig
VALUE to_a()
{
Container::iterator i = $self->begin();
Container::iterator e = $self->end();
Container::const_iterator i = $self->begin();
Container::const_iterator e = $self->end();
VALUE ary = rb_ary_new2( std::distance( i, e ) );
VALUE tmp;
for ( ; i != e; ++i )
{
tmp = swig::from<Container::value_type>( *i );
tmp = swig::from( *i );
rb_ary_push( ary, tmp );
}
return ary;
@ -565,13 +564,16 @@ namespace swig
VALUE tmp;
for ( ; i != e; ++i )
{
tmp = swig::from<Container::value_type>( *i );
tmp = swig::from( *i );
tmp = rb_obj_as_string( tmp );
str = rb_str_buf_append( str, tmp );
}
return str;
}
}
}
%enddef
%define %swig_container_methods(Container...)
%enddef

View file

@ -132,8 +132,8 @@
}
%define %swig_map_common(Map...)
%swig_sequence_iterator(Map);
%swig_container_methods(Map)
// %swig_sequence_methods_common(Map);
// %swig_sequence_iterator(Map);
%extend {
VALUE __getitem__(const key_type& key) const {
@ -178,6 +178,23 @@
}
return ary;
}
Map* each_key()
{
if ( !rb_block_given_p() )
rb_raise( rb_eArgError, "no block given");
VALUE r;
Map::iterator i = self->begin();
Map::iterator e = self->end();
for ( ; i != e; ++i )
{
r = swig::from( i->first );
rb_yield(r);
}
return self;
}
VALUE values() {
Map::size_type size = self->size();
@ -197,6 +214,23 @@
return ary;
}
Map* each_value()
{
if ( !rb_block_given_p() )
rb_raise( rb_eArgError, "no block given");
VALUE r;
Map::iterator i = self->begin();
Map::iterator e = self->end();
for ( ; i != e; ++i )
{
r = swig::from( i->second );
rb_yield(r);
}
return self;
}
VALUE entries() {
Map::size_type size = self->size();
int rubysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
@ -210,7 +244,8 @@
Map::const_iterator i = self->begin();
Map::const_iterator e = self->end();
for ( ; i != e; ++i ) {
rb_ary_push( ary, swig::from(*i) );
rb_ary_push( ary, swig::from<std::pair<Map::key_type,
Map::mapped_type> >(*i) );
}
return ary;
}
@ -236,9 +271,65 @@
%define %swig_map_methods(Map...)
%swig_map_common(Map)
%extend {
void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) {
(*self)[key] = x;
}
VALUE inspect()
{
Map::const_iterator i = $self->begin();
Map::const_iterator e = $self->end();
VALUE str = rb_str_new2( swig::type_name< Map >() );
str = rb_str_cat2( str, " {" );
bool comma = false;
VALUE tmp;
for ( ; i != e; ++i, comma = true )
{
if (comma) str = rb_str_cat2( str, "," );
// @todo: improve -- this should just be swig::from(*i)
tmp = swig::from< std::pair<Map::key_type,
Map::mapped_type> >( *i );
tmp = rb_obj_as_string( tmp );
str = rb_str_buf_append( str, tmp );
}
str = rb_str_cat2( str, "}" );
return str;
}
VALUE to_a()
{
Map::const_iterator i = $self->begin();
Map::const_iterator e = $self->end();
VALUE ary = rb_ary_new2( std::distance( i, e ) );
VALUE tmp;
for ( ; i != e; ++i )
{
// @todo: improve -- this should just be swig::from(*i)
tmp = swig::from< std::pair<Map::key_type,
Map::mapped_type> >( *i );
rb_ary_push( ary, tmp );
}
return ary;
}
VALUE to_s()
{
Map::iterator i = $self->begin();
Map::iterator e = $self->end();
VALUE str = rb_str_new2( "" );
VALUE tmp;
for ( ; i != e; ++i )
{
// @todo: improve -- this should just be swig::from(*i)
tmp = swig::from< std::pair<Map::key_type,
Map::mapped_type> >( *i );
tmp = rb_obj_as_string( tmp );
str = rb_str_buf_append( str, tmp );
}
return str;
}
}
%enddef

View file

@ -85,11 +85,108 @@
}
}
%define %swig_multimap_methods(Type...)
%swig_map_common(Type);
%define %swig_multimap_methods(MultiMap...)
%swig_map_common(MultiMap);
%extend {
void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) {
self->insert(Type::value_type(key,x));
self->insert(MultiMap::value_type(key,x));
}
VALUE inspect()
{
MultiMap::iterator i = $self->begin();
MultiMap::iterator e = $self->end();
VALUE str = rb_str_new2( swig::type_name< MultiMap >() );
str = rb_str_cat2( str, " {" );
VALUE tmp;
while ( i != e )
{
const MultiMap::key_type& key = i->first;
const MultiMap::key_type& oldkey = key;
tmp = swig::from( key );
str = rb_str_buf_append( str, rb_inspect(tmp) );
VALUE vals = rb_ary_new();
for ( ; i != e && key == oldkey; ++i )
{
const MultiMap::mapped_type& val = i->second;
tmp = swig::from( val );
rb_ary_push( vals, tmp );
}
if ( RARRAY_LEN(vals) == 1 )
{
str = rb_str_buf_append( str, rb_inspect(tmp) );
}
else
{
str = rb_str_buf_append( str, rb_inspect(vals) );
}
}
str = rb_str_cat2( str, "}" );
return str;
}
VALUE to_a()
{
MultiMap::const_iterator i = $self->begin();
MultiMap::const_iterator e = $self->end();
VALUE ary = rb_ary_new2( std::distance( i, e ) );
VALUE tmp;
while ( i != e )
{
const MultiMap::key_type& key = i->first;
const MultiMap::key_type& oldkey = key;
tmp = swig::from( key );
rb_ary_push( ary, tmp );
VALUE vals = rb_ary_new();
for ( ; i != e && key == oldkey; ++i )
{
const MultiMap::mapped_type& val = i->second;
tmp = swig::from( val );
rb_ary_push( vals, tmp );
}
if ( RARRAY_LEN(vals) == 1 )
{
rb_ary_push( ary, tmp );
}
else
{
rb_ary_push( ary, vals );
}
}
return ary;
}
VALUE to_s()
{
MultiMap::iterator i = $self->begin();
MultiMap::iterator e = $self->end();
VALUE str = rb_str_new2( "" );
VALUE tmp;
while ( i != e )
{
const MultiMap::key_type& key = i->first;
const MultiMap::key_type& oldkey = key;
tmp = swig::from( key );
tmp = rb_obj_as_string( tmp );
str = rb_str_buf_append( str, tmp );
VALUE vals = rb_ary_new();
for ( ; i != e && key == oldkey; ++i )
{
const MultiMap::mapped_type& val = i->second;
tmp = swig::from( val );
rb_ary_push( vals, tmp );
}
tmp = rb_obj_as_string( vals );
str = rb_str_buf_append( str, tmp );
}
return str;
}
}
%enddef

View file

@ -91,7 +91,8 @@
}
} else {
value_type *p;
res = SWIG_ConvertPtr(obj,(void**)&p,swig::type_info<value_type>(),0);
res = SWIG_ConvertPtr(obj,(void**)&p,
swig::type_info<value_type>(),0);
if (SWIG_IsOK(res) && val) *val = p;
}
return res;
@ -146,8 +147,9 @@
%define %swig_pair_methods(pair...)
%extend {
VALUE inspect()
VALUE inspect() const
{
VALUE tmp;
VALUE str = rb_str_new2( swig::type_name< pair >() );
@ -163,7 +165,7 @@
return str;
}
VALUE to_s()
VALUE to_s() const
{
VALUE tmp;
VALUE str = rb_str_new2( "(" );

View file

@ -12,7 +12,7 @@ namespace std {
%traits_swigtype(T);
%traits_swigtype(U);
%fragment(SWIG_Traits_frag(std::pair<T,U >), "header",
fragment=SWIG_Traits_frag(T),
fragment=SWIG_Traits_frag(U),