package org.eclipse.core.internal.resources;
import java.util.*;
import org.eclipse.core.internal.utils.IStringPoolParticipant;
import org.eclipse.core.internal.utils.StringPool;
@SuppressWarnings("unchecked")
public class MarkerAttributeMap<V> implements Map<String, V>, IStringPoolParticipant {
protected Object[] elements = null;
protected int count = 0;
protected static final int DEFAULT_SIZE = 16;
protected static final int GROW_SIZE = 10;
private static final Object[] EMPTY = new Object[0];
public MarkerAttributeMap() {
this(DEFAULT_SIZE);
}
public MarkerAttributeMap(int initialCapacity) {
elements = initialCapacity > 0 ? new Object[initialCapacity * 2] : EMPTY;
}
public MarkerAttributeMap(Map<String, ? extends V> map) {
this(map.size());
putAll(map);
}
@Override
public void clear() {
count = 0;
elements = EMPTY;
}
@Override
public boolean containsKey(Object key) {
if (count == 0)
return false;
key = ((String) key).intern();
for (int i = 0; i < elements.length; i = i + 2)
if (elements[i] == key)
return true;
return false;
}
@Override
public boolean containsValue(Object value) {
if (count == 0)
return false;
for (int i = 1; i < elements.length; i = i + 2)
if (elements[i] != null && elements[i].equals(value))
return true;
return false;
}
@Override
public Set<Entry<String, V>> entrySet() {
return toHashMap().entrySet();
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Map))
return false;
Map<String, V> other = (Map<String, V>) o;
if (count != other.size())
return false;
if (count == 0)
return true;
if (!keySet().equals(other.keySet()))
return false;
for (int i = 0; i < elements.length; i = i + 2) {
if (elements[i] != null && (!elements[i + 1].equals(other.get(elements[i]))))
return false;
}
return true;
}
@Override
public V get(Object key) {
if (count == 0)
return null;
key = ((String) key).intern();
for (int i = 0; i < elements.length; i = i + 2)
if (elements[i] == key)
return (V) elements[i + 1];
return null;
}
protected void grow() {
Object[] expanded = new Object[elements.length + GROW_SIZE];
System.arraycopy(elements, 0, expanded, 0, elements.length);
elements = expanded;
}
@Override
public int hashCode() {
int hash = 0;
if (count == 0)
return hash;
for (int i = 0; i < elements.length; i = i + 2) {
if (elements[i] != null) {
hash += elements[i].hashCode();
}
}
return hash;
}
@Override
public boolean isEmpty() {
return count == 0;
}
@Override
public Set<String> keySet() {
Set<String> result = new HashSet<>(size());
if (count == 0)
return result;
for (int i = 0; i < elements.length; i = i + 2) {
if (elements[i] != null) {
result.add((String) elements[i]);
}
}
return result;
}
@Override
public V put(String k, V value) {
if (k == null)
throw new NullPointerException();
if (value == null)
return remove(k);
String key = k.intern();
if (elements.length <= (count * 2))
grow();
if (count == 0) {
elements[0] = key;
elements[1] = value;
count++;
return null;
}
for (int i = 0; i < elements.length; i = i + 2) {
if (elements[i] == key) {
Object oldValue = elements[i + 1];
elements[i + 1] = value;
return (V) oldValue;
}
}
for (int i = 0; i < elements.length; i = i + 2) {
if (elements[i] == null) {
elements[i] = key;
elements[i + 1] = value;
count++;
return null;
}
}
return null;
}
@Override
public void putAll(Map<? extends String, ? extends V> map) {
for (Map.Entry<? extends String, ? extends V> e : map.entrySet())
put(e.getKey(), e.getValue());
}
@Override
public V remove(Object key) {
if (count == 0)
return null;
key = ((String) key).intern();
for (int i = 0; i < elements.length; i = i + 2) {
if (elements[i] == key) {
elements[i] = null;
Object result = elements[i + 1];
elements[i + 1] = null;
count--;
return (V) result;
}
}
return null;
}
@Override
public int size() {
return count;
}
@Override
public void shareStrings(StringPool set) {
Object[] array = elements;
if (array == null)
return;
for (int i = 1; i < array.length; i = i + 2) {
Object o = array[i];
if (o instanceof String)
array[i] = set.add((String) o);
else if (o instanceof IStringPoolParticipant)
((IStringPoolParticipant) o).shareStrings(set);
}
}
private HashMap<String, V> toHashMap() {
HashMap<String, V> result = new HashMap<>(size());
if (count == 0)
return result;
for (int i = 0; i < elements.length; i = i + 2) {
if (elements[i] != null) {
result.put((String) elements[i], (V) elements[i + 1]);
}
}
return result;
}
@Override
public Collection<V> values() {
Set<V> result = new HashSet<>(size());
if (count == 0)
return result;
for (int i = 1; i < elements.length; i = i + 2) {
if (elements[i] != null) {
result.add((V) elements[i]);
}
}
return result;
}
}