blob: 6806940cb0abd0bba05cdaa564f8b1c835d0486b [file] [log] [blame]
/*
* Copyright 2000-2010 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.openapi.vcs;
import com.intellij.util.containers.ReadonlyList;
import com.intellij.util.containers.StepList;
import java.util.ArrayList;
import java.util.List;
/**
* @author irengrig
*/
public class BigArray<T> implements StepList<T> {
private final int mySize2Power;
private final List<ArrayList<T>> myList;
private int myPack;
private int mySize;
// pack size = 2^size2Power
public BigArray(final int size2Power) {
assert (size2Power > 1) && (size2Power < 16);
mySize2Power = size2Power;
myList = new ArrayList<ArrayList<T>>();
myPack = (int) Math.pow(2, size2Power);
mySize = 0;
}
public T get(final int idx) {
final int itemNumber = idx >> mySize2Power;
return myList.get(itemNumber).get(idx ^ (itemNumber << mySize2Power));
}
public void add(final T t) {
final ArrayList<T> commits;
if (myList.isEmpty() || (myList.get(myList.size() - 1).size() == myPack)) {
commits = new ArrayList<T>(myPack);
myList.add(commits);
} else {
commits = myList.get(myList.size() - 1);
}
++ mySize;
commits.add(t);
}
@Override
public ReadonlyList<T> cut(int idxFromIncluded) {
if (idxFromIncluded >= getSize()) return ReadonlyList.EMPTY;
final int itemNumber = idxFromIncluded >> mySize2Power;
final int insideIdx = idxFromIncluded ^ (itemNumber << mySize2Power);
final ArrayList<T> start = myList.get(itemNumber);
final NotRegularReadonlyList<T> result =
new NotRegularReadonlyList<T>(new ArrayList<ArrayList<T>>(myList.subList(itemNumber + 1, myList.size())),
mySize2Power, start.subList(insideIdx, start.size()));
myList.set(itemNumber, new ArrayList<T>(start.subList(0, insideIdx)));
for (int i = myList.size() - 1; i > itemNumber; -- i) {
myList.remove(i);
}
mySize = myList.isEmpty() ? 0 : (((myList.size() - 1) * myPack + myList.get(myList.size() - 1).size()));
return result;
}
@Override
public void ensureCapacity(int minCapacity) {
}
public int getSize() {
//if (myList.isEmpty()) return 0;
//return ((myList.size() - 1) * myPack + myList.get(myList.size() - 1).size());
return mySize;
}
public void clear() {
myList.clear();
mySize = 0;
}
private static class NotRegularReadonlyList<T> implements ReadonlyList<T> {
private final int mySize2Power;
private final List<T> myStart;
private final List<ArrayList<T>> myList;
private int myPack;
private NotRegularReadonlyList(List<ArrayList<T>> list, int size2Power, List<T> start) {
myList = list;
mySize2Power = size2Power;
myStart = start;
myPack = (int) Math.pow(2, size2Power);
}
@Override
public T get(int idx) {
if (idx < myStart.size()) {
return myStart.get(idx);
}
int corrected = idx - myStart.size();
final int itemNumber = corrected >> mySize2Power;
return myList.get(itemNumber).get(corrected ^ (itemNumber << mySize2Power));
}
@Override
public int getSize() {
if (myList.isEmpty()) {
return myStart.size();
}
return ((myList.size() - 1) * myPack + myList.get(myList.size() - 1).size()) + myStart.size();
}
}
}