| /* | |
| Multimaps | |
| */ | |
| %include <std_map.i> | |
| %fragment("StdMultimapTraits","header",fragment="StdMapCommonTraits") | |
| { | |
| namespace swig { | |
| template <class RubySeq, class K, class T > | |
| inline void | |
| assign(const RubySeq& rubyseq, std::multimap<K,T > *multimap) { | |
| typedef typename std::multimap<K,T>::value_type value_type; | |
| typename RubySeq::const_iterator it = rubyseq.begin(); | |
| for (;it != rubyseq.end(); ++it) { | |
| multimap->insert(value_type(it->first, it->second)); | |
| } | |
| } | |
| template <class K, class T> | |
| struct traits_asptr<std::multimap<K,T> > { | |
| typedef std::multimap<K,T> multimap_type; | |
| static int asptr(VALUE obj, std::multimap<K,T> **val) { | |
| int res = SWIG_ERROR; | |
| if ( TYPE(obj) == T_HASH ) { | |
| static ID id_to_a = rb_intern("to_a"); | |
| VALUE items = rb_funcall2(obj, id_to_a, 0, 0); | |
| return traits_asptr_stdseq<std::multimap<K,T>, std::pair<K, T> >::asptr(items, val); | |
| } else { | |
| multimap_type *p; | |
| res = SWIG_ConvertPtr(obj,(void**)&p,swig::type_info<multimap_type>(),0); | |
| if (SWIG_IsOK(res) && val) *val = p; | |
| } | |
| return res; | |
| } | |
| }; | |
| template <class K, class T > | |
| struct traits_from<std::multimap<K,T> > { | |
| typedef std::multimap<K,T> multimap_type; | |
| typedef typename multimap_type::const_iterator const_iterator; | |
| typedef typename multimap_type::size_type size_type; | |
| static VALUE from(const multimap_type& multimap) { | |
| swig_type_info *desc = swig::type_info<multimap_type>(); | |
| if (desc && desc->clientdata) { | |
| return SWIG_NewPointerObj(new multimap_type(multimap), desc, SWIG_POINTER_OWN); | |
| } else { | |
| size_type size = multimap.size(); | |
| int rubysize = (size <= (size_type) INT_MAX) ? (int) size : -1; | |
| if (rubysize < 0) { | |
| SWIG_RUBY_THREAD_BEGIN_BLOCK; | |
| rb_raise(rb_eRuntimeError, | |
| "multimap size not valid in Ruby"); | |
| SWIG_RUBY_THREAD_END_BLOCK; | |
| return Qnil; | |
| } | |
| VALUE obj = rb_hash_new(); | |
| for (const_iterator i= multimap.begin(); i!= multimap.end(); ++i) { | |
| VALUE key = swig::from(i->first); | |
| VALUE val = swig::from(i->second); | |
| VALUE oldval = rb_hash_aref( obj, key ); | |
| if ( oldval == Qnil ) | |
| rb_hash_aset(obj, key, val); | |
| else { | |
| // Multiple values for this key, create array if needed | |
| // and add a new element to it. | |
| VALUE ary; | |
| if ( TYPE(oldval) == T_ARRAY ) | |
| ary = oldval; | |
| else | |
| { | |
| ary = rb_ary_new2(2); | |
| rb_ary_push( ary, oldval ); | |
| rb_hash_aset( obj, key, ary ); | |
| } | |
| rb_ary_push( ary, val ); | |
| } | |
| } | |
| return obj; | |
| } | |
| } | |
| }; | |
| } | |
| } | |
| %define %swig_multimap_methods(MultiMap...) | |
| %swig_map_common(%arg(MultiMap)); | |
| %extend { | |
| VALUE __getitem__(const key_type& key) const { | |
| std::pair<MultiMap::const_iterator, MultiMap::const_iterator > r = $self->equal_range(key); | |
| if ( r.first != r.second ) | |
| { | |
| VALUE ary = rb_ary_new(); | |
| for (MultiMap::const_iterator i = r.first ; i != r.second; ++i ) | |
| { | |
| rb_ary_push( ary, swig::from<MultiMap::mapped_type>( i->second ) ); | |
| } | |
| if ( RARRAY_LEN(ary) == 1 ) | |
| return RARRAY_PTR(ary)[0]; | |
| return ary; | |
| } | |
| else | |
| return Qnil; | |
| } | |
| void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { | |
| self->insert(MultiMap::value_type(key,x)); | |
| } | |
| VALUE inspect() | |
| { | |
| MultiMap::iterator i = $self->begin(); | |
| MultiMap::iterator e = $self->end(); | |
| const char *type_name = swig::type_name< MultiMap >(); | |
| VALUE str = rb_str_new2( type_name ); | |
| 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) ); | |
| str = rb_str_cat2( str, "=>" ); | |
| 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 | |
| %mixin std::multimap "Enumerable"; | |
| %rename("delete") std::multimap::__delete__; | |
| %rename("reject!") std::multimap::reject_bang; | |
| %rename("map!") std::multimap::map_bang; | |
| %rename("empty?") std::multimap::empty; | |
| %rename("include?" ) std::multimap::__contains__ const; | |
| %rename("has_key?" ) std::multimap::has_key const; | |
| %alias std::multimap::push "<<"; | |
| %include <std/std_multimap.i> | |