Update #0 - First Release

This commit is contained in:
LAX1DUDE
2022-12-25 01:12:28 -08:00
commit e7179fad45
2154 changed files with 256324 additions and 0 deletions

View File

@ -0,0 +1,503 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Static utility methods pertaining to {@code boolean} primitives, that are not
* already found in either {@link Boolean} or {@link Arrays}.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
@GwtCompatible
public final class Booleans {
private Booleans() {
}
/**
* Returns a hash code for {@code value}; equal to the result of invoking
* {@code ((Boolean) value).hashCode()}.
*
* @param value a primitive {@code boolean} value
* @return a hash code for the value
*/
public static int hashCode(boolean value) {
return value ? 1231 : 1237;
}
/**
* Compares the two specified {@code boolean} values in the standard way
* ({@code false} is considered less than {@code true}). The sign of the value
* returned is the same as that of {@code ((Boolean) a).compareTo(b)}.
*
* <p>
* <b>Note:</b> projects using JDK 7 or later should use the equivalent
* {@link Boolean#compare} method instead.
*
* @param a the first {@code boolean} to compare
* @param b the second {@code boolean} to compare
* @return a positive number if only {@code a} is {@code true}, a negative
* number if only {@code b} is true, or zero if {@code a == b}
*/
public static int compare(boolean a, boolean b) {
return (a == b) ? 0 : (a ? 1 : -1);
}
/**
* Returns {@code true} if {@code target} is present as an element anywhere in
* {@code array}.
*
* <p>
* <b>Note:</b> consider representing the array as a {@link BitSet} instead,
* replacing {@code Booleans.contains(array, true)} with
* {@code !bitSet.isEmpty()} and {@code Booleans.contains(array, false)} with
* {@code bitSet.nextClearBit(0) == sizeOfBitSet}.
*
* @param array an array of {@code boolean} values, possibly empty
* @param target a primitive {@code boolean} value
* @return {@code true} if {@code array[i] == target} for some value of {@code
* i}
*/
public static boolean contains(boolean[] array, boolean target) {
for (boolean value : array) {
if (value == target) {
return true;
}
}
return false;
}
/**
* Returns the index of the first appearance of the value {@code target} in
* {@code array}.
*
* <p>
* <b>Note:</b> consider representing the array as a {@link BitSet} instead, and
* using {@link BitSet#nextSetBit(int)} or {@link BitSet#nextClearBit(int)}.
*
* @param array an array of {@code boolean} values, possibly empty
* @param target a primitive {@code boolean} value
* @return the least index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int indexOf(boolean[] array, boolean target) {
return indexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int indexOf(boolean[] array, boolean target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the start position of the first occurrence of the specified {@code
* target} within {@code array}, or {@code -1} if there is no such occurrence.
*
* <p>
* More formally, returns the lowest index {@code i} such that {@code
* java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
* the same elements as {@code target}.
*
* @param array the array to search for the sequence {@code target}
* @param target the array to search for as a sub-sequence of {@code array}
*/
public static int indexOf(boolean[] array, boolean[] target) {
checkNotNull(array, "array");
checkNotNull(target, "target");
if (target.length == 0) {
return 0;
}
outer: for (int i = 0; i < array.length - target.length + 1; i++) {
for (int j = 0; j < target.length; j++) {
if (array[i + j] != target[j]) {
continue outer;
}
}
return i;
}
return -1;
}
/**
* Returns the index of the last appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code boolean} values, possibly empty
* @param target a primitive {@code boolean} value
* @return the greatest index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int lastIndexOf(boolean[] array, boolean target) {
return lastIndexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int lastIndexOf(boolean[] array, boolean target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the values from each provided array combined into a single array. For
* example, {@code concat(new boolean[] {a, b}, new boolean[] {}, new boolean[]
* {c}} returns the array {@code {a, b, c}}.
*
* @param arrays zero or more {@code boolean} arrays
* @return a single array containing all the values from the source arrays, in
* order
*/
public static boolean[] concat(boolean[]... arrays) {
int length = 0;
for (boolean[] array : arrays) {
length += array.length;
}
boolean[] result = new boolean[length];
int pos = 0;
for (boolean[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}
/**
* Returns an array containing the same values as {@code array}, but guaranteed
* to be of a specified minimum length. If {@code array} already has a length of
* at least {@code minLength}, it is returned directly. Otherwise, a new array
* of size {@code minLength + padding} is returned, containing the values of
* {@code array}, and zeroes in the remaining places.
*
* @param array the source array
* @param minLength the minimum length the returned array must guarantee
* @param padding an extra amount to "grow" the array by if growth is
* necessary
* @throws IllegalArgumentException if {@code minLength} or {@code padding} is
* negative
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
public static boolean[] ensureCapacity(boolean[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength) ? copyOf(array, minLength + padding) : array;
}
// Arrays.copyOf() requires Java 6
private static boolean[] copyOf(boolean[] original, int length) {
boolean[] copy = new boolean[length];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
return copy;
}
/**
* Returns a string containing the supplied {@code boolean} values separated by
* {@code separator}. For example, {@code join("-", false, true, false)} returns
* the string {@code "false-true-false"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of {@code boolean} values, possibly empty
*/
public static String join(String separator, boolean... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 7);
builder.append(array[0]);
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(array[i]);
}
return builder.toString();
}
/**
* Returns a comparator that compares two {@code boolean} arrays
* lexicographically. That is, it compares, using
* {@link #compare(boolean, boolean)}), the first pair of values that follow any
* common prefix, or when one array is a prefix of the other, treats the shorter
* array as the lesser. For example,
* {@code [] < [false] < [false, true] < [true]}.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link Arrays#equals(boolean[], boolean[])}.
*
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
* Lexicographical order article at Wikipedia</a>
* @since 2.0
*/
public static Comparator<boolean[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
private enum LexicographicalComparator implements Comparator<boolean[]> {
INSTANCE;
@Override
public int compare(boolean[] left, boolean[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
int result = Booleans.compare(left[i], right[i]);
if (result != 0) {
return result;
}
}
return left.length - right.length;
}
}
/**
* Copies a collection of {@code Boolean} instances into a new array of
* primitive {@code boolean} values.
*
* <p>
* Elements are copied from the argument collection as if by {@code
* collection.toArray()}. Calling this method is as thread-safe as calling that
* method.
*
* <p>
* <b>Note:</b> consider representing the collection as a {@link BitSet}
* instead.
*
* @param collection a collection of {@code Boolean} objects
* @return an array containing the same values as {@code collection}, in the
* same order, converted to primitives
* @throws NullPointerException if {@code collection} or any of its elements is
* null
*/
public static boolean[] toArray(Collection<Boolean> collection) {
if (collection instanceof BooleanArrayAsList) {
return ((BooleanArrayAsList) collection).toBooleanArray();
}
Object[] boxedArray = collection.toArray();
int len = boxedArray.length;
boolean[] array = new boolean[len];
for (int i = 0; i < len; i++) {
// checkNotNull for GWT (do not optimize)
array[i] = (Boolean) checkNotNull(boxedArray[i]);
}
return array;
}
/**
* Returns a fixed-size list backed by the specified array, similar to
* {@link Arrays#asList(Object[])}. The list supports
* {@link List#set(int, Object)}, but any attempt to set a value to {@code null}
* will result in a {@link NullPointerException}.
*
* <p>
* The returned list maintains the values, but not the identities, of
* {@code Boolean} objects written to or read from it. For example, whether
* {@code list.get(0) == list.get(0)} is true for the returned list is
* unspecified.
*
* @param backingArray the array to back the list
* @return a list view of the array
*/
public static List<Boolean> asList(boolean... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new BooleanArrayAsList(backingArray);
}
@GwtCompatible
private static class BooleanArrayAsList extends AbstractList<Boolean> implements RandomAccess, Serializable {
final boolean[] array;
final int start;
final int end;
BooleanArrayAsList(boolean[] array) {
this(array, 0, array.length);
}
BooleanArrayAsList(boolean[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
public int size() {
return end - start;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Boolean get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Boolean) && Booleans.indexOf(array, (Boolean) target, start, end) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Boolean) {
int i = Booleans.indexOf(array, (Boolean) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Boolean) {
int i = Booleans.lastIndexOf(array, (Boolean) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public Boolean set(int index, Boolean element) {
checkElementIndex(index, size());
boolean oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
array[start + index] = checkNotNull(element);
return oldValue;
}
@Override
public List<Boolean> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new BooleanArrayAsList(array, start + fromIndex, start + toIndex);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof BooleanArrayAsList) {
BooleanArrayAsList that = (BooleanArrayAsList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (array[start + i] != that.array[that.start + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Booleans.hashCode(array[i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 7);
builder.append(array[start] ? "[true" : "[false");
for (int i = start + 1; i < end; i++) {
builder.append(array[i] ? ", true" : ", false");
}
return builder.append(']').toString();
}
boolean[] toBooleanArray() {
// Arrays.copyOfRange() is not available under GWT
int size = size();
boolean[] result = new boolean[size];
System.arraycopy(array, start, result, 0, size);
return result;
}
private static final long serialVersionUID = 0;
}
/**
* Returns the number of {@code values} that are {@code true}.
*
* @since 16.0
*/
@Beta
public static int countTrue(boolean... values) {
int count = 0;
for (boolean value : values) {
if (value) {
count++;
}
}
return count;
}
}

View File

@ -0,0 +1,397 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.RandomAccess;
import com.google.common.annotations.GwtCompatible;
/**
* Static utility methods pertaining to {@code byte} primitives, that are not
* already found in either {@link Byte} or {@link Arrays}, <i>and interpret
* bytes as neither signed nor unsigned</i>. The methods which specifically
* treat bytes as signed or unsigned are found in {@link SignedBytes} and
* {@link UnsignedBytes}.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
// TODO(kevinb): how to prevent warning on UnsignedBytes when building GWT
// javadoc?
@GwtCompatible
public final class Bytes {
private Bytes() {
}
/**
* Returns a hash code for {@code value}; equal to the result of invoking
* {@code ((Byte) value).hashCode()}.
*
* @param value a primitive {@code byte} value
* @return a hash code for the value
*/
public static int hashCode(byte value) {
return value;
}
/**
* Returns {@code true} if {@code target} is present as an element anywhere in
* {@code array}.
*
* @param array an array of {@code byte} values, possibly empty
* @param target a primitive {@code byte} value
* @return {@code true} if {@code array[i] == target} for some value of {@code
* i}
*/
public static boolean contains(byte[] array, byte target) {
for (byte value : array) {
if (value == target) {
return true;
}
}
return false;
}
/**
* Returns the index of the first appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code byte} values, possibly empty
* @param target a primitive {@code byte} value
* @return the least index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int indexOf(byte[] array, byte target) {
return indexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int indexOf(byte[] array, byte target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the start position of the first occurrence of the specified {@code
* target} within {@code array}, or {@code -1} if there is no such occurrence.
*
* <p>
* More formally, returns the lowest index {@code i} such that {@code
* java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
* the same elements as {@code target}.
*
* @param array the array to search for the sequence {@code target}
* @param target the array to search for as a sub-sequence of {@code array}
*/
public static int indexOf(byte[] array, byte[] target) {
checkNotNull(array, "array");
checkNotNull(target, "target");
if (target.length == 0) {
return 0;
}
outer: for (int i = 0; i < array.length - target.length + 1; i++) {
for (int j = 0; j < target.length; j++) {
if (array[i + j] != target[j]) {
continue outer;
}
}
return i;
}
return -1;
}
/**
* Returns the index of the last appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code byte} values, possibly empty
* @param target a primitive {@code byte} value
* @return the greatest index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int lastIndexOf(byte[] array, byte target) {
return lastIndexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int lastIndexOf(byte[] array, byte target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the values from each provided array combined into a single array. For
* example, {@code concat(new byte[] {a, b}, new byte[] {}, new byte[] {c}}
* returns the array {@code {a, b, c}}.
*
* @param arrays zero or more {@code byte} arrays
* @return a single array containing all the values from the source arrays, in
* order
*/
public static byte[] concat(byte[]... arrays) {
int length = 0;
for (byte[] array : arrays) {
length += array.length;
}
byte[] result = new byte[length];
int pos = 0;
for (byte[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}
/**
* Returns an array containing the same values as {@code array}, but guaranteed
* to be of a specified minimum length. If {@code array} already has a length of
* at least {@code minLength}, it is returned directly. Otherwise, a new array
* of size {@code minLength + padding} is returned, containing the values of
* {@code array}, and zeroes in the remaining places.
*
* @param array the source array
* @param minLength the minimum length the returned array must guarantee
* @param padding an extra amount to "grow" the array by if growth is
* necessary
* @throws IllegalArgumentException if {@code minLength} or {@code padding} is
* negative
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
public static byte[] ensureCapacity(byte[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength) ? copyOf(array, minLength + padding) : array;
}
// Arrays.copyOf() requires Java 6
private static byte[] copyOf(byte[] original, int length) {
byte[] copy = new byte[length];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
return copy;
}
/**
* Returns an array containing each value of {@code collection}, converted to a
* {@code byte} value in the manner of {@link Number#byteValue}.
*
* <p>
* Elements are copied from the argument collection as if by {@code
* collection.toArray()}. Calling this method is as thread-safe as calling that
* method.
*
* @param collection a collection of {@code Number} instances
* @return an array containing the same values as {@code collection}, in the
* same order, converted to primitives
* @throws NullPointerException if {@code collection} or any of its elements is
* null
* @since 1.0 (parameter was {@code Collection<Byte>} before 12.0)
*/
public static byte[] toArray(Collection<? extends Number> collection) {
if (collection instanceof ByteArrayAsList) {
return ((ByteArrayAsList) collection).toByteArray();
}
Object[] boxedArray = collection.toArray();
int len = boxedArray.length;
byte[] array = new byte[len];
for (int i = 0; i < len; i++) {
// checkNotNull for GWT (do not optimize)
array[i] = ((Number) checkNotNull(boxedArray[i])).byteValue();
}
return array;
}
/**
* Returns a fixed-size list backed by the specified array, similar to
* {@link Arrays#asList(Object[])}. The list supports
* {@link List#set(int, Object)}, but any attempt to set a value to {@code null}
* will result in a {@link NullPointerException}.
*
* <p>
* The returned list maintains the values, but not the identities, of
* {@code Byte} objects written to or read from it. For example, whether
* {@code list.get(0) == list.get(0)} is true for the returned list is
* unspecified.
*
* @param backingArray the array to back the list
* @return a list view of the array
*/
public static List<Byte> asList(byte... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new ByteArrayAsList(backingArray);
}
@GwtCompatible
private static class ByteArrayAsList extends AbstractList<Byte> implements RandomAccess, Serializable {
final byte[] array;
final int start;
final int end;
ByteArrayAsList(byte[] array) {
this(array, 0, array.length);
}
ByteArrayAsList(byte[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
public int size() {
return end - start;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Byte get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Byte) && Bytes.indexOf(array, (Byte) target, start, end) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Byte) {
int i = Bytes.indexOf(array, (Byte) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Byte) {
int i = Bytes.lastIndexOf(array, (Byte) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public Byte set(int index, Byte element) {
checkElementIndex(index, size());
byte oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
array[start + index] = checkNotNull(element);
return oldValue;
}
@Override
public List<Byte> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new ByteArrayAsList(array, start + fromIndex, start + toIndex);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof ByteArrayAsList) {
ByteArrayAsList that = (ByteArrayAsList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (array[start + i] != that.array[that.start + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Bytes.hashCode(array[i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 5);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
builder.append(", ").append(array[i]);
}
return builder.append(']').toString();
}
byte[] toByteArray() {
// Arrays.copyOfRange() is not available under GWT
int size = size();
byte[] result = new byte[size];
System.arraycopy(array, start, result, 0, size);
return result;
}
private static final long serialVersionUID = 0;
}
}

View File

@ -0,0 +1,553 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
import com.google.common.annotations.GwtCompatible;
/**
* Static utility methods pertaining to {@code char} primitives, that are not
* already found in either {@link Character} or {@link Arrays}.
*
* <p>
* All the operations in this class treat {@code char} values strictly
* numerically; they are neither Unicode-aware nor locale-dependent.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
@GwtCompatible(emulated = true)
public final class Chars {
private Chars() {
}
/**
* The number of bytes required to represent a primitive {@code char} value.
*/
public static final int BYTES = Character.SIZE / Byte.SIZE;
/**
* Returns a hash code for {@code value}; equal to the result of invoking
* {@code ((Character) value).hashCode()}.
*
* @param value a primitive {@code char} value
* @return a hash code for the value
*/
public static int hashCode(char value) {
return value;
}
/**
* Returns the {@code char} value that is equal to {@code value}, if possible.
*
* @param value any value in the range of the {@code char} type
* @return the {@code char} value that equals {@code value}
* @throws IllegalArgumentException if {@code value} is greater than
* {@link Character#MAX_VALUE} or less than
* {@link Character#MIN_VALUE}
*/
public static char checkedCast(long value) {
char result = (char) value;
if (result != value) {
// don't use checkArgument here, to avoid boxing
throw new IllegalArgumentException("Out of range: " + value);
}
return result;
}
/**
* Returns the {@code char} nearest in value to {@code value}.
*
* @param value any {@code long} value
* @return the same value cast to {@code char} if it is in the range of the
* {@code char} type, {@link Character#MAX_VALUE} if it is too large, or
* {@link Character#MIN_VALUE} if it is too small
*/
public static char saturatedCast(long value) {
if (value > Character.MAX_VALUE) {
return Character.MAX_VALUE;
}
if (value < Character.MIN_VALUE) {
return Character.MIN_VALUE;
}
return (char) value;
}
/**
* Compares the two specified {@code char} values. The sign of the value
* returned is the same as that of {@code ((Character) a).compareTo(b)}.
*
* <p>
* <b>Note:</b> projects using JDK 7 or later should use the equivalent
* {@link Character#compare} method instead.
*
* @param a the first {@code char} to compare
* @param b the second {@code char} to compare
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are
* equal
*/
public static int compare(char a, char b) {
return a - b; // safe due to restricted range
}
/**
* Returns {@code true} if {@code target} is present as an element anywhere in
* {@code array}.
*
* @param array an array of {@code char} values, possibly empty
* @param target a primitive {@code char} value
* @return {@code true} if {@code array[i] == target} for some value of {@code
* i}
*/
public static boolean contains(char[] array, char target) {
for (char value : array) {
if (value == target) {
return true;
}
}
return false;
}
/**
* Returns the index of the first appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code char} values, possibly empty
* @param target a primitive {@code char} value
* @return the least index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int indexOf(char[] array, char target) {
return indexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int indexOf(char[] array, char target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the start position of the first occurrence of the specified {@code
* target} within {@code array}, or {@code -1} if there is no such occurrence.
*
* <p>
* More formally, returns the lowest index {@code i} such that {@code
* java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
* the same elements as {@code target}.
*
* @param array the array to search for the sequence {@code target}
* @param target the array to search for as a sub-sequence of {@code array}
*/
public static int indexOf(char[] array, char[] target) {
checkNotNull(array, "array");
checkNotNull(target, "target");
if (target.length == 0) {
return 0;
}
outer: for (int i = 0; i < array.length - target.length + 1; i++) {
for (int j = 0; j < target.length; j++) {
if (array[i + j] != target[j]) {
continue outer;
}
}
return i;
}
return -1;
}
/**
* Returns the index of the last appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code char} values, possibly empty
* @param target a primitive {@code char} value
* @return the greatest index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int lastIndexOf(char[] array, char target) {
return lastIndexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int lastIndexOf(char[] array, char target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the least value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code char} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static char min(char... array) {
checkArgument(array.length > 0);
char min = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}
/**
* Returns the greatest value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code char} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static char max(char... array) {
checkArgument(array.length > 0);
char max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
/**
* Returns the values from each provided array combined into a single array. For
* example, {@code concat(new char[] {a, b}, new char[] {}, new char[] {c}}
* returns the array {@code {a, b, c}}.
*
* @param arrays zero or more {@code char} arrays
* @return a single array containing all the values from the source arrays, in
* order
*/
public static char[] concat(char[]... arrays) {
int length = 0;
for (char[] array : arrays) {
length += array.length;
}
char[] result = new char[length];
int pos = 0;
for (char[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}
/**
* Returns an array containing the same values as {@code array}, but guaranteed
* to be of a specified minimum length. If {@code array} already has a length of
* at least {@code minLength}, it is returned directly. Otherwise, a new array
* of size {@code minLength + padding} is returned, containing the values of
* {@code array}, and zeroes in the remaining places.
*
* @param array the source array
* @param minLength the minimum length the returned array must guarantee
* @param padding an extra amount to "grow" the array by if growth is
* necessary
* @throws IllegalArgumentException if {@code minLength} or {@code padding} is
* negative
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
public static char[] ensureCapacity(char[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength) ? copyOf(array, minLength + padding) : array;
}
// Arrays.copyOf() requires Java 6
private static char[] copyOf(char[] original, int length) {
char[] copy = new char[length];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
return copy;
}
/**
* Returns a string containing the supplied {@code char} values separated by
* {@code separator}. For example, {@code join("-", '1', '2', '3')} returns the
* string {@code "1-2-3"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of {@code char} values, possibly empty
*/
public static String join(String separator, char... array) {
checkNotNull(separator);
int len = array.length;
if (len == 0) {
return "";
}
StringBuilder builder = new StringBuilder(len + separator.length() * (len - 1));
builder.append(array[0]);
for (int i = 1; i < len; i++) {
builder.append(separator).append(array[i]);
}
return builder.toString();
}
/**
* Returns a comparator that compares two {@code char} arrays lexicographically.
* That is, it compares, using {@link #compare(char, char)}), the first pair of
* values that follow any common prefix, or when one array is a prefix of the
* other, treats the shorter array as the lesser. For example,
* {@code [] < ['a'] < ['a', 'b'] < ['b']}.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link Arrays#equals(char[], char[])}.
*
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
* Lexicographical order article at Wikipedia</a>
* @since 2.0
*/
public static Comparator<char[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
private enum LexicographicalComparator implements Comparator<char[]> {
INSTANCE;
@Override
public int compare(char[] left, char[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
int result = Chars.compare(left[i], right[i]);
if (result != 0) {
return result;
}
}
return left.length - right.length;
}
}
/**
* Copies a collection of {@code Character} instances into a new array of
* primitive {@code char} values.
*
* <p>
* Elements are copied from the argument collection as if by {@code
* collection.toArray()}. Calling this method is as thread-safe as calling that
* method.
*
* @param collection a collection of {@code Character} objects
* @return an array containing the same values as {@code collection}, in the
* same order, converted to primitives
* @throws NullPointerException if {@code collection} or any of its elements is
* null
*/
public static char[] toArray(Collection<Character> collection) {
if (collection instanceof CharArrayAsList) {
return ((CharArrayAsList) collection).toCharArray();
}
Object[] boxedArray = collection.toArray();
int len = boxedArray.length;
char[] array = new char[len];
for (int i = 0; i < len; i++) {
// checkNotNull for GWT (do not optimize)
array[i] = (Character) checkNotNull(boxedArray[i]);
}
return array;
}
/**
* Returns a fixed-size list backed by the specified array, similar to
* {@link Arrays#asList(Object[])}. The list supports
* {@link List#set(int, Object)}, but any attempt to set a value to {@code null}
* will result in a {@link NullPointerException}.
*
* <p>
* The returned list maintains the values, but not the identities, of
* {@code Character} objects written to or read from it. For example, whether
* {@code list.get(0) == list.get(0)} is true for the returned list is
* unspecified.
*
* @param backingArray the array to back the list
* @return a list view of the array
*/
public static List<Character> asList(char... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new CharArrayAsList(backingArray);
}
@GwtCompatible
private static class CharArrayAsList extends AbstractList<Character> implements RandomAccess, Serializable {
final char[] array;
final int start;
final int end;
CharArrayAsList(char[] array) {
this(array, 0, array.length);
}
CharArrayAsList(char[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
public int size() {
return end - start;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Character get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Character) && Chars.indexOf(array, (Character) target, start, end) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Character) {
int i = Chars.indexOf(array, (Character) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Character) {
int i = Chars.lastIndexOf(array, (Character) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public Character set(int index, Character element) {
checkElementIndex(index, size());
char oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
array[start + index] = checkNotNull(element);
return oldValue;
}
@Override
public List<Character> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new CharArrayAsList(array, start + fromIndex, start + toIndex);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof CharArrayAsList) {
CharArrayAsList that = (CharArrayAsList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (array[start + i] != that.array[that.start + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Chars.hashCode(array[i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 3);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
builder.append(", ").append(array[i]);
}
return builder.append(']').toString();
}
char[] toCharArray() {
// Arrays.copyOfRange() is not available under GWT
int size = size();
char[] result = new char[size];
System.arraycopy(array, start, result, 0, size);
return result;
}
private static final long serialVersionUID = 0;
}
}

View File

@ -0,0 +1,649 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import static java.lang.Double.NEGATIVE_INFINITY;
import static java.lang.Double.POSITIVE_INFINITY;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Converter;
/**
* Static utility methods pertaining to {@code double} primitives, that are not
* already found in either {@link Double} or {@link Arrays}.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
@GwtCompatible(emulated = true)
public final class Doubles {
private Doubles() {
}
/**
* The number of bytes required to represent a primitive {@code double} value.
*
* @since 10.0
*/
public static final int BYTES = Double.SIZE / Byte.SIZE;
/**
* Returns a hash code for {@code value}; equal to the result of invoking
* {@code ((Double) value).hashCode()}.
*
* @param value a primitive {@code double} value
* @return a hash code for the value
*/
public static int hashCode(double value) {
return ((Double) value).hashCode();
// TODO(kevinb): do it this way when we can (GWT problem):
// long bits = Double.doubleToLongBits(value);
// return (int) (bits ^ (bits >>> 32));
}
/**
* Compares the two specified {@code double} values. The sign of the value
* returned is the same as that of <code>((Double) a).{@linkplain
* Double#compareTo compareTo}(b)</code>. As with that method, {@code NaN} is
* treated as greater than all other values, and {@code 0.0 > -0.0}.
*
* <p>
* <b>Note:</b> this method simply delegates to the JDK method
* {@link Double#compare}. It is provided for consistency with the other
* primitive types, whose compare methods were not added to the JDK until JDK 7.
*
* @param a the first {@code double} to compare
* @param b the second {@code double} to compare
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are
* equal
*/
public static int compare(double a, double b) {
return Double.compare(a, b);
}
/**
* Returns {@code true} if {@code value} represents a real number. This is
* equivalent to, but not necessarily implemented as,
* {@code !(Double.isInfinite(value) || Double.isNaN(value))}.
*
* @since 10.0
*/
public static boolean isFinite(double value) {
return NEGATIVE_INFINITY < value & value < POSITIVE_INFINITY;
}
/**
* Returns {@code true} if {@code target} is present as an element anywhere in
* {@code array}. Note that this always returns {@code false} when {@code
* target} is {@code NaN}.
*
* @param array an array of {@code double} values, possibly empty
* @param target a primitive {@code double} value
* @return {@code true} if {@code array[i] == target} for some value of {@code
* i}
*/
public static boolean contains(double[] array, double target) {
for (double value : array) {
if (value == target) {
return true;
}
}
return false;
}
/**
* Returns the index of the first appearance of the value {@code target} in
* {@code array}. Note that this always returns {@code -1} when {@code target}
* is {@code NaN}.
*
* @param array an array of {@code double} values, possibly empty
* @param target a primitive {@code double} value
* @return the least index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int indexOf(double[] array, double target) {
return indexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int indexOf(double[] array, double target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the start position of the first occurrence of the specified {@code
* target} within {@code array}, or {@code -1} if there is no such occurrence.
*
* <p>
* More formally, returns the lowest index {@code i} such that {@code
* java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
* the same elements as {@code target}.
*
* <p>
* Note that this always returns {@code -1} when {@code target} contains
* {@code NaN}.
*
* @param array the array to search for the sequence {@code target}
* @param target the array to search for as a sub-sequence of {@code array}
*/
public static int indexOf(double[] array, double[] target) {
checkNotNull(array, "array");
checkNotNull(target, "target");
if (target.length == 0) {
return 0;
}
outer: for (int i = 0; i < array.length - target.length + 1; i++) {
for (int j = 0; j < target.length; j++) {
if (array[i + j] != target[j]) {
continue outer;
}
}
return i;
}
return -1;
}
/**
* Returns the index of the last appearance of the value {@code target} in
* {@code array}. Note that this always returns {@code -1} when {@code target}
* is {@code NaN}.
*
* @param array an array of {@code double} values, possibly empty
* @param target a primitive {@code double} value
* @return the greatest index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int lastIndexOf(double[] array, double target) {
return lastIndexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int lastIndexOf(double[] array, double target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the least value present in {@code array}, using the same rules of
* comparison as {@link Math#min(double, double)}.
*
* @param array a <i>nonempty</i> array of {@code double} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static double min(double... array) {
checkArgument(array.length > 0);
double min = array[0];
for (int i = 1; i < array.length; i++) {
min = Math.min(min, array[i]);
}
return min;
}
/**
* Returns the greatest value present in {@code array}, using the same rules of
* comparison as {@link Math#max(double, double)}.
*
* @param array a <i>nonempty</i> array of {@code double} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static double max(double... array) {
checkArgument(array.length > 0);
double max = array[0];
for (int i = 1; i < array.length; i++) {
max = Math.max(max, array[i]);
}
return max;
}
/**
* Returns the values from each provided array combined into a single array. For
* example, {@code concat(new double[] {a, b}, new double[] {}, new double[]
* {c}} returns the array {@code {a, b, c}}.
*
* @param arrays zero or more {@code double} arrays
* @return a single array containing all the values from the source arrays, in
* order
*/
public static double[] concat(double[]... arrays) {
int length = 0;
for (double[] array : arrays) {
length += array.length;
}
double[] result = new double[length];
int pos = 0;
for (double[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}
private static final class DoubleConverter extends Converter<String, Double> implements Serializable {
static final DoubleConverter INSTANCE = new DoubleConverter();
@Override
protected Double doForward(String value) {
return Double.valueOf(value);
}
@Override
protected String doBackward(Double value) {
return value.toString();
}
@Override
public String toString() {
return "Doubles.stringConverter()";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 1;
}
/**
* Returns a serializable converter object that converts between strings and
* doubles using {@link Double#valueOf} and {@link Double#toString()}.
*
* @since 16.0
*/
@Beta
public static Converter<String, Double> stringConverter() {
return DoubleConverter.INSTANCE;
}
/**
* Returns an array containing the same values as {@code array}, but guaranteed
* to be of a specified minimum length. If {@code array} already has a length of
* at least {@code minLength}, it is returned directly. Otherwise, a new array
* of size {@code minLength + padding} is returned, containing the values of
* {@code array}, and zeroes in the remaining places.
*
* @param array the source array
* @param minLength the minimum length the returned array must guarantee
* @param padding an extra amount to "grow" the array by if growth is
* necessary
* @throws IllegalArgumentException if {@code minLength} or {@code padding} is
* negative
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
public static double[] ensureCapacity(double[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength) ? copyOf(array, minLength + padding) : array;
}
// Arrays.copyOf() requires Java 6
private static double[] copyOf(double[] original, int length) {
double[] copy = new double[length];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
return copy;
}
/**
* Returns a string containing the supplied {@code double} values, converted to
* strings as specified by {@link Double#toString(double)}, and separated by
* {@code separator}. For example, {@code join("-", 1.0, 2.0, 3.0)} returns the
* string {@code "1.0-2.0-3.0"}.
*
* <p>
* Note that {@link Double#toString(double)} formats {@code double} differently
* in GWT sometimes. In the previous example, it returns the string
* {@code "1-2-3"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of {@code double} values, possibly empty
*/
public static String join(String separator, double... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 12);
builder.append(array[0]);
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(array[i]);
}
return builder.toString();
}
/**
* Returns a comparator that compares two {@code double} arrays
* lexicographically. That is, it compares, using
* {@link #compare(double, double)}), the first pair of values that follow any
* common prefix, or when one array is a prefix of the other, treats the shorter
* array as the lesser. For example, {@code [] < [1.0] < [1.0, 2.0] < [2.0]}.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link Arrays#equals(double[], double[])}.
*
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
* Lexicographical order article at Wikipedia</a>
* @since 2.0
*/
public static Comparator<double[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
private enum LexicographicalComparator implements Comparator<double[]> {
INSTANCE;
@Override
public int compare(double[] left, double[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
int result = Doubles.compare(left[i], right[i]);
if (result != 0) {
return result;
}
}
return left.length - right.length;
}
}
/**
* Returns an array containing each value of {@code collection}, converted to a
* {@code double} value in the manner of {@link Number#doubleValue}.
*
* <p>
* Elements are copied from the argument collection as if by {@code
* collection.toArray()}. Calling this method is as thread-safe as calling that
* method.
*
* @param collection a collection of {@code Number} instances
* @return an array containing the same values as {@code collection}, in the
* same order, converted to primitives
* @throws NullPointerException if {@code collection} or any of its elements is
* null
* @since 1.0 (parameter was {@code Collection<Double>} before 12.0)
*/
public static double[] toArray(Collection<? extends Number> collection) {
if (collection instanceof DoubleArrayAsList) {
return ((DoubleArrayAsList) collection).toDoubleArray();
}
Object[] boxedArray = collection.toArray();
int len = boxedArray.length;
double[] array = new double[len];
for (int i = 0; i < len; i++) {
// checkNotNull for GWT (do not optimize)
array[i] = ((Number) checkNotNull(boxedArray[i])).doubleValue();
}
return array;
}
/**
* Returns a fixed-size list backed by the specified array, similar to
* {@link Arrays#asList(Object[])}. The list supports
* {@link List#set(int, Object)}, but any attempt to set a value to {@code null}
* will result in a {@link NullPointerException}.
*
* <p>
* The returned list maintains the values, but not the identities, of
* {@code Double} objects written to or read from it. For example, whether
* {@code list.get(0) == list.get(0)} is true for the returned list is
* unspecified.
*
* <p>
* The returned list may have unexpected behavior if it contains {@code
* NaN}, or if {@code NaN} is used as a parameter to any of its methods.
*
* @param backingArray the array to back the list
* @return a list view of the array
*/
public static List<Double> asList(double... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new DoubleArrayAsList(backingArray);
}
@GwtCompatible
private static class DoubleArrayAsList extends AbstractList<Double> implements RandomAccess, Serializable {
final double[] array;
final int start;
final int end;
DoubleArrayAsList(double[] array) {
this(array, 0, array.length);
}
DoubleArrayAsList(double[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
public int size() {
return end - start;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Double get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Double) && Doubles.indexOf(array, (Double) target, start, end) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Double) {
int i = Doubles.indexOf(array, (Double) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Double) {
int i = Doubles.lastIndexOf(array, (Double) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public Double set(int index, Double element) {
checkElementIndex(index, size());
double oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
array[start + index] = checkNotNull(element);
return oldValue;
}
@Override
public List<Double> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new DoubleArrayAsList(array, start + fromIndex, start + toIndex);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof DoubleArrayAsList) {
DoubleArrayAsList that = (DoubleArrayAsList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (array[start + i] != that.array[that.start + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Doubles.hashCode(array[i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 12);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
builder.append(", ").append(array[i]);
}
return builder.append(']').toString();
}
double[] toDoubleArray() {
// Arrays.copyOfRange() is not available under GWT
int size = size();
double[] result = new double[size];
System.arraycopy(array, start, result, 0, size);
return result;
}
private static final long serialVersionUID = 0;
}
/**
* This is adapted from the regex suggested by {@link Double#valueOf(String)}
* for prevalidating inputs. All valid inputs must pass this regex, but it's
* semantically fine if not all inputs that pass this regex are valid -- only a
* performance hit is incurred, not a semantics bug.
*/
@GwtIncompatible("regular expressions")
static final Pattern FLOATING_POINT_PATTERN = fpPattern();
@GwtIncompatible("regular expressions")
private static Pattern fpPattern() {
String decimal = "(?:\\d++(?:\\.\\d*+)?|\\.\\d++)";
String completeDec = decimal + "(?:[eE][+-]?\\d++)?[fFdD]?";
String hex = "(?:\\p{XDigit}++(?:\\.\\p{XDigit}*+)?|\\.\\p{XDigit}++)";
String completeHex = "0[xX]" + hex + "[pP][+-]?\\d++[fFdD]?";
String fpPattern = "[+-]?(?:NaN|Infinity|" + completeDec + "|" + completeHex + ")";
return Pattern.compile(fpPattern);
}
/**
* Parses the specified string as a double-precision floating point value. The
* ASCII character {@code '-'} (<code>'&#92;u002D'</code>) is recognized as the
* minus sign.
*
* <p>
* Unlike {@link Double#parseDouble(String)}, this method returns {@code null}
* instead of throwing an exception if parsing fails. Valid inputs are exactly
* those accepted by {@link Double#valueOf(String)}, except that leading and
* trailing whitespace is not permitted.
*
* <p>
* This implementation is likely to be faster than {@code
* Double.parseDouble} if many failures are expected.
*
* @param string the string representation of a {@code double} value
* @return the floating point value represented by {@code string}, or
* {@code null} if {@code string} has a length of zero or cannot be
* parsed as a {@code double} value
* @since 14.0
*/
@GwtIncompatible("regular expressions")
@Nullable
@Beta
public static Double tryParse(String string) {
if (FLOATING_POINT_PATTERN.matcher(string).matches()) {
// TODO(user): could be potentially optimized, but only with
// extensive testing
try {
return Double.parseDouble(string);
} catch (NumberFormatException e) {
// Double.parseDouble has changed specs several times, so fall through
// gracefully
}
}
return null;
}
}

View File

@ -0,0 +1,626 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import static java.lang.Float.NEGATIVE_INFINITY;
import static java.lang.Float.POSITIVE_INFINITY;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Converter;
/**
* Static utility methods pertaining to {@code float} primitives, that are not
* already found in either {@link Float} or {@link Arrays}.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
@GwtCompatible(emulated = true)
public final class Floats {
private Floats() {
}
/**
* The number of bytes required to represent a primitive {@code float} value.
*
* @since 10.0
*/
public static final int BYTES = Float.SIZE / Byte.SIZE;
/**
* Returns a hash code for {@code value}; equal to the result of invoking
* {@code ((Float) value).hashCode()}.
*
* @param value a primitive {@code float} value
* @return a hash code for the value
*/
public static int hashCode(float value) {
// TODO(kevinb): is there a better way, that's still gwt-safe?
return ((Float) value).hashCode();
}
/**
* Compares the two specified {@code float} values using
* {@link Float#compare(float, float)}. You may prefer to invoke that method
* directly; this method exists only for consistency with the other utilities in
* this package.
*
* <p>
* <b>Note:</b> this method simply delegates to the JDK method
* {@link Float#compare}. It is provided for consistency with the other
* primitive types, whose compare methods were not added to the JDK until JDK 7.
*
* @param a the first {@code float} to compare
* @param b the second {@code float} to compare
* @return the result of invoking {@link Float#compare(float, float)}
*/
public static int compare(float a, float b) {
return Float.compare(a, b);
}
/**
* Returns {@code true} if {@code value} represents a real number. This is
* equivalent to, but not necessarily implemented as,
* {@code !(Float.isInfinite(value) || Float.isNaN(value))}.
*
* @since 10.0
*/
public static boolean isFinite(float value) {
return NEGATIVE_INFINITY < value & value < POSITIVE_INFINITY;
}
/**
* Returns {@code true} if {@code target} is present as an element anywhere in
* {@code array}. Note that this always returns {@code false} when {@code
* target} is {@code NaN}.
*
* @param array an array of {@code float} values, possibly empty
* @param target a primitive {@code float} value
* @return {@code true} if {@code array[i] == target} for some value of {@code
* i}
*/
public static boolean contains(float[] array, float target) {
for (float value : array) {
if (value == target) {
return true;
}
}
return false;
}
/**
* Returns the index of the first appearance of the value {@code target} in
* {@code array}. Note that this always returns {@code -1} when {@code target}
* is {@code NaN}.
*
* @param array an array of {@code float} values, possibly empty
* @param target a primitive {@code float} value
* @return the least index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int indexOf(float[] array, float target) {
return indexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int indexOf(float[] array, float target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the start position of the first occurrence of the specified {@code
* target} within {@code array}, or {@code -1} if there is no such occurrence.
*
* <p>
* More formally, returns the lowest index {@code i} such that {@code
* java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
* the same elements as {@code target}.
*
* <p>
* Note that this always returns {@code -1} when {@code target} contains
* {@code NaN}.
*
* @param array the array to search for the sequence {@code target}
* @param target the array to search for as a sub-sequence of {@code array}
*/
public static int indexOf(float[] array, float[] target) {
checkNotNull(array, "array");
checkNotNull(target, "target");
if (target.length == 0) {
return 0;
}
outer: for (int i = 0; i < array.length - target.length + 1; i++) {
for (int j = 0; j < target.length; j++) {
if (array[i + j] != target[j]) {
continue outer;
}
}
return i;
}
return -1;
}
/**
* Returns the index of the last appearance of the value {@code target} in
* {@code array}. Note that this always returns {@code -1} when {@code target}
* is {@code NaN}.
*
* @param array an array of {@code float} values, possibly empty
* @param target a primitive {@code float} value
* @return the greatest index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int lastIndexOf(float[] array, float target) {
return lastIndexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int lastIndexOf(float[] array, float target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the least value present in {@code array}, using the same rules of
* comparison as {@link Math#min(float, float)}.
*
* @param array a <i>nonempty</i> array of {@code float} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static float min(float... array) {
checkArgument(array.length > 0);
float min = array[0];
for (int i = 1; i < array.length; i++) {
min = Math.min(min, array[i]);
}
return min;
}
/**
* Returns the greatest value present in {@code array}, using the same rules of
* comparison as {@link Math#min(float, float)}.
*
* @param array a <i>nonempty</i> array of {@code float} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static float max(float... array) {
checkArgument(array.length > 0);
float max = array[0];
for (int i = 1; i < array.length; i++) {
max = Math.max(max, array[i]);
}
return max;
}
/**
* Returns the values from each provided array combined into a single array. For
* example, {@code concat(new float[] {a, b}, new float[] {}, new float[] {c}}
* returns the array {@code {a, b, c}}.
*
* @param arrays zero or more {@code float} arrays
* @return a single array containing all the values from the source arrays, in
* order
*/
public static float[] concat(float[]... arrays) {
int length = 0;
for (float[] array : arrays) {
length += array.length;
}
float[] result = new float[length];
int pos = 0;
for (float[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}
private static final class FloatConverter extends Converter<String, Float> implements Serializable {
static final FloatConverter INSTANCE = new FloatConverter();
@Override
protected Float doForward(String value) {
return Float.valueOf(value);
}
@Override
protected String doBackward(Float value) {
return value.toString();
}
@Override
public String toString() {
return "Floats.stringConverter()";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 1;
}
/**
* Returns a serializable converter object that converts between strings and
* floats using {@link Float#valueOf} and {@link Float#toString()}.
*
* @since 16.0
*/
@Beta
public static Converter<String, Float> stringConverter() {
return FloatConverter.INSTANCE;
}
/**
* Returns an array containing the same values as {@code array}, but guaranteed
* to be of a specified minimum length. If {@code array} already has a length of
* at least {@code minLength}, it is returned directly. Otherwise, a new array
* of size {@code minLength + padding} is returned, containing the values of
* {@code array}, and zeroes in the remaining places.
*
* @param array the source array
* @param minLength the minimum length the returned array must guarantee
* @param padding an extra amount to "grow" the array by if growth is
* necessary
* @throws IllegalArgumentException if {@code minLength} or {@code padding} is
* negative
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
public static float[] ensureCapacity(float[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength) ? copyOf(array, minLength + padding) : array;
}
// Arrays.copyOf() requires Java 6
private static float[] copyOf(float[] original, int length) {
float[] copy = new float[length];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
return copy;
}
/**
* Returns a string containing the supplied {@code float} values, converted to
* strings as specified by {@link Float#toString(float)}, and separated by
* {@code separator}. For example, {@code join("-", 1.0f, 2.0f, 3.0f)} returns
* the string {@code "1.0-2.0-3.0"}.
*
* <p>
* Note that {@link Float#toString(float)} formats {@code float} differently in
* GWT. In the previous example, it returns the string {@code
* "1-2-3"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of {@code float} values, possibly empty
*/
public static String join(String separator, float... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 12);
builder.append(array[0]);
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(array[i]);
}
return builder.toString();
}
/**
* Returns a comparator that compares two {@code float} arrays
* lexicographically. That is, it compares, using
* {@link #compare(float, float)}), the first pair of values that follow any
* common prefix, or when one array is a prefix of the other, treats the shorter
* array as the lesser. For example, {@code [] < [1.0f] < [1.0f, 2.0f]
* < [2.0f]}.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link Arrays#equals(float[], float[])}.
*
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
* Lexicographical order article at Wikipedia</a>
* @since 2.0
*/
public static Comparator<float[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
private enum LexicographicalComparator implements Comparator<float[]> {
INSTANCE;
@Override
public int compare(float[] left, float[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
int result = Floats.compare(left[i], right[i]);
if (result != 0) {
return result;
}
}
return left.length - right.length;
}
}
/**
* Returns an array containing each value of {@code collection}, converted to a
* {@code float} value in the manner of {@link Number#floatValue}.
*
* <p>
* Elements are copied from the argument collection as if by {@code
* collection.toArray()}. Calling this method is as thread-safe as calling that
* method.
*
* @param collection a collection of {@code Number} instances
* @return an array containing the same values as {@code collection}, in the
* same order, converted to primitives
* @throws NullPointerException if {@code collection} or any of its elements is
* null
* @since 1.0 (parameter was {@code Collection<Float>} before 12.0)
*/
public static float[] toArray(Collection<? extends Number> collection) {
if (collection instanceof FloatArrayAsList) {
return ((FloatArrayAsList) collection).toFloatArray();
}
Object[] boxedArray = collection.toArray();
int len = boxedArray.length;
float[] array = new float[len];
for (int i = 0; i < len; i++) {
// checkNotNull for GWT (do not optimize)
array[i] = ((Number) checkNotNull(boxedArray[i])).floatValue();
}
return array;
}
/**
* Returns a fixed-size list backed by the specified array, similar to
* {@link Arrays#asList(Object[])}. The list supports
* {@link List#set(int, Object)}, but any attempt to set a value to {@code null}
* will result in a {@link NullPointerException}.
*
* <p>
* The returned list maintains the values, but not the identities, of
* {@code Float} objects written to or read from it. For example, whether
* {@code list.get(0) == list.get(0)} is true for the returned list is
* unspecified.
*
* <p>
* The returned list may have unexpected behavior if it contains {@code
* NaN}, or if {@code NaN} is used as a parameter to any of its methods.
*
* @param backingArray the array to back the list
* @return a list view of the array
*/
public static List<Float> asList(float... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new FloatArrayAsList(backingArray);
}
@GwtCompatible
private static class FloatArrayAsList extends AbstractList<Float> implements RandomAccess, Serializable {
final float[] array;
final int start;
final int end;
FloatArrayAsList(float[] array) {
this(array, 0, array.length);
}
FloatArrayAsList(float[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
public int size() {
return end - start;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Float get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Float) && Floats.indexOf(array, (Float) target, start, end) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Float) {
int i = Floats.indexOf(array, (Float) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Float) {
int i = Floats.lastIndexOf(array, (Float) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public Float set(int index, Float element) {
checkElementIndex(index, size());
float oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
array[start + index] = checkNotNull(element);
return oldValue;
}
@Override
public List<Float> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new FloatArrayAsList(array, start + fromIndex, start + toIndex);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof FloatArrayAsList) {
FloatArrayAsList that = (FloatArrayAsList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (array[start + i] != that.array[that.start + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Floats.hashCode(array[i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 12);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
builder.append(", ").append(array[i]);
}
return builder.append(']').toString();
}
float[] toFloatArray() {
// Arrays.copyOfRange() is not available under GWT
int size = size();
float[] result = new float[size];
System.arraycopy(array, start, result, 0, size);
return result;
}
private static final long serialVersionUID = 0;
}
/**
* Parses the specified string as a single-precision floating point value. The
* ASCII character {@code '-'} (<code>'&#92;u002D'</code>) is recognized as the
* minus sign.
*
* <p>
* Unlike {@link Float#parseFloat(String)}, this method returns {@code null}
* instead of throwing an exception if parsing fails. Valid inputs are exactly
* those accepted by {@link Float#valueOf(String)}, except that leading and
* trailing whitespace is not permitted.
*
* <p>
* This implementation is likely to be faster than {@code
* Float.parseFloat} if many failures are expected.
*
* @param string the string representation of a {@code float} value
* @return the floating point value represented by {@code string}, or
* {@code null} if {@code string} has a length of zero or cannot be
* parsed as a {@code float} value
* @since 14.0
*/
@GwtIncompatible("regular expressions")
@Nullable
@Beta
public static Float tryParse(String string) {
if (Doubles.FLOATING_POINT_PATTERN.matcher(string).matches()) {
// TODO(user): could be potentially optimized, but only with
// extensive testing
try {
return Float.parseFloat(string);
} catch (NumberFormatException e) {
// Float.parseFloat has changed specs several times, so fall through
// gracefully
}
}
return null;
}
}

View File

@ -0,0 +1,760 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
import javax.annotation.CheckForNull;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Converter;
/**
* Static utility methods pertaining to {@code int} primitives, that are not
* already found in either {@link Integer} or {@link Arrays}.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
@GwtCompatible(emulated = true)
public final class Ints {
private Ints() {
}
/**
* The number of bytes required to represent a primitive {@code int} value.
*/
public static final int BYTES = Integer.SIZE / Byte.SIZE;
/**
* The largest power of two that can be represented as an {@code int}.
*
* @since 10.0
*/
public static final int MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2);
/**
* Returns a hash code for {@code value}; equal to the result of invoking
* {@code ((Integer) value).hashCode()}.
*
* @param value a primitive {@code int} value
* @return a hash code for the value
*/
public static int hashCode(int value) {
return value;
}
/**
* Returns the {@code int} value that is equal to {@code value}, if possible.
*
* @param value any value in the range of the {@code int} type
* @return the {@code int} value that equals {@code value}
* @throws IllegalArgumentException if {@code value} is greater than
* {@link Integer#MAX_VALUE} or less than
* {@link Integer#MIN_VALUE}
*/
public static int checkedCast(long value) {
int result = (int) value;
if (result != value) {
// don't use checkArgument here, to avoid boxing
throw new IllegalArgumentException("Out of range: " + value);
}
return result;
}
/**
* Returns the {@code int} nearest in value to {@code value}.
*
* @param value any {@code long} value
* @return the same value cast to {@code int} if it is in the range of the
* {@code int} type, {@link Integer#MAX_VALUE} if it is too large, or
* {@link Integer#MIN_VALUE} if it is too small
*/
public static int saturatedCast(long value) {
if (value > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
if (value < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
return (int) value;
}
/**
* Compares the two specified {@code int} values. The sign of the value returned
* is the same as that of {@code ((Integer) a).compareTo(b)}.
*
* <p>
* <b>Note:</b> projects using JDK 7 or later should use the equivalent
* {@link Integer#compare} method instead.
*
* @param a the first {@code int} to compare
* @param b the second {@code int} to compare
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are
* equal
*/
public static int compare(int a, int b) {
return (a < b) ? -1 : ((a > b) ? 1 : 0);
}
/**
* Returns {@code true} if {@code target} is present as an element anywhere in
* {@code array}.
*
* @param array an array of {@code int} values, possibly empty
* @param target a primitive {@code int} value
* @return {@code true} if {@code array[i] == target} for some value of {@code
* i}
*/
public static boolean contains(int[] array, int target) {
for (int value : array) {
if (value == target) {
return true;
}
}
return false;
}
/**
* Returns the index of the first appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code int} values, possibly empty
* @param target a primitive {@code int} value
* @return the least index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int indexOf(int[] array, int target) {
return indexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int indexOf(int[] array, int target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the start position of the first occurrence of the specified {@code
* target} within {@code array}, or {@code -1} if there is no such occurrence.
*
* <p>
* More formally, returns the lowest index {@code i} such that {@code
* java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
* the same elements as {@code target}.
*
* @param array the array to search for the sequence {@code target}
* @param target the array to search for as a sub-sequence of {@code array}
*/
public static int indexOf(int[] array, int[] target) {
checkNotNull(array, "array");
checkNotNull(target, "target");
if (target.length == 0) {
return 0;
}
outer: for (int i = 0; i < array.length - target.length + 1; i++) {
for (int j = 0; j < target.length; j++) {
if (array[i + j] != target[j]) {
continue outer;
}
}
return i;
}
return -1;
}
/**
* Returns the index of the last appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code int} values, possibly empty
* @param target a primitive {@code int} value
* @return the greatest index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int lastIndexOf(int[] array, int target) {
return lastIndexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int lastIndexOf(int[] array, int target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the least value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code int} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static int min(int... array) {
checkArgument(array.length > 0);
int min = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}
/**
* Returns the greatest value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code int} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static int max(int... array) {
checkArgument(array.length > 0);
int max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
/**
* Returns the values from each provided array combined into a single array. For
* example, {@code concat(new int[] {a, b}, new int[] {}, new int[] {c}} returns
* the array {@code {a, b, c}}.
*
* @param arrays zero or more {@code int} arrays
* @return a single array containing all the values from the source arrays, in
* order
*/
public static int[] concat(int[]... arrays) {
int length = 0;
for (int[] array : arrays) {
length += array.length;
}
int[] result = new int[length];
int pos = 0;
for (int[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}
/**
* Returns a big-endian representation of {@code value} in a 4-element byte
* array; equivalent to {@code ByteBuffer.allocate(4).putInt(value).array()}.
* For example, the input value {@code 0x12131415} would yield the byte array
* {@code {0x12, 0x13, 0x14, 0x15}}.
*
* <p>
* If you need to convert and concatenate several values (possibly even of
* different types), use a shared {@link java.nio.ByteBuffer} instance, or use
* {@link com.google.common.io.ByteStreams#newDataOutput()} to get a growable
* buffer.
*/
@GwtIncompatible("doesn't work")
public static byte[] toByteArray(int value) {
return new byte[] { (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value };
}
/**
* Returns the {@code int} value whose big-endian representation is stored in
* the first 4 bytes of {@code bytes}; equivalent to {@code
* ByteBuffer.wrap(bytes).getInt()}. For example, the input byte array
* {@code {0x12, 0x13, 0x14, 0x15, 0x33}} would yield the {@code int} value
* {@code
* 0x12131415}.
*
* <p>
* Arguably, it's preferable to use {@link java.nio.ByteBuffer}; that library
* exposes much more flexibility at little cost in readability.
*
* @throws IllegalArgumentException if {@code bytes} has fewer than 4 elements
*/
@GwtIncompatible("doesn't work")
public static int fromByteArray(byte[] bytes) {
checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3]);
}
/**
* Returns the {@code int} value whose byte representation is the given 4 bytes,
* in big-endian order; equivalent to {@code Ints.fromByteArray(new byte[] {b1,
* b2, b3, b4})}.
*
* @since 7.0
*/
@GwtIncompatible("doesn't work")
public static int fromBytes(byte b1, byte b2, byte b3, byte b4) {
return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | (b4 & 0xFF);
}
private static final class IntConverter extends Converter<String, Integer> implements Serializable {
static final IntConverter INSTANCE = new IntConverter();
@Override
protected Integer doForward(String value) {
return Integer.decode(value);
}
@Override
protected String doBackward(Integer value) {
return value.toString();
}
@Override
public String toString() {
return "Ints.stringConverter()";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 1;
}
/**
* Returns a serializable converter object that converts between strings and
* integers using {@link Integer#decode} and {@link Integer#toString()}.
*
* @since 16.0
*/
@Beta
public static Converter<String, Integer> stringConverter() {
return IntConverter.INSTANCE;
}
/**
* Returns an array containing the same values as {@code array}, but guaranteed
* to be of a specified minimum length. If {@code array} already has a length of
* at least {@code minLength}, it is returned directly. Otherwise, a new array
* of size {@code minLength + padding} is returned, containing the values of
* {@code array}, and zeroes in the remaining places.
*
* @param array the source array
* @param minLength the minimum length the returned array must guarantee
* @param padding an extra amount to "grow" the array by if growth is
* necessary
* @throws IllegalArgumentException if {@code minLength} or {@code padding} is
* negative
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
public static int[] ensureCapacity(int[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength) ? copyOf(array, minLength + padding) : array;
}
// Arrays.copyOf() requires Java 6
private static int[] copyOf(int[] original, int length) {
int[] copy = new int[length];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
return copy;
}
/**
* Returns a string containing the supplied {@code int} values separated by
* {@code separator}. For example, {@code join("-", 1, 2, 3)} returns the string
* {@code "1-2-3"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of {@code int} values, possibly empty
*/
public static String join(String separator, int... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 5);
builder.append(array[0]);
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(array[i]);
}
return builder.toString();
}
/**
* Returns a comparator that compares two {@code int} arrays lexicographically.
* That is, it compares, using {@link #compare(int, int)}), the first pair of
* values that follow any common prefix, or when one array is a prefix of the
* other, treats the shorter array as the lesser. For example,
* {@code [] < [1] < [1, 2] < [2]}.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link Arrays#equals(int[], int[])}.
*
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
* Lexicographical order article at Wikipedia</a>
* @since 2.0
*/
public static Comparator<int[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
private enum LexicographicalComparator implements Comparator<int[]> {
INSTANCE;
@Override
public int compare(int[] left, int[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
int result = Ints.compare(left[i], right[i]);
if (result != 0) {
return result;
}
}
return left.length - right.length;
}
}
/**
* Returns an array containing each value of {@code collection}, converted to a
* {@code int} value in the manner of {@link Number#intValue}.
*
* <p>
* Elements are copied from the argument collection as if by {@code
* collection.toArray()}. Calling this method is as thread-safe as calling that
* method.
*
* @param collection a collection of {@code Number} instances
* @return an array containing the same values as {@code collection}, in the
* same order, converted to primitives
* @throws NullPointerException if {@code collection} or any of its elements is
* null
* @since 1.0 (parameter was {@code Collection<Integer>} before 12.0)
*/
public static int[] toArray(Collection<? extends Number> collection) {
if (collection instanceof IntArrayAsList) {
return ((IntArrayAsList) collection).toIntArray();
}
Object[] boxedArray = collection.toArray();
int len = boxedArray.length;
int[] array = new int[len];
for (int i = 0; i < len; i++) {
// checkNotNull for GWT (do not optimize)
array[i] = ((Number) checkNotNull(boxedArray[i])).intValue();
}
return array;
}
/**
* Returns a fixed-size list backed by the specified array, similar to
* {@link Arrays#asList(Object[])}. The list supports
* {@link List#set(int, Object)}, but any attempt to set a value to {@code null}
* will result in a {@link NullPointerException}.
*
* <p>
* The returned list maintains the values, but not the identities, of
* {@code Integer} objects written to or read from it. For example, whether
* {@code list.get(0) == list.get(0)} is true for the returned list is
* unspecified.
*
* @param backingArray the array to back the list
* @return a list view of the array
*/
public static List<Integer> asList(int... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new IntArrayAsList(backingArray);
}
@GwtCompatible
private static class IntArrayAsList extends AbstractList<Integer> implements RandomAccess, Serializable {
final int[] array;
final int start;
final int end;
IntArrayAsList(int[] array) {
this(array, 0, array.length);
}
IntArrayAsList(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
public int size() {
return end - start;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Integer get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Integer) && Ints.indexOf(array, (Integer) target, start, end) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Integer) {
int i = Ints.indexOf(array, (Integer) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Integer) {
int i = Ints.lastIndexOf(array, (Integer) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public Integer set(int index, Integer element) {
checkElementIndex(index, size());
int oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
array[start + index] = checkNotNull(element);
return oldValue;
}
@Override
public List<Integer> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new IntArrayAsList(array, start + fromIndex, start + toIndex);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof IntArrayAsList) {
IntArrayAsList that = (IntArrayAsList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (array[start + i] != that.array[that.start + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Ints.hashCode(array[i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 5);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
builder.append(", ").append(array[i]);
}
return builder.append(']').toString();
}
int[] toIntArray() {
// Arrays.copyOfRange() is not available under GWT
int size = size();
int[] result = new int[size];
System.arraycopy(array, start, result, 0, size);
return result;
}
private static final long serialVersionUID = 0;
}
private static final byte[] asciiDigits = new byte[128];
static {
Arrays.fill(asciiDigits, (byte) -1);
for (int i = 0; i <= 9; i++) {
asciiDigits['0' + i] = (byte) i;
}
for (int i = 0; i <= 26; i++) {
asciiDigits['A' + i] = (byte) (10 + i);
asciiDigits['a' + i] = (byte) (10 + i);
}
}
private static int digit(char c) {
return (c < 128) ? asciiDigits[c] : -1;
}
/**
* Parses the specified string as a signed decimal integer value. The ASCII
* character {@code '-'} (<code>'&#92;u002D'</code>) is recognized as the minus
* sign.
*
* <p>
* Unlike {@link Integer#parseInt(String)}, this method returns {@code null}
* instead of throwing an exception if parsing fails. Additionally, this method
* only accepts ASCII digits, and returns {@code null} if non-ASCII digits are
* present in the string.
*
* <p>
* Note that strings prefixed with ASCII {@code '+'} are rejected, even under
* JDK 7, despite the change to {@link Integer#parseInt(String)} for that
* version.
*
* @param string the string representation of an integer value
* @return the integer value represented by {@code string}, or {@code null} if
* {@code string} has a length of zero or cannot be parsed as an integer
* value
* @since 11.0
*/
@Beta
@CheckForNull
@GwtIncompatible("TODO")
public static Integer tryParse(String string) {
return tryParse(string, 10);
}
/**
* Parses the specified string as a signed integer value using the specified
* radix. The ASCII character {@code '-'} (<code>'&#92;u002D'</code>) is
* recognized as the minus sign.
*
* <p>
* Unlike {@link Integer#parseInt(String, int)}, this method returns
* {@code null} instead of throwing an exception if parsing fails. Additionally,
* this method only accepts ASCII digits, and returns {@code null} if non-ASCII
* digits are present in the string.
*
* <p>
* Note that strings prefixed with ASCII {@code '+'} are rejected, even under
* JDK 7, despite the change to {@link Integer#parseInt(String, int)} for that
* version.
*
* @param string the string representation of an integer value
* @param radix the radix to use when parsing
* @return the integer value represented by {@code string} using {@code radix},
* or {@code null} if {@code string} has a length of zero or cannot be
* parsed as an integer value
* @throws IllegalArgumentException if {@code radix < Character.MIN_RADIX} or
* {@code radix > Character.MAX_RADIX}
*/
@CheckForNull
@GwtIncompatible("TODO")
static Integer tryParse(String string, int radix) {
if (checkNotNull(string).isEmpty()) {
return null;
}
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
throw new IllegalArgumentException("radix must be between MIN_RADIX and MAX_RADIX but was " + radix);
}
boolean negative = string.charAt(0) == '-';
int index = negative ? 1 : 0;
if (index == string.length()) {
return null;
}
int digit = digit(string.charAt(index++));
if (digit < 0 || digit >= radix) {
return null;
}
int accum = -digit;
int cap = Integer.MIN_VALUE / radix;
while (index < string.length()) {
digit = digit(string.charAt(index++));
if (digit < 0 || digit >= radix || accum < cap) {
return null;
}
accum *= radix;
if (accum < Integer.MIN_VALUE + digit) {
return null;
}
accum -= digit;
}
if (negative) {
return accum;
} else if (accum == Integer.MIN_VALUE) {
return null;
} else {
return -accum;
}
}
}

View File

@ -0,0 +1,674 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Converter;
/**
* Static utility methods pertaining to {@code long} primitives, that are not
* already found in either {@link Long} or {@link Arrays}.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
@GwtCompatible
public final class Longs {
private Longs() {
}
/**
* The number of bytes required to represent a primitive {@code long} value.
*/
public static final int BYTES = Long.SIZE / Byte.SIZE;
/**
* The largest power of two that can be represented as a {@code long}.
*
* @since 10.0
*/
public static final long MAX_POWER_OF_TWO = 1L << (Long.SIZE - 2);
/**
* Returns a hash code for {@code value}; equal to the result of invoking
* {@code ((Long) value).hashCode()}.
*
* <p>
* This method always return the value specified by {@link Long#hashCode()} in
* java, which might be different from {@code ((Long) value).hashCode()} in GWT
* because {@link Long#hashCode()} in GWT does not obey the JRE contract.
*
* @param value a primitive {@code long} value
* @return a hash code for the value
*/
public static int hashCode(long value) {
return (int) (value ^ (value >>> 32));
}
/**
* Compares the two specified {@code long} values. The sign of the value
* returned is the same as that of {@code ((Long) a).compareTo(b)}.
*
* <p>
* <b>Note:</b> projects using JDK 7 or later should use the equivalent
* {@link Long#compare} method instead.
*
* @param a the first {@code long} to compare
* @param b the second {@code long} to compare
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are
* equal
*/
public static int compare(long a, long b) {
return (a < b) ? -1 : ((a > b) ? 1 : 0);
}
/**
* Returns {@code true} if {@code target} is present as an element anywhere in
* {@code array}.
*
* @param array an array of {@code long} values, possibly empty
* @param target a primitive {@code long} value
* @return {@code true} if {@code array[i] == target} for some value of {@code
* i}
*/
public static boolean contains(long[] array, long target) {
for (long value : array) {
if (value == target) {
return true;
}
}
return false;
}
/**
* Returns the index of the first appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code long} values, possibly empty
* @param target a primitive {@code long} value
* @return the least index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int indexOf(long[] array, long target) {
return indexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int indexOf(long[] array, long target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the start position of the first occurrence of the specified {@code
* target} within {@code array}, or {@code -1} if there is no such occurrence.
*
* <p>
* More formally, returns the lowest index {@code i} such that {@code
* java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
* the same elements as {@code target}.
*
* @param array the array to search for the sequence {@code target}
* @param target the array to search for as a sub-sequence of {@code array}
*/
public static int indexOf(long[] array, long[] target) {
checkNotNull(array, "array");
checkNotNull(target, "target");
if (target.length == 0) {
return 0;
}
outer: for (int i = 0; i < array.length - target.length + 1; i++) {
for (int j = 0; j < target.length; j++) {
if (array[i + j] != target[j]) {
continue outer;
}
}
return i;
}
return -1;
}
/**
* Returns the index of the last appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code long} values, possibly empty
* @param target a primitive {@code long} value
* @return the greatest index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int lastIndexOf(long[] array, long target) {
return lastIndexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int lastIndexOf(long[] array, long target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the least value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code long} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static long min(long... array) {
checkArgument(array.length > 0);
long min = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}
/**
* Returns the greatest value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code long} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static long max(long... array) {
checkArgument(array.length > 0);
long max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
/**
* Returns the values from each provided array combined into a single array. For
* example, {@code concat(new long[] {a, b}, new long[] {}, new long[] {c}}
* returns the array {@code {a, b, c}}.
*
* @param arrays zero or more {@code long} arrays
* @return a single array containing all the values from the source arrays, in
* order
*/
public static long[] concat(long[]... arrays) {
int length = 0;
for (long[] array : arrays) {
length += array.length;
}
long[] result = new long[length];
int pos = 0;
for (long[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}
/**
* Returns a big-endian representation of {@code value} in an 8-element byte
* array; equivalent to {@code ByteBuffer.allocate(8).putLong(value).array()}.
* For example, the input value {@code 0x1213141516171819L} would yield the byte
* array {@code {0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19}}.
*
* <p>
* If you need to convert and concatenate several values (possibly even of
* different types), use a shared {@link java.nio.ByteBuffer} instance, or use
* {@link com.google.common.io.ByteStreams#newDataOutput()} to get a growable
* buffer.
*/
public static byte[] toByteArray(long value) {
// Note that this code needs to stay compatible with GWT, which has known
// bugs when narrowing byte casts of long values occur.
byte[] result = new byte[8];
for (int i = 7; i >= 0; i--) {
result[i] = (byte) (value & 0xffL);
value >>= 8;
}
return result;
}
/**
* Returns the {@code long} value whose big-endian representation is stored in
* the first 8 bytes of {@code bytes}; equivalent to {@code
* ByteBuffer.wrap(bytes).getLong()}. For example, the input byte array
* {@code {0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19}} would yield the
* {@code long} value {@code 0x1213141516171819L}.
*
* <p>
* Arguably, it's preferable to use {@link java.nio.ByteBuffer}; that library
* exposes much more flexibility at little cost in readability.
*
* @throws IllegalArgumentException if {@code bytes} has fewer than 8 elements
*/
public static long fromByteArray(byte[] bytes) {
checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]);
}
/**
* Returns the {@code long} value whose byte representation is the given 8
* bytes, in big-endian order; equivalent to {@code Longs.fromByteArray(new
* byte[] {b1, b2, b3, b4, b5, b6, b7, b8})}.
*
* @since 7.0
*/
public static long fromBytes(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7, byte b8) {
return (b1 & 0xFFL) << 56 | (b2 & 0xFFL) << 48 | (b3 & 0xFFL) << 40 | (b4 & 0xFFL) << 32 | (b5 & 0xFFL) << 24
| (b6 & 0xFFL) << 16 | (b7 & 0xFFL) << 8 | (b8 & 0xFFL);
}
/**
* Parses the specified string as a signed decimal long value. The ASCII
* character {@code '-'} (<code>'&#92;u002D'</code>) is recognized as the minus
* sign.
*
* <p>
* Unlike {@link Long#parseLong(String)}, this method returns {@code null}
* instead of throwing an exception if parsing fails. Additionally, this method
* only accepts ASCII digits, and returns {@code null} if non-ASCII digits are
* present in the string.
*
* <p>
* Note that strings prefixed with ASCII {@code '+'} are rejected, even under
* JDK 7, despite the change to {@link Long#parseLong(String)} for that version.
*
* @param string the string representation of a long value
* @return the long value represented by {@code string}, or {@code null} if
* {@code string} has a length of zero or cannot be parsed as a long
* value
* @since 14.0
*/
@Beta
public static Long tryParse(String string) {
if (checkNotNull(string).isEmpty()) {
return null;
}
boolean negative = string.charAt(0) == '-';
int index = negative ? 1 : 0;
if (index == string.length()) {
return null;
}
int digit = string.charAt(index++) - '0';
if (digit < 0 || digit > 9) {
return null;
}
long accum = -digit;
while (index < string.length()) {
digit = string.charAt(index++) - '0';
if (digit < 0 || digit > 9 || accum < Long.MIN_VALUE / 10) {
return null;
}
accum *= 10;
if (accum < Long.MIN_VALUE + digit) {
return null;
}
accum -= digit;
}
if (negative) {
return accum;
} else if (accum == Long.MIN_VALUE) {
return null;
} else {
return -accum;
}
}
private static final class LongConverter extends Converter<String, Long> implements Serializable {
static final LongConverter INSTANCE = new LongConverter();
@Override
protected Long doForward(String value) {
return Long.decode(value);
}
@Override
protected String doBackward(Long value) {
return value.toString();
}
@Override
public String toString() {
return "Longs.stringConverter()";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 1;
}
/**
* Returns a serializable converter object that converts between strings and
* longs using {@link Long#decode} and {@link Long#toString()}.
*
* @since 16.0
*/
@Beta
public static Converter<String, Long> stringConverter() {
return LongConverter.INSTANCE;
}
/**
* Returns an array containing the same values as {@code array}, but guaranteed
* to be of a specified minimum length. If {@code array} already has a length of
* at least {@code minLength}, it is returned directly. Otherwise, a new array
* of size {@code minLength + padding} is returned, containing the values of
* {@code array}, and zeroes in the remaining places.
*
* @param array the source array
* @param minLength the minimum length the returned array must guarantee
* @param padding an extra amount to "grow" the array by if growth is
* necessary
* @throws IllegalArgumentException if {@code minLength} or {@code padding} is
* negative
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
public static long[] ensureCapacity(long[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength) ? copyOf(array, minLength + padding) : array;
}
// Arrays.copyOf() requires Java 6
private static long[] copyOf(long[] original, int length) {
long[] copy = new long[length];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
return copy;
}
/**
* Returns a string containing the supplied {@code long} values separated by
* {@code separator}. For example, {@code join("-", 1L, 2L, 3L)} returns the
* string {@code "1-2-3"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of {@code long} values, possibly empty
*/
public static String join(String separator, long... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 10);
builder.append(array[0]);
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(array[i]);
}
return builder.toString();
}
/**
* Returns a comparator that compares two {@code long} arrays lexicographically.
* That is, it compares, using {@link #compare(long, long)}), the first pair of
* values that follow any common prefix, or when one array is a prefix of the
* other, treats the shorter array as the lesser. For example,
* {@code [] < [1L] < [1L, 2L] < [2L]}.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link Arrays#equals(long[], long[])}.
*
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
* Lexicographical order article at Wikipedia</a>
* @since 2.0
*/
public static Comparator<long[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
private enum LexicographicalComparator implements Comparator<long[]> {
INSTANCE;
@Override
public int compare(long[] left, long[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
int result = Longs.compare(left[i], right[i]);
if (result != 0) {
return result;
}
}
return left.length - right.length;
}
}
/**
* Returns an array containing each value of {@code collection}, converted to a
* {@code long} value in the manner of {@link Number#longValue}.
*
* <p>
* Elements are copied from the argument collection as if by {@code
* collection.toArray()}. Calling this method is as thread-safe as calling that
* method.
*
* @param collection a collection of {@code Number} instances
* @return an array containing the same values as {@code collection}, in the
* same order, converted to primitives
* @throws NullPointerException if {@code collection} or any of its elements is
* null
* @since 1.0 (parameter was {@code Collection<Long>} before 12.0)
*/
public static long[] toArray(Collection<? extends Number> collection) {
if (collection instanceof LongArrayAsList) {
return ((LongArrayAsList) collection).toLongArray();
}
Object[] boxedArray = collection.toArray();
int len = boxedArray.length;
long[] array = new long[len];
for (int i = 0; i < len; i++) {
// checkNotNull for GWT (do not optimize)
array[i] = ((Number) checkNotNull(boxedArray[i])).longValue();
}
return array;
}
/**
* Returns a fixed-size list backed by the specified array, similar to
* {@link Arrays#asList(Object[])}. The list supports
* {@link List#set(int, Object)}, but any attempt to set a value to {@code null}
* will result in a {@link NullPointerException}.
*
* <p>
* The returned list maintains the values, but not the identities, of
* {@code Long} objects written to or read from it. For example, whether
* {@code list.get(0) == list.get(0)} is true for the returned list is
* unspecified.
*
* @param backingArray the array to back the list
* @return a list view of the array
*/
public static List<Long> asList(long... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new LongArrayAsList(backingArray);
}
@GwtCompatible
private static class LongArrayAsList extends AbstractList<Long> implements RandomAccess, Serializable {
final long[] array;
final int start;
final int end;
LongArrayAsList(long[] array) {
this(array, 0, array.length);
}
LongArrayAsList(long[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
public int size() {
return end - start;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Long get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Long) && Longs.indexOf(array, (Long) target, start, end) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Long) {
int i = Longs.indexOf(array, (Long) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Long) {
int i = Longs.lastIndexOf(array, (Long) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public Long set(int index, Long element) {
checkElementIndex(index, size());
long oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
array[start + index] = checkNotNull(element);
return oldValue;
}
@Override
public List<Long> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new LongArrayAsList(array, start + fromIndex, start + toIndex);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof LongArrayAsList) {
LongArrayAsList that = (LongArrayAsList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (array[start + i] != that.array[that.start + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Longs.hashCode(array[i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 10);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
builder.append(", ").append(array[i]);
}
return builder.append(']').toString();
}
long[] toLongArray() {
// Arrays.copyOfRange() is not available under GWT
int size = size();
long[] result = new long[size];
System.arraycopy(array, start, result, 0, size);
return result;
}
private static final long serialVersionUID = 0;
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import com.google.common.annotations.GwtCompatible;
/**
* A string to be parsed as a number and the radix to interpret it in.
*/
@GwtCompatible
final class ParseRequest {
final String rawValue;
final int radix;
private ParseRequest(String rawValue, int radix) {
this.rawValue = rawValue;
this.radix = radix;
}
static ParseRequest fromString(String stringValue) {
if (stringValue.length() == 0) {
throw new NumberFormatException("empty string");
}
// Handle radix specifier if present
String rawValue;
int radix;
char firstChar = stringValue.charAt(0);
if (stringValue.startsWith("0x") || stringValue.startsWith("0X")) {
rawValue = stringValue.substring(2);
radix = 16;
} else if (firstChar == '#') {
rawValue = stringValue.substring(1);
radix = 16;
} else if (firstChar == '0' && stringValue.length() > 1) {
rawValue = stringValue.substring(1);
radix = 8;
} else {
rawValue = stringValue;
radix = 10;
}
return new ParseRequest(rawValue, radix);
}
}

View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Contains static utility methods pertaining to primitive types and their
* corresponding wrapper types.
*
* @author Kevin Bourrillion
* @since 1.0
*/
public final class Primitives {
private Primitives() {
}
/** A map from primitive types to their corresponding wrapper types. */
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER_TYPE;
/** A map from wrapper types to their corresponding primitive types. */
private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPE;
// Sad that we can't use a BiMap. :(
static {
Map<Class<?>, Class<?>> primToWrap = new HashMap<Class<?>, Class<?>>(16);
Map<Class<?>, Class<?>> wrapToPrim = new HashMap<Class<?>, Class<?>>(16);
add(primToWrap, wrapToPrim, boolean.class, Boolean.class);
add(primToWrap, wrapToPrim, byte.class, Byte.class);
add(primToWrap, wrapToPrim, char.class, Character.class);
add(primToWrap, wrapToPrim, double.class, Double.class);
add(primToWrap, wrapToPrim, float.class, Float.class);
add(primToWrap, wrapToPrim, int.class, Integer.class);
add(primToWrap, wrapToPrim, long.class, Long.class);
add(primToWrap, wrapToPrim, short.class, Short.class);
add(primToWrap, wrapToPrim, void.class, Void.class);
PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
}
private static void add(Map<Class<?>, Class<?>> forward, Map<Class<?>, Class<?>> backward, Class<?> key,
Class<?> value) {
forward.put(key, value);
backward.put(value, key);
}
/**
* Returns an immutable set of all nine primitive types (including {@code
* void}). Note that a simpler way to test whether a {@code Class} instance is a
* member of this set is to call {@link Class#isPrimitive}.
*
* @since 3.0
*/
public static Set<Class<?>> allPrimitiveTypes() {
return PRIMITIVE_TO_WRAPPER_TYPE.keySet();
}
/**
* Returns an immutable set of all nine primitive-wrapper types (including
* {@link Void}).
*
* @since 3.0
*/
public static Set<Class<?>> allWrapperTypes() {
return WRAPPER_TO_PRIMITIVE_TYPE.keySet();
}
/**
* Returns {@code true} if {@code type} is one of the nine primitive-wrapper
* types, such as {@link Integer}.
*
* @see Class#isPrimitive
*/
public static boolean isWrapperType(Class<?> type) {
return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(checkNotNull(type));
}
/**
* Returns the corresponding wrapper type of {@code type} if it is a primitive
* type; otherwise returns {@code type} itself. Idempotent.
*
* <pre>
* wrap(int.class) == Integer.class
* wrap(Integer.class) == Integer.class
* wrap(String.class) == String.class
* </pre>
*/
public static <T> Class<T> wrap(Class<T> type) {
checkNotNull(type);
// cast is safe: long.class and Long.class are both of type Class<Long>
@SuppressWarnings("unchecked")
Class<T> wrapped = (Class<T>) PRIMITIVE_TO_WRAPPER_TYPE.get(type);
return (wrapped == null) ? type : wrapped;
}
/**
* Returns the corresponding primitive type of {@code type} if it is a wrapper
* type; otherwise returns {@code type} itself. Idempotent.
*
* <pre>
* unwrap(Integer.class) == int.class
* unwrap(int.class) == int.class
* unwrap(String.class) == String.class
* </pre>
*/
public static <T> Class<T> unwrap(Class<T> type) {
checkNotNull(type);
// cast is safe: long.class and Long.class are both of type Class<Long>
@SuppressWarnings("unchecked")
Class<T> unwrapped = (Class<T>) WRAPPER_TO_PRIMITIVE_TYPE.get(type);
return (unwrapped == null) ? type : unwrapped;
}
}

View File

@ -0,0 +1,644 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndexes;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.RandomAccess;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Converter;
/**
* Static utility methods pertaining to {@code short} primitives, that are not
* already found in either {@link Short} or {@link Arrays}.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
@GwtCompatible(emulated = true)
public final class Shorts {
private Shorts() {
}
/**
* The number of bytes required to represent a primitive {@code short} value.
*/
public static final int BYTES = Short.SIZE / Byte.SIZE;
/**
* The largest power of two that can be represented as a {@code short}.
*
* @since 10.0
*/
public static final short MAX_POWER_OF_TWO = 1 << (Short.SIZE - 2);
/**
* Returns a hash code for {@code value}; equal to the result of invoking
* {@code ((Short) value).hashCode()}.
*
* @param value a primitive {@code short} value
* @return a hash code for the value
*/
public static int hashCode(short value) {
return value;
}
/**
* Returns the {@code short} value that is equal to {@code value}, if possible.
*
* @param value any value in the range of the {@code short} type
* @return the {@code short} value that equals {@code value}
* @throws IllegalArgumentException if {@code value} is greater than
* {@link Short#MAX_VALUE} or less than
* {@link Short#MIN_VALUE}
*/
public static short checkedCast(long value) {
short result = (short) value;
if (result != value) {
// don't use checkArgument here, to avoid boxing
throw new IllegalArgumentException("Out of range: " + value);
}
return result;
}
/**
* Returns the {@code short} nearest in value to {@code value}.
*
* @param value any {@code long} value
* @return the same value cast to {@code short} if it is in the range of the
* {@code short} type, {@link Short#MAX_VALUE} if it is too large, or
* {@link Short#MIN_VALUE} if it is too small
*/
public static short saturatedCast(long value) {
if (value > Short.MAX_VALUE) {
return Short.MAX_VALUE;
}
if (value < Short.MIN_VALUE) {
return Short.MIN_VALUE;
}
return (short) value;
}
/**
* Compares the two specified {@code short} values. The sign of the value
* returned is the same as that of {@code ((Short) a).compareTo(b)}.
*
* <p>
* <b>Note:</b> projects using JDK 7 or later should use the equivalent
* {@link Short#compare} method instead.
*
* @param a the first {@code short} to compare
* @param b the second {@code short} to compare
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are
* equal
*/
public static int compare(short a, short b) {
return a - b; // safe due to restricted range
}
/**
* Returns {@code true} if {@code target} is present as an element anywhere in
* {@code array}.
*
* @param array an array of {@code short} values, possibly empty
* @param target a primitive {@code short} value
* @return {@code true} if {@code array[i] == target} for some value of {@code
* i}
*/
public static boolean contains(short[] array, short target) {
for (short value : array) {
if (value == target) {
return true;
}
}
return false;
}
/**
* Returns the index of the first appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code short} values, possibly empty
* @param target a primitive {@code short} value
* @return the least index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int indexOf(short[] array, short target) {
return indexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int indexOf(short[] array, short target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the start position of the first occurrence of the specified {@code
* target} within {@code array}, or {@code -1} if there is no such occurrence.
*
* <p>
* More formally, returns the lowest index {@code i} such that {@code
* java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
* the same elements as {@code target}.
*
* @param array the array to search for the sequence {@code target}
* @param target the array to search for as a sub-sequence of {@code array}
*/
public static int indexOf(short[] array, short[] target) {
checkNotNull(array, "array");
checkNotNull(target, "target");
if (target.length == 0) {
return 0;
}
outer: for (int i = 0; i < array.length - target.length + 1; i++) {
for (int j = 0; j < target.length; j++) {
if (array[i + j] != target[j]) {
continue outer;
}
}
return i;
}
return -1;
}
/**
* Returns the index of the last appearance of the value {@code target} in
* {@code array}.
*
* @param array an array of {@code short} values, possibly empty
* @param target a primitive {@code short} value
* @return the greatest index {@code i} for which {@code array[i] == target}, or
* {@code -1} if no such index exists.
*/
public static int lastIndexOf(short[] array, short target) {
return lastIndexOf(array, target, 0, array.length);
}
// TODO(kevinb): consider making this public
private static int lastIndexOf(short[] array, short target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
/**
* Returns the least value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code short} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static short min(short... array) {
checkArgument(array.length > 0);
short min = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}
/**
* Returns the greatest value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code short} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static short max(short... array) {
checkArgument(array.length > 0);
short max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
/**
* Returns the values from each provided array combined into a single array. For
* example, {@code concat(new short[] {a, b}, new short[] {}, new short[] {c}}
* returns the array {@code {a, b, c}}.
*
* @param arrays zero or more {@code short} arrays
* @return a single array containing all the values from the source arrays, in
* order
*/
public static short[] concat(short[]... arrays) {
int length = 0;
for (short[] array : arrays) {
length += array.length;
}
short[] result = new short[length];
int pos = 0;
for (short[] array : arrays) {
System.arraycopy(array, 0, result, pos, array.length);
pos += array.length;
}
return result;
}
/**
* Returns a big-endian representation of {@code value} in a 2-element byte
* array; equivalent to {@code
* ByteBuffer.allocate(2).putShort(value).array()}. For example, the input value
* {@code (short) 0x1234} would yield the byte array {@code {0x12, 0x34}}.
*
* <p>
* If you need to convert and concatenate several values (possibly even of
* different types), use a shared {@link java.nio.ByteBuffer} instance, or use
* {@link com.google.common.io.ByteStreams#newDataOutput()} to get a growable
* buffer.
*/
@GwtIncompatible("doesn't work")
public static byte[] toByteArray(short value) {
return new byte[] { (byte) (value >> 8), (byte) value };
}
/**
* Returns the {@code short} value whose big-endian representation is stored in
* the first 2 bytes of {@code bytes}; equivalent to {@code
* ByteBuffer.wrap(bytes).getShort()}. For example, the input byte array
* {@code {0x54, 0x32}} would yield the {@code short} value {@code 0x5432}.
*
* <p>
* Arguably, it's preferable to use {@link java.nio.ByteBuffer}; that library
* exposes much more flexibility at little cost in readability.
*
* @throws IllegalArgumentException if {@code bytes} has fewer than 2 elements
*/
@GwtIncompatible("doesn't work")
public static short fromByteArray(byte[] bytes) {
checkArgument(bytes.length >= BYTES, "array too small: %s < %s", bytes.length, BYTES);
return fromBytes(bytes[0], bytes[1]);
}
/**
* Returns the {@code short} value whose byte representation is the given 2
* bytes, in big-endian order; equivalent to {@code Shorts.fromByteArray(new
* byte[] {b1, b2})}.
*
* @since 7.0
*/
@GwtIncompatible("doesn't work")
public static short fromBytes(byte b1, byte b2) {
return (short) ((b1 << 8) | (b2 & 0xFF));
}
private static final class ShortConverter extends Converter<String, Short> implements Serializable {
static final ShortConverter INSTANCE = new ShortConverter();
@Override
protected Short doForward(String value) {
return Short.decode(value);
}
@Override
protected String doBackward(Short value) {
return value.toString();
}
@Override
public String toString() {
return "Shorts.stringConverter()";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 1;
}
/**
* Returns a serializable converter object that converts between strings and
* shorts using {@link Short#decode} and {@link Short#toString()}.
*
* @since 16.0
*/
@Beta
public static Converter<String, Short> stringConverter() {
return ShortConverter.INSTANCE;
}
/**
* Returns an array containing the same values as {@code array}, but guaranteed
* to be of a specified minimum length. If {@code array} already has a length of
* at least {@code minLength}, it is returned directly. Otherwise, a new array
* of size {@code minLength + padding} is returned, containing the values of
* {@code array}, and zeroes in the remaining places.
*
* @param array the source array
* @param minLength the minimum length the returned array must guarantee
* @param padding an extra amount to "grow" the array by if growth is
* necessary
* @throws IllegalArgumentException if {@code minLength} or {@code padding} is
* negative
* @return an array containing the values of {@code array}, with guaranteed
* minimum length {@code minLength}
*/
public static short[] ensureCapacity(short[] array, int minLength, int padding) {
checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
checkArgument(padding >= 0, "Invalid padding: %s", padding);
return (array.length < minLength) ? copyOf(array, minLength + padding) : array;
}
// Arrays.copyOf() requires Java 6
private static short[] copyOf(short[] original, int length) {
short[] copy = new short[length];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
return copy;
}
/**
* Returns a string containing the supplied {@code short} values separated by
* {@code separator}. For example, {@code join("-", (short) 1, (short) 2,
* (short) 3)} returns the string {@code "1-2-3"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of {@code short} values, possibly empty
*/
public static String join(String separator, short... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 6);
builder.append(array[0]);
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(array[i]);
}
return builder.toString();
}
/**
* Returns a comparator that compares two {@code short} arrays
* lexicographically. That is, it compares, using
* {@link #compare(short, short)}), the first pair of values that follow any
* common prefix, or when one array is a prefix of the other, treats the shorter
* array as the lesser. For example, {@code [] < [(short) 1] <
* [(short) 1, (short) 2] < [(short) 2]}.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link Arrays#equals(short[], short[])}.
*
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
* Lexicographical order article at Wikipedia</a>
* @since 2.0
*/
public static Comparator<short[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
private enum LexicographicalComparator implements Comparator<short[]> {
INSTANCE;
@Override
public int compare(short[] left, short[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
int result = Shorts.compare(left[i], right[i]);
if (result != 0) {
return result;
}
}
return left.length - right.length;
}
}
/**
* Returns an array containing each value of {@code collection}, converted to a
* {@code short} value in the manner of {@link Number#shortValue}.
*
* <p>
* Elements are copied from the argument collection as if by {@code
* collection.toArray()}. Calling this method is as thread-safe as calling that
* method.
*
* @param collection a collection of {@code Number} instances
* @return an array containing the same values as {@code collection}, in the
* same order, converted to primitives
* @throws NullPointerException if {@code collection} or any of its elements is
* null
* @since 1.0 (parameter was {@code Collection<Short>} before 12.0)
*/
public static short[] toArray(Collection<? extends Number> collection) {
if (collection instanceof ShortArrayAsList) {
return ((ShortArrayAsList) collection).toShortArray();
}
Object[] boxedArray = collection.toArray();
int len = boxedArray.length;
short[] array = new short[len];
for (int i = 0; i < len; i++) {
// checkNotNull for GWT (do not optimize)
array[i] = ((Number) checkNotNull(boxedArray[i])).shortValue();
}
return array;
}
/**
* Returns a fixed-size list backed by the specified array, similar to
* {@link Arrays#asList(Object[])}. The list supports
* {@link List#set(int, Object)}, but any attempt to set a value to {@code null}
* will result in a {@link NullPointerException}.
*
* <p>
* The returned list maintains the values, but not the identities, of
* {@code Short} objects written to or read from it. For example, whether
* {@code list.get(0) == list.get(0)} is true for the returned list is
* unspecified.
*
* @param backingArray the array to back the list
* @return a list view of the array
*/
public static List<Short> asList(short... backingArray) {
if (backingArray.length == 0) {
return Collections.emptyList();
}
return new ShortArrayAsList(backingArray);
}
@GwtCompatible
private static class ShortArrayAsList extends AbstractList<Short> implements RandomAccess, Serializable {
final short[] array;
final int start;
final int end;
ShortArrayAsList(short[] array) {
this(array, 0, array.length);
}
ShortArrayAsList(short[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
public int size() {
return end - start;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Short get(int index) {
checkElementIndex(index, size());
return array[start + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Short) && Shorts.indexOf(array, (Short) target, start, end) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Short) {
int i = Shorts.indexOf(array, (Short) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Short) {
int i = Shorts.lastIndexOf(array, (Short) target, start, end);
if (i >= 0) {
return i - start;
}
}
return -1;
}
@Override
public Short set(int index, Short element) {
checkElementIndex(index, size());
short oldValue = array[start + index];
// checkNotNull for GWT (do not optimize)
array[start + index] = checkNotNull(element);
return oldValue;
}
@Override
public List<Short> subList(int fromIndex, int toIndex) {
int size = size();
checkPositionIndexes(fromIndex, toIndex, size);
if (fromIndex == toIndex) {
return Collections.emptyList();
}
return new ShortArrayAsList(array, start + fromIndex, start + toIndex);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof ShortArrayAsList) {
ShortArrayAsList that = (ShortArrayAsList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (array[start + i] != that.array[that.start + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = start; i < end; i++) {
result = 31 * result + Shorts.hashCode(array[i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 6);
builder.append('[').append(array[start]);
for (int i = start + 1; i < end; i++) {
builder.append(", ").append(array[i]);
}
return builder.append(']').toString();
}
short[] toShortArray() {
// Arrays.copyOfRange() is not available under GWT
int size = size();
short[] result = new short[size];
System.arraycopy(array, start, result, 0, size);
return result;
}
private static final long serialVersionUID = 0;
}
}

View File

@ -0,0 +1,208 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Comparator;
import com.google.common.annotations.GwtCompatible;
/**
* Static utility methods pertaining to {@code byte} primitives that interpret
* values as signed. The corresponding methods that treat the values as unsigned
* are found in {@link UnsignedBytes}, and the methods for which signedness is
* not an issue are in {@link Bytes}.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @since 1.0
*/
// TODO(kevinb): how to prevent warning on UnsignedBytes when building GWT
// javadoc?
@GwtCompatible
public final class SignedBytes {
private SignedBytes() {
}
/**
* The largest power of two that can be represented as a signed {@code byte}.
*
* @since 10.0
*/
public static final byte MAX_POWER_OF_TWO = 1 << 6;
/**
* Returns the {@code byte} value that is equal to {@code value}, if possible.
*
* @param value any value in the range of the {@code byte} type
* @return the {@code byte} value that equals {@code value}
* @throws IllegalArgumentException if {@code value} is greater than
* {@link Byte#MAX_VALUE} or less than
* {@link Byte#MIN_VALUE}
*/
public static byte checkedCast(long value) {
byte result = (byte) value;
if (result != value) {
// don't use checkArgument here, to avoid boxing
throw new IllegalArgumentException("Out of range: " + value);
}
return result;
}
/**
* Returns the {@code byte} nearest in value to {@code value}.
*
* @param value any {@code long} value
* @return the same value cast to {@code byte} if it is in the range of the
* {@code byte} type, {@link Byte#MAX_VALUE} if it is too large, or
* {@link Byte#MIN_VALUE} if it is too small
*/
public static byte saturatedCast(long value) {
if (value > Byte.MAX_VALUE) {
return Byte.MAX_VALUE;
}
if (value < Byte.MIN_VALUE) {
return Byte.MIN_VALUE;
}
return (byte) value;
}
/**
* Compares the two specified {@code byte} values. The sign of the value
* returned is the same as that of {@code ((Byte) a).compareTo(b)}.
*
* <p>
* <b>Note:</b> this method behaves identically to the JDK 7 method
* {@link Byte#compare}.
*
* @param a the first {@code byte} to compare
* @param b the second {@code byte} to compare
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are
* equal
*/
// TODO(kevinb): if Ints.compare etc. are ever removed, *maybe* remove this
// one too, which would leave compare methods only on the Unsigned* classes.
public static int compare(byte a, byte b) {
return a - b; // safe due to restricted range
}
/**
* Returns the least value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code byte} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static byte min(byte... array) {
checkArgument(array.length > 0);
byte min = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}
/**
* Returns the greatest value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code byte} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static byte max(byte... array) {
checkArgument(array.length > 0);
byte max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
/**
* Returns a string containing the supplied {@code byte} values separated by
* {@code separator}. For example, {@code join(":", 0x01, 0x02, -0x01)} returns
* the string {@code "1:2:-1"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of {@code byte} values, possibly empty
*/
public static String join(String separator, byte... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 5);
builder.append(array[0]);
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(array[i]);
}
return builder.toString();
}
/**
* Returns a comparator that compares two {@code byte} arrays lexicographically.
* That is, it compares, using {@link #compare(byte, byte)}), the first pair of
* values that follow any common prefix, or when one array is a prefix of the
* other, treats the shorter array as the lesser. For example,
* {@code [] < [0x01] < [0x01, 0x80] <
* [0x01, 0x7F] < [0x02]}. Values are treated as signed.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link java.util.Arrays#equals(byte[], byte[])}.
*
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
* Lexicographical order article at Wikipedia</a>
* @since 2.0
*/
public static Comparator<byte[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
private enum LexicographicalComparator implements Comparator<byte[]> {
INSTANCE;
@Override
public int compare(byte[] left, byte[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
int result = SignedBytes.compare(left[i], right[i]);
if (result != 0) {
return result;
}
}
return left.length - right.length;
}
}
}

View File

@ -0,0 +1,262 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
/**
* Static utility methods pertaining to {@code byte} primitives that interpret
* values as <i>unsigned</i> (that is, any negative value {@code b} is treated
* as the positive value {@code 256 + b}). The corresponding methods that treat
* the values as signed are found in {@link SignedBytes}, and the methods for
* which signedness is not an issue are in {@link Bytes}.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* @author Kevin Bourrillion
* @author Martin Buchholz
* @author Hiroshi Yamauchi
* @author Louis Wasserman
* @since 1.0
*/
public final class UnsignedBytes {
private UnsignedBytes() {
}
/**
* The largest power of two that can be represented as an unsigned {@code
* byte}.
*
* @since 10.0
*/
public static final byte MAX_POWER_OF_TWO = (byte) 0x80;
/**
* The largest value that fits into an unsigned byte.
*
* @since 13.0
*/
public static final byte MAX_VALUE = (byte) 0xFF;
private static final int UNSIGNED_MASK = 0xFF;
/**
* Returns the value of the given byte as an integer, when treated as unsigned.
* That is, returns {@code value + 256} if {@code value} is negative;
* {@code value} itself otherwise.
*
* @since 6.0
*/
public static int toInt(byte value) {
return value & UNSIGNED_MASK;
}
/**
* Returns the {@code byte} value that, when treated as unsigned, is equal to
* {@code value}, if possible.
*
* @param value a value between 0 and 255 inclusive
* @return the {@code byte} value that, when treated as unsigned, equals
* {@code value}
* @throws IllegalArgumentException if {@code value} is negative or greater than
* 255
*/
public static byte checkedCast(long value) {
if ((value >> Byte.SIZE) != 0) {
// don't use checkArgument here, to avoid boxing
throw new IllegalArgumentException("Out of range: " + value);
}
return (byte) value;
}
/**
* Returns the {@code byte} value that, when treated as unsigned, is nearest in
* value to {@code value}.
*
* @param value any {@code long} value
* @return {@code (byte) 255} if {@code value >= 255}, {@code (byte) 0} if
* {@code value <= 0}, and {@code value} cast to {@code byte} otherwise
*/
public static byte saturatedCast(long value) {
if (value > toInt(MAX_VALUE)) {
return MAX_VALUE; // -1
}
if (value < 0) {
return (byte) 0;
}
return (byte) value;
}
/**
* Compares the two specified {@code byte} values, treating them as unsigned
* values between 0 and 255 inclusive. For example, {@code (byte) -127} is
* considered greater than {@code (byte) 127} because it is seen as having the
* value of positive {@code 129}.
*
* @param a the first {@code byte} to compare
* @param b the second {@code byte} to compare
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are
* equal
*/
public static int compare(byte a, byte b) {
return toInt(a) - toInt(b);
}
/**
* Returns the least value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code byte} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static byte min(byte... array) {
checkArgument(array.length > 0);
int min = toInt(array[0]);
for (int i = 1; i < array.length; i++) {
int next = toInt(array[i]);
if (next < min) {
min = next;
}
}
return (byte) min;
}
/**
* Returns the greatest value present in {@code array}.
*
* @param array a <i>nonempty</i> array of {@code byte} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array
* @throws IllegalArgumentException if {@code array} is empty
*/
public static byte max(byte... array) {
checkArgument(array.length > 0);
int max = toInt(array[0]);
for (int i = 1; i < array.length; i++) {
int next = toInt(array[i]);
if (next > max) {
max = next;
}
}
return (byte) max;
}
/**
* Returns a string representation of x, where x is treated as unsigned.
*
* @since 13.0
*/
@Beta
public static String toString(byte x) {
return toString(x, 10);
}
/**
* Returns a string representation of {@code x} for the given radix, where
* {@code x} is treated as unsigned.
*
* @param x the value to convert to a string.
* @param radix the radix to use while working with {@code x}
* @throws IllegalArgumentException if {@code radix} is not between
* {@link Character#MIN_RADIX} and
* {@link Character#MAX_RADIX}.
* @since 13.0
*/
@Beta
public static String toString(byte x, int radix) {
checkArgument(radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
"radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", radix);
// Benchmarks indicate this is probably not worth optimizing.
return Integer.toString(toInt(x), radix);
}
/**
* Returns the unsigned {@code byte} value represented by the given decimal
* string.
*
* @throws NumberFormatException if the string does not contain a valid unsigned
* {@code byte} value
* @throws NullPointerException if {@code s} is null (in contrast to
* {@link Byte#parseByte(String)})
* @since 13.0
*/
@Beta
public static byte parseUnsignedByte(String string) {
return parseUnsignedByte(string, 10);
}
/**
* Returns the unsigned {@code byte} value represented by a string with the
* given radix.
*
* @param string the string containing the unsigned {@code byte} representation
* to be parsed.
* @param radix the radix to use while parsing {@code string}
* @throws NumberFormatException if the string does not contain a valid unsigned
* {@code byte} with the given radix, or if
* {@code radix} is not between
* {@link Character#MIN_RADIX} and
* {@link Character#MAX_RADIX}.
* @throws NullPointerException if {@code s} is null (in contrast to
* {@link Byte#parseByte(String)})
* @since 13.0
*/
@Beta
public static byte parseUnsignedByte(String string, int radix) {
int parse = Integer.parseInt(checkNotNull(string), radix);
// We need to throw a NumberFormatException, so we have to duplicate
// checkedCast. =(
if (parse >> Byte.SIZE == 0) {
return (byte) parse;
} else {
throw new NumberFormatException("out of range: " + parse);
}
}
/**
* Returns a string containing the supplied {@code byte} values separated by
* {@code separator}. For example, {@code join(":", (byte) 1, (byte) 2,
* (byte) 255)} returns the string {@code "1:2:255"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of {@code byte} values, possibly empty
*/
public static String join(String separator, byte... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * (3 + separator.length()));
builder.append(toInt(array[0]));
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(toString(array[i]));
}
return builder.toString();
}
}

View File

@ -0,0 +1,277 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.primitives.UnsignedInts.INT_MASK;
import static com.google.common.primitives.UnsignedInts.compare;
import static com.google.common.primitives.UnsignedInts.toLong;
import java.math.BigInteger;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* A wrapper class for unsigned {@code int} values, supporting arithmetic
* operations.
*
* <p>
* In some cases, when speed is more important than code readability, it may be
* faster simply to treat primitive {@code int} values as unsigned, using the
* methods from {@link UnsignedInts}.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
* unsigned primitive utilities</a>.
*
* @author Louis Wasserman
* @since 11.0
*/
@GwtCompatible(emulated = true)
public final class UnsignedInteger extends Number implements Comparable<UnsignedInteger> {
public static final UnsignedInteger ZERO = fromIntBits(0);
public static final UnsignedInteger ONE = fromIntBits(1);
public static final UnsignedInteger MAX_VALUE = fromIntBits(-1);
private final int value;
private UnsignedInteger(int value) {
// GWT doesn't consistently overflow values to make them 32-bit, so we need to
// force it.
this.value = value & 0xffffffff;
}
/**
* Returns an {@code UnsignedInteger} corresponding to a given bit
* representation. The argument is interpreted as an unsigned 32-bit value.
* Specifically, the sign bit of {@code bits} is interpreted as a normal bit,
* and all other bits are treated as usual.
*
* <p>
* If the argument is nonnegative, the returned result will be equal to
* {@code bits}, otherwise, the result will be equal to {@code 2^32 + bits}.
*
* <p>
* To represent unsigned decimal constants, consider {@link #valueOf(long)}
* instead.
*
* @since 14.0
*/
public static UnsignedInteger fromIntBits(int bits) {
return new UnsignedInteger(bits);
}
/**
* Returns an {@code UnsignedInteger} that is equal to {@code value}, if
* possible. The inverse operation of {@link #longValue()}.
*/
public static UnsignedInteger valueOf(long value) {
checkArgument((value & INT_MASK) == value, "value (%s) is outside the range for an unsigned integer value",
value);
return fromIntBits((int) value);
}
/**
* Returns a {@code UnsignedInteger} representing the same value as the
* specified {@link BigInteger}. This is the inverse operation of
* {@link #bigIntegerValue()}.
*
* @throws IllegalArgumentException if {@code value} is negative or
* {@code value >= 2^32}
*/
public static UnsignedInteger valueOf(BigInteger value) {
checkNotNull(value);
checkArgument(value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
"value (%s) is outside the range for an unsigned integer value", value);
return fromIntBits(value.intValue());
}
/**
* Returns an {@code UnsignedInteger} holding the value of the specified
* {@code String}, parsed as an unsigned {@code int} value.
*
* @throws NumberFormatException if the string does not contain a parsable
* unsigned {@code int} value
*/
public static UnsignedInteger valueOf(String string) {
return valueOf(string, 10);
}
/**
* Returns an {@code UnsignedInteger} holding the value of the specified
* {@code String}, parsed as an unsigned {@code int} value in the specified
* radix.
*
* @throws NumberFormatException if the string does not contain a parsable
* unsigned {@code int} value
*/
public static UnsignedInteger valueOf(String string, int radix) {
return fromIntBits(UnsignedInts.parseUnsignedInt(string, radix));
}
/**
* Returns the result of adding this and {@code val}. If the result would have
* more than 32 bits, returns the low 32 bits of the result.
*
* @since 14.0
*/
@CheckReturnValue
public UnsignedInteger plus(UnsignedInteger val) {
return fromIntBits(this.value + checkNotNull(val).value);
}
/**
* Returns the result of subtracting this and {@code val}. If the result would
* be negative, returns the low 32 bits of the result.
*
* @since 14.0
*/
@CheckReturnValue
public UnsignedInteger minus(UnsignedInteger val) {
return fromIntBits(value - checkNotNull(val).value);
}
/**
* Returns the result of multiplying this and {@code val}. If the result would
* have more than 32 bits, returns the low 32 bits of the result.
*
* @since 14.0
*/
@CheckReturnValue
@GwtIncompatible("Does not truncate correctly")
public UnsignedInteger times(UnsignedInteger val) {
// TODO(user): make this GWT-compatible
return fromIntBits(value * checkNotNull(val).value);
}
/**
* Returns the result of dividing this by {@code val}.
*
* @throws ArithmeticException if {@code val} is zero
* @since 14.0
*/
@CheckReturnValue
public UnsignedInteger dividedBy(UnsignedInteger val) {
return fromIntBits(UnsignedInts.divide(value, checkNotNull(val).value));
}
/**
* Returns this mod {@code val}.
*
* @throws ArithmeticException if {@code val} is zero
* @since 14.0
*/
@CheckReturnValue
public UnsignedInteger mod(UnsignedInteger val) {
return fromIntBits(UnsignedInts.remainder(value, checkNotNull(val).value));
}
/**
* Returns the value of this {@code UnsignedInteger} as an {@code int}. This is
* an inverse operation to {@link #fromIntBits}.
*
* <p>
* Note that if this {@code UnsignedInteger} holds a value {@code >= 2^31}, the
* returned value will be equal to {@code this - 2^32}.
*/
@Override
public int intValue() {
return value;
}
/**
* Returns the value of this {@code UnsignedInteger} as a {@code long}.
*/
@Override
public long longValue() {
return toLong(value);
}
/**
* Returns the value of this {@code UnsignedInteger} as a {@code float},
* analogous to a widening primitive conversion from {@code int} to
* {@code float}, and correctly rounded.
*/
@Override
public float floatValue() {
return longValue();
}
/**
* Returns the value of this {@code UnsignedInteger} as a {@code float},
* analogous to a widening primitive conversion from {@code int} to
* {@code double}, and correctly rounded.
*/
@Override
public double doubleValue() {
return longValue();
}
/**
* Returns the value of this {@code UnsignedInteger} as a {@link BigInteger}.
*/
public BigInteger bigIntegerValue() {
return BigInteger.valueOf(longValue());
}
/**
* Compares this unsigned integer to another unsigned integer. Returns {@code 0}
* if they are equal, a negative number if {@code this < other}, and a positive
* number if {@code this > other}.
*/
@Override
public int compareTo(UnsignedInteger other) {
checkNotNull(other);
return compare(value, other.value);
}
@Override
public int hashCode() {
return value;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof UnsignedInteger) {
UnsignedInteger other = (UnsignedInteger) obj;
return value == other.value;
}
return false;
}
/**
* Returns a string representation of the {@code UnsignedInteger} value, in base
* 10.
*/
@Override
public String toString() {
return toString(10);
}
/**
* Returns a string representation of the {@code UnsignedInteger} value, in base
* {@code radix}. If {@code radix < Character.MIN_RADIX} or
* {@code radix > Character.MAX_RADIX}, the radix {@code 10} is used.
*/
public String toString(int radix) {
return UnsignedInts.toString(value, radix);
}
}

View File

@ -0,0 +1,296 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Arrays;
import java.util.Comparator;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Static utility methods pertaining to {@code int} primitives that interpret
* values as <i>unsigned</i> (that is, any negative value {@code x} is treated
* as the positive value {@code 2^32 + x}). The methods for which signedness is
* not an issue are in {@link Ints}, as well as signed versions of methods for
* which signedness is an issue.
*
* <p>
* In addition, this class provides several static methods for converting an
* {@code int} to a {@code String} and a {@code String} to an {@code int} that
* treat the {@code int} as an unsigned number.
*
* <p>
* Users of these utilities must be <i>extremely careful</i> not to mix up
* signed and unsigned {@code int} values. When possible, it is recommended that
* the {@link UnsignedInteger} wrapper class be used, at a small efficiency
* penalty, to enforce the distinction in the type system.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
* unsigned primitive utilities</a>.
*
* @author Louis Wasserman
* @since 11.0
*/
@Beta
@GwtCompatible
public final class UnsignedInts {
static final long INT_MASK = 0xffffffffL;
private UnsignedInts() {
}
static int flip(int value) {
return value ^ Integer.MIN_VALUE;
}
/**
* Compares the two specified {@code int} values, treating them as unsigned
* values between {@code 0} and {@code 2^32 - 1} inclusive.
*
* @param a the first unsigned {@code int} to compare
* @param b the second unsigned {@code int} to compare
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are
* equal
*/
public static int compare(int a, int b) {
return Ints.compare(flip(a), flip(b));
}
/**
* Returns the value of the given {@code int} as a {@code long}, when treated as
* unsigned.
*/
public static long toLong(int value) {
return value & INT_MASK;
}
/**
* Returns the least value present in {@code array}, treating values as
* unsigned.
*
* @param array a <i>nonempty</i> array of unsigned {@code int} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array according to {@link #compare}
* @throws IllegalArgumentException if {@code array} is empty
*/
public static int min(int... array) {
checkArgument(array.length > 0);
int min = flip(array[0]);
for (int i = 1; i < array.length; i++) {
int next = flip(array[i]);
if (next < min) {
min = next;
}
}
return flip(min);
}
/**
* Returns the greatest value present in {@code array}, treating values as
* unsigned.
*
* @param array a <i>nonempty</i> array of unsigned {@code int} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array according to {@link #compare}
* @throws IllegalArgumentException if {@code array} is empty
*/
public static int max(int... array) {
checkArgument(array.length > 0);
int max = flip(array[0]);
for (int i = 1; i < array.length; i++) {
int next = flip(array[i]);
if (next > max) {
max = next;
}
}
return flip(max);
}
/**
* Returns a string containing the supplied unsigned {@code int} values
* separated by {@code separator}. For example, {@code join("-", 1, 2, 3)}
* returns the string {@code "1-2-3"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of unsigned {@code int} values, possibly empty
*/
public static String join(String separator, int... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 5);
builder.append(toString(array[0]));
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(toString(array[i]));
}
return builder.toString();
}
/**
* Returns a comparator that compares two arrays of unsigned {@code int} values
* lexicographically. That is, it compares, using {@link #compare(int, int)}),
* the first pair of values that follow any common prefix, or when one array is
* a prefix of the other, treats the shorter array as the lesser. For example,
* {@code [] < [1] < [1, 2] < [2] < [1 << 31]}.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link Arrays#equals(int[], int[])}.
*
* @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
* Lexicographical order article at Wikipedia</a>
*/
public static Comparator<int[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
enum LexicographicalComparator implements Comparator<int[]> {
INSTANCE;
@Override
public int compare(int[] left, int[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
if (left[i] != right[i]) {
return UnsignedInts.compare(left[i], right[i]);
}
}
return left.length - right.length;
}
}
/**
* Returns dividend / divisor, where the dividend and divisor are treated as
* unsigned 32-bit quantities.
*
* @param dividend the dividend (numerator)
* @param divisor the divisor (denominator)
* @throws ArithmeticException if divisor is 0
*/
public static int divide(int dividend, int divisor) {
return (int) (toLong(dividend) / toLong(divisor));
}
/**
* Returns dividend % divisor, where the dividend and divisor are treated as
* unsigned 32-bit quantities.
*
* @param dividend the dividend (numerator)
* @param divisor the divisor (denominator)
* @throws ArithmeticException if divisor is 0
*/
public static int remainder(int dividend, int divisor) {
return (int) (toLong(dividend) % toLong(divisor));
}
/**
* Returns the unsigned {@code int} value represented by the given string.
*
* Accepts a decimal, hexadecimal, or octal number given by specifying the
* following prefix:
*
* <ul>
* <li>{@code 0x}<i>HexDigits</i>
* <li>{@code 0X}<i>HexDigits</i>
* <li>{@code #}<i>HexDigits</i>
* <li>{@code 0}<i>OctalDigits</i>
* </ul>
*
* @throws NumberFormatException if the string does not contain a valid unsigned
* {@code int} value
* @since 13.0
*/
public static int decode(String stringValue) {
ParseRequest request = ParseRequest.fromString(stringValue);
try {
return parseUnsignedInt(request.rawValue, request.radix);
} catch (NumberFormatException e) {
NumberFormatException decodeException = new NumberFormatException("Error parsing value: " + stringValue);
decodeException.initCause(e);
throw decodeException;
}
}
/**
* Returns the unsigned {@code int} value represented by the given decimal
* string.
*
* @throws NumberFormatException if the string does not contain a valid unsigned
* {@code int} value
* @throws NullPointerException if {@code s} is null (in contrast to
* {@link Integer#parseInt(String)})
*/
public static int parseUnsignedInt(String s) {
return parseUnsignedInt(s, 10);
}
/**
* Returns the unsigned {@code int} value represented by a string with the given
* radix.
*
* @param string the string containing the unsigned integer representation to be
* parsed.
* @param radix the radix to use while parsing {@code s}; must be between
* {@link Character#MIN_RADIX} and {@link Character#MAX_RADIX}.
* @throws NumberFormatException if the string does not contain a valid unsigned
* {@code int}, or if supplied radix is invalid.
* @throws NullPointerException if {@code s} is null (in contrast to
* {@link Integer#parseInt(String)})
*/
public static int parseUnsignedInt(String string, int radix) {
checkNotNull(string);
long result = Long.parseLong(string, radix);
if ((result & INT_MASK) != result) {
throw new NumberFormatException(
"Input " + string + " in base " + radix + " is not in the range of an unsigned integer");
}
return (int) result;
}
/**
* Returns a string representation of x, where x is treated as unsigned.
*/
public static String toString(int x) {
return toString(x, 10);
}
/**
* Returns a string representation of {@code x} for the given radix, where
* {@code x} is treated as unsigned.
*
* @param x the value to convert to a string.
* @param radix the radix to use while working with {@code x}
* @throws IllegalArgumentException if {@code radix} is not between
* {@link Character#MIN_RADIX} and
* {@link Character#MAX_RADIX}.
*/
public static String toString(int x, int radix) {
long asLong = x & INT_MASK;
return Long.toString(asLong, radix);
}
}

View File

@ -0,0 +1,284 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.math.BigInteger;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A wrapper class for unsigned {@code long} values, supporting arithmetic
* operations.
*
* <p>
* In some cases, when speed is more important than code readability, it may be
* faster simply to treat primitive {@code long} values as unsigned, using the
* methods from {@link UnsignedLongs}.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
* unsigned primitive utilities</a>.
*
* @author Louis Wasserman
* @author Colin Evans
* @since 11.0
*/
@GwtCompatible(serializable = true)
public final class UnsignedLong extends Number implements Comparable<UnsignedLong>, Serializable {
private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
public static final UnsignedLong ZERO = new UnsignedLong(0);
public static final UnsignedLong ONE = new UnsignedLong(1);
public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L);
private final long value;
private UnsignedLong(long value) {
this.value = value;
}
/**
* Returns an {@code UnsignedLong} corresponding to a given bit representation.
* The argument is interpreted as an unsigned 64-bit value. Specifically, the
* sign bit of {@code bits} is interpreted as a normal bit, and all other bits
* are treated as usual.
*
* <p>
* If the argument is nonnegative, the returned result will be equal to
* {@code bits}, otherwise, the result will be equal to {@code 2^64 + bits}.
*
* <p>
* To represent decimal constants less than {@code 2^63}, consider
* {@link #valueOf(long)} instead.
*
* @since 14.0
*/
public static UnsignedLong fromLongBits(long bits) {
// TODO(user): consider caching small values, like Long.valueOf
return new UnsignedLong(bits);
}
/**
* Returns an {@code UnsignedLong} representing the same value as the specified
* {@code long}.
*
* @throws IllegalArgumentException if {@code value} is negative
* @since 14.0
*/
public static UnsignedLong valueOf(long value) {
checkArgument(value >= 0, "value (%s) is outside the range for an unsigned long value", value);
return fromLongBits(value);
}
/**
* Returns a {@code UnsignedLong} representing the same value as the specified
* {@code BigInteger}. This is the inverse operation of
* {@link #bigIntegerValue()}.
*
* @throws IllegalArgumentException if {@code value} is negative or
* {@code value >= 2^64}
*/
public static UnsignedLong valueOf(BigInteger value) {
checkNotNull(value);
checkArgument(value.signum() >= 0 && value.bitLength() <= Long.SIZE,
"value (%s) is outside the range for an unsigned long value", value);
return fromLongBits(value.longValue());
}
/**
* Returns an {@code UnsignedLong} holding the value of the specified
* {@code String}, parsed as an unsigned {@code long} value.
*
* @throws NumberFormatException if the string does not contain a parsable
* unsigned {@code long} value
*/
public static UnsignedLong valueOf(String string) {
return valueOf(string, 10);
}
/**
* Returns an {@code UnsignedLong} holding the value of the specified
* {@code String}, parsed as an unsigned {@code long} value in the specified
* radix.
*
* @throws NumberFormatException if the string does not contain a parsable
* unsigned {@code long} value, or {@code radix}
* is not between {@link Character#MIN_RADIX} and
* {@link Character#MAX_RADIX}
*/
public static UnsignedLong valueOf(String string, int radix) {
return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix));
}
/**
* Returns the result of adding this and {@code val}. If the result would have
* more than 64 bits, returns the low 64 bits of the result.
*
* @since 14.0
*/
public UnsignedLong plus(UnsignedLong val) {
return fromLongBits(this.value + checkNotNull(val).value);
}
/**
* Returns the result of subtracting this and {@code val}. If the result would
* have more than 64 bits, returns the low 64 bits of the result.
*
* @since 14.0
*/
public UnsignedLong minus(UnsignedLong val) {
return fromLongBits(this.value - checkNotNull(val).value);
}
/**
* Returns the result of multiplying this and {@code val}. If the result would
* have more than 64 bits, returns the low 64 bits of the result.
*
* @since 14.0
*/
@CheckReturnValue
public UnsignedLong times(UnsignedLong val) {
return fromLongBits(value * checkNotNull(val).value);
}
/**
* Returns the result of dividing this by {@code val}.
*
* @since 14.0
*/
@CheckReturnValue
public UnsignedLong dividedBy(UnsignedLong val) {
return fromLongBits(UnsignedLongs.divide(value, checkNotNull(val).value));
}
/**
* Returns this modulo {@code val}.
*
* @since 14.0
*/
@CheckReturnValue
public UnsignedLong mod(UnsignedLong val) {
return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value));
}
/**
* Returns the value of this {@code UnsignedLong} as an {@code int}.
*/
@Override
public int intValue() {
return (int) value;
}
/**
* Returns the value of this {@code UnsignedLong} as a {@code long}. This is an
* inverse operation to {@link #fromLongBits}.
*
* <p>
* Note that if this {@code UnsignedLong} holds a value {@code >= 2^63}, the
* returned value will be equal to {@code this - 2^64}.
*/
@Override
public long longValue() {
return value;
}
/**
* Returns the value of this {@code UnsignedLong} as a {@code float}, analogous
* to a widening primitive conversion from {@code long} to {@code float}, and
* correctly rounded.
*/
@Override
public float floatValue() {
@SuppressWarnings("cast")
float fValue = (float) (value & UNSIGNED_MASK);
if (value < 0) {
fValue += 0x1.0p63f;
}
return fValue;
}
/**
* Returns the value of this {@code UnsignedLong} as a {@code double}, analogous
* to a widening primitive conversion from {@code long} to {@code double}, and
* correctly rounded.
*/
@Override
public double doubleValue() {
@SuppressWarnings("cast")
double dValue = (double) (value & UNSIGNED_MASK);
if (value < 0) {
dValue += 0x1.0p63;
}
return dValue;
}
/**
* Returns the value of this {@code UnsignedLong} as a {@link BigInteger}.
*/
public BigInteger bigIntegerValue() {
BigInteger bigInt = BigInteger.valueOf(value & UNSIGNED_MASK);
if (value < 0) {
bigInt = bigInt.setBit(Long.SIZE - 1);
}
return bigInt;
}
@Override
public int compareTo(UnsignedLong o) {
checkNotNull(o);
return UnsignedLongs.compare(value, o.value);
}
@Override
public int hashCode() {
return Longs.hashCode(value);
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof UnsignedLong) {
UnsignedLong other = (UnsignedLong) obj;
return value == other.value;
}
return false;
}
/**
* Returns a string representation of the {@code UnsignedLong} value, in base
* 10.
*/
@Override
public String toString() {
return UnsignedLongs.toString(value);
}
/**
* Returns a string representation of the {@code UnsignedLong} value, in base
* {@code radix}. If {@code radix < Character.MIN_RADIX} or
* {@code radix > Character.MAX_RADIX}, the radix {@code 10} is used.
*/
public String toString(int radix) {
return UnsignedLongs.toString(value, radix);
}
}

View File

@ -0,0 +1,415 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.primitives;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* Static utility methods pertaining to {@code long} primitives that interpret
* values as <i>unsigned</i> (that is, any negative value {@code x} is treated
* as the positive value {@code 2^64 + x}). The methods for which signedness is
* not an issue are in {@link Longs}, as well as signed versions of methods for
* which signedness is an issue.
*
* <p>
* In addition, this class provides several static methods for converting a
* {@code long} to a {@code String} and a {@code String} to a {@code long} that
* treat the {@code long} as an unsigned number.
*
* <p>
* Users of these utilities must be <i>extremely careful</i> not to mix up
* signed and unsigned {@code long} values. When possible, it is recommended
* that the {@link UnsignedLong} wrapper class be used, at a small efficiency
* penalty, to enforce the distinction in the type system.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
* unsigned primitive utilities</a>.
*
* @author Louis Wasserman
* @author Brian Milch
* @author Colin Evans
* @since 10.0
*/
@Beta
@GwtCompatible
public final class UnsignedLongs {
private UnsignedLongs() {
}
public static final long MAX_VALUE = -1L; // Equivalent to 2^64 - 1
/**
* A (self-inverse) bijection which converts the ordering on unsigned longs to
* the ordering on longs, that is, {@code a <= b} as unsigned longs if and only
* if {@code flip(a) <= flip(b)} as signed longs.
*/
private static long flip(long a) {
return a ^ Long.MIN_VALUE;
}
/**
* Compares the two specified {@code long} values, treating them as unsigned
* values between {@code 0} and {@code 2^64 - 1} inclusive.
*
* @param a the first unsigned {@code long} to compare
* @param b the second unsigned {@code long} to compare
* @return a negative value if {@code a} is less than {@code b}; a positive
* value if {@code a} is greater than {@code b}; or zero if they are
* equal
*/
public static int compare(long a, long b) {
return Longs.compare(flip(a), flip(b));
}
/**
* Returns the least value present in {@code array}, treating values as
* unsigned.
*
* @param array a <i>nonempty</i> array of unsigned {@code long} values
* @return the value present in {@code array} that is less than or equal to
* every other value in the array according to {@link #compare}
* @throws IllegalArgumentException if {@code array} is empty
*/
public static long min(long... array) {
checkArgument(array.length > 0);
long min = flip(array[0]);
for (int i = 1; i < array.length; i++) {
long next = flip(array[i]);
if (next < min) {
min = next;
}
}
return flip(min);
}
/**
* Returns the greatest value present in {@code array}, treating values as
* unsigned.
*
* @param array a <i>nonempty</i> array of unsigned {@code long} values
* @return the value present in {@code array} that is greater than or equal to
* every other value in the array according to {@link #compare}
* @throws IllegalArgumentException if {@code array} is empty
*/
public static long max(long... array) {
checkArgument(array.length > 0);
long max = flip(array[0]);
for (int i = 1; i < array.length; i++) {
long next = flip(array[i]);
if (next > max) {
max = next;
}
}
return flip(max);
}
/**
* Returns a string containing the supplied unsigned {@code long} values
* separated by {@code separator}. For example, {@code join("-", 1, 2, 3)}
* returns the string {@code "1-2-3"}.
*
* @param separator the text that should appear between consecutive values in
* the resulting string (but not at the start or end)
* @param array an array of unsigned {@code long} values, possibly empty
*/
public static String join(String separator, long... array) {
checkNotNull(separator);
if (array.length == 0) {
return "";
}
// For pre-sizing a builder, just get the right order of magnitude
StringBuilder builder = new StringBuilder(array.length * 5);
builder.append(toString(array[0]));
for (int i = 1; i < array.length; i++) {
builder.append(separator).append(toString(array[i]));
}
return builder.toString();
}
/**
* Returns a comparator that compares two arrays of unsigned {@code long} values
* lexicographically. That is, it compares, using {@link #compare(long, long)}),
* the first pair of values that follow any common prefix, or when one array is
* a prefix of the other, treats the shorter array as the lesser. For example,
* {@code [] < [1L] < [1L, 2L] < [2L] < [1L << 63]}.
*
* <p>
* The returned comparator is inconsistent with {@link Object#equals(Object)}
* (since arrays support only identity equality), but it is consistent with
* {@link Arrays#equals(long[], long[])}.
*
* @see <a href=
* "http://en.wikipedia.org/wiki/Lexicographical_order">Lexicographical
* order article at Wikipedia</a>
*/
public static Comparator<long[]> lexicographicalComparator() {
return LexicographicalComparator.INSTANCE;
}
enum LexicographicalComparator implements Comparator<long[]> {
INSTANCE;
@Override
public int compare(long[] left, long[] right) {
int minLength = Math.min(left.length, right.length);
for (int i = 0; i < minLength; i++) {
if (left[i] != right[i]) {
return UnsignedLongs.compare(left[i], right[i]);
}
}
return left.length - right.length;
}
}
/**
* Returns dividend / divisor, where the dividend and divisor are treated as
* unsigned 64-bit quantities.
*
* @param dividend the dividend (numerator)
* @param divisor the divisor (denominator)
* @throws ArithmeticException if divisor is 0
*/
public static long divide(long dividend, long divisor) {
if (divisor < 0) { // i.e., divisor >= 2^63:
if (compare(dividend, divisor) < 0) {
return 0; // dividend < divisor
} else {
return 1; // dividend >= divisor
}
}
// Optimization - use signed division if dividend < 2^63
if (dividend >= 0) {
return dividend / divisor;
}
/*
* Otherwise, approximate the quotient, check, and correct if necessary. Our
* approximation is guaranteed to be either exact or one less than the correct
* value. This follows from fact that floor(floor(x)/i) == floor(x/i) for any
* real x and integer i != 0. The proof is not quite trivial.
*/
long quotient = ((dividend >>> 1) / divisor) << 1;
long rem = dividend - quotient * divisor;
return quotient + (compare(rem, divisor) >= 0 ? 1 : 0);
}
/**
* Returns dividend % divisor, where the dividend and divisor are treated as
* unsigned 64-bit quantities.
*
* @param dividend the dividend (numerator)
* @param divisor the divisor (denominator)
* @throws ArithmeticException if divisor is 0
* @since 11.0
*/
public static long remainder(long dividend, long divisor) {
if (divisor < 0) { // i.e., divisor >= 2^63:
if (compare(dividend, divisor) < 0) {
return dividend; // dividend < divisor
} else {
return dividend - divisor; // dividend >= divisor
}
}
// Optimization - use signed modulus if dividend < 2^63
if (dividend >= 0) {
return dividend % divisor;
}
/*
* Otherwise, approximate the quotient, check, and correct if necessary. Our
* approximation is guaranteed to be either exact or one less than the correct
* value. This follows from fact that floor(floor(x)/i) == floor(x/i) for any
* real x and integer i != 0. The proof is not quite trivial.
*/
long quotient = ((dividend >>> 1) / divisor) << 1;
long rem = dividend - quotient * divisor;
return rem - (compare(rem, divisor) >= 0 ? divisor : 0);
}
/**
* Returns the unsigned {@code long} value represented by the given decimal
* string.
*
* @throws NumberFormatException if the string does not contain a valid unsigned
* {@code long} value
* @throws NullPointerException if {@code s} is null (in contrast to
* {@link Long#parseLong(String)})
*/
public static long parseUnsignedLong(String s) {
return parseUnsignedLong(s, 10);
}
/**
* Returns the unsigned {@code long} value represented by the given string.
*
* Accepts a decimal, hexadecimal, or octal number given by specifying the
* following prefix:
*
* <ul>
* <li>{@code 0x}<i>HexDigits</i>
* <li>{@code 0X}<i>HexDigits</i>
* <li>{@code #}<i>HexDigits</i>
* <li>{@code 0}<i>OctalDigits</i>
* </ul>
*
* @throws NumberFormatException if the string does not contain a valid unsigned
* {@code long} value
* @since 13.0
*/
public static long decode(String stringValue) {
ParseRequest request = ParseRequest.fromString(stringValue);
try {
return parseUnsignedLong(request.rawValue, request.radix);
} catch (NumberFormatException e) {
NumberFormatException decodeException = new NumberFormatException("Error parsing value: " + stringValue);
decodeException.initCause(e);
throw decodeException;
}
}
/**
* Returns the unsigned {@code long} value represented by a string with the
* given radix.
*
* @param s the string containing the unsigned {@code long} representation
* to be parsed.
* @param radix the radix to use while parsing {@code s}
* @throws NumberFormatException if the string does not contain a valid unsigned
* {@code long} with the given radix, or if
* {@code radix} is not between
* {@link Character#MIN_RADIX} and
* {@link Character#MAX_RADIX}.
* @throws NullPointerException if {@code s} is null (in contrast to
* {@link Long#parseLong(String)})
*/
public static long parseUnsignedLong(String s, int radix) {
checkNotNull(s);
if (s.length() == 0) {
throw new NumberFormatException("empty string");
}
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
throw new NumberFormatException("illegal radix: " + radix);
}
int max_safe_pos = maxSafeDigits[radix] - 1;
long value = 0;
for (int pos = 0; pos < s.length(); pos++) {
int digit = Character.digit(s.charAt(pos), radix);
if (digit == -1) {
throw new NumberFormatException(s);
}
if (pos > max_safe_pos && overflowInParse(value, digit, radix)) {
throw new NumberFormatException("Too large for unsigned long: " + s);
}
value = (value * radix) + digit;
}
return value;
}
/**
* Returns true if (current * radix) + digit is a number too large to be
* represented by an unsigned long. This is useful for detecting overflow while
* parsing a string representation of a number. Does not verify whether supplied
* radix is valid, passing an invalid radix will give undefined results or an
* ArrayIndexOutOfBoundsException.
*/
private static boolean overflowInParse(long current, int digit, int radix) {
if (current >= 0) {
if (current < maxValueDivs[radix]) {
return false;
}
if (current > maxValueDivs[radix]) {
return true;
}
// current == maxValueDivs[radix]
return (digit > maxValueMods[radix]);
}
// current < 0: high bit is set
return true;
}
/**
* Returns a string representation of x, where x is treated as unsigned.
*/
public static String toString(long x) {
return toString(x, 10);
}
/**
* Returns a string representation of {@code x} for the given radix, where
* {@code x} is treated as unsigned.
*
* @param x the value to convert to a string.
* @param radix the radix to use while working with {@code x}
* @throws IllegalArgumentException if {@code radix} is not between
* {@link Character#MIN_RADIX} and
* {@link Character#MAX_RADIX}.
*/
public static String toString(long x, int radix) {
checkArgument(radix >= Character.MIN_RADIX && radix <= Character.MAX_RADIX,
"radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", radix);
if (x == 0) {
// Simply return "0"
return "0";
} else {
char[] buf = new char[64];
int i = buf.length;
if (x < 0) {
// Separate off the last digit using unsigned division. That will leave
// a number that is nonnegative as a signed integer.
long quotient = divide(x, radix);
long rem = x - quotient * radix;
buf[--i] = Character.forDigit((int) rem, radix);
x = quotient;
}
// Simple modulo/division approach
while (x > 0) {
buf[--i] = Character.forDigit((int) (x % radix), radix);
x /= radix;
}
// Generate string
return new String(buf, i, buf.length - i);
}
}
// calculated as 0xffffffffffffffff / radix
private static final long[] maxValueDivs = new long[Character.MAX_RADIX + 1];
private static final int[] maxValueMods = new int[Character.MAX_RADIX + 1];
private static final int[] maxSafeDigits = new int[Character.MAX_RADIX + 1];
static {
BigInteger overflow = new BigInteger("10000000000000000", 16);
for (int i = Character.MIN_RADIX; i <= Character.MAX_RADIX; i++) {
maxValueDivs[i] = divide(MAX_VALUE, i);
maxValueMods[i] = (int) remainder(MAX_VALUE, i);
maxSafeDigits[i] = overflow.toString(i).length() - 1;
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Static utilities for working with the eight primitive types and {@code void},
* and value types for treating them as unsigned.
*
* <p>
* This package is a part of the open-source
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
*
* <p>
* See the Guava User Guide article on
* <a href= "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
* primitive utilities</a>.
*
* <h2>Contents</h2>
*
* <h3>General static utilities</h3>
*
* <ul>
* <li>{@link com.google.common.primitives.Primitives}
* </ul>
*
* <h3>Per-type static utilities</h3>
*
* <ul>
* <li>{@link com.google.common.primitives.Booleans}
* <li>{@link com.google.common.primitives.Bytes}
* <ul>
* <li>{@link com.google.common.primitives.SignedBytes}
* <li>{@link com.google.common.primitives.UnsignedBytes}
* </ul>
* <li>{@link com.google.common.primitives.Chars}
* <li>{@link com.google.common.primitives.Doubles}
* <li>{@link com.google.common.primitives.Floats}
* <li>{@link com.google.common.primitives.Ints}
* <ul>
* <li>{@link com.google.common.primitives.UnsignedInts}
* </ul>
* <li>{@link com.google.common.primitives.Longs}
* <ul>
* <li>{@link com.google.common.primitives.UnsignedLongs}
* </ul>
* <li>{@link com.google.common.primitives.Shorts}
* </ul>
*
* <h3>Value types</h3>
* <ul>
* <li>{@link com.google.common.primitives.UnsignedInteger}
* <li>{@link com.google.common.primitives.UnsignedLong}
* </ul>
*/
@ParametersAreNonnullByDefault
package com.google.common.primitives;
import javax.annotation.ParametersAreNonnullByDefault;