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 }