/* * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.util.keyFMap; import com.intellij.openapi.util.Key; import org.jetbrains.annotations.NotNull; class ArrayBackedFMap implements KeyFMap { static final int ARRAY_THRESHOLD = 8; private final int[] keys; private final Object[] values; ArrayBackedFMap(@NotNull int[] keys, @NotNull Object[] values) { this.keys = keys; this.values = values; } @NotNull @Override public <V> KeyFMap plus(@NotNull Key<V> key, @NotNull V value) { int oldSize = size(); int keyCode = key.hashCode(); int[] newKeys = null; Object[] newValues = null; int i; for (i = 0; i < oldSize; i++) { int oldKey = keys[i]; if (keyCode == oldKey) { if (value == values[i]) return this; newKeys = new int[oldSize]; newValues = new Object[oldSize]; System.arraycopy(keys, 0, newKeys, 0, oldSize); System.arraycopy(values, 0, newValues, 0, oldSize); newValues[i] = value; break; } } if (i == oldSize) { if (oldSize == ARRAY_THRESHOLD) { return new MapBackedFMap(keys, keyCode, values, value); } int newSize = oldSize + 1; newKeys = new int[newSize]; newValues = new Object[newSize]; System.arraycopy(keys, 0, newKeys, 0, oldSize); System.arraycopy(values, 0, newValues, 0, oldSize); newKeys[oldSize] = keyCode; newValues[oldSize] = value; } return new ArrayBackedFMap(newKeys, newValues); } private int size() { return keys.length; } @NotNull @Override public KeyFMap minus(@NotNull Key<?> key) { int oldSize = size(); int keyCode = key.hashCode(); for (int i = 0; i< oldSize; i++) { int oldKey = keys[i]; if (keyCode == oldKey) { if (oldSize == 3) { int i1 = (2-i)/2; int i2 = 3 - (i+2)/2; return new PairElementsFMap(keys[i1], values[i1], keys[i2], values[i2]); } int newSize = oldSize - 1; int[] newKeys = new int[newSize]; Object[] newValues = new Object[newSize]; System.arraycopy(keys, 0, newKeys, 0, i); System.arraycopy(values, 0, newValues, 0, i); System.arraycopy(keys, i+1, newKeys, i, oldSize-i-1); System.arraycopy(values, i+1, newValues, i, oldSize-i-1); return new ArrayBackedFMap(newKeys, newValues); } } return this; //if (i == oldSize) { //newKeys = new int[oldSize]; //newValues = new Object[oldSize]; //System.arraycopy(keys, 0, newKeys, 0, oldSize); //System.arraycopy(values, 0, newValues, 0, oldSize); //} } @Override public <V> V get(@NotNull Key<V> key) { int oldSize = size(); int keyCode = key.hashCode(); for (int i = 0; i < oldSize; i++) { int oldKey = keys[i]; if (keyCode == oldKey) { //noinspection unchecked return (V)values[i]; } } return null; } @Override public String toString() { String s = ""; for (int i = 0; i < keys.length; i++) { int key = keys[i]; Object value = values[i]; s += (s.isEmpty() ? "" : ", ") + Key.getKeyByIndex(key) + " -> " + value; } return "(" + s + ")"; } @Override public boolean isEmpty() { return false; } }