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