| /* |
| * 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(); |
| } |
| } |
| } |