    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          // checkNotNull for GWT (do not optimize)
    533          array[start + index] = checkNotNull(element);
    534          return oldValue;
    535        }
    536
    537        @Override public List<Short> subList(int fromIndex, int toIndex) {
    538          int size = size();
    539          checkPositionIndexes(fromIndex, toIndex, size);
    540          if (fromIndex == toIndex) {
    541            return Collections.emptyList();
    542          }
    543          return new ShortArrayAsList(array, start + fromIndex, start + toIndex);
    544        }
    545
    546        @Override public boolean equals(Object object) {
    547          if (object == this) {
    548            return true;
    549          }
    550          if (object instanceof ShortArrayAsList) {
    551            ShortArrayAsList that = (ShortArrayAsList) object;
    552            int size = size();
    553            if (that.size() != size) {
    554              return false;
    555            }
    556            for (int i = 0; i < size; i++) {
    557              if (array[start + i] != that.array[that.start + i]) {
    558                return false;
    559              }
    560            }
    561            return true;
    562          }
    563          return super.equals(object);
    564        }
    565
    566        @Override public int hashCode() {
    567          int result = 1;
    568          for (int i = start; i < end; i++) {
    569            result = 31 * result + Shorts.hashCode(array[i]);
    570          }
    571          return result;
    572        }
    573
    574        @Override public String toString() {
    575          StringBuilder builder = new StringBuilder(size() * 6);
    576          builder.append('[').append(array[start]);
    577          for (int i = start + 1; i < end; i++) {
    578            builder.append(", ").append(array[i]);
    579          }
    580          return builder.append(']').toString();
    581        }
    582
    583        short[] toShortArray() {
    584          // Arrays.copyOfRange() is not available under GWT
    585          int size = size();
    586          short[] result = new short[size];
    587          System.arraycopy(array, start, result, 0, size);
    588          return result;
    589        }
    590
    591        private static final long serialVersionUID = 0;
    592      }
    593    }