View Javadoc
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> and others
5    *
6    * This program and the accompanying materials are made available under the
7    * terms of the Eclipse Distribution License v. 1.0 which is available at
8    * https://www.eclipse.org/org/documents/edl-v10.php.
9    *
10   * SPDX-License-Identifier: BSD-3-Clause
11   */
12  
13  package org.eclipse.jgit.revwalk;
14  
15  import java.text.MessageFormat;
16  import java.util.AbstractList;
17  
18  import org.eclipse.jgit.internal.JGitText;
19  
20  /**
21   * An ordered list of {@link org.eclipse.jgit.revwalk.RevObject} subclasses.
22   *
23   * @param <E>
24   *            type of subclass of RevObject the list is storing.
25   */
26  public class RevObjectList<E extends RevObject> extends AbstractList<E> {
27  	static final int BLOCK_SHIFT = 8;
28  
29  	static final int BLOCK_SIZE = 1 << BLOCK_SHIFT;
30  
31  	/**
32  	 * Items stored in this list.
33  	 * <p>
34  	 * If {@link Block#shift} = 0 this block holds the list elements; otherwise
35  	 * it holds pointers to other {@link Block} instances which use a shift that
36  	 * is {@link #BLOCK_SHIFT} smaller.
37  	 */
38  	protected Block contents = new Block(0);
39  
40  	/** Current number of elements in the list. */
41  	protected int size = 0;
42  
43  	/**
44  	 * Create an empty object list.
45  	 */
46  	public RevObjectList() {
47  		// Initialized above.
48  	}
49  
50  	/** {@inheritDoc} */
51  	@Override
52  	public void add(int index, E element) {
53  		if (index != size)
54  			throw new UnsupportedOperationException(MessageFormat.format(
55  					JGitText.get().unsupportedOperationNotAddAtEnd,
56  					Integer.valueOf(index)));
57  		set(index, element);
58  		size++;
59  	}
60  
61  	/** {@inheritDoc} */
62  	@Override
63  	@SuppressWarnings("unchecked")
64  	public E set(int index, E element) {
65  		Block s = contents;
66  		while (index >> s.shift >= BLOCK_SIZE) {
67  			s = new Block(s.shift + BLOCK_SHIFT);
68  			s.contents[0] = contents;
69  			contents = s;
70  		}
71  		while (s.shift > 0) {
72  			final int i = index >> s.shift;
73  			index -= i << s.shift;
74  			if (s.contents[i] == null)
75  				s.contents[i] = new Block(s.shift - BLOCK_SHIFT);
76  			s = (Block) s.contents[i];
77  		}
78  		final Object old = s.contents[index];
79  		s.contents[index] = element;
80  		return (E) old;
81  	}
82  
83  	/** {@inheritDoc} */
84  	@Override
85  	@SuppressWarnings("unchecked")
86  	public E get(int index) {
87  		Block s = contents;
88  		if (index >> s.shift >= 1024)
89  			return null;
90  		while (s != null && s.shift > 0) {
91  			final int i = index >> s.shift;
92  			index -= i << s.shift;
93  			s = (Block) s.contents[i];
94  		}
95  		return s != null ? (E) s.contents[index] : null;
96  	}
97  
98  	/** {@inheritDoc} */
99  	@Override
100 	public int size() {
101 		return size;
102 	}
103 
104 	/** {@inheritDoc} */
105 	@Override
106 	public void clear() {
107 		contents = new Block(0);
108 		size = 0;
109 	}
110 
111 	/** One level of contents, either an intermediate level or a leaf level. */
112 	protected static class Block {
113 		final Object[] contents = new Object[BLOCK_SIZE];
114 
115 		final int shift;
116 
117 		Block(int s) {
118 			shift = s;
119 		}
120 	}
121 }