platform35/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/MarkerSet.java
changeset 40 eb3c938c7fef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform35/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/MarkerSet.java	Thu Jul 30 11:56:23 2009 -0500
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.internal.resources;
+
+import org.eclipse.core.internal.utils.IStringPoolParticipant;
+import org.eclipse.core.internal.utils.StringPool;
+
+public class MarkerSet implements Cloneable, IStringPoolParticipant {
+	protected static final int MINIMUM_SIZE = 5;
+	protected int elementCount = 0;
+	protected IMarkerSetElement[] elements;
+
+	public MarkerSet() {
+		this(MINIMUM_SIZE);
+	}
+
+	public MarkerSet(int capacity) {
+		super();
+		this.elements = new IMarkerSetElement[Math.max(MINIMUM_SIZE, capacity * 2)];
+	}
+
+	public void add(IMarkerSetElement element) {
+		if (element == null)
+			return;
+		int hash = hashFor(element.getId()) % elements.length;
+
+		// search for an empty slot at the end of the array
+		for (int i = hash; i < elements.length; i++) {
+			if (elements[i] == null) {
+				elements[i] = element;
+				elementCount++;
+				// grow if necessary
+				if (shouldGrow())
+					expand();
+				return;
+			}
+		}
+
+		// search for an empty slot at the beginning of the array
+		for (int i = 0; i < hash - 1; i++) {
+			if (elements[i] == null) {
+				elements[i] = element;
+				elementCount++;
+				// grow if necessary
+				if (shouldGrow())
+					expand();
+				return;
+			}
+		}
+
+		// if we didn't find a free slot, then try again with the expanded set
+		expand();
+		add(element);
+	}
+
+	public void addAll(IMarkerSetElement[] toAdd) {
+		for (int i = 0; i < toAdd.length; i++)
+			add(toAdd[i]);
+	}
+
+	protected Object clone() {
+		try {
+			MarkerSet copy = (MarkerSet) super.clone();
+			//copy the attribute array
+			copy.elements = (IMarkerSetElement[]) elements.clone();
+			return copy;
+		} catch (CloneNotSupportedException e) {
+			//cannot happen because this class implements Cloneable
+			return null;
+		}
+	}
+
+	public boolean contains(long id) {
+		return get(id) != null;
+	}
+
+	public IMarkerSetElement[] elements() {
+		IMarkerSetElement[] result = new IMarkerSetElement[elementCount];
+		int j = 0;
+		for (int i = 0; i < elements.length; i++) {
+			IMarkerSetElement element = elements[i];
+			if (element != null)
+				result[j++] = element;
+		}
+		return result;
+	}
+
+	/**
+	 * The array isn't large enough so double its size and rehash
+	 * all its current values.
+	 */
+	protected void expand() {
+		IMarkerSetElement[] array = new IMarkerSetElement[elements.length * 2];
+		int maxArrayIndex = array.length - 1;
+		for (int i = 0; i < elements.length; i++) {
+			IMarkerSetElement element = elements[i];
+			if (element != null) {
+				int hash = hashFor(element.getId()) % array.length;
+				while (array[hash] != null) {
+					hash++;
+					if (hash > maxArrayIndex)
+						hash = 0;
+				}
+				array[hash] = element;
+			}
+		}
+		elements = array;
+	}
+
+	/**
+	 * Returns the set element with the given id, or null
+	 * if not found.
+	 */
+	public IMarkerSetElement get(long id) {
+		if (elementCount == 0)
+			return null;
+		int hash = hashFor(id) % elements.length;
+
+		// search the last half of the array
+		for (int i = hash; i < elements.length; i++) {
+			IMarkerSetElement element = elements[i];
+			if (element == null)
+				return null;
+			if (element.getId() == id)
+				return element;
+		}
+
+		// search the beginning of the array
+		for (int i = 0; i < hash - 1; i++) {
+			IMarkerSetElement element = elements[i];
+			if (element == null)
+				return null;
+			if (element.getId() == id)
+				return element;
+		}
+
+		// marker info not found so return null
+		return null;
+	}
+
+	private int hashFor(long id) {
+		return Math.abs((int) id);
+	}
+
+	public boolean isEmpty() {
+		return elementCount == 0;
+	}
+
+	/**
+	 * The element at the given index has been removed so move
+	 * elements to keep the set properly hashed.
+	 */
+	protected void rehashTo(int anIndex) {
+
+		int target = anIndex;
+		int index = anIndex + 1;
+		if (index >= elements.length)
+			index = 0;
+		IMarkerSetElement element = elements[index];
+		while (element != null) {
+			int hashIndex = hashFor(element.getId()) % elements.length;
+			boolean match;
+			if (index < target)
+				match = !(hashIndex > target || hashIndex <= index);
+			else
+				match = !(hashIndex > target && hashIndex <= index);
+			if (match) {
+				elements[target] = element;
+				target = index;
+			}
+			index++;
+			if (index >= elements.length)
+				index = 0;
+			element = elements[index];
+		}
+		elements[target] = null;
+	}
+
+	public void remove(long id) {
+		int hash = hashFor(id) % elements.length;
+
+		for (int i = hash; i < elements.length; i++) {
+			IMarkerSetElement element = elements[i];
+			if (element == null)
+				return;
+			if (element.getId() == id) {
+				rehashTo(i);
+				elementCount--;
+			}
+		}
+
+		for (int i = 0; i < hash - 1; i++) {
+			IMarkerSetElement element = elements[i];
+			if (element == null)
+				return;
+			if (element.getId() == id) {
+				rehashTo(i);
+				elementCount--;
+			}
+		}
+	}
+
+	public void remove(IMarkerSetElement element) {
+		remove(element.getId());
+	}
+
+	public void removeAll(IMarkerSetElement[] toRemove) {
+		for (int i = 0; i < toRemove.length; i++)
+			remove(toRemove[i]);
+	}
+
+	private boolean shouldGrow() {
+		return elementCount > elements.length * 0.75;
+	}
+
+	public int size() {
+		return elementCount;
+	}
+
+	/* (non-Javadoc
+	 * Method declared on IStringPoolParticipant
+	 */
+	public void shareStrings(StringPool set) {
+		//copy elements for thread safety
+		Object[] array = elements;
+		if (array == null)
+			return;
+		for (int i = 0; i < array.length; i++) {
+			Object o = array[i];
+			if (o instanceof String)
+				array[i] = set.add((String) o);
+			if (o instanceof IStringPoolParticipant)
+				((IStringPoolParticipant) o).shareStrings(set);
+		}
+	}
+}