1/*
2 * Copyright (C) 2008 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.primitives;
18
19import static com.google.common.base.Preconditions.checkArgument;
20import static com.google.common.base.Preconditions.checkElementIndex;
21import static com.google.common.base.Preconditions.checkNotNull;
22import static com.google.common.base.Preconditions.checkPositionIndexes;
23
24import com.google.common.annotations.Beta;
25import com.google.common.annotations.GwtCompatible;
26import com.google.common.annotations.GwtIncompatible;
27
28import java.io.Serializable;
29import java.util.AbstractList;
30import java.util.Arrays;
31import java.util.Collection;
32import java.util.Collections;
33import java.util.Comparator;
34import java.util.List;
35import java.util.RandomAccess;
36
37import javax.annotation.CheckForNull;
38
39/**
40 * Static utility methods pertaining to {@code int} primitives, that are not
41 * already found in either {@link Integer} or {@link Arrays}.
42 *
43 * @author Kevin Bourrillion
44 * @since 1.0
45 */
46@GwtCompatible(emulated = true)
47public final class Ints {
48  private Ints() {}
49
50  /**
51   * The number of bytes required to represent a primitive {@code int}
52   * value.
53   */
54  public static final int BYTES = Integer.SIZE / Byte.SIZE;
55
56  /**
57   * The largest power of two that can be represented as an {@code int}.
58   *
59   * @since 10.0
60   */
61  public static final int MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2);
62
63  /**
64   * Returns a hash code for {@code value}; equal to the result of invoking
65   * {@code ((Integer) value).hashCode()}.
66   *
67   * @param value a primitive {@code int} value
68   * @return a hash code for the value
69   */
70  public static int hashCode(int value) {
71    return value;
72  }
73
74  /**
75   * Returns the {@code int} value that is equal to {@code value}, if possible.
76   *
77   * @param value any value in the range of the {@code int} type
78   * @return the {@code int} value that equals {@code value}
79   * @throws IllegalArgumentException if {@code value} is greater than {@link
80   *     Integer#MAX_VALUE} or less than {@link Integer#MIN_VALUE}
81   */
82  public static int checkedCast(long value) {
83    int result = (int) value;
84    checkArgument(result == value, "Out of range: %s", value);
85    return result;
86  }
87
88  /**
89   * Returns the {@code int} nearest in value to {@code value}.
90   *
91   * @param value any {@code long} value
92   * @return the same value cast to {@code int} if it is in the range of the
93   *     {@code int} type, {@link Integer#MAX_VALUE} if it is too large,
94   *     or {@link Integer#MIN_VALUE} if it is too small
95   */
96  public static int saturatedCast(long value) {
97    if (value > Integer.MAX_VALUE) {
98      return Integer.MAX_VALUE;
99    }
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}
615