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.common.annotations.GwtIncompatible;
025import com.google.common.annotations.J2ktIncompatible;
026import com.google.errorprone.annotations.InlineMe;
027import java.io.Serializable;
028import java.util.AbstractList;
029import java.util.Arrays;
030import java.util.Collection;
031import java.util.Collections;
032import java.util.Comparator;
033import java.util.List;
034import java.util.RandomAccess;
035import org.jspecify.annotations.Nullable;
036
037/**
038 * Static utility methods pertaining to {@code boolean} primitives, that are not already found in
039 * either {@link Boolean} or {@link Arrays}.
040 *
041 * <p>See the Guava User Guide article on <a
042 * href="https://github.com/google/guava/wiki/PrimitivesExplained">primitive utilities</a>.
043 *
044 * @author Kevin Bourrillion
045 * @since 1.0
046 */
047@GwtCompatible
048public final class Booleans {
049  private Booleans() {}
050
051  /** Comparators for {@code Boolean} values. */
052  private enum BooleanComparator implements Comparator<Boolean> {
053    TRUE_FIRST(1, "Booleans.trueFirst()"),
054    FALSE_FIRST(-1, "Booleans.falseFirst()");
055
056    private final int trueValue;
057    private final String toString;
058
059    BooleanComparator(int trueValue, String toString) {
060      this.trueValue = trueValue;
061      this.toString = toString;
062    }
063
064    @Override
065    public int compare(Boolean a, Boolean b) {
066      int aVal = a ? trueValue : 0;
067      int bVal = b ? trueValue : 0;
068      return bVal - aVal;
069    }
070
071    @Override
072    public String toString() {
073      return toString;
074    }
075  }
076
077  /**
078   * Returns a {@code Comparator<Boolean>} that sorts {@code true} before {@code false}.
079   *
080   * <p>This is particularly useful in Java 8+ in combination with {@code Comparator.comparing},
081   * e.g. {@code Comparator.comparing(Foo::hasBar, trueFirst())}.
082   *
083   * @since 21.0
084   */
085  public static Comparator<Boolean> trueFirst() {
086    return BooleanComparator.TRUE_FIRST;
087  }
088
089  /**
090   * Returns a {@code Comparator<Boolean>} that sorts {@code false} before {@code true}.
091   *
092   * <p>This is particularly useful in Java 8+ in combination with {@code Comparator.comparing},
093   * e.g. {@code Comparator.comparing(Foo::hasBar, falseFirst())}.
094   *
095   * @since 21.0
096   */
097  public static Comparator<Boolean> falseFirst() {
098    return BooleanComparator.FALSE_FIRST;
099  }
100
101  /**
102   * Returns a hash code for {@code value}; equal to the result of invoking {@code ((Boolean)
103   * value).hashCode()}.
104   *
105   * <p><b>Java 8+ users:</b> use {@link Boolean#hashCode(boolean)} instead.
106   *
107   * @param value a primitive {@code boolean} value
108   * @return a hash code for the value
109   */
110  public static int hashCode(boolean value) {
111    return value ? 1231 : 1237;
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      System.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      int minLength = min(left.length, right.length);
326      for (int i = 0; i < minLength; i++) {
327        int result = Boolean.compare(left[i], right[i]);
328        if (result != 0) {
329          return result;
330        }
331      }
332      return left.length - right.length;
333    }
334
335    @Override
336    public String toString() {
337      return "Booleans.lexicographicalComparator()";
338    }
339  }
340
341  /**
342   * Copies a collection of {@code Boolean} instances into a new array of primitive {@code boolean}
343   * values.
344   *
345   * <p>Elements are copied from the argument collection as if by {@code collection.toArray()}.
346   * Calling this method is as thread-safe as calling that method.
347   *
348   * <p><b>Note:</b> consider representing the collection as a {@link java.util.BitSet} instead.
349   *
350   * @param collection a collection of {@code Boolean} objects
351   * @return an array containing the same values as {@code collection}, in the same order, converted
352   *     to primitives
353   * @throws NullPointerException if {@code collection} or any of its elements is null
354   */
355  public static boolean[] toArray(Collection<Boolean> collection) {
356    if (collection instanceof BooleanArrayAsList) {
357      return ((BooleanArrayAsList) collection).toBooleanArray();
358    }
359
360    Object[] boxedArray = collection.toArray();
361    int len = boxedArray.length;
362    boolean[] array = new boolean[len];
363    for (int i = 0; i < len; i++) {
364      // checkNotNull for GWT (do not optimize)
365      array[i] = (Boolean) checkNotNull(boxedArray[i]);
366    }
367    return array;
368  }
369
370  /**
371   * Returns a fixed-size list backed by the specified array, similar to {@link
372   * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)}, but any attempt to
373   * set a value to {@code null} will result in a {@link NullPointerException}.
374   *
375   * <p>There are at most two distinct objects in this list, {@code (Boolean) true} and {@code
376   * (Boolean) false}. Java guarantees that those are always represented by the same objects.
377   *
378   * <p>The returned list is serializable.
379   *
380   * @param backingArray the array to back the list
381   * @return a list view of the array
382   */
383  public static List<Boolean> asList(boolean... backingArray) {
384    if (backingArray.length == 0) {
385      return Collections.emptyList();
386    }
387    return new BooleanArrayAsList(backingArray);
388  }
389
390  @GwtCompatible
391  private static class BooleanArrayAsList extends AbstractList<Boolean>
392      implements RandomAccess, Serializable {
393    final boolean[] array;
394    final int start;
395    final int end;
396
397    BooleanArrayAsList(boolean[] array) {
398      this(array, 0, array.length);
399    }
400
401    BooleanArrayAsList(boolean[] array, int start, int end) {
402      this.array = array;
403      this.start = start;
404      this.end = end;
405    }
406
407    @Override
408    public int size() {
409      return end - start;
410    }
411
412    @Override
413    public boolean isEmpty() {
414      return false;
415    }
416
417    @Override
418    public Boolean get(int index) {
419      checkElementIndex(index, size());
420      return array[start + index];
421    }
422
423    @Override
424    public boolean contains(@Nullable Object target) {
425      // Overridden to prevent a ton of boxing
426      return (target instanceof Boolean)
427          && Booleans.indexOf(array, (Boolean) target, start, end) != -1;
428    }
429
430    @Override
431    public int indexOf(@Nullable Object target) {
432      // Overridden to prevent a ton of boxing
433      if (target instanceof Boolean) {
434        int i = Booleans.indexOf(array, (Boolean) target, start, end);
435        if (i >= 0) {
436          return i - start;
437        }
438      }
439      return -1;
440    }
441
442    @Override
443    public int lastIndexOf(@Nullable Object target) {
444      // Overridden to prevent a ton of boxing
445      if (target instanceof Boolean) {
446        int i = Booleans.lastIndexOf(array, (Boolean) target, start, end);
447        if (i >= 0) {
448          return i - start;
449        }
450      }
451      return -1;
452    }
453
454    @Override
455    public Boolean set(int index, Boolean element) {
456      checkElementIndex(index, size());
457      boolean oldValue = array[start + index];
458      // checkNotNull for GWT (do not optimize)
459      array[start + index] = checkNotNull(element);
460      return oldValue;
461    }
462
463    @Override
464    public List<Boolean> subList(int fromIndex, int toIndex) {
465      int size = size();
466      checkPositionIndexes(fromIndex, toIndex, size);
467      if (fromIndex == toIndex) {
468        return Collections.emptyList();
469      }
470      return new BooleanArrayAsList(array, start + fromIndex, start + toIndex);
471    }
472
473    @Override
474    public boolean equals(@Nullable Object object) {
475      if (object == this) {
476        return true;
477      }
478      if (object instanceof BooleanArrayAsList) {
479        BooleanArrayAsList that = (BooleanArrayAsList) object;
480        int size = size();
481        if (that.size() != size) {
482          return false;
483        }
484        for (int i = 0; i < size; i++) {
485          if (array[start + i] != that.array[that.start + i]) {
486            return false;
487          }
488        }
489        return true;
490      }
491      return super.equals(object);
492    }
493
494    @Override
495    public int hashCode() {
496      int result = 1;
497      for (int i = start; i < end; i++) {
498        result = 31 * result + Booleans.hashCode(array[i]);
499      }
500      return result;
501    }
502
503    @Override
504    public String toString() {
505      StringBuilder builder = new StringBuilder(size() * 7);
506      builder.append(array[start] ? "[true" : "[false");
507      for (int i = start + 1; i < end; i++) {
508        builder.append(array[i] ? ", true" : ", false");
509      }
510      return builder.append(']').toString();
511    }
512
513    boolean[] toBooleanArray() {
514      return Arrays.copyOfRange(array, start, end);
515    }
516
517    @GwtIncompatible @J2ktIncompatible private static final long serialVersionUID = 0;
518  }
519
520  /**
521   * Returns the number of {@code values} that are {@code true}.
522   *
523   * @since 16.0
524   */
525  public static int countTrue(boolean... values) {
526    int count = 0;
527    for (boolean value : values) {
528      if (value) {
529        count++;
530      }
531    }
532    return count;
533  }
534
535  /**
536   * Reverses the elements of {@code array}. This is equivalent to {@code
537   * Collections.reverse(Booleans.asList(array))}, but is likely to be more efficient.
538   *
539   * @since 23.1
540   */
541  public static void reverse(boolean[] array) {
542    checkNotNull(array);
543    reverse(array, 0, array.length);
544  }
545
546  /**
547   * Reverses the elements of {@code array} between {@code fromIndex} inclusive and {@code toIndex}
548   * exclusive. This is equivalent to {@code
549   * Collections.reverse(Booleans.asList(array).subList(fromIndex, toIndex))}, but is likely to be
550   * more efficient.
551   *
552   * @throws IndexOutOfBoundsException if {@code fromIndex < 0}, {@code toIndex > array.length}, or
553   *     {@code toIndex > fromIndex}
554   * @since 23.1
555   */
556  public static void reverse(boolean[] array, int fromIndex, int toIndex) {
557    checkNotNull(array);
558    checkPositionIndexes(fromIndex, toIndex, array.length);
559    for (int i = fromIndex, j = toIndex - 1; i < j; i++, j--) {
560      boolean tmp = array[i];
561      array[i] = array[j];
562      array[j] = tmp;
563    }
564  }
565
566  /**
567   * Performs a right rotation of {@code array} of "distance" places, so that the first element is
568   * moved to index "distance", and the element at index {@code i} ends up at index {@code (distance
569   * + i) mod array.length}. This is equivalent to {@code Collections.rotate(Booleans.asList(array),
570   * distance)}, but is somewhat faster.
571   *
572   * <p>The provided "distance" may be negative, which will rotate left.
573   *
574   * @since 32.0.0
575   */
576  public static void rotate(boolean[] array, int distance) {
577    rotate(array, distance, 0, array.length);
578  }
579
580  /**
581   * Performs a right rotation of {@code array} between {@code fromIndex} inclusive and {@code
582   * toIndex} exclusive. This is equivalent to {@code
583   * Collections.rotate(Booleans.asList(array).subList(fromIndex, toIndex), distance)}, but is
584   * somewhat faster.
585   *
586   * <p>The provided "distance" may be negative, which will rotate left.
587   *
588   * @throws IndexOutOfBoundsException if {@code fromIndex < 0}, {@code toIndex > array.length}, or
589   *     {@code toIndex > fromIndex}
590   * @since 32.0.0
591   */
592  public static void rotate(boolean[] array, int distance, int fromIndex, int toIndex) {
593    // See Ints.rotate for more details about possible algorithms here.
594    checkNotNull(array);
595    checkPositionIndexes(fromIndex, toIndex, array.length);
596    if (array.length <= 1) {
597      return;
598    }
599
600    int length = toIndex - fromIndex;
601    // Obtain m = (-distance mod length), a non-negative value less than "length". This is how many
602    // places left to rotate.
603    int m = -distance % length;
604    m = (m < 0) ? m + length : m;
605    // The current index of what will become the first element of the rotated section.
606    int newFirstIndex = m + fromIndex;
607    if (newFirstIndex == fromIndex) {
608      return;
609    }
610
611    reverse(array, fromIndex, newFirstIndex);
612    reverse(array, newFirstIndex, toIndex);
613    reverse(array, fromIndex, toIndex);
614  }
615}