IntList.java

  1. /*
  2.  *  Licensed to the Apache Software Foundation (ASF) under one or more
  3.  *  contributor license agreements.  See the NOTICE file distributed with
  4.  *  this work for additional information regarding copyright ownership.
  5.  *  The ASF licenses this file to You under the Apache License, Version 2.0
  6.  *  (the "License"); you may not use this file except in compliance with
  7.  *  the License.  You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *  Unless required by applicable law or agreed to in writing, software
  12.  *  distributed under the License is distributed on an "AS IS" BASIS,
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *  See the License for the specific language governing permissions and
  15.  *  limitations under the License.
  16.  */
  17. package org.apache.commons.compress.harmony.pack200;

  18. import java.util.Arrays;

  19. /**
  20.  * IntList is based on {@link java.util.ArrayList}, but is written specifically for ints in order to reduce boxing and unboxing to Integers, reduce the memory
  21.  * required and improve performance of pack200.
  22.  */
  23. public class IntList {

  24.     private int[] array;
  25.     private int firstIndex;
  26.     private int lastIndex;
  27.     private int modCount;

  28.     /**
  29.      * Constructs a new instance of IntList with capacity for ten elements.
  30.      */
  31.     public IntList() {
  32.         this(10);
  33.     }

  34.     /**
  35.      * Constructs a new instance of IntList with the specified capacity.
  36.      *
  37.      * @param capacity the initial capacity of this IntList
  38.      */
  39.     public IntList(final int capacity) {
  40.         if (capacity < 0) {
  41.             throw new IllegalArgumentException();
  42.         }
  43.         firstIndex = lastIndex = 0;
  44.         array = new int[capacity];
  45.     }

  46.     /**
  47.      * Adds the specified object at the end of this IntList.
  48.      *
  49.      * @param object the object to add
  50.      * @return true
  51.      */
  52.     public boolean add(final int object) {
  53.         if (lastIndex == array.length) {
  54.             growAtEnd(1);
  55.         }
  56.         array[lastIndex++] = object;
  57.         modCount++;
  58.         return true;
  59.     }

  60.     public void add(final int location, final int object) {
  61.         final int size = lastIndex - firstIndex;
  62.         if (0 < location && location < size) {
  63.             if (firstIndex == 0 && lastIndex == array.length) {
  64.                 growForInsert(location, 1);
  65.             } else if (location < size / 2 && firstIndex > 0 || lastIndex == array.length) {
  66.                 System.arraycopy(array, firstIndex, array, --firstIndex, location);
  67.             } else {
  68.                 final int index = location + firstIndex;
  69.                 System.arraycopy(array, index, array, index + 1, size - location);
  70.                 lastIndex++;
  71.             }
  72.             array[location + firstIndex] = object;
  73.         } else if (location == 0) {
  74.             if (firstIndex == 0) {
  75.                 growAtFront(1);
  76.             }
  77.             array[--firstIndex] = object;
  78.         } else if (location == size) {
  79.             if (lastIndex == array.length) {
  80.                 growAtEnd(1);
  81.             }
  82.             array[lastIndex++] = object;
  83.         } else {
  84.             throw new IndexOutOfBoundsException();
  85.         }

  86.         modCount++;
  87.     }

  88.     public void addAll(final IntList list) {
  89.         growAtEnd(list.size());
  90.         for (int i = 0; i < list.size(); i++) {
  91.             add(list.get(i));
  92.         }
  93.     }

  94.     public void clear() {
  95.         if (firstIndex != lastIndex) {
  96.             Arrays.fill(array, firstIndex, lastIndex, -1);
  97.             firstIndex = lastIndex = 0;
  98.             modCount++;
  99.         }
  100.     }

  101.     public int get(final int location) {
  102.         if (0 <= location && location < lastIndex - firstIndex) {
  103.             return array[firstIndex + location];
  104.         }
  105.         throw new IndexOutOfBoundsException("" + location);
  106.     }

  107.     private void growAtEnd(final int required) {
  108.         final int size = lastIndex - firstIndex;
  109.         if (firstIndex >= required - (array.length - lastIndex)) {
  110.             final int newLast = lastIndex - firstIndex;
  111.             if (size > 0) {
  112.                 System.arraycopy(array, firstIndex, array, 0, size);
  113.             }
  114.             firstIndex = 0;
  115.             lastIndex = newLast;
  116.         } else {
  117.             int increment = size / 2;
  118.             if (required > increment) {
  119.                 increment = required;
  120.             }
  121.             if (increment < 12) {
  122.                 increment = 12;
  123.             }
  124.             final int[] newArray = new int[size + increment];
  125.             if (size > 0) {
  126.                 System.arraycopy(array, firstIndex, newArray, 0, size);
  127.                 firstIndex = 0;
  128.                 lastIndex = size;
  129.             }
  130.             array = newArray;
  131.         }
  132.     }

  133.     private void growAtFront(final int required) {
  134.         final int size = lastIndex - firstIndex;
  135.         if (array.length - lastIndex + firstIndex >= required) {
  136.             final int newFirst = array.length - size;
  137.             if (size > 0) {
  138.                 System.arraycopy(array, firstIndex, array, newFirst, size);
  139.             }
  140.             firstIndex = newFirst;
  141.             lastIndex = array.length;
  142.         } else {
  143.             int increment = size / 2;
  144.             if (required > increment) {
  145.                 increment = required;
  146.             }
  147.             if (increment < 12) {
  148.                 increment = 12;
  149.             }
  150.             final int[] newArray = new int[size + increment];
  151.             if (size > 0) {
  152.                 System.arraycopy(array, firstIndex, newArray, newArray.length - size, size);
  153.             }
  154.             firstIndex = newArray.length - size;
  155.             lastIndex = newArray.length;
  156.             array = newArray;
  157.         }
  158.     }

  159.     private void growForInsert(final int location, final int required) {
  160.         final int size = lastIndex - firstIndex;
  161.         int increment = size / 2;
  162.         if (required > increment) {
  163.             increment = required;
  164.         }
  165.         if (increment < 12) {
  166.             increment = 12;
  167.         }
  168.         final int[] newArray = new int[size + increment];
  169.         final int newFirst = increment - required;
  170.         // Copy elements after location to the new array skipping inserted
  171.         // elements
  172.         System.arraycopy(array, location + firstIndex, newArray, newFirst + location + required, size - location);
  173.         // Copy elements before location to the new array from firstIndex
  174.         System.arraycopy(array, firstIndex, newArray, newFirst, location);
  175.         firstIndex = newFirst;
  176.         lastIndex = size + increment;

  177.         array = newArray;
  178.     }

  179.     public void increment(final int location) {
  180.         if (0 > location || location >= lastIndex - firstIndex) {
  181.             throw new IndexOutOfBoundsException("" + location);
  182.         }
  183.         array[firstIndex + location]++;
  184.     }

  185.     public boolean isEmpty() {
  186.         return lastIndex == firstIndex;
  187.     }

  188.     public int remove(final int location) {
  189.         int result;
  190.         final int size = lastIndex - firstIndex;
  191.         if (0 > location || location >= size) {
  192.             throw new IndexOutOfBoundsException();
  193.         }
  194.         if (location == size - 1) {
  195.             result = array[--lastIndex];
  196.             array[lastIndex] = 0;
  197.         } else if (location == 0) {
  198.             result = array[firstIndex];
  199.             array[firstIndex++] = 0;
  200.         } else {
  201.             final int elementIndex = firstIndex + location;
  202.             result = array[elementIndex];
  203.             if (location < size / 2) {
  204.                 System.arraycopy(array, firstIndex, array, firstIndex + 1, location);
  205.                 array[firstIndex++] = 0;
  206.             } else {
  207.                 System.arraycopy(array, elementIndex + 1, array, elementIndex, size - location - 1);
  208.                 array[--lastIndex] = 0;
  209.             }
  210.         }
  211.         if (firstIndex == lastIndex) {
  212.             firstIndex = lastIndex = 0;
  213.         }

  214.         modCount++;
  215.         return result;
  216.     }

  217.     public int size() {
  218.         return lastIndex - firstIndex;
  219.     }

  220.     public int[] toArray() {
  221.         final int size = lastIndex - firstIndex;
  222.         final int[] result = new int[size];
  223.         System.arraycopy(array, firstIndex, result, 0, size);
  224.         return result;
  225.     }

  226. }