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