~eda-qa/dhlib/main

1 by edA-qa mort-ora-y
first
1
/* <license>
2
 * This file is part of the dis-Emi-A HaXe Library. Copyright © edA-qa mort-ora-y
3
 * For full copyright and license information please refer to doc/license.txt.
4
 * </license> 
5
 */
6
#if flash9
7
import flash.utils.Dictionary;
8
#elseif neko
9
#elseif js
10
#else 
11
#error	//other targets not tested, though they might work with the default implementation
12
#end
13
14
/**
15
 * Implements an Object based mapping system.
16
 *
17
 * @see Hash -- shares the same functions but the keys are objects now
18
 * NOTE: has no toString function since the contain objects may not
19
 * have useful representations.
20
 *
21
 * NOTE for Neko/JS: In neko this works by adding an additional field to the hashed object.
22
 * This shouldn't change the use of most objects, but you must be aware of
23
 * this if you intend to add an array, or enumerable type, to the ObjectHash.
24
 * NOTE For Flash9: This implemented using the native Dictionary object since static
25
 * types cannot have arbitrary values created on them.  It is unfortunate that Flash9
26
 * doesn't have this ability, since if it did, I wouldn't likely need the ObjectHash at
27
 * all!
28
 *
29
 * NOTE on null: As with arrays and many other structures, the storage of nulls
30
 * is not really allowed.  They are generally the same as not existing, but in this
31
 * class the behaviour is undefined (and not allowed).
32
 */
33
class ObjectHash<T>
34
{
35
#if flash9
36
	var back : Dictionary;
37
#else
38
	var back : IntHash<T>;
39
	var keyMap : IntHash<Dynamic>;
40
	static var keyCount : Int = 1;
41
	
42
	//use a unique field name in case other people use the same technique
43
	define(`KEYFIELD',__uuid8476e280dcb411dc95ff0800200c9a66)
44
	inline function objKey( key : Dynamic ) : Int
45
	{
46
		if( key.KEYFIELD == null )
47
			key.KEYFIELD = keyCount++;
48
		return key.KEYFIELD;
49
	}
50
#end
51
52
	public function new() : Void 
53
	{
54
#if flash9
55
		back = new Dictionary( false );
56
#else
57
		back = new IntHash<T>();
58
		keyMap = new IntHash<Dynamic>();
59
#end
60
	}
61
	
62
	inline public function set( key : Dynamic, value : T ) : Void 
63
	{
64
		ASSERT_NOTNULL( value );
65
		ASSERT_NOTNULL( key );
66
#if flash9
67
		untyped back[key] = value;
68
#else
69
		back.set( objKey( key ), value );
70
		keyMap.set( objKey( key ), key );
71
#end
72
	}
73
	
74
	inline public function get( key : Dynamic ) : Null<T> 
75
	{	
76
		ASSERT_NOTNULL( key );
77
#if flash9
78
		return untyped back[key];
79
#else
80
		return back.get( objKey( key ) ); 
81
#end
82
	}
83
	
84
	inline public function exists( key : Dynamic ) : Bool 
85
	{
86
		ASSERT_NOTNULL( key );
87
#if flash9
88
		return untyped back[key] != null;
89
#else
90
		return back.exists( objKey( key ) );
91
#end
92
	}
93
		
94
	inline public function remove( key : Dynamic ) : Bool		
95
	{
96
		ASSERT_NOTNULL( key );
97
#if flash9
98
		if( untyped back[key] == null )
99
			return false;
100
		else
101
		{
102
			untyped __delete__(back,key);
103
			return true;
104
		}
105
#else
106
		keyMap.remove( objKey( key ) );
107
		return back.remove( objKey( key ) );
108
#end
109
	}
110
	
111
	public function keys() : Iterator<Dynamic>	
112
	{
113
#if flash9	
114
		return untyped (__keys__(back)).iterator();
115
#else
116
		return keyMap.iterator();
117
#end
118
	}
119
	
120
	public function iterator() : Iterator<T>
121
	{
122
#if flash9
123
		var me = this;
124
		return untyped 
125
		{
126
			keyIter : me.keys(),
127
			hasNext : function() 
128
				{ 
129
					return this.keyIter.hasNext(); 
130
				},
131
			next : function() 
132
				{ 
133
					var key = untyped this.keyIter.next(); 
134
					return me.get( key ); 
135
				}
136
		};
137
#else
138
		return back.iterator();
139
#end
140
	}
141
}