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