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