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.collections.primitives;
18
19 import java.io.IOException;
20 import java.io.ObjectInputStream;
21 import java.io.ObjectOutputStream;
22 import java.io.Serializable;
23
24 /**
25 * An {@link IntList} backed by an array of unsigned
26 * <code>short</code> values.
27 * This list stores <code>int</code> values
28 * in the range [{@link #MIN_VALUE <code>0</code>},
29 * {@link #MAX_VALUE <code>65535</code>}] in 16-bits
30 * per element. Attempts to use elements outside this
31 * range may cause an
32 * {@link IllegalArgumentException IllegalArgumentException}
33 * to be thrown.
34 * <p />
35 * This implementation supports all optional methods.
36 *
37 * @since Commons Primitives 1.0
38 * @version $Revision: 480460 $ $Date: 2006-11-29 03:14:21 -0500 (Wed, 29 Nov 2006) $
39 *
40 * @author Rodney Waldhoff
41 */
42 public class ArrayUnsignedShortList extends RandomAccessIntList implements IntList, Serializable {
43
44 // constructors
45 //-------------------------------------------------------------------------
46
47 /**
48 * Construct an empty list with the default
49 * initial capacity.
50 */
51 public ArrayUnsignedShortList() {
52 this(8);
53 }
54
55 /**
56 * Construct an empty list with the given
57 * initial capacity.
58 * @throws IllegalArgumentException when <i>initialCapacity</i> is negative
59 */
60 public ArrayUnsignedShortList(int initialCapacity) {
61 if(initialCapacity < 0) {
62 throw new IllegalArgumentException("capacity " + initialCapacity);
63 }
64 _data = new short[initialCapacity];
65 _size = 0;
66 }
67
68 /**
69 * Constructs a list containing the elements of the given collection,
70 * in the order they are returned by that collection's iterator.
71 *
72 * @see ArrayIntList#addAll(org.apache.commons.collections.primitives.IntCollection)
73 * @param that the non-<code>null</code> collection of <code>int</code>s
74 * to add
75 * @throws NullPointerException if <i>that</i> is <code>null</code>
76 */
77 public ArrayUnsignedShortList(IntCollection that) {
78 this(that.size());
79 addAll(that);
80 }
81
82 /**
83 * Constructs a list by copying the specified array.
84 *
85 * @param array the array to initialize the collection with
86 * @throws NullPointerException if the array is <code>null</code>
87 */
88 public ArrayUnsignedShortList(int[] array) {
89 this(array.length);
90 for(int i=0;i<array.length;i++) {
91 _data[i] = fromInt(array[i]);
92 }
93 _size = array.length;
94 }
95
96 // IntList methods
97 //-------------------------------------------------------------------------
98
99 /**
100 * Returns the element at the specified position within
101 * me.
102 * By construction, the returned value will be
103 * between {@link #MIN_VALUE} and {@link #MAX_VALUE}, inclusive.
104 *
105 * @param index the index of the element to return
106 * @return the value of the element at the specified position
107 * @throws IndexOutOfBoundsException if the specified index is out of range
108 */
109 public int get(int index) {
110 checkRange(index);
111 return toInt(_data[index]);
112 }
113
114 public int size() {
115 return _size;
116 }
117
118 /**
119 * Removes the element at the specified position in
120 * (optional operation). Any subsequent elements
121 * are shifted to the left, subtracting one from their
122 * indices. Returns the element that was removed.
123 * By construction, the returned value will be
124 * between {@link #MIN_VALUE} and {@link #MAX_VALUE}, inclusive.
125 *
126 * @param index the index of the element to remove
127 * @return the value of the element that was removed
128 *
129 * @throws UnsupportedOperationException when this operation is not
130 * supported
131 * @throws IndexOutOfBoundsException if the specified index is out of range
132 */
133 public int removeElementAt(int index) {
134 checkRange(index);
135 incrModCount();
136 int oldval = toInt(_data[index]);
137 int numtomove = _size - index - 1;
138 if(numtomove > 0) {
139 System.arraycopy(_data,index+1,_data,index,numtomove);
140 }
141 _size--;
142 return oldval;
143 }
144
145 /**
146 * Replaces the element at the specified
147 * position in me with the specified element
148 * (optional operation).
149 * Throws {@link IllegalArgumentException} if <i>element</i>
150 * is less than {@link #MIN_VALUE} or greater than {@link #MAX_VALUE}.
151 *
152 * @param index the index of the element to change
153 * @param element the value to be stored at the specified position
154 * @return the value previously stored at the specified position
155 *
156 * @throws UnsupportedOperationException when this operation is not
157 * supported
158 * @throws IndexOutOfBoundsException if the specified index is out of range
159 */
160 public int set(int index, int element) {
161 assertValidUnsignedShort(element);
162 checkRange(index);
163 incrModCount();
164 int oldval = toInt(_data[index]);
165 _data[index] = fromInt(element);
166 return oldval;
167 }
168
169 /**
170 * Inserts the specified element at the specified position
171 * (optional operation). Shifts the element currently
172 * at that position (if any) and any subsequent elements to the
173 * right, increasing their indices.
174 * Throws {@link IllegalArgumentException} if <i>element</i>
175 * is less than {@link #MIN_VALUE} or greater than {@link #MAX_VALUE}.
176 *
177 * @param index the index at which to insert the element
178 * @param element the value to insert
179 *
180 * @throws UnsupportedOperationException when this operation is not
181 * supported
182 * @throws IllegalArgumentException if some aspect of the specified element
183 * prevents it from being added to me
184 * @throws IndexOutOfBoundsException if the specified index is out of range
185 */
186 public void add(int index, int element) {
187 assertValidUnsignedShort(element);
188 checkRangeIncludingEndpoint(index);
189 incrModCount();
190 ensureCapacity(_size+1);
191 int numtomove = _size-index;
192 System.arraycopy(_data,index,_data,index+1,numtomove);
193 _data[index] = fromInt(element);
194 _size++;
195 }
196
197 public void clear() {
198 incrModCount();
199 _size = 0;
200 }
201
202 // capacity methods
203 //-------------------------------------------------------------------------
204
205 /**
206 * Increases my capacity, if necessary, to ensure that I can hold at
207 * least the number of elements specified by the minimum capacity
208 * argument without growing.
209 */
210 public void ensureCapacity(int mincap) {
211 incrModCount();
212 if(mincap > _data.length) {
213 int newcap = (_data.length * 3)/2 + 1;
214 short[] olddata = _data;
215 _data = new short[newcap < mincap ? mincap : newcap];
216 System.arraycopy(olddata,0,_data,0,_size);
217 }
218 }
219
220 /**
221 * Reduce my capacity, if necessary, to match my
222 * current {@link #size size}.
223 */
224 public void trimToSize() {
225 incrModCount();
226 if(_size < _data.length) {
227 short[] olddata = _data;
228 _data = new short[_size];
229 System.arraycopy(olddata,0,_data,0,_size);
230 }
231 }
232
233 // private methods
234 //-------------------------------------------------------------------------
235
236 private final int toInt(short value) {
237 return value & MAX_VALUE;
238 }
239
240 private final short fromInt(int value) {
241 return (short)(value&MAX_VALUE);
242 }
243
244 private final void assertValidUnsignedShort(int value) throws IllegalArgumentException {
245 if(value > MAX_VALUE) {
246 throw new IllegalArgumentException(value + " > " + MAX_VALUE);
247 }
248 if(value < MIN_VALUE) {
249 throw new IllegalArgumentException(value + " < " + MIN_VALUE);
250 }
251 }
252
253 private void writeObject(ObjectOutputStream out) throws IOException{
254 out.defaultWriteObject();
255 out.writeInt(_data.length);
256 for(int i=0;i<_size;i++) {
257 out.writeShort(_data[i]);
258 }
259 }
260
261 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
262 in.defaultReadObject();
263 _data = new short[in.readInt()];
264 for(int i=0;i<_size;i++) {
265 _data[i] = in.readShort();
266 }
267 }
268
269 private final void checkRange(int index) {
270 if(index < 0 || index >= _size) {
271 throw new IndexOutOfBoundsException("Should be at least 0 and less than " + _size + ", found " + index);
272 }
273 }
274
275 private final void checkRangeIncludingEndpoint(int index) {
276 if(index < 0 || index > _size) {
277 throw new IndexOutOfBoundsException("Should be at least 0 and at most " + _size + ", found " + index);
278 }
279 }
280
281 // attributes
282 //-------------------------------------------------------------------------
283
284 /** The maximum possible unsigned 16-bit value (<code>0xFFFF</code>). */
285 public static final int MAX_VALUE = 0xFFFF;
286
287
288 /** The minimum possible unsigned 16-bit value (<code>0x0000</code>). */
289 public static final int MIN_VALUE = 0;
290
291 private transient short[] _data = null;
292 private int _size = 0;
293
294 }