Mercurial > projects > dwt-addons
comparison dwtx/dwtxhelper/Collection.d @ 195:a4d38d47ddc4
HashMap support for null values and keys
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 03 Feb 2009 16:08:10 +0100 |
parents | 6d35b9960800 |
children | 489eb3f36068 |
comparison
equal
deleted
inserted
replaced
194:6d35b9960800 | 195:a4d38d47ddc4 |
---|---|
198 public void set(Object o); | 198 public void set(Object o); |
199 } | 199 } |
200 | 200 |
201 /////////////////////////////////////////////////////////////////////////////////////////////////// | 201 /////////////////////////////////////////////////////////////////////////////////////////////////// |
202 /////////////////////////////////////////////////////////////////////////////////////////////////// | 202 /////////////////////////////////////////////////////////////////////////////////////////////////// |
203 class MapEntry : Map.Entry { | 203 class MapEntry : Map.Entry { |
204 Map map; | 204 Map map; |
205 Object key; | 205 Object key; |
206 private this( Map map, Object key){ | 206 private this( Map map, Object key){ |
207 this.map = map; | 207 this.map = map; |
208 this.key = key; | 208 this.key = key; |
209 } | 209 } |
210 public override int opEquals(Object o){ | 210 public override int opEquals(Object o){ |
211 if( auto other = cast(MapEntry)o){ | 211 if( auto other = cast(MapEntry)o){ |
212 | 212 |
213 if(( getKey() is null ? other.getKey() is null : getKey() == other.getKey() ) && | 213 if(( getKey() is null ? other.getKey() is null : getKey() == other.getKey() ) && |
214 ( getValue() is null ? other.getValue() is null : getValue() == other.getValue() )){ | 214 ( getValue() is null ? other.getValue() is null : getValue() == other.getValue() )){ |
215 return true; | 215 return true; |
216 } | |
217 return false; | |
218 } | 216 } |
219 return false; | 217 return false; |
220 } | 218 } |
221 public Object getKey(){ | 219 return false; |
222 return key; | 220 } |
223 } | 221 public Object getKey(){ |
224 public Object getValue(){ | 222 return key; |
225 return map.get(key); | 223 } |
226 } | 224 public Object getValue(){ |
227 public override hash_t toHash(){ | 225 return map.get(key); |
228 return ( getKey() is null ? 0 : getKey().toHash() ) ^ | 226 } |
229 ( getValue() is null ? 0 : getValue().toHash() ); | 227 public override hash_t toHash(){ |
230 } | 228 return ( getKey() is null ? 0 : getKey().toHash() ) ^ |
231 public Object setValue(Object value){ | 229 ( getValue() is null ? 0 : getValue().toHash() ); |
232 return map.put( key, value ); | 230 } |
233 } | 231 public Object setValue(Object value){ |
234 | 232 return map.put( key, value ); |
235 } | 233 } |
234 | |
235 } | |
236 | |
237 private struct ObjRef { | |
238 Object obj; | |
239 static ObjRef opCall( Object obj ){ | |
240 ObjRef res; | |
241 res.obj = obj; | |
242 return res; | |
243 } | |
244 public hash_t toHash(){ | |
245 return obj is null ? 0 : obj.toHash(); | |
246 } | |
247 public int opEquals( ObjRef other ){ | |
248 return obj is null ? other.obj is null : obj.opEquals( other.obj ); | |
249 } | |
250 public int opEquals( Object other ){ | |
251 return obj is null ? other is null : obj.opEquals( other ); | |
252 } | |
253 } | |
236 | 254 |
237 class HashMap : Map { | 255 class HashMap : Map { |
238 //FIXME "NULL" is used to work around tango ticket 1468. | |
239 static Object NULL; | |
240 // The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls. | 256 // The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls. |
241 alias tango.util.container.HashMap.HashMap!(Object,Object) MapType; | 257 alias tango.util.container.HashMap.HashMap!(ObjRef,ObjRef) MapType; |
242 private MapType map; | 258 private MapType map; |
243 | 259 |
244 public this(){ | 260 public this(){ |
245 if( NULL is null ) NULL = new Object(); | |
246 map = new MapType(); | 261 map = new MapType(); |
247 } | 262 } |
248 public this(int initialCapacity){ | 263 public this(int initialCapacity){ |
249 this(); | 264 this(); |
250 } | 265 } |
251 public this(int initialCapacity, float loadFactor){ | 266 public this(int initialCapacity, float loadFactor){ |
252 if( NULL is null ) NULL = new Object(); | |
253 map = new MapType(loadFactor); | 267 map = new MapType(loadFactor); |
254 } | 268 } |
255 public this(Map m){ | 269 public this(Map m){ |
256 this(); | 270 this(); |
257 putAll(m); | 271 putAll(m); |
258 } | 272 } |
259 public void clear(){ | 273 public void clear(){ |
260 map.clear(); | 274 map.clear(); |
261 } | 275 } |
262 public bool containsKey(Object key){ | 276 public bool containsKey(Object key){ |
263 Object v; | 277 ObjRef v; |
264 return map.get(key, v ); | 278 ObjRef keyr = ObjRef(key); |
279 return map.get(keyr, v ); | |
265 } | 280 } |
266 public bool containsKey(String key){ | 281 public bool containsKey(String key){ |
267 return containsKey(stringcast(key)); | 282 return containsKey(stringcast(key)); |
268 } | 283 } |
269 public bool containsValue(Object value){ | 284 public bool containsValue(Object value){ |
270 Object v = (value is null) ? NULL : value; | 285 ObjRef valuer = ObjRef(value); |
271 return map.contains(v); | 286 return map.contains(valuer); |
272 } | 287 } |
273 public Set entrySet(){ | 288 public Set entrySet(){ |
274 HashSet res = new HashSet(); | 289 HashSet res = new HashSet(); |
275 foreach( k, v; map ){ | 290 foreach( k, v; map ){ |
276 res.add( new MapEntry(this,k)); | 291 res.add( new MapEntry(this,k.obj)); |
277 } | 292 } |
278 return res; | 293 return res; |
279 } | 294 } |
280 public override int opEquals(Object o){ | 295 public override int opEquals(Object o){ |
281 if( auto other = cast(HashMap) o ){ | 296 if( auto other = cast(HashMap) o ){ |
282 if( other.size() !is size() ){ | 297 if( other.size() !is size() ){ |
283 return false; | 298 return false; |
284 } | 299 } |
285 foreach( k, v; map ){ | 300 foreach( k, v; map ){ |
286 Object vo = other.get(k); | 301 auto vo = other.get(k.obj); |
287 if( v != vo ){ | 302 if( v != vo ){ |
288 return false; | 303 return false; |
289 } | 304 } |
290 } | 305 } |
291 return true; | 306 return true; |
292 } | 307 } |
293 return false; | 308 return false; |
294 } | 309 } |
295 public Object get(Object key){ | 310 public Object get(Object key){ |
296 if( auto v = key in map ){ | 311 ObjRef keyr = ObjRef(key); |
297 if( *v is NULL ) return null; | 312 if( auto v = keyr in map ){ |
298 return *v; | 313 return (*v).obj; |
299 } | 314 } |
300 return null; | 315 return null; |
301 } | 316 } |
302 public Object get(String key){ | 317 public Object get(String key){ |
303 return get(stringcast(key)); | 318 return get(stringcast(key)); |
309 return map.isEmpty(); | 324 return map.isEmpty(); |
310 } | 325 } |
311 public Set keySet(){ | 326 public Set keySet(){ |
312 HashSet res = new HashSet(); | 327 HashSet res = new HashSet(); |
313 foreach( k, v; map ){ | 328 foreach( k, v; map ){ |
314 res.add(k); | 329 res.add(k.obj); |
315 } | 330 } |
316 return res; | 331 return res; |
317 } | 332 } |
318 public Object put(Object key, Object value){ | 333 public Object put(Object key, Object value){ |
319 Object v = (value is null) ? NULL : value; | 334 ObjRef valuer = ObjRef(value); |
335 ObjRef keyr = ObjRef(key); | |
320 Object res = null; | 336 Object res = null; |
321 if( auto vold = key in map ){ | 337 if( auto vold = keyr in map ){ |
322 res = *vold; | 338 res = (*vold).obj; |
323 } | 339 } |
324 map[ key ] = v; | 340 map[ keyr ] = valuer; |
325 return res; | 341 return res; |
326 } | 342 } |
327 public Object put(String key, Object value){ | 343 public Object put(String key, Object value){ |
328 return put( stringcast(key), value ); | 344 return put( stringcast(key), value ); |
329 } | 345 } |
333 public Object put(String key, String value){ | 349 public Object put(String key, String value){ |
334 return put( stringcast(key), stringcast(value) ); | 350 return put( stringcast(key), stringcast(value) ); |
335 } | 351 } |
336 public void putAll(Map t){ | 352 public void putAll(Map t){ |
337 foreach( k, v; t ){ | 353 foreach( k, v; t ){ |
338 Object vi = (v is null) ? NULL : v; | 354 map[ObjRef(k)] = ObjRef(v); |
339 map[k] = vi; | |
340 } | 355 } |
341 } | 356 } |
342 public Object remove(Object key){ | 357 public Object remove(Object key){ |
343 if( auto v = key in map ){ | 358 ObjRef keyr = ObjRef(key); |
344 Object res = *v; | 359 if( auto v = keyr in map ){ |
345 map.remove(key); | 360 Object res = (*v).obj; |
346 if( res is NULL ) return null; | 361 map.remove(keyr); |
347 return res; | 362 return res; |
348 } | 363 } |
349 map.remove(key); | 364 map.remove(keyr); |
350 return null; | 365 return null; |
351 } | 366 } |
352 public Object remove(String key){ | 367 public Object remove(String key){ |
353 return remove(stringcast(key)); | 368 return remove(stringcast(key)); |
354 } | 369 } |
356 return map.size(); | 371 return map.size(); |
357 } | 372 } |
358 public Collection values(){ | 373 public Collection values(){ |
359 ArrayList res = new ArrayList( size() ); | 374 ArrayList res = new ArrayList( size() ); |
360 foreach( k, v; map ){ | 375 foreach( k, v; map ){ |
361 res.add( v ); | 376 res.add( v.obj ); |
362 } | 377 } |
363 return res; | 378 return res; |
364 } | 379 } |
365 | 380 |
366 public int opApply (int delegate(ref Object value) dg){ | 381 public int opApply (int delegate(ref Object value) dg){ |
367 return map.opApply( dg ); | 382 int ldg( ref ObjRef or ){ |
383 return dg( or.obj ); | |
384 } | |
385 return map.opApply( &ldg ); | |
368 } | 386 } |
369 public int opApply (int delegate(ref Object key, ref Object value) dg){ | 387 public int opApply (int delegate(ref Object key, ref Object value) dg){ |
370 return map.opApply( dg ); | 388 int ldg( ref ObjRef key, ref ObjRef value ){ |
389 return dg( key.obj, value.obj ); | |
390 } | |
391 return map.opApply( &ldg ); | |
371 } | 392 } |
372 | 393 |
373 } | 394 } |
374 | 395 |
375 class IdentityHashMap : Map { | 396 class IdentityHashMap : Map { |