PageRenderTime 10ms CodeModel.GetById 2ms app.highlight 3ms RepoModel.GetById 2ms app.codeStats 0ms

/trunk/Lib/ruby/std_multimap.i

#
Swig | 227 lines | 200 code | 24 blank | 3 comment | 0 complexity | 14333228382c263b3bc6093805625988 MD5 | raw file
  1/*
  2  Multimaps
  3*/
  4%include <std_map.i>
  5
  6%fragment("StdMultimapTraits","header",fragment="StdSequenceTraits")
  7{
  8  namespace swig {
  9    template <class RubySeq, class K, class T >
 10    inline void 
 11    assign(const RubySeq& rubyseq, std::multimap<K,T > *multimap) {
 12      typedef typename std::multimap<K,T>::value_type value_type;
 13      typename RubySeq::const_iterator it = rubyseq.begin();
 14      for (;it != rubyseq.end(); ++it) {
 15	multimap->insert(value_type(it->first, it->second));
 16      }
 17    }
 18
 19    template <class K, class T>
 20    struct traits_asptr<std::multimap<K,T> >  {
 21      typedef std::multimap<K,T> multimap_type;
 22      static int asptr(VALUE obj, std::multimap<K,T> **val) {
 23	int res = SWIG_ERROR;
 24	if ( TYPE(obj) == T_HASH ) {
 25	  static ID id_to_a = rb_intern("to_a");
 26	  VALUE items = rb_funcall(obj, id_to_a, 0);
 27	  return traits_asptr_stdseq<std::multimap<K,T>, std::pair<K, T> >::asptr(items, val);
 28	} else {
 29	  multimap_type *p;
 30	  res = SWIG_ConvertPtr(obj,(void**)&p,swig::type_info<multimap_type>(),0);
 31	  if (SWIG_IsOK(res) && val)  *val = p;
 32	}
 33	return res;
 34      }
 35    };
 36      
 37    template <class K, class T >
 38    struct traits_from<std::multimap<K,T> >  {
 39      typedef std::multimap<K,T> multimap_type;
 40      typedef typename multimap_type::const_iterator const_iterator;
 41      typedef typename multimap_type::size_type size_type;
 42            
 43      static VALUE from(const multimap_type& multimap) {
 44	swig_type_info *desc = swig::type_info<multimap_type>();
 45	if (desc && desc->clientdata) {
 46	  return SWIG_NewPointerObj(new multimap_type(multimap), desc, SWIG_POINTER_OWN);
 47	} else {
 48	  size_type size = multimap.size();
 49	  int rubysize = (size <= (size_type) INT_MAX) ? (int) size : -1;
 50	  if (rubysize < 0) {
 51	    SWIG_RUBY_THREAD_BEGIN_BLOCK;
 52	    rb_raise(rb_eRuntimeError,
 53		     "multimap size not valid in Ruby");
 54	    SWIG_RUBY_THREAD_END_BLOCK;
 55	    return Qnil;
 56	  }
 57	  VALUE obj = rb_hash_new();
 58	  for (const_iterator i= multimap.begin(); i!= multimap.end(); ++i) {
 59	    VALUE key = swig::from(i->first);
 60	    VALUE val = swig::from(i->second);
 61
 62	    VALUE oldval = rb_hash_aref( obj, key );
 63	    if ( oldval == Qnil )
 64	      rb_hash_aset(obj, key, val);
 65	    else {
 66	      // Multiple values for this key, create array if needed
 67	      // and add a new element to it.
 68	      VALUE ary;
 69	      if ( TYPE(oldval) == T_ARRAY )
 70		ary = oldval;
 71	      else
 72		{
 73		  ary = rb_ary_new2(2);
 74		  rb_ary_push( ary, oldval );
 75		  rb_hash_aset( obj, key, ary );
 76		}
 77	      rb_ary_push( ary, val );
 78	    }
 79	    
 80	  }
 81	  return obj;
 82	}
 83      }
 84    };
 85  }
 86}
 87
 88%define %swig_multimap_methods(MultiMap...) 
 89  %swig_map_common(%arg(MultiMap));
 90
 91  %extend {
 92    VALUE __getitem__(const key_type& key) const {
 93      MultiMap::const_iterator i = self->find(key);
 94      if ( i != self->end() )
 95	{
 96	  MultiMap::const_iterator e = $self->upper_bound(key);
 97	  VALUE ary = rb_ary_new();
 98	  for ( ; i != e; ++i )
 99	    {
100	      rb_ary_push( ary, swig::from<MultiMap::mapped_type>( i->second ) );
101	    }
102	  if ( RARRAY_LEN(ary) == 1 )
103	    return RARRAY_PTR(ary)[0];
104	  return ary;
105	}
106      else
107	return Qnil;
108    }
109
110    void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) {
111      self->insert(MultiMap::value_type(key,x));
112    }
113
114  VALUE inspect()
115    {
116      MultiMap::iterator i = $self->begin();
117      MultiMap::iterator e = $self->end();
118      const char *type_name = swig::type_name< MultiMap >();
119      VALUE str = rb_str_new2( type_name );
120      str = rb_str_cat2( str, " {" );
121      VALUE tmp;
122      while ( i != e )
123	{
124	  const MultiMap::key_type& key    = i->first;
125	  const MultiMap::key_type& oldkey = key;
126	  tmp = swig::from( key );
127	  str = rb_str_buf_append( str, rb_inspect(tmp) );
128	  str = rb_str_cat2( str, "=>" );
129
130	  VALUE vals = rb_ary_new();
131	  for ( ; i != e && key == oldkey; ++i )
132	    {
133	      const MultiMap::mapped_type& val = i->second;
134	      tmp = swig::from( val );
135	      rb_ary_push( vals, tmp );
136	    }
137
138	  if ( RARRAY_LEN(vals) == 1 )
139	    {
140	      str = rb_str_buf_append( str, rb_inspect(tmp) );
141	    }
142	  else
143	    {
144	      str = rb_str_buf_append( str, rb_inspect(vals) );
145	    }
146	}
147      str = rb_str_cat2( str, "}" );
148      return str;
149    }
150
151  VALUE to_a()
152    {
153      MultiMap::const_iterator i = $self->begin();
154      MultiMap::const_iterator e = $self->end();
155      VALUE ary = rb_ary_new2( std::distance( i, e ) );
156      VALUE tmp;
157      while ( i != e )
158	{
159	  const MultiMap::key_type& key    = i->first;
160	  const MultiMap::key_type& oldkey = key;
161	  tmp = swig::from( key );
162	  rb_ary_push( ary, tmp );
163
164	  VALUE vals = rb_ary_new();
165	  for ( ; i != e && key == oldkey; ++i )
166	    {
167	      const MultiMap::mapped_type& val = i->second;
168	      tmp = swig::from( val );
169	      rb_ary_push( vals, tmp );
170	    }
171
172	  if ( RARRAY_LEN(vals) == 1 )
173	    {
174	      rb_ary_push( ary, tmp );
175	    }
176	  else
177	    {
178	      rb_ary_push( ary, vals );
179	    }
180	}
181      return ary;
182    }
183
184  VALUE to_s()
185    {
186      MultiMap::iterator i = $self->begin();
187      MultiMap::iterator e = $self->end();
188      VALUE str = rb_str_new2( "" );
189      VALUE tmp;
190      while ( i != e )
191	{
192	  const MultiMap::key_type& key    = i->first;
193	  const MultiMap::key_type& oldkey = key;
194	  tmp = swig::from( key );
195	  tmp = rb_obj_as_string( tmp );
196	  str = rb_str_buf_append( str, tmp );
197
198	  VALUE vals = rb_ary_new();
199	  for ( ; i != e && key == oldkey; ++i )
200	    {
201	      const MultiMap::mapped_type& val = i->second;
202	      tmp = swig::from( val );
203	      rb_ary_push( vals, tmp );
204	    }
205
206	  tmp = rb_obj_as_string( vals );
207	  str = rb_str_buf_append( str, tmp );
208	}
209      return str;
210    }
211  }
212%enddef
213
214
215%mixin std::multimap "Enumerable";
216
217%rename("delete")     std::multimap::__delete__;
218%rename("reject!")    std::multimap::reject_bang;
219%rename("map!")       std::multimap::map_bang;
220%rename("empty?")     std::multimap::empty;
221%rename("include?" )  std::multimap::__contains__ const;
222%rename("has_key?" )  std::multimap::has_key const;
223
224%alias  std::multimap::push          "<<";
225
226%include <std/std_multimap.i>
227