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 {