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