1 /* 2 * Copyright (C) 2009, Google Inc. 3 * Copyright (C) 2009, Jonas Fonseca <fonseca@diku.dk> 4 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> 5 * and other copyright owners as documented in the project's IP log. 6 * 7 * This program and the accompanying materials are made available 8 * under the terms of the Eclipse Distribution License v1.0 which 9 * accompanies this distribution, is reproduced below, and is 10 * available at http://www.eclipse.org/org/documents/edl-v10.php 11 * 12 * All rights reserved. 13 * 14 * Redistribution and use in source and binary forms, with or 15 * without modification, are permitted provided that the following 16 * conditions are met: 17 * 18 * - Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 21 * - Redistributions in binary form must reproduce the above 22 * copyright notice, this list of conditions and the following 23 * disclaimer in the documentation and/or other materials provided 24 * with the distribution. 25 * 26 * - Neither the name of the Eclipse Foundation, Inc. nor the 27 * names of its contributors may be used to endorse or promote 28 * products derived from this software without specific prior 29 * written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 32 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 34 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 36 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 38 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 39 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 40 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 43 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 */ 45 46 package org.eclipse.jgit.revwalk; 47 48 import java.text.MessageFormat; 49 import java.util.AbstractList; 50 51 import org.eclipse.jgit.internal.JGitText; 52 53 /** 54 * An ordered list of {@link RevObject} subclasses. 55 * 56 * @param <E> 57 * type of subclass of RevObject the list is storing. 58 */ 59 public class RevObjectList<E extends RevObject> extends AbstractList<E> { 60 static final int BLOCK_SHIFT = 8; 61 62 static final int BLOCK_SIZE = 1 << BLOCK_SHIFT; 63 64 /** 65 * Items stored in this list. 66 * <p> 67 * If {@link Block#shift} = 0 this block holds the list elements; otherwise 68 * it holds pointers to other {@link Block} instances which use a shift that 69 * is {@link #BLOCK_SHIFT} smaller. 70 */ 71 protected Block contents = new Block(0); 72 73 /** Current number of elements in the list. */ 74 protected int size = 0; 75 76 /** Create an empty object list. */ 77 public RevObjectList() { 78 // Initialized above. 79 } 80 81 @Override 82 public void add(final int index, final E element) { 83 if (index != size) 84 throw new UnsupportedOperationException(MessageFormat.format( 85 JGitText.get().unsupportedOperationNotAddAtEnd, 86 Integer.valueOf(index))); 87 set(index, element); 88 size++; 89 } 90 91 @Override 92 @SuppressWarnings("unchecked") 93 public E set(int index, E element) { 94 Block s = contents; 95 while (index >> s.shift >= BLOCK_SIZE) { 96 s = new Block(s.shift + BLOCK_SHIFT); 97 s.contents[0] = contents; 98 contents = s; 99 } 100 while (s.shift > 0) { 101 final int i = index >> s.shift; 102 index -= i << s.shift; 103 if (s.contents[i] == null) 104 s.contents[i] = new Block(s.shift - BLOCK_SHIFT); 105 s = (Block) s.contents[i]; 106 } 107 final Object old = s.contents[index]; 108 s.contents[index] = element; 109 return (E) old; 110 } 111 112 @Override 113 @SuppressWarnings("unchecked") 114 public E get(int index) { 115 Block s = contents; 116 if (index >> s.shift >= 1024) 117 return null; 118 while (s != null && s.shift > 0) { 119 final int i = index >> s.shift; 120 index -= i << s.shift; 121 s = (Block) s.contents[i]; 122 } 123 return s != null ? (E) s.contents[index] : null; 124 } 125 126 @Override 127 public int size() { 128 return size; 129 } 130 131 @Override 132 public void clear() { 133 contents = new Block(0); 134 size = 0; 135 } 136 137 /** One level of contents, either an intermediate level or a leaf level. */ 138 protected static class Block { 139 final Object[] contents = new Object[BLOCK_SIZE]; 140 141 final int shift; 142 143 Block(final int s) { 144 shift = s; 145 } 146 } 147 }