1 // 2 // Maps 3 // 4 %fragment("StdMapCommonTraits","header",fragment="StdSequenceTraits") 5 { 6 namespace swig { 7 template <class ValueType> 8 struct from_key_oper 9 { 10 typedef const ValueType& argument_type; 11 typedef VALUE result_type; 12 result_type operator()(argument_type v) const 13 { 14 return swig::from(v.first); 15 } 16 }; 17 18 template <class ValueType> 19 struct from_value_oper 20 { 21 typedef const ValueType& argument_type; 22 typedef VALUE result_type; 23 result_type operator()(argument_type v) const 24 { 25 return swig::from(v.second); 26 } 27 }; 28 29 template<class OutIterator, class FromOper, 30 class ValueType = typename OutIterator::value_type> 31 struct MapIterator_T : ConstIteratorClosed_T<OutIterator, ValueType, FromOper> 32 { 33 MapIterator_T(OutIterator curr, OutIterator first, OutIterator last, VALUE seq) 34 : ConstIteratorClosed_T<OutIterator,ValueType,FromOper>(curr, first, last, seq) 35 { 36 } 37 }; 38 39 40 template<class OutIterator, 41 class FromOper = from_key_oper<typename OutIterator::value_type> > 42 struct MapKeyIterator_T : MapIterator_T<OutIterator, FromOper> 43 { 44 MapKeyIterator_T(OutIterator curr, OutIterator first, OutIterator last, VALUE seq) 45 : MapIterator_T<OutIterator, FromOper>(curr, first, last, seq) 46 { 47 } 48 }; 49 50 template<typename OutIter> 51 inline ConstIterator* 52 make_output_key_iterator(const OutIter& current, const OutIter& begin, 53 const OutIter& end, VALUE seq = 0) 54 { 55 return new MapKeyIterator_T<OutIter>(current, begin, end, seq); 56 } 57 58 template<class OutIterator, 59 class FromOper = from_value_oper<typename OutIterator::value_type> > 60 struct MapValueIterator_T : MapIterator_T<OutIterator, FromOper> 61 { 62 MapValueIterator_T(OutIterator curr, OutIterator first, OutIterator last, VALUE seq) 63 : MapIterator_T<OutIterator, FromOper>(curr, first, last, seq) 64 { 65 } 66 }; 67 68 69 template<typename OutIter> 70 inline ConstIterator* 71 make_output_value_iterator(const OutIter& current, const OutIter& begin, 72 const OutIter& end, VALUE seq = 0) 73 { 74 return new MapValueIterator_T<OutIter>(current, begin, end, seq); 75 } 76 } 77 } 78 79 %fragment("StdMapTraits","header",fragment="StdMapCommonTraits") 80 { 81 namespace swig { 82 template <class RubySeq, class K, class T > 83 inline void 84 assign(const RubySeq& rubyseq, std::map<K,T > *map) { 85 typedef typename std::map<K,T>::value_type value_type; 86 typename RubySeq::const_iterator it = rubyseq.begin(); 87 for (;it != rubyseq.end(); ++it) { 88 map->insert(value_type(it->first, it->second)); 89 } 90 } 91 92 template <class K, class T> 93 struct traits_asptr<std::map<K,T> > { 94 typedef std::map<K,T> map_type; 95 static int asptr(VALUE obj, map_type **val) { 96 int res = SWIG_ERROR; 97 if ( TYPE(obj) == T_HASH ) { 98 static ID id_to_a = rb_intern("to_a"); 99 VALUE items = rb_funcall(obj, id_to_a, 0); 100 res = traits_asptr_stdseq<std::map<K,T>, std::pair<K, T> >::asptr(items, val); 101 } else { 102 map_type *p; 103 res = SWIG_ConvertPtr(obj,(void**)&p,swig::type_info<map_type>(),0); 104 if (SWIG_IsOK(res) && val) *val = p; 105 } 106 return res; 107 } 108 }; 109 110 template <class K, class T > 111 struct traits_from<std::map<K,T> > { 112 typedef std::map<K,T> map_type; 113 typedef typename map_type::const_iterator const_iterator; 114 typedef typename map_type::size_type size_type; 115 116 static VALUE from(const map_type& map) { 117 swig_type_info *desc = swig::type_info<map_type>(); 118 if (desc && desc->clientdata) { 119 return SWIG_NewPointerObj(new map_type(map), desc, SWIG_POINTER_OWN); 120 } else { 121 size_type size = map.size(); 122 int rubysize = (size <= (size_type) INT_MAX) ? (int) size : -1; 123 if (rubysize < 0) { 124 SWIG_RUBY_THREAD_BEGIN_BLOCK; 125 rb_raise( rb_eRuntimeError, "map size not valid in Ruby"); 126 SWIG_RUBY_THREAD_END_BLOCK; 127 return Qnil; 128 } 129 VALUE obj = rb_hash_new(); 130 for (const_iterator i= map.begin(); i!= map.end(); ++i) { 131 VALUE key = swig::from(i->first); 132 VALUE val = swig::from(i->second); 133 rb_hash_aset(obj, key, val); 134 } 135 return obj; 136 } 137 } 138 }; 139 } 140 } 141 142 %define %swig_map_common(Map...) 143 %swig_container_methods(%arg(Map)); 144 // %swig_sequence_iterator(%arg(Map)); 145 146 %extend { 147 148 VALUE __delete__(const key_type& key) { 149 Map::iterator i = self->find(key); 150 if (i != self->end()) { 151 self->erase(i); 152 return swig::from( key ); 153 } 154 else { 155 return Qnil; 156 } 157 } 158 159 bool has_key(const key_type& key) const { 160 Map::const_iterator i = self->find(key); 161 return i != self->end(); 162 } 163 164 VALUE keys() { 165 Map::size_type size = self->size(); 166 int rubysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; 167 if (rubysize < 0) { 168 SWIG_RUBY_THREAD_BEGIN_BLOCK; 169 rb_raise(rb_eRuntimeError, "map size not valid in Ruby"); 170 SWIG_RUBY_THREAD_END_BLOCK; 171 return Qnil; 172 } 173 VALUE ary = rb_ary_new2(rubysize); 174 Map::const_iterator i = self->begin(); 175 Map::const_iterator e = self->end(); 176 for ( ; i != e; ++i ) { 177 rb_ary_push( ary, swig::from(i->first) ); 178 } 179 return ary; 180 } 181 182 Map* each() 183 { 184 if ( !rb_block_given_p() ) 185 rb_raise( rb_eArgError, "no block given"); 186 187 VALUE k, v; 188 Map::iterator i = self->begin(); 189 Map::iterator e = self->end(); 190 for ( ; i != e; ++i ) 191 { 192 const Map::key_type& key = i->first; 193 const Map::mapped_type& val = i->second; 194 195 k = swig::from<Map::key_type>(key); 196 v = swig::from<Map::mapped_type>(val); 197 rb_yield_values(2, k, v); 198 } 199 200 return self; 201 } 202 203 %newobject select; 204 Map* select() { 205 if ( !rb_block_given_p() ) 206 rb_raise( rb_eArgError, "no block given" ); 207 208 Map* r = new Map; 209 Map::iterator i = $self->begin(); 210 Map::iterator e = $self->end(); 211 for ( ; i != e; ++i ) 212 { 213 VALUE k = swig::from<Map::key_type>(i->first); 214 VALUE v = swig::from<Map::mapped_type>(i->second); 215 if ( RTEST( rb_yield_values(2, k, v) ) ) 216 $self->insert(r->end(), *i); 217 } 218 219 return r; 220 } 221 222 %typemap(in) (int argc, VALUE* argv) { 223 $1 = argc; 224 $2 = argv; 225 } 226 227 VALUE values_at(int argc, VALUE* argv, ...) { 228 229 VALUE r = rb_ary_new(); 230 ID id = rb_intern("[]"); 231 swig_type_info* type = swig::type_info< Map >(); 232 VALUE me = SWIG_NewPointerObj( $self, type, 0 ); 233 for ( int i = 0; i < argc; ++i ) 234 { 235 VALUE key = argv[i]; 236 VALUE tmp = rb_funcall( me, id, 1, key ); 237 rb_ary_push( r, tmp ); 238 } 239 240 return r; 241 } 242 243 244 Map* each_key() 245 { 246 if ( !rb_block_given_p() ) 247 rb_raise( rb_eArgError, "no block given"); 248 249 VALUE r; 250 Map::iterator i = self->begin(); 251 Map::iterator e = self->end(); 252 for ( ; i != e; ++i ) 253 { 254 r = swig::from( i->first ); 255 rb_yield(r); 256 } 257 258 return self; 259 } 260 261 VALUE values() { 262 Map::size_type size = self->size(); 263 int rubysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; 264 if (rubysize < 0) { 265 SWIG_RUBY_THREAD_BEGIN_BLOCK; 266 rb_raise(rb_eRuntimeError, "map size not valid in Ruby"); 267 SWIG_RUBY_THREAD_END_BLOCK; 268 return Qnil; 269 } 270 VALUE ary = rb_ary_new2(rubysize); 271 Map::const_iterator i = self->begin(); 272 Map::const_iterator e = self->end(); 273 for ( ; i != e; ++i ) { 274 rb_ary_push( ary, swig::from(i->second) ); 275 } 276 return ary; 277 } 278 279 Map* each_value() 280 { 281 if ( !rb_block_given_p() ) 282 rb_raise( rb_eArgError, "no block given"); 283 284 VALUE r; 285 Map::iterator i = self->begin(); 286 Map::iterator e = self->end(); 287 for ( ; i != e; ++i ) 288 { 289 r = swig::from( i->second ); 290 rb_yield(r); 291 } 292 293 return self; 294 } 295 296 VALUE entries() { 297 Map::size_type size = self->size(); 298 int rubysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1; 299 if (rubysize < 0) { 300 SWIG_RUBY_THREAD_BEGIN_BLOCK; 301 rb_raise(rb_eRuntimeError, "map size not valid in Ruby"); 302 SWIG_RUBY_THREAD_END_BLOCK; 303 return Qnil; 304 } 305 VALUE ary = rb_ary_new2(rubysize); 306 Map::const_iterator i = self->begin(); 307 Map::const_iterator e = self->end(); 308 for ( ; i != e; ++i ) { 309 rb_ary_push( ary, swig::from<std::pair<Map::key_type, 310 Map::mapped_type> >(*i) ); 311 } 312 return ary; 313 } 314 315 bool __contains__(const key_type& key) { 316 return self->find(key) != self->end(); 317 } 318 319 %newobject key_iterator(VALUE *RUBY_SELF); 320 swig::ConstIterator* key_iterator(VALUE *RUBY_SELF) { 321 return swig::make_output_key_iterator($self->begin(), $self->begin(), 322 $self->end(), *RUBY_SELF); 323 } 324 325 %newobject value_iterator(VALUE *RUBY_SELF); 326 swig::ConstIterator* value_iterator(VALUE *RUBY_SELF) { 327 return swig::make_output_value_iterator($self->begin(), $self->begin(), 328 $self->end(), *RUBY_SELF); 329 } 330 331 } 332 %enddef 333 334 %define %swig_map_methods(Map...) 335 %swig_map_common(Map) 336 %extend { 337 VALUE __getitem__(const key_type& key) const { 338 Map::const_iterator i = self->find(key); 339 if ( i != self->end() ) 340 return swig::from<Map::mapped_type>( i->second ); 341 else 342 return Qnil; 343 } 344 345 void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { 346 (*self)[key] = x; 347 } 348 349 VALUE inspect() 350 { 351 Map::const_iterator i = $self->begin(); 352 Map::const_iterator e = $self->end(); 353 const char *type_name = swig::type_name< Map >(); 354 VALUE str = rb_str_new2( type_name ); 355 str = rb_str_cat2( str, " {" ); 356 bool comma = false; 357 VALUE tmp; 358 for ( ; i != e; ++i, comma = true ) 359 { 360 if (comma) str = rb_str_cat2( str, "," ); 361 tmp = swig::from< Map::key_type >( i->first ); 362 tmp = rb_inspect( tmp ); 363 str = rb_str_buf_append( str, tmp ); 364 str = rb_str_cat2( str, "=>" ); 365 tmp = swig::from< Map::mapped_type >( i->second ); 366 tmp = rb_inspect( tmp ); 367 str = rb_str_buf_append( str, tmp ); 368 } 369 str = rb_str_cat2( str, "}" ); 370 return str; 371 } 372 373 VALUE to_a() 374 { 375 Map::const_iterator i = $self->begin(); 376 Map::const_iterator e = $self->end(); 377 VALUE ary = rb_ary_new2( std::distance( i, e ) ); 378 VALUE tmp; 379 for ( ; i != e; ++i ) 380 { 381 // @todo: improve -- this should just be swig::from(*i) 382 tmp = swig::from< std::pair<Map::key_type, 383 Map::mapped_type> >( *i ); 384 rb_ary_push( ary, tmp ); 385 } 386 return ary; 387 } 388 389 VALUE to_s() 390 { 391 Map::iterator i = $self->begin(); 392 Map::iterator e = $self->end(); 393 VALUE str = rb_str_new2( "" ); 394 VALUE tmp; 395 for ( ; i != e; ++i ) 396 { 397 // @todo: improve -- this should just be swig::from(*i) 398 tmp = swig::from< std::pair<Map::key_type, 399 Map::mapped_type> >( *i ); 400 tmp = rb_obj_as_string( tmp ); 401 str = rb_str_buf_append( str, tmp ); 402 } 403 return str; 404 } 405 406 } 407 %enddef 408 409 410 %mixin std::map "Enumerable"; 411 412 413 %rename("delete") std::map::__delete__; 414 %rename("reject!") std::map::reject_bang; 415 %rename("map!") std::map::map_bang; 416 %rename("empty?") std::map::empty; 417 %rename("include?" ) std::map::__contains__ const; 418 %rename("has_key?" ) std::map::has_key const; 419 420 %alias std::map::push "<<"; 421 422 423 %include <std/std_map.i> 424