Mercurial > projects > dwt-addons
comparison dwtx/core/internal/jobs/ObjectMap.d @ 122:9d0585bcb7aa
Add core.jobs package
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 12 Aug 2008 02:34:21 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
121:c0304616ea23 | 122:9d0585bcb7aa |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2006 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module dwtx.core.internal.jobs.ObjectMap; | |
14 | |
15 import dwt.dwthelper.utils; | |
16 import dwtx.dwtxhelper.Collection; | |
17 import dwtx.core.internal.jobs.StringPool; | |
18 | |
19 /** | |
20 * A specialized map implementation that is optimized for a small set of object | |
21 * keys. | |
22 * | |
23 * Implemented as a single array that alternates keys and values. | |
24 * | |
25 * Note: This class is copied from dwtx.core.resources | |
26 */ | |
27 public class ObjectMap : Map { | |
28 // 8 attribute keys, 8 attribute values | |
29 protected static const int DEFAULT_SIZE = 16; | |
30 protected static const int GROW_SIZE = 10; | |
31 protected int count = 0; | |
32 protected Object[] elements = null; | |
33 | |
34 /** | |
35 * Creates a new object map. | |
36 * | |
37 * @param initialCapacity | |
38 * The initial number of elements that will fit in the map. | |
39 */ | |
40 public this(int initialCapacity) { | |
41 if (initialCapacity > 0) | |
42 elements = new Object[Math.max(initialCapacity * 2, 0)]; | |
43 } | |
44 | |
45 /** | |
46 * Creates a new object map of the same size as the given map and populate | |
47 * it with the key/attribute pairs found in the map. | |
48 * | |
49 * @param map | |
50 * The entries in the given map will be added to the new map. | |
51 */ | |
52 public this(Map map) { | |
53 this(map.size()); | |
54 putAll(map); | |
55 } | |
56 | |
57 /** | |
58 * @see Map#clear() | |
59 */ | |
60 public void clear() { | |
61 elements = null; | |
62 count = 0; | |
63 } | |
64 | |
65 /** | |
66 * @see java.lang.Object#clone() | |
67 */ | |
68 public Object clone() { | |
69 return new ObjectMap(this); | |
70 } | |
71 | |
72 /** | |
73 * @see Map#containsKey(java.lang.Object) | |
74 */ | |
75 public bool containsKey(Object key) { | |
76 if (elements is null || count is 0) | |
77 return false; | |
78 for (int i = 0; i < elements.length; i = i + 2) | |
79 if (elements[i] !is null && elements[i].opEquals(key)) | |
80 return true; | |
81 return false; | |
82 } | |
83 public bool containsKey(String key) { | |
84 return containsKey(stringcast(key)); | |
85 } | |
86 /** | |
87 * @see Map#containsValue(java.lang.Object) | |
88 */ | |
89 public bool containsValue(Object value) { | |
90 if (elements is null || count is 0) | |
91 return false; | |
92 for (int i = 1; i < elements.length; i = i + 2) | |
93 if (elements[i] !is null && elements[i].opEquals(value)) | |
94 return true; | |
95 return false; | |
96 } | |
97 | |
98 /** | |
99 * @see Map#entrySet() | |
100 * | |
101 * Note: This implementation does not conform properly to the | |
102 * specification in the Map interface. The returned collection will not | |
103 * be bound to this map and will not remain in sync with this map. | |
104 */ | |
105 public Set entrySet() { | |
106 return count is 0 ? Collections.EMPTY_SET : toHashMap().entrySet(); | |
107 } | |
108 | |
109 /** | |
110 * @see Object#equals(java.lang.Object) | |
111 */ | |
112 public override int opEquals(Object o) { | |
113 if (!(cast(Map)o )) | |
114 return false; | |
115 Map other = cast(Map) o; | |
116 //must be same size | |
117 if (count !is other.size()) | |
118 return false; | |
119 //keysets must be equal | |
120 if (!(cast(Object)keySet()).opEquals(cast(Object)other.keySet())) | |
121 return false; | |
122 //values for each key must be equal | |
123 for (int i = 0; i < elements.length; i = i + 2) { | |
124 if (elements[i] !is null && (!elements[i + 1].opEquals(other.get(elements[i])))) | |
125 return false; | |
126 } | |
127 return true; | |
128 } | |
129 | |
130 /** | |
131 * @see Map#get(java.lang.Object) | |
132 */ | |
133 public Object get(Object key) { | |
134 if (elements is null || count is 0) | |
135 return null; | |
136 for (int i = 0; i < elements.length; i = i + 2) | |
137 if (elements[i] !is null && elements[i].opEquals(key)) | |
138 return elements[i + 1]; | |
139 return null; | |
140 } | |
141 public Object get(String key) { | |
142 return get(stringcast(key)); | |
143 } | |
144 | |
145 /** | |
146 * The capacity of the map has been exceeded, grow the array by GROW_SIZE to | |
147 * accomodate more entries. | |
148 */ | |
149 protected void grow() { | |
150 Object[] expanded = new Object[elements.length + GROW_SIZE]; | |
151 System.arraycopy(elements, 0, expanded, 0, elements.length); | |
152 elements = expanded; | |
153 } | |
154 | |
155 /** | |
156 * @see Object#hashCode() | |
157 */ | |
158 public override hash_t toHash() { | |
159 int hash = 0; | |
160 for (int i = 0; i < elements.length; i = i + 2) { | |
161 if (elements[i] !is null) { | |
162 hash += elements[i].toHash(); | |
163 } | |
164 } | |
165 return hash; | |
166 } | |
167 | |
168 /** | |
169 * @see Map#isEmpty() | |
170 */ | |
171 public bool isEmpty() { | |
172 return count is 0; | |
173 } | |
174 | |
175 /** | |
176 * Returns all keys in this table as an array. | |
177 */ | |
178 public String[] keys() { | |
179 String[] result = new String[count]; | |
180 int next = 0; | |
181 for (int i = 0; i < elements.length; i = i + 2) | |
182 if (elements[i] !is null) | |
183 result[next++] = stringcast( elements[i] ); | |
184 return result; | |
185 } | |
186 | |
187 /** | |
188 * @see Map#keySet() | |
189 * | |
190 * Note: This implementation does not conform properly to the | |
191 * specification in the Map interface. The returned collection will not | |
192 * be bound to this map and will not remain in sync with this map. | |
193 */ | |
194 public Set keySet() { | |
195 Set result = new HashSet(size()); | |
196 for (int i = 0; i < elements.length; i = i + 2) { | |
197 if (elements[i] !is null) { | |
198 result.add(elements[i]); | |
199 } | |
200 } | |
201 return result; | |
202 } | |
203 | |
204 /** | |
205 * @see Map#put(java.lang.Object, java.lang.Object) | |
206 */ | |
207 public Object put(Object key, Object value) { | |
208 if (key is null) | |
209 throw new NullPointerException(); | |
210 if (value is null) | |
211 return remove(key); | |
212 | |
213 // handle the case where we don't have any attributes yet | |
214 if (elements is null) | |
215 elements = new Object[DEFAULT_SIZE]; | |
216 if (count is 0) { | |
217 elements[0] = key; | |
218 elements[1] = value; | |
219 count++; | |
220 return null; | |
221 } | |
222 | |
223 int emptyIndex = -1; | |
224 // replace existing value if it exists | |
225 for (int i = 0; i < elements.length; i += 2) { | |
226 if (elements[i] !is null) { | |
227 if (elements[i].opEquals(key)) { | |
228 Object oldValue = elements[i + 1]; | |
229 elements[i + 1] = value; | |
230 return oldValue; | |
231 } | |
232 } else if (emptyIndex is -1) { | |
233 // keep track of the first empty index | |
234 emptyIndex = i; | |
235 } | |
236 } | |
237 // this will put the emptyIndex greater than the size but | |
238 // that's ok because we will grow first. | |
239 if (emptyIndex is -1) | |
240 emptyIndex = count * 2; | |
241 | |
242 // otherwise add it to the list of elements. | |
243 // grow if necessary | |
244 if (elements.length <= (count * 2)) | |
245 grow(); | |
246 elements[emptyIndex] = key; | |
247 elements[emptyIndex + 1] = value; | |
248 count++; | |
249 return null; | |
250 } | |
251 public Object put(String key, Object value) { | |
252 return put( stringcast(key), value ); | |
253 } | |
254 public Object put(Object key, String value) { | |
255 return put( key, stringcast(value) ); | |
256 } | |
257 public Object put(String key, String value) { | |
258 return put( stringcast(key), stringcast(value) ); | |
259 } | |
260 | |
261 /** | |
262 * @see Map#putAll(java.util.Map) | |
263 */ | |
264 public void putAll(Map map) { | |
265 for (Iterator i = map.keySet().iterator(); i.hasNext();) { | |
266 Object key = i.next(); | |
267 Object value = map.get(key); | |
268 put(key, value); | |
269 } | |
270 } | |
271 | |
272 /** | |
273 * @see Map#remove(java.lang.Object) | |
274 */ | |
275 public Object remove(Object key) { | |
276 if (elements is null || count is 0) | |
277 return null; | |
278 for (int i = 0; i < elements.length; i = i + 2) { | |
279 if (elements[i] !is null && elements[i].opEquals(key)) { | |
280 elements[i] = null; | |
281 Object result = elements[i + 1]; | |
282 elements[i + 1] = null; | |
283 count--; | |
284 return result; | |
285 } | |
286 } | |
287 return null; | |
288 } | |
289 public Object remove(String key) { | |
290 return remove( stringcast(key)); | |
291 } | |
292 | |
293 /* (non-Javadoc | |
294 * Method declared on IStringPoolParticipant | |
295 */ | |
296 public void shareStrings(StringPool set) { | |
297 //copy elements for thread safety | |
298 Object[] array = elements; | |
299 if (array is null) | |
300 return; | |
301 for (int i = 0; i < array.length; i++) { | |
302 Object o = array[i]; | |
303 if (cast(ArrayWrapperString)o ) | |
304 array[i] = stringcast(set.add(stringcast( o))); | |
305 } | |
306 } | |
307 | |
308 /** | |
309 * @see Map#size() | |
310 */ | |
311 public int size() { | |
312 return count; | |
313 } | |
314 | |
315 /** | |
316 * Creates a new hash map with the same contents as this map. | |
317 */ | |
318 private HashMap toHashMap() { | |
319 HashMap result = new HashMap(size()); | |
320 for (int i = 0; i < elements.length; i = i + 2) { | |
321 if (elements[i] !is null) { | |
322 result.put(elements[i], elements[i + 1]); | |
323 } | |
324 } | |
325 return result; | |
326 } | |
327 | |
328 /** | |
329 * @see Map#values() | |
330 * | |
331 * Note: This implementation does not conform properly to the | |
332 * specification in the Map interface. The returned collection will not | |
333 * be bound to this map and will not remain in sync with this map. | |
334 */ | |
335 public Collection values() { | |
336 Set result = new HashSet(size()); | |
337 for (int i = 1; i < elements.length; i = i + 2) { | |
338 if (elements[i] !is null) { | |
339 result.add(elements[i]); | |
340 } | |
341 } | |
342 return result; | |
343 } | |
344 | |
345 public int opApply (int delegate(ref Object value) dg){ | |
346 implMissing(__FILE__, __LINE__ ); | |
347 return 0; | |
348 } | |
349 public int opApply (int delegate(ref Object key, ref Object value) dg){ | |
350 implMissing(__FILE__, __LINE__ ); | |
351 return 0; | |
352 } | |
353 | |
354 } |