RevObjectList.java

  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. package org.eclipse.jgit.revwalk;

  13. import java.text.MessageFormat;
  14. import java.util.AbstractList;

  15. import org.eclipse.jgit.internal.JGitText;

  16. /**
  17.  * An ordered list of {@link org.eclipse.jgit.revwalk.RevObject} subclasses.
  18.  *
  19.  * @param <E>
  20.  *            type of subclass of RevObject the list is storing.
  21.  */
  22. public class RevObjectList<E extends RevObject> extends AbstractList<E> {
  23.     static final int BLOCK_SHIFT = 8;

  24.     static final int BLOCK_SIZE = 1 << BLOCK_SHIFT;

  25.     /**
  26.      * Items stored in this list.
  27.      * <p>
  28.      * If {@link Block#shift} = 0 this block holds the list elements; otherwise
  29.      * it holds pointers to other {@link Block} instances which use a shift that
  30.      * is {@link #BLOCK_SHIFT} smaller.
  31.      */
  32.     protected Block contents = new Block(0);

  33.     /** Current number of elements in the list. */
  34.     protected int size = 0;

  35.     /**
  36.      * Create an empty object list.
  37.      */
  38.     public RevObjectList() {
  39.         // Initialized above.
  40.     }

  41.     /** {@inheritDoc} */
  42.     @Override
  43.     public void add(int index, E element) {
  44.         if (index != size)
  45.             throw new UnsupportedOperationException(MessageFormat.format(
  46.                     JGitText.get().unsupportedOperationNotAddAtEnd,
  47.                     Integer.valueOf(index)));
  48.         set(index, element);
  49.         size++;
  50.     }

  51.     /** {@inheritDoc} */
  52.     @Override
  53.     @SuppressWarnings("unchecked")
  54.     public E set(int index, E element) {
  55.         Block s = contents;
  56.         while (index >> s.shift >= BLOCK_SIZE) {
  57.             s = new Block(s.shift + BLOCK_SHIFT);
  58.             s.contents[0] = contents;
  59.             contents = s;
  60.         }
  61.         while (s.shift > 0) {
  62.             final int i = index >> s.shift;
  63.             index -= i << s.shift;
  64.             if (s.contents[i] == null)
  65.                 s.contents[i] = new Block(s.shift - BLOCK_SHIFT);
  66.             s = (Block) s.contents[i];
  67.         }
  68.         final Object old = s.contents[index];
  69.         s.contents[index] = element;
  70.         return (E) old;
  71.     }

  72.     /** {@inheritDoc} */
  73.     @Override
  74.     @SuppressWarnings("unchecked")
  75.     public E get(int index) {
  76.         Block s = contents;
  77.         if (index >> s.shift >= 1024)
  78.             return null;
  79.         while (s != null && s.shift > 0) {
  80.             final int i = index >> s.shift;
  81.             index -= i << s.shift;
  82.             s = (Block) s.contents[i];
  83.         }
  84.         return s != null ? (E) s.contents[index] : null;
  85.     }

  86.     /** {@inheritDoc} */
  87.     @Override
  88.     public int size() {
  89.         return size;
  90.     }

  91.     /** {@inheritDoc} */
  92.     @Override
  93.     public void clear() {
  94.         contents = new Block(0);
  95.         size = 0;
  96.     }

  97.     /** One level of contents, either an intermediate level or a leaf level. */
  98.     protected static class Block {
  99.         final Object[] contents = new Object[BLOCK_SIZE];

  100.         final int shift;

  101.         Block(int s) {
  102.             shift = s;
  103.         }
  104.     }
  105. }