blob: 387962a8b03b5d11cf1d5b1c328527edf07b5480 [file] [log] [blame]
/*
* Copyright 2000-2009 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.psi.impl.cache;
import com.intellij.util.ArrayUtil;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntIntHashMap;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.Nullable;
/**
* @author max
*/
public class SmartIntToIntArrayMap {
@Nullable TIntObjectHashMap<TIntArrayList> myMultipleValuesMap = null;
TIntIntHashMap mySingleValueMap = new TIntIntHashMap(10, 0.9f);
public int[] keys() {
int[] multiKeys = myMultipleValuesMap != null ? myMultipleValuesMap.keys() : ArrayUtil.EMPTY_INT_ARRAY;
int[] singleKeys = mySingleValueMap.keys();
if (singleKeys.length == 0) return multiKeys;
int[] combinedKeys = new int[multiKeys.length + singleKeys.length];
System.arraycopy(multiKeys, 0, combinedKeys, 0, multiKeys.length);
System.arraycopy(singleKeys, 0, combinedKeys, multiKeys.length, singleKeys.length);
return combinedKeys;
}
public void addOccurence(int key, int value) {
if (myMultipleValuesMap != null && myMultipleValuesMap.containsKey(key)) {
addToMultimap(key, value);
}
else if (mySingleValueMap.containsKey(key)) {
int storedId = mySingleValueMap.get(key);
if (storedId == value) return;
mySingleValueMap.remove(key);
addToMultimap(key, storedId);
addToMultimap(key, value);
}
else {
mySingleValueMap.put(key, value);
}
}
private void addToMultimap(int key, int value) {
if (myMultipleValuesMap == null) {
myMultipleValuesMap = new TIntObjectHashMap<TIntArrayList>(10, 0.9f);
}
final TIntObjectHashMap<TIntArrayList> map = myMultipleValuesMap;
TIntArrayList list = map.get(key);
if (list == null) {
list = new TIntArrayList(3);
map.put(key, list);
}
if (!list.contains(value)) list.add(value);
}
public void removeOccurence(int key, int value) {
if (mySingleValueMap.containsKey(key)) {
mySingleValueMap.remove(key);
}
else {
removeFromMultiMap(key, value);
}
}
private void removeFromMultiMap(int key, int value) {
final TIntObjectHashMap<TIntArrayList> map = myMultipleValuesMap;
if (map == null) return;
TIntArrayList list = map.get(key);
if (list != null) {
int offset = list.indexOf(value);
if (offset != -1) {
list.remove(offset);
if (list.isEmpty()) {
map.remove(key);
}
}
}
}
public int[] get(int key) {
if (mySingleValueMap.containsKey(key)) {
int id = mySingleValueMap.get(key);
return new int[]{id};
}
return getFromMultimap(key);
}
private int[] getFromMultimap(int key) {
TIntArrayList res = myMultipleValuesMap != null ? myMultipleValuesMap.get(key) : null;
if (res == null) return ArrayUtil.EMPTY_INT_ARRAY;
return res.toNativeArray();
}
}