Merge "BlockList: Micro-optimize appending from another BlockList"
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/BlockListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/BlockListTest.java
index 7151af1..8b042bd 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/BlockListTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/BlockListTest.java
@@ -282,6 +282,24 @@ public void testAddRemoveAdd() {
 	}
 
 	@Test
+	public void testAddAllFromOtherList() {
+		BlockList<Integer> src = new BlockList<Integer>(4);
+		int cnt = BlockList.BLOCK_SIZE * 2;
+
+		for (int i = 0; i < cnt; i++)
+			src.add(Integer.valueOf(42 + i));
+		src.add(Integer.valueOf(1));
+
+		BlockList<Integer> dst = new BlockList<Integer>(4);
+		dst.add(Integer.valueOf(255));
+		dst.addAll(src);
+		assertEquals(cnt + 2, dst.size());
+		for (int i = 0; i < cnt; i++)
+			assertEquals(Integer.valueOf(42 + i), dst.get(i + 1));
+		assertEquals(Integer.valueOf(1), dst.get(dst.size() - 1));
+	}
+
+	@Test
 	public void testFastIterator() {
 		BlockList<Integer> list = new BlockList<Integer>(4);
 		int cnt = BlockList.BLOCK_SIZE * 3;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/BlockList.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/BlockList.java
index ac29771..50715ac 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/BlockList.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/BlockList.java
@@ -141,6 +141,52 @@ public T set(int index, T element) {
 		return old;
 	}
 
+	/**
+	 * Quickly append all elements of another BlockList.
+	 *
+	 * @param src
+	 *            the list to copy elements from.
+	 */
+	public void addAll(BlockList<T> src) {
+		if (src.size == 0)
+			return;
+
+		int srcDirIdx = 0;
+		for (; srcDirIdx < src.tailDirIdx; srcDirIdx++)
+			addAll(src.directory[srcDirIdx], 0, BLOCK_SIZE);
+		if (src.tailBlkIdx != 0)
+			addAll(src.tailBlock, 0, src.tailBlkIdx);
+	}
+
+	/**
+	 * Quickly append all elements from an array.
+	 *
+	 * @param src
+	 *            the source array.
+	 * @param srcIdx
+	 *            first index to copy.
+	 * @param srcCnt
+	 *            number of elements to copy.
+	 */
+	public void addAll(T[] src, int srcIdx, int srcCnt) {
+		while (0 < srcCnt) {
+			int i = tailBlkIdx;
+			int n = Math.min(srcCnt, BLOCK_SIZE - i);
+			if (n == 0) {
+				// Our tail is full, expand by one.
+				add(src[srcIdx++]);
+				srcCnt--;
+				continue;
+			}
+
+			System.arraycopy(src, srcIdx, tailBlock, i, n);
+			tailBlkIdx += n;
+			size += n;
+			srcIdx += n;
+			srcCnt -= n;
+		}
+	}
+
 	@Override
 	public boolean add(T element) {
 		int i = tailBlkIdx;