001    /*
002     * Copyright (C) 2008 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.primitives;
018    
019    import static com.google.common.base.Preconditions.checkArgument;
020    import static com.google.common.base.Preconditions.checkElementIndex;
021    import static com.google.common.base.Preconditions.checkNotNull;
022    import static com.google.common.base.Preconditions.checkPositionIndexes;
023    
024    import com.google.common.annotations.GwtCompatible;
025    import com.google.common.annotations.GwtIncompatible;
026    
027    import java.io.Serializable;
028    import java.util.AbstractList;
029    import java.util.Arrays;
030    import java.util.Collection;
031    import java.util.Collections;
032    import java.util.Comparator;
033    import java.util.List;
034    import java.util.RandomAccess;
035    
036    /**
037     * Static utility methods pertaining to {@code short} primitives, that are not
038     * already found in either {@link Short} or {@link Arrays}.
039     *
040     * <p>See the Guava User Guide article on <a href=
041     * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
042     * primitive utilities</a>.
043     *
044     * @author Kevin Bourrillion
045     * @since 1.0
046     */
047    @GwtCompatible(emulated = true)
048    public final class Shorts {
049      private Shorts() {}
050    
051      /**
052       * The number of bytes required to represent a primitive {@code short}
053       * value.
054       */
055      public static final int BYTES = Short.SIZE / Byte.SIZE;
056    
057      /**
058       * The largest power of two that can be represented as a {@code short}.
059       *
060       * @since 10.0
061       */
062      public static final short MAX_POWER_OF_TWO = 1 << (Short.SIZE - 2);
063    
064      /**
065       * Returns a hash code for {@code value}; equal to the result of invoking
066       * {@code ((Short) value).hashCode()}.
067       *
068       * @param value a primitive {@code short} value
069       * @return a hash code for the value
070       */
071      public static int hashCode(short value) {
072        return value;
073      }
074    
075      /**
076       * Returns the {@code short} value that is equal to {@code value}, if
077       * possible.
078       *
079       * @param value any value in the range of the {@code short} type
080       * @return the {@code short} value that equals {@code value}
081       * @throws IllegalArgumentException if {@code value} is greater than {@link
082       *     Short#MAX_VALUE} or less than {@link Short#MIN_VALUE}
083       */
084      public static short checkedCast(long value) {
085        short result = (short) value;
086        checkArgument(result == value, "Out of range: %s", value);
087        return result;
088      }
089    
090      /**
091       * Returns the {@code short} nearest in value to {@code value}.
092       *
093       * @param value any {@code long} value
094       * @return the same value cast to {@code short} if it is in the range of the
095       *     {@code short} type, {@link Short#MAX_VALUE} if it is too large,
096       *     or {@link Short#MIN_VALUE} if it is too small
097       */
098      public static short saturatedCast(long value) {
099        if (value > Short.MAX_VALUE) {
100          return Short.MAX_VALUE;
101        }
102        if (value < Short.MIN_VALUE) {
103          return Short.MIN_VALUE;
104        }
105        return (short) value;
106      }
107    
108      /**
109       * Compares the two specified {@code short} values. The sign of the value
110       * returned is the same as that of {@code ((Short) a).compareTo(b)}.
111       *
112       * @param a the first {@code short} to compare
113       * @param b the second {@code short} to compare
114       * @return a negative value if {@code a} is less than {@code b}; a positive
115       *     value if {@code a} is greater than {@code b}; or zero if they are equal
116       */
117      public static int compare(short a, short b) {
118        return a - b; // safe due to restricted range
119      }
120    
121      /**
122       * Returns {@code true} if {@code target} is present as an element anywhere in
123       * {@code array}.
124       *
125       * @param array an array of {@code short} values, possibly empty
126       * @param target a primitive {@code short} value
127       * @return {@code true} if {@code array[i] == target} for some value of {@code
128       *     i}
129       */
130      public static boolean contains(short[] array, short target) {
131        for (short value : array) {
132          if (value == target) {
133            return true;
134          }
135        }
136        return false;
137      }
138    
139      /**
140       * Returns the index of the first appearance of the value {@code target} in
141       * {@code array}.
142       *
143       * @param array an array of {@code short} values, possibly empty
144       * @param target a primitive {@code short} value
145       * @return the least index {@code i} for which {@code array[i] == target}, or
146       *     {@code -1} if no such index exists.
147       */
148      public static int indexOf(short[] array, short target) {
149        return indexOf(array, target, 0, array.length);
150      }
151    
152      // TODO(kevinb): consider making this public
153      private static int indexOf(
154          short[] array, short target, int start, int end) {
155        for (int i = start; i < end; i++) {
156          if (array[i] == target) {
157            return i;
158          }
159        }
160        return -1;
161      }
162    
163      /**
164       * Returns the start position of the first occurrence of the specified {@code
165       * target} within {@code array}, or {@code -1} if there is no such occurrence.
166       *
167       * <p>More formally, returns the lowest index {@code i} such that {@code
168       * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
169       * the same elements as {@code target}.
170       *
171       * @param array the array to search for the sequence {@code target}
172       * @param target the array to search for as a sub-sequence of {@code array}
173       */
174      public static int indexOf(short[] array, short[] target) {
175        checkNotNull(array, "array");
176        checkNotNull(target, "target");
177        if (target.length == 0) {
178          return 0;
179        }
180    
181        outer:
182        for (int i = 0; i < array.length - target.length + 1; i++) {
183          for (int j = 0; j < target.length; j++) {
184            if (array[i + j] != target[j]) {
185              continue outer;
186            }
187          }
188          return i;
189        }
190        return -1;
191      }
192    
193      /**
194       * Returns the index of the last appearance of the value {@code target} in
195       * {@code array}.
196       *
197       * @param array an array of {@code short} values, possibly empty
198       * @param target a primitive {@code short} value
199       * @return the greatest index {@code i} for which {@code array[i] == target},
200       *     or {@code -1} if no such index exists.
201       */
202      public static int lastIndexOf(short[] array, short target) {
203        return lastIndexOf(array, target, 0, array.length);
204      }
205    
206      // TODO(kevinb): consider making this public
207      private static int lastIndexOf(
208          short[] array, short target, int start, int end) {
209        for (int i = end - 1; i >= start; i--) {
210          if (array[i] == target) {
211            return i;
212          }
213        }
214        return -1;
215      }
216    
217      /**
218       * Returns the least value present in {@code array}.
219       *
220       * @param array a <i>nonempty</i> array of {@code short} values
221       * @return the value present in {@code array} that is less than or equal to
222       *     every other value in the array
223       * @throws IllegalArgumentException if {@code array} is empty
224       */
225      public static short min(short... array) {
226        checkArgument(array.length > 0);
227        short min = array[0];
228        for (int i = 1; i < array.length; i++) {
229          if (array[i] < min) {
230            min = array[i];
231          }
232        }
233        return min;
234      }
235    
236      /**
237       * Returns the greatest value present in {@code array}.
238       *
239       * @param array a <i>nonempty</i> array of {@code short} values
240       * @return the value present in {@code array} that is greater than or equal to
241       *     every other value in the array
242       * @throws IllegalArgumentException if {@code array} is empty
243       */
244      public static short max(short... array) {
245        checkArgument(array.length > 0);
246        short max = array[0];
247        for (int i = 1; i < array.length; i++) {
248          if (array[i] > max) {
249            max = array[i];
250          }
251        }
252        return max;
253      }
254    
255      /**
256       * Returns the values from each provided array combined into a single array.
257       * For example, {@code concat(new short[] {a, b}, new short[] {}, new
258       * short[] {c}} returns the array {@code {a, b, c}}.
259       *
260       * @param arrays zero or more {@code short} arrays
261       * @return a single array containing all the values from the source arrays, in
262       *     order
263       */
264      public static short[] concat(short[]... arrays) {
265        int length = 0;
266        for (short[] array : arrays) {
267          length += array.length;
268        }
269        short[] result = new short[length];
270        int pos = 0;
271        for (short[] array : arrays) {
272          System.arraycopy(array, 0, result, pos, array.length);
273          pos += array.length;
274        }
275        return result;
276      }
277    
278      /**
279       * Returns a big-endian representation of {@code value} in a 2-element byte
280       * array; equivalent to {@code
281       * ByteBuffer.allocate(2).putShort(value).array()}.  For example, the input
282       * value {@code (short) 0x1234} would yield the byte array {@code {0x12,
283       * 0x34}}.
284       *
285       * <p>If you need to convert and concatenate several values (possibly even of
286       * different types), use a shared {@link java.nio.ByteBuffer} instance, or use
287       * {@link com.google.common.io.ByteStreams#newDataOutput()} to get a growable
288       * buffer.
289       */
290      @GwtIncompatible("doesn't work")
291      public static byte[] toByteArray(short value) {
292        return new byte[] {
293            (byte) (value >> 8),
294            (byte) value};
295      }
296    
297      /**
298       * Returns the {@code short} value whose big-endian representation is
299       * stored in the first 2 bytes of {@code bytes}; equivalent to {@code
300       * ByteBuffer.wrap(bytes).getShort()}. For example, the input byte array
301       * {@code {0x54, 0x32}} would yield the {@code short} value {@code 0x5432}.
302       *
303       * <p>Arguably, it's preferable to use {@link java.nio.ByteBuffer}; that
304       * library exposes much more flexibility at little cost in readability.
305       *
306       * @throws IllegalArgumentException if {@code bytes} has fewer than 2
307       *     elements
308       */
309      @GwtIncompatible("doesn't work")
310      public static short fromByteArray(byte[] bytes) {
311        checkArgument(bytes.length >= BYTES,
312            "array too small: %s < %s", bytes.length, BYTES);
313        return fromBytes(bytes[0], bytes[1]);
314      }
315    
316      /**
317       * Returns the {@code short} value whose byte representation is the given 2
318       * bytes, in big-endian order; equivalent to {@code Shorts.fromByteArray(new
319       * byte[] {b1, b2})}.
320       *
321       * @since 7.0
322       */
323      @GwtIncompatible("doesn't work")
324      public static short fromBytes(byte b1, byte b2) {
325        return (short) ((b1 << 8) | (b2 & 0xFF));
326      }
327    
328      /**
329       * Returns an array containing the same values as {@code array}, but
330       * guaranteed to be of a specified minimum length. If {@code array} already
331       * has a length of at least {@code minLength}, it is returned directly.
332       * Otherwise, a new array of size {@code minLength + padding} is returned,
333       * containing the values of {@code array}, and zeroes in the remaining places.
334       *
335       * @param array the source array
336       * @param minLength the minimum length the returned array must guarantee
337       * @param padding an extra amount to "grow" the array by if growth is
338       *     necessary
339       * @throws IllegalArgumentException if {@code minLength} or {@code padding} is
340       *     negative
341       * @return an array containing the values of {@code array}, with guaranteed
342       *     minimum length {@code minLength}
343       */
344      public static short[] ensureCapacity(
345          short[] array, int minLength, int padding) {
346        checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
347        checkArgument(padding >= 0, "Invalid padding: %s", padding);
348        return (array.length < minLength)
349            ? copyOf(array, minLength + padding)
350            : array;
351      }
352    
353      // Arrays.copyOf() requires Java 6
354      private static short[] copyOf(short[] original, int length) {
355        short[] copy = new short[length];
356        System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
357        return copy;
358      }
359    
360      /**
361       * Returns a string containing the supplied {@code short} values separated
362       * by {@code separator}. For example, {@code join("-", (short) 1, (short) 2,
363       * (short) 3)} returns the string {@code "1-2-3"}.
364       *
365       * @param separator the text that should appear between consecutive values in
366       *     the resulting string (but not at the start or end)
367       * @param array an array of {@code short} values, possibly empty
368       */
369      public static String join(String separator, short... array) {
370        checkNotNull(separator);
371        if (array.length == 0) {
372          return "";
373        }
374    
375        // For pre-sizing a builder, just get the right order of magnitude
376        StringBuilder builder = new StringBuilder(array.length * 6);
377        builder.append(array[0]);
378        for (int i = 1; i < array.length; i++) {
379          builder.append(separator).append(array[i]);
380        }
381        return builder.toString();
382      }
383    
384      /**
385       * Returns a comparator that compares two {@code short} arrays
386       * lexicographically. That is, it compares, using {@link
387       * #compare(short, short)}), the first pair of values that follow any
388       * common prefix, or when one array is a prefix of the other, treats the
389       * shorter array as the lesser. For example, {@code [] < [(short) 1] <
390       * [(short) 1, (short) 2] < [(short) 2]}.
391       *
392       * <p>The returned comparator is inconsistent with {@link
393       * Object#equals(Object)} (since arrays support only identity equality), but
394       * it is consistent with {@link Arrays#equals(short[], short[])}.
395       *
396       * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
397       *     Lexicographical order article at Wikipedia</a>
398       * @since 2.0
399       */
400      public static Comparator<short[]> lexicographicalComparator() {
401        return LexicographicalComparator.INSTANCE;
402      }
403    
404      private enum LexicographicalComparator implements Comparator<short[]> {
405        INSTANCE;
406    
407        @Override
408        public int compare(short[] left, short[] right) {
409          int minLength = Math.min(left.length, right.length);
410          for (int i = 0; i < minLength; i++) {
411            int result = Shorts.compare(left[i], right[i]);
412            if (result != 0) {
413              return result;
414            }
415          }
416          return left.length - right.length;
417        }
418      }
419    
420      /**
421       * Returns an array containing each value of {@code collection}, converted to
422       * a {@code short} value in the manner of {@link Number#shortValue}.
423       *
424       * <p>Elements are copied from the argument collection as if by {@code
425       * collection.toArray()}.  Calling this method is as thread-safe as calling
426       * that method.
427       *
428       * @param collection a collection of {@code Number} instances
429       * @return an array containing the same values as {@code collection}, in the
430       *     same order, converted to primitives
431       * @throws NullPointerException if {@code collection} or any of its elements
432       *     is null
433       * @since 1.0 (parameter was {@code Collection<Short>} before 12.0)
434       */
435      public static short[] toArray(Collection<? extends Number> collection) {
436        if (collection instanceof ShortArrayAsList) {
437          return ((ShortArrayAsList) collection).toShortArray();
438        }
439    
440        Object[] boxedArray = collection.toArray();
441        int len = boxedArray.length;
442        short[] array = new short[len];
443        for (int i = 0; i < len; i++) {
444          // checkNotNull for GWT (do not optimize)
445          array[i] = ((Number) checkNotNull(boxedArray[i])).shortValue();
446        }
447        return array;
448      }
449    
450      /**
451       * Returns a fixed-size list backed by the specified array, similar to {@link
452       * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)},
453       * but any attempt to set a value to {@code null} will result in a {@link
454       * NullPointerException}.
455       *
456       * <p>The returned list maintains the values, but not the identities, of
457       * {@code Short} objects written to or read from it.  For example, whether
458       * {@code list.get(0) == list.get(0)} is true for the returned list is
459       * unspecified.
460       *
461       * @param backingArray the array to back the list
462       * @return a list view of the array
463       */
464      public static List<Short> asList(short... backingArray) {
465        if (backingArray.length == 0) {
466          return Collections.emptyList();
467        }
468        return new ShortArrayAsList(backingArray);
469      }
470    
471      @GwtCompatible
472      private static class ShortArrayAsList extends AbstractList<Short>
473          implements RandomAccess, Serializable {
474        final short[] array;
475        final int start;
476        final int end;
477    
478        ShortArrayAsList(short[] array) {
479          this(array, 0, array.length);
480        }
481    
482        ShortArrayAsList(short[] array, int start, int end) {
483          this.array = array;
484          this.start = start;
485          this.end = end;
486        }
487    
488        @Override public int size() {
489          return end - start;
490        }
491    
492        @Override public boolean isEmpty() {
493          return false;
494        }
495    
496        @Override public Short get(int index) {
497          checkElementIndex(index, size());
498          return array[start + index];
499        }
500    
501        @Override public boolean contains(Object target) {
502          // Overridden to prevent a ton of boxing
503          return (target instanceof Short)
504              && Shorts.indexOf(array, (Short) target, start, end) != -1;
505        }
506    
507        @Override public int indexOf(Object target) {
508          // Overridden to prevent a ton of boxing
509          if (target instanceof Short) {
510            int i = Shorts.indexOf(array, (Short) target, start, end);
511            if (i >= 0) {
512              return i - start;
513            }
514          }
515          return -1;
516        }
517    
518        @Override public int lastIndexOf(Object target) {
519          // Overridden to prevent a ton of boxing
520          if (target instanceof Short) {
521            int i = Shorts.lastIndexOf(array, (Short) target, start, end);
522            if (i >= 0) {
523              return i - start;
524            }
525          }
526          return -1;
527        }
528    
529        @Override public Short set(int index, Short element) {
530          checkElementIndex(index, size());
531          short oldValue = array[start + index];
532          array[start + index] = checkNotNull(element);  // checkNotNull for GWT (do not optimize)
533          return oldValue;
534        }
535    
536        @Override public List<Short> subList(int fromIndex, int toIndex) {
537          int size = size();
538          checkPositionIndexes(fromIndex, toIndex, size);
539          if (fromIndex == toIndex) {
540            return Collections.emptyList();
541          }
542          return new ShortArrayAsList(array, start + fromIndex, start + toIndex);
543        }
544    
545        @Override public boolean equals(Object object) {
546          if (object == this) {
547            return true;
548          }
549          if (object instanceof ShortArrayAsList) {
550            ShortArrayAsList that = (ShortArrayAsList) object;
551            int size = size();
552            if (that.size() != size) {
553              return false;
554            }
555            for (int i = 0; i < size; i++) {
556              if (array[start + i] != that.array[that.start + i]) {
557                return false;
558              }
559            }
560            return true;
561          }
562          return super.equals(object);
563        }
564    
565        @Override public int hashCode() {
566          int result = 1;
567          for (int i = start; i < end; i++) {
568            result = 31 * result + Shorts.hashCode(array[i]);
569          }
570          return result;
571        }
572    
573        @Override public String toString() {
574          StringBuilder builder = new StringBuilder(size() * 6);
575          builder.append('[').append(array[start]);
576          for (int i = start + 1; i < end; i++) {
577            builder.append(", ").append(array[i]);
578          }
579          return builder.append(']').toString();
580        }
581    
582        short[] toShortArray() {
583          // Arrays.copyOfRange() requires Java 6
584          int size = size();
585          short[] result = new short[size];
586          System.arraycopy(array, start, result, 0, size);
587          return result;
588        }
589    
590        private static final long serialVersionUID = 0;
591      }
592    }