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