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 org.eclipse.jgit.revwalk.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 /** 77 * Create an empty object list. 78 */ 79 public RevObjectList() { 80 // Initialized above. 81 } 82 83 /** {@inheritDoc} */ 84 @Override 85 public void add(int index, E element) { 86 if (index != size) 87 throw new UnsupportedOperationException(MessageFormat.format( 88 JGitText.get().unsupportedOperationNotAddAtEnd, 89 Integer.valueOf(index))); 90 set(index, element); 91 size++; 92 } 93 94 /** {@inheritDoc} */ 95 @Override 96 @SuppressWarnings("unchecked") 97 public E set(int index, E element) { 98 Block s = contents; 99 while (index >> s.shift >= BLOCK_SIZE) { 100 s = new Block(s.shift + BLOCK_SHIFT); 101 s.contents[0] = contents; 102 contents = s; 103 } 104 while (s.shift > 0) { 105 final int i = index >> s.shift; 106 index -= i << s.shift; 107 if (s.contents[i] == null) 108 s.contents[i] = new Block(s.shift - BLOCK_SHIFT); 109 s = (Block) s.contents[i]; 110 } 111 final Object old = s.contents[index]; 112 s.contents[index] = element; 113 return (E) old; 114 } 115 116 /** {@inheritDoc} */ 117 @Override 118 @SuppressWarnings("unchecked") 119 public E get(int index) { 120 Block s = contents; 121 if (index >> s.shift >= 1024) 122 return null; 123 while (s != null && s.shift > 0) { 124 final int i = index >> s.shift; 125 index -= i << s.shift; 126 s = (Block) s.contents[i]; 127 } 128 return s != null ? (E) s.contents[index] : null; 129 } 130 131 /** {@inheritDoc} */ 132 @Override 133 public int size() { 134 return size; 135 } 136 137 /** {@inheritDoc} */ 138 @Override 139 public void clear() { 140 contents = new Block(0); 141 size = 0; 142 } 143 144 /** One level of contents, either an intermediate level or a leaf level. */ 145 protected static class Block { 146 final Object[] contents = new Object[BLOCK_SIZE]; 147 148 final int shift; 149 150 Block(int s) { 151 shift = s; 152 } 153 } 154 }