Coverage Summary for Class: UnsignedInts (com.google.common.primitives)

Class Method, % Line, %
UnsignedInts 4.8% (1/21) 2.7% (2/73)
UnsignedInts$LexicographicalComparator 0% (0/3) 0% (0/8)
Total 4.2% (1/24) 2.5% (2/81)


1 /* 2  * Copyright (C) 2011 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5  * in compliance with the License. You may obtain a copy of the License at 6  * 7  * http://www.apache.org/licenses/LICENSE-2.0 8  * 9  * Unless required by applicable law or agreed to in writing, software distributed under the License 10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11  * or implied. See the License for the specific language governing permissions and limitations under 12  * the License. 13  */ 14  15 package com.google.common.primitives; 16  17 import static com.google.common.base.Preconditions.checkArgument; 18 import static com.google.common.base.Preconditions.checkNotNull; 19 import static com.google.common.base.Preconditions.checkPositionIndexes; 20  21 import com.google.common.annotations.Beta; 22 import com.google.common.annotations.GwtCompatible; 23 import com.google.errorprone.annotations.CanIgnoreReturnValue; 24 import java.util.Arrays; 25 import java.util.Comparator; 26  27 /** 28  * Static utility methods pertaining to {@code int} primitives that interpret values as 29  * <i>unsigned</i> (that is, any negative value {@code x} is treated as the positive value {@code 30  * 2^32 + x}). The methods for which signedness is not an issue are in {@link Ints}, as well as 31  * signed versions of methods for which signedness is an issue. 32  * 33  * <p>In addition, this class provides several static methods for converting an {@code int} to a 34  * {@code String} and a {@code String} to an {@code int} that treat the {@code int} as an unsigned 35  * number. 36  * 37  * <p>Users of these utilities must be <i>extremely careful</i> not to mix up signed and unsigned 38  * {@code int} values. When possible, it is recommended that the {@link UnsignedInteger} wrapper 39  * class be used, at a small efficiency penalty, to enforce the distinction in the type system. 40  * 41  * <p>See the Guava User Guide article on <a 42  * href="https://github.com/google/guava/wiki/PrimitivesExplained#unsigned-support">unsigned 43  * primitive utilities</a>. 44  * 45  * @author Louis Wasserman 46  * @since 11.0 47  */ 48 @Beta 49 @GwtCompatible 50 @ElementTypesAreNonnullByDefault 51 public final class UnsignedInts { 52  static final long INT_MASK = 0xffffffffL; 53  54  private UnsignedInts() {} 55  56  static int flip(int value) { 57  return value ^ Integer.MIN_VALUE; 58  } 59  60  /** 61  * Compares the two specified {@code int} values, treating them as unsigned values between {@code 62  * 0} and {@code 2^32 - 1} inclusive. 63  * 64  * <p><b>Java 8 users:</b> use {@link Integer#compareUnsigned(int, int)} instead. 65  * 66  * @param a the first unsigned {@code int} to compare 67  * @param b the second unsigned {@code int} to compare 68  * @return a negative value if {@code a} is less than {@code b}; a positive value if {@code a} is 69  * greater than {@code b}; or zero if they are equal 70  */ 71  public static int compare(int a, int b) { 72  return Ints.compare(flip(a), flip(b)); 73  } 74  75  /** 76  * Returns the value of the given {@code int} as a {@code long}, when treated as unsigned. 77  * 78  * <p><b>Java 8 users:</b> use {@link Integer#toUnsignedLong(int)} instead. 79  */ 80  public static long toLong(int value) { 81  return value & INT_MASK; 82  } 83  84  /** 85  * Returns the {@code int} value that, when treated as unsigned, is equal to {@code value}, if 86  * possible. 87  * 88  * @param value a value between 0 and 2<sup>32</sup>-1 inclusive 89  * @return the {@code int} value that, when treated as unsigned, equals {@code value} 90  * @throws IllegalArgumentException if {@code value} is negative or greater than or equal to 91  * 2<sup>32</sup> 92  * @since 21.0 93  */ 94  public static int checkedCast(long value) { 95  checkArgument((value >> Integer.SIZE) == 0, "out of range: %s", value); 96  return (int) value; 97  } 98  99  /** 100  * Returns the {@code int} value that, when treated as unsigned, is nearest in value to {@code 101  * value}. 102  * 103  * @param value any {@code long} value 104  * @return {@code 2^32 - 1} if {@code value >= 2^32}, {@code 0} if {@code value <= 0}, and {@code 105  * value} cast to {@code int} otherwise 106  * @since 21.0 107  */ 108  public static int saturatedCast(long value) { 109  if (value <= 0) { 110  return 0; 111  } else if (value >= (1L << 32)) { 112  return -1; 113  } else { 114  return (int) value; 115  } 116  } 117  118  /** 119  * Returns the least value present in {@code array}, treating values as unsigned. 120  * 121  * @param array a <i>nonempty</i> array of unsigned {@code int} values 122  * @return the value present in {@code array} that is less than or equal to every other value in 123  * the array according to {@link #compare} 124  * @throws IllegalArgumentException if {@code array} is empty 125  */ 126  public static int min(int... array) { 127  checkArgument(array.length > 0); 128  int min = flip(array[0]); 129  for (int i = 1; i < array.length; i++) { 130  int next = flip(array[i]); 131  if (next < min) { 132  min = next; 133  } 134  } 135  return flip(min); 136  } 137  138  /** 139  * Returns the greatest value present in {@code array}, treating values as unsigned. 140  * 141  * @param array a <i>nonempty</i> array of unsigned {@code int} values 142  * @return the value present in {@code array} that is greater than or equal to every other value 143  * in the array according to {@link #compare} 144  * @throws IllegalArgumentException if {@code array} is empty 145  */ 146  public static int max(int... array) { 147  checkArgument(array.length > 0); 148  int max = flip(array[0]); 149  for (int i = 1; i < array.length; i++) { 150  int next = flip(array[i]); 151  if (next > max) { 152  max = next; 153  } 154  } 155  return flip(max); 156  } 157  158  /** 159  * Returns a string containing the supplied unsigned {@code int} values separated by {@code 160  * separator}. For example, {@code join("-", 1, 2, 3)} returns the string {@code "1-2-3"}. 161  * 162  * @param separator the text that should appear between consecutive values in the resulting string 163  * (but not at the start or end) 164  * @param array an array of unsigned {@code int} values, possibly empty 165  */ 166  public static String join(String separator, int... array) { 167  checkNotNull(separator); 168  if (array.length == 0) { 169  return ""; 170  } 171  172  // For pre-sizing a builder, just get the right order of magnitude 173  StringBuilder builder = new StringBuilder(array.length * 5); 174  builder.append(toString(array[0])); 175  for (int i = 1; i < array.length; i++) { 176  builder.append(separator).append(toString(array[i])); 177  } 178  return builder.toString(); 179  } 180  181  /** 182  * Returns a comparator that compares two arrays of unsigned {@code int} values <a 183  * href="http://en.wikipedia.org/wiki/Lexicographical_order">lexicographically</a>. That is, it 184  * compares, using {@link #compare(int, int)}), the first pair of values that follow any common 185  * prefix, or when one array is a prefix of the other, treats the shorter array as the lesser. For 186  * example, {@code [] < [1] < [1, 2] < [2] < [1 << 31]}. 187  * 188  * <p>The returned comparator is inconsistent with {@link Object#equals(Object)} (since arrays 189  * support only identity equality), but it is consistent with {@link Arrays#equals(int[], int[])}. 190  */ 191  public static Comparator<int[]> lexicographicalComparator() { 192  return LexicographicalComparator.INSTANCE; 193  } 194  195  enum LexicographicalComparator implements Comparator<int[]> { 196  INSTANCE; 197  198  @Override 199  public int compare(int[] left, int[] right) { 200  int minLength = Math.min(left.length, right.length); 201  for (int i = 0; i < minLength; i++) { 202  if (left[i] != right[i]) { 203  return UnsignedInts.compare(left[i], right[i]); 204  } 205  } 206  return left.length - right.length; 207  } 208  209  @Override 210  public String toString() { 211  return "UnsignedInts.lexicographicalComparator()"; 212  } 213  } 214  215  /** 216  * Sorts the array, treating its elements as unsigned 32-bit integers. 217  * 218  * @since 23.1 219  */ 220  public static void sort(int[] array) { 221  checkNotNull(array); 222  sort(array, 0, array.length); 223  } 224  225  /** 226  * Sorts the array between {@code fromIndex} inclusive and {@code toIndex} exclusive, treating its 227  * elements as unsigned 32-bit integers. 228  * 229  * @since 23.1 230  */ 231  public static void sort(int[] array, int fromIndex, int toIndex) { 232  checkNotNull(array); 233  checkPositionIndexes(fromIndex, toIndex, array.length); 234  for (int i = fromIndex; i < toIndex; i++) { 235  array[i] = flip(array[i]); 236  } 237  Arrays.sort(array, fromIndex, toIndex); 238  for (int i = fromIndex; i < toIndex; i++) { 239  array[i] = flip(array[i]); 240  } 241  } 242  243  /** 244  * Sorts the elements of {@code array} in descending order, interpreting them as unsigned 32-bit 245  * integers. 246  * 247  * @since 23.1 248  */ 249  public static void sortDescending(int[] array) { 250  checkNotNull(array); 251  sortDescending(array, 0, array.length); 252  } 253  254  /** 255  * Sorts the elements of {@code array} between {@code fromIndex} inclusive and {@code toIndex} 256  * exclusive in descending order, interpreting them as unsigned 32-bit integers. 257  * 258  * @since 23.1 259  */ 260  public static void sortDescending(int[] array, int fromIndex, int toIndex) { 261  checkNotNull(array); 262  checkPositionIndexes(fromIndex, toIndex, array.length); 263  for (int i = fromIndex; i < toIndex; i++) { 264  array[i] ^= Integer.MAX_VALUE; 265  } 266  Arrays.sort(array, fromIndex, toIndex); 267  for (int i = fromIndex; i < toIndex; i++) { 268  array[i] ^= Integer.MAX_VALUE; 269  } 270  } 271  272  /** 273  * Returns dividend / divisor, where the dividend and divisor are treated as unsigned 32-bit 274  * quantities. 275  * 276  * <p><b>Java 8 users:</b> use {@link Integer#divideUnsigned(int, int)} instead. 277  * 278  * @param dividend the dividend (numerator) 279  * @param divisor the divisor (denominator) 280  * @throws ArithmeticException if divisor is 0 281  */ 282  public static int divide(int dividend, int divisor) { 283  return (int) (toLong(dividend) / toLong(divisor)); 284  } 285  286  /** 287  * Returns dividend % divisor, where the dividend and divisor are treated as unsigned 32-bit 288  * quantities. 289  * 290  * <p><b>Java 8 users:</b> use {@link Integer#remainderUnsigned(int, int)} instead. 291  * 292  * @param dividend the dividend (numerator) 293  * @param divisor the divisor (denominator) 294  * @throws ArithmeticException if divisor is 0 295  */ 296  public static int remainder(int dividend, int divisor) { 297  return (int) (toLong(dividend) % toLong(divisor)); 298  } 299  300  /** 301  * Returns the unsigned {@code int} value represented by the given string. 302  * 303  * <p>Accepts a decimal, hexadecimal, or octal number given by specifying the following prefix: 304  * 305  * <ul> 306  * <li>{@code 0x}<i>HexDigits</i> 307  * <li>{@code 0X}<i>HexDigits</i> 308  * <li>{@code #}<i>HexDigits</i> 309  * <li>{@code 0}<i>OctalDigits</i> 310  * </ul> 311  * 312  * @throws NumberFormatException if the string does not contain a valid unsigned {@code int} value 313  * @since 13.0 314  */ 315  @CanIgnoreReturnValue 316  public static int decode(String stringValue) { 317  ParseRequest request = ParseRequest.fromString(stringValue); 318  319  try { 320  return parseUnsignedInt(request.rawValue, request.radix); 321  } catch (NumberFormatException e) { 322  NumberFormatException decodeException = 323  new NumberFormatException("Error parsing value: " + stringValue); 324  decodeException.initCause(e); 325  throw decodeException; 326  } 327  } 328  329  /** 330  * Returns the unsigned {@code int} value represented by the given decimal string. 331  * 332  * <p><b>Java 8 users:</b> use {@link Integer#parseUnsignedInt(String)} instead. 333  * 334  * @throws NumberFormatException if the string does not contain a valid unsigned {@code int} value 335  * @throws NullPointerException if {@code s} is null (in contrast to {@link 336  * Integer#parseInt(String)}) 337  */ 338  @CanIgnoreReturnValue 339  public static int parseUnsignedInt(String s) { 340  return parseUnsignedInt(s, 10); 341  } 342  343  /** 344  * Returns the unsigned {@code int} value represented by a string with the given radix. 345  * 346  * <p><b>Java 8 users:</b> use {@link Integer#parseUnsignedInt(String, int)} instead. 347  * 348  * @param string the string containing the unsigned integer representation to be parsed. 349  * @param radix the radix to use while parsing {@code s}; must be between {@link 350  * Character#MIN_RADIX} and {@link Character#MAX_RADIX}. 351  * @throws NumberFormatException if the string does not contain a valid unsigned {@code int}, or 352  * if supplied radix is invalid. 353  * @throws NullPointerException if {@code s} is null (in contrast to {@link 354  * Integer#parseInt(String)}) 355  */ 356  @CanIgnoreReturnValue 357  public static int parseUnsignedInt(String string, int radix) { 358  checkNotNull(string); 359  long result = Long.parseLong(string, radix); 360  if ((result & INT_MASK) != result) { 361  throw new NumberFormatException( 362  "Input " + string + " in base " + radix + " is not in the range of an unsigned integer"); 363  } 364  return (int) result; 365  } 366  367  /** 368  * Returns a string representation of x, where x is treated as unsigned. 369  * 370  * <p><b>Java 8 users:</b> use {@link Integer#toUnsignedString(int)} instead. 371  */ 372  public static String toString(int x) { 373  return toString(x, 10); 374  } 375  376  /** 377  * Returns a string representation of {@code x} for the given radix, where {@code x} is treated as 378  * unsigned. 379  * 380  * <p><b>Java 8 users:</b> use {@link Integer#toUnsignedString(int, int)} instead. 381  * 382  * @param x the value to convert to a string. 383  * @param radix the radix to use while working with {@code x} 384  * @throws IllegalArgumentException if {@code radix} is not between {@link Character#MIN_RADIX} 385  * and {@link Character#MAX_RADIX}. 386  */ 387  public static String toString(int x, int radix) { 388  long asLong = x & INT_MASK; 389  return Long.toString(asLong, radix); 390  } 391 }