001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.compress.harmony.pack200; 018 019import java.util.Arrays; 020 021/** 022 * 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 023 * required and improve performance of pack200. 024 */ 025public class IntList { 026 027 private int[] array; 028 private int firstIndex; 029 private int lastIndex; 030 private int modCount; 031 032 /** 033 * Constructs a new instance of IntList with capacity for ten elements. 034 */ 035 public IntList() { 036 this(10); 037 } 038 039 /** 040 * Constructs a new instance of IntList with the specified capacity. 041 * 042 * @param capacity the initial capacity of this IntList 043 */ 044 public IntList(final int capacity) { 045 if (capacity < 0) { 046 throw new IllegalArgumentException(); 047 } 048 firstIndex = lastIndex = 0; 049 array = new int[capacity]; 050 } 051 052 /** 053 * Adds the specified object at the end of this IntList. 054 * 055 * @param object the object to add 056 * @return true 057 */ 058 public boolean add(final int object) { 059 if (lastIndex == array.length) { 060 growAtEnd(1); 061 } 062 array[lastIndex++] = object; 063 modCount++; 064 return true; 065 } 066 067 public void add(final int location, final int object) { 068 final int size = lastIndex - firstIndex; 069 if (0 < location && location < size) { 070 if (firstIndex == 0 && lastIndex == array.length) { 071 growForInsert(location, 1); 072 } else if (location < size / 2 && firstIndex > 0 || lastIndex == array.length) { 073 System.arraycopy(array, firstIndex, array, --firstIndex, location); 074 } else { 075 final int index = location + firstIndex; 076 System.arraycopy(array, index, array, index + 1, size - location); 077 lastIndex++; 078 } 079 array[location + firstIndex] = object; 080 } else if (location == 0) { 081 if (firstIndex == 0) { 082 growAtFront(1); 083 } 084 array[--firstIndex] = object; 085 } else if (location == size) { 086 if (lastIndex == array.length) { 087 growAtEnd(1); 088 } 089 array[lastIndex++] = object; 090 } else { 091 throw new IndexOutOfBoundsException(); 092 } 093 094 modCount++; 095 } 096 097 public void addAll(final IntList list) { 098 growAtEnd(list.size()); 099 for (int i = 0; i < list.size(); i++) { 100 add(list.get(i)); 101 } 102 } 103 104 public void clear() { 105 if (firstIndex != lastIndex) { 106 Arrays.fill(array, firstIndex, lastIndex, -1); 107 firstIndex = lastIndex = 0; 108 modCount++; 109 } 110 } 111 112 public int get(final int location) { 113 if (0 <= location && location < lastIndex - firstIndex) { 114 return array[firstIndex + location]; 115 } 116 throw new IndexOutOfBoundsException("" + location); 117 } 118 119 private void growAtEnd(final int required) { 120 final int size = lastIndex - firstIndex; 121 if (firstIndex >= required - (array.length - lastIndex)) { 122 final int newLast = lastIndex - firstIndex; 123 if (size > 0) { 124 System.arraycopy(array, firstIndex, array, 0, size); 125 } 126 firstIndex = 0; 127 lastIndex = newLast; 128 } else { 129 int increment = size / 2; 130 if (required > increment) { 131 increment = required; 132 } 133 if (increment < 12) { 134 increment = 12; 135 } 136 final int[] newArray = new int[size + increment]; 137 if (size > 0) { 138 System.arraycopy(array, firstIndex, newArray, 0, size); 139 firstIndex = 0; 140 lastIndex = size; 141 } 142 array = newArray; 143 } 144 } 145 146 private void growAtFront(final int required) { 147 final int size = lastIndex - firstIndex; 148 if (array.length - lastIndex + firstIndex >= required) { 149 final int newFirst = array.length - size; 150 if (size > 0) { 151 System.arraycopy(array, firstIndex, array, newFirst, size); 152 } 153 firstIndex = newFirst; 154 lastIndex = array.length; 155 } else { 156 int increment = size / 2; 157 if (required > increment) { 158 increment = required; 159 } 160 if (increment < 12) { 161 increment = 12; 162 } 163 final int[] newArray = new int[size + increment]; 164 if (size > 0) { 165 System.arraycopy(array, firstIndex, newArray, newArray.length - size, size); 166 } 167 firstIndex = newArray.length - size; 168 lastIndex = newArray.length; 169 array = newArray; 170 } 171 } 172 173 private void growForInsert(final int location, final int required) { 174 final int size = lastIndex - firstIndex; 175 int increment = size / 2; 176 if (required > increment) { 177 increment = required; 178 } 179 if (increment < 12) { 180 increment = 12; 181 } 182 final int[] newArray = new int[size + increment]; 183 final int newFirst = increment - required; 184 // Copy elements after location to the new array skipping inserted 185 // elements 186 System.arraycopy(array, location + firstIndex, newArray, newFirst + location + required, size - location); 187 // Copy elements before location to the new array from firstIndex 188 System.arraycopy(array, firstIndex, newArray, newFirst, location); 189 firstIndex = newFirst; 190 lastIndex = size + increment; 191 192 array = newArray; 193 } 194 195 public void increment(final int location) { 196 if (0 > location || location >= lastIndex - firstIndex) { 197 throw new IndexOutOfBoundsException("" + location); 198 } 199 array[firstIndex + location]++; 200 } 201 202 public boolean isEmpty() { 203 return lastIndex == firstIndex; 204 } 205 206 public int remove(final int location) { 207 int result; 208 final int size = lastIndex - firstIndex; 209 if (0 > location || location >= size) { 210 throw new IndexOutOfBoundsException(); 211 } 212 if (location == size - 1) { 213 result = array[--lastIndex]; 214 array[lastIndex] = 0; 215 } else if (location == 0) { 216 result = array[firstIndex]; 217 array[firstIndex++] = 0; 218 } else { 219 final int elementIndex = firstIndex + location; 220 result = array[elementIndex]; 221 if (location < size / 2) { 222 System.arraycopy(array, firstIndex, array, firstIndex + 1, location); 223 array[firstIndex++] = 0; 224 } else { 225 System.arraycopy(array, elementIndex + 1, array, elementIndex, size - location - 1); 226 array[--lastIndex] = 0; 227 } 228 } 229 if (firstIndex == lastIndex) { 230 firstIndex = lastIndex = 0; 231 } 232 233 modCount++; 234 return result; 235 } 236 237 public int size() { 238 return lastIndex - firstIndex; 239 } 240 241 public int[] toArray() { 242 final int size = lastIndex - firstIndex; 243 final int[] result = new int[size]; 244 System.arraycopy(array, firstIndex, result, 0, size); 245 return result; 246 } 247 248}