android support! thanks to TachiWeb devs.

This commit is contained in:
Aria Moradi
2021-01-02 04:57:20 +03:30
parent ced07d4e1e
commit 1e46a0c78c
291 changed files with 68699 additions and 16 deletions
@@ -0,0 +1,471 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* 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.android.internal.util;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArraySet;
import libcore.util.EmptyArray;
import java.lang.reflect.Array;
import java.util.*;
/**
* ArrayUtils contains some methods that you can call to find out
* the most efficient increments by which to grow arrays.
*/
public class ArrayUtils {
private static final int CACHE_SIZE = 73;
private static Object[] sCache = new Object[CACHE_SIZE];
private ArrayUtils() { /* cannot be instantiated */ }
public static byte[] newUnpaddedByteArray(int minLen) {
return new byte[minLen];
}
public static char[] newUnpaddedCharArray(int minLen) {
return new char[minLen];
}
public static int[] newUnpaddedIntArray(int minLen) {
return new int[minLen];
}
public static boolean[] newUnpaddedBooleanArray(int minLen) {
return new boolean[minLen];
}
public static long[] newUnpaddedLongArray(int minLen) {
return new long[minLen];
}
public static float[] newUnpaddedFloatArray(int minLen) {
return new float[minLen];
}
public static Object[] newUnpaddedObjectArray(int minLen) {
return new Object[minLen];
}
/**
* Checks if the beginnings of two byte arrays are equal.
*
* @param array1 the first byte array
* @param array2 the second byte array
* @param length the number of bytes to check
* @return true if they're equal, false otherwise
*/
public static boolean equals(byte[] array1, byte[] array2, int length) {
if (length < 0) {
throw new IllegalArgumentException();
}
if (array1 == array2) {
return true;
}
if (array1 == null || array2 == null || array1.length < length || array2.length < length) {
return false;
}
for (int i = 0; i < length; i++) {
if (array1[i] != array2[i]) {
return false;
}
}
return true;
}
/**
* Returns an empty array of the specified type. The intent is that
* it will return the same empty array every time to avoid reallocation,
* although this is not guaranteed.
*/
@SuppressWarnings("unchecked")
public static <T> T[] emptyArray(Class<T> kind) {
if (kind == Object.class) {
return (T[]) EmptyArray.OBJECT;
}
int bucket = (kind.hashCode() & 0x7FFFFFFF) % CACHE_SIZE;
Object cache = sCache[bucket];
if (cache == null || cache.getClass().getComponentType() != kind) {
cache = Array.newInstance(kind, 0);
sCache[bucket] = cache;
// Log.e("cache", "new empty " + kind.getName() + " at " + bucket);
}
return (T[]) cache;
}
/**
* Checks if given array is null or has zero elements.
*/
public static boolean isEmpty(@Nullable Collection<?> array) {
return array == null || array.isEmpty();
}
/**
* Checks if given array is null or has zero elements.
*/
public static <T> boolean isEmpty(@Nullable T[] array) {
return array == null || array.length == 0;
}
/**
* Checks if given array is null or has zero elements.
*/
public static boolean isEmpty(@Nullable int[] array) {
return array == null || array.length == 0;
}
/**
* Checks if given array is null or has zero elements.
*/
public static boolean isEmpty(@Nullable long[] array) {
return array == null || array.length == 0;
}
/**
* Checks if given array is null or has zero elements.
*/
public static boolean isEmpty(@Nullable byte[] array) {
return array == null || array.length == 0;
}
/**
* Checks if given array is null or has zero elements.
*/
public static boolean isEmpty(@Nullable boolean[] array) {
return array == null || array.length == 0;
}
/**
* Checks that value is present as at least one of the elements of the array.
* @param array the array to check in
* @param value the value to check for
* @return true if the value is present in the array
*/
public static <T> boolean contains(@Nullable T[] array, T value) {
return indexOf(array, value) != -1;
}
/**
* Return first index of {@code value} in {@code array}, or {@code -1} if
* not found.
*/
public static <T> int indexOf(@Nullable T[] array, T value) {
if (array == null) return -1;
for (int i = 0; i < array.length; i++) {
if (Objects.equals(array[i], value)) return i;
}
return -1;
}
/**
* Test if all {@code check} items are contained in {@code array}.
*/
public static <T> boolean containsAll(@Nullable T[] array, T[] check) {
if (check == null) return true;
for (T checkItem : check) {
if (!contains(array, checkItem)) {
return false;
}
}
return true;
}
/**
* Test if any {@code check} items are contained in {@code array}.
*/
public static <T> boolean containsAny(@Nullable T[] array, T[] check) {
if (check == null) return false;
for (T checkItem : check) {
if (contains(array, checkItem)) {
return true;
}
}
return false;
}
public static boolean contains(@Nullable int[] array, int value) {
if (array == null) return false;
for (int element : array) {
if (element == value) {
return true;
}
}
return false;
}
public static boolean contains(@Nullable long[] array, long value) {
if (array == null) return false;
for (long element : array) {
if (element == value) {
return true;
}
}
return false;
}
public static long total(@Nullable long[] array) {
long total = 0;
if (array != null) {
for (long value : array) {
total += value;
}
}
return total;
}
public static int[] convertToIntArray(List<Integer> list) {
int[] array = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
array[i] = list.get(i);
}
return array;
}
/**
* Adds value to given array if not already present, providing set-like
* behavior.
*/
@SuppressWarnings("unchecked")
public static @NonNull <T> T[] appendElement(Class<T> kind, @Nullable T[] array, T element) {
final T[] result;
final int end;
if (array != null) {
if (contains(array, element)) return array;
end = array.length;
result = (T[])Array.newInstance(kind, end + 1);
System.arraycopy(array, 0, result, 0, end);
} else {
end = 0;
result = (T[])Array.newInstance(kind, 1);
}
result[end] = element;
return result;
}
/**
* Removes value from given array if present, providing set-like behavior.
*/
@SuppressWarnings("unchecked")
public static @Nullable <T> T[] removeElement(Class<T> kind, @Nullable T[] array, T element) {
if (array != null) {
if (!contains(array, element)) return array;
final int length = array.length;
for (int i = 0; i < length; i++) {
if (Objects.equals(array[i], element)) {
if (length == 1) {
return null;
}
T[] result = (T[])Array.newInstance(kind, length - 1);
System.arraycopy(array, 0, result, 0, i);
System.arraycopy(array, i + 1, result, i, length - i - 1);
return result;
}
}
}
return array;
}
/**
* Adds value to given array if not already present, providing set-like
* behavior.
*/
public static @NonNull int[] appendInt(@Nullable int[] cur, int val) {
if (cur == null) {
return new int[] { val };
}
final int N = cur.length;
for (int i = 0; i < N; i++) {
if (cur[i] == val) {
return cur;
}
}
int[] ret = new int[N + 1];
System.arraycopy(cur, 0, ret, 0, N);
ret[N] = val;
return ret;
}
/**
* Removes value from given array if present, providing set-like behavior.
*/
public static @Nullable int[] removeInt(@Nullable int[] cur, int val) {
if (cur == null) {
return null;
}
final int N = cur.length;
for (int i = 0; i < N; i++) {
if (cur[i] == val) {
int[] ret = new int[N - 1];
if (i > 0) {
System.arraycopy(cur, 0, ret, 0, i);
}
if (i < (N - 1)) {
System.arraycopy(cur, i + 1, ret, i, N - i - 1);
}
return ret;
}
}
return cur;
}
/**
* Removes value from given array if present, providing set-like behavior.
*/
public static @Nullable String[] removeString(@Nullable String[] cur, String val) {
if (cur == null) {
return null;
}
final int N = cur.length;
for (int i = 0; i < N; i++) {
if (Objects.equals(cur[i], val)) {
String[] ret = new String[N - 1];
if (i > 0) {
System.arraycopy(cur, 0, ret, 0, i);
}
if (i < (N - 1)) {
System.arraycopy(cur, i + 1, ret, i, N - i - 1);
}
return ret;
}
}
return cur;
}
/**
* Adds value to given array if not already present, providing set-like
* behavior.
*/
public static @NonNull long[] appendLong(@Nullable long[] cur, long val) {
if (cur == null) {
return new long[] { val };
}
final int N = cur.length;
for (int i = 0; i < N; i++) {
if (cur[i] == val) {
return cur;
}
}
long[] ret = new long[N + 1];
System.arraycopy(cur, 0, ret, 0, N);
ret[N] = val;
return ret;
}
/**
* Removes value from given array if present, providing set-like behavior.
*/
public static @Nullable long[] removeLong(@Nullable long[] cur, long val) {
if (cur == null) {
return null;
}
final int N = cur.length;
for (int i = 0; i < N; i++) {
if (cur[i] == val) {
long[] ret = new long[N - 1];
if (i > 0) {
System.arraycopy(cur, 0, ret, 0, i);
}
if (i < (N - 1)) {
System.arraycopy(cur, i + 1, ret, i, N - i - 1);
}
return ret;
}
}
return cur;
}
public static @Nullable long[] cloneOrNull(@Nullable long[] array) {
return (array != null) ? array.clone() : null;
}
public static @Nullable <T> ArraySet<T> cloneOrNull(@Nullable ArraySet<T> array) {
return (array != null) ? new ArraySet<T>(array) : null;
}
public static @NonNull <T> ArraySet<T> add(@Nullable ArraySet<T> cur, T val) {
if (cur == null) {
cur = new ArraySet<>();
}
cur.add(val);
return cur;
}
public static @Nullable <T> ArraySet<T> remove(@Nullable ArraySet<T> cur, T val) {
if (cur == null) {
return null;
}
cur.remove(val);
if (cur.isEmpty()) {
return null;
} else {
return cur;
}
}
public static <T> boolean contains(@Nullable ArraySet<T> cur, T val) {
return (cur != null) ? cur.contains(val) : false;
}
public static @NonNull <T> ArrayList<T> add(@Nullable ArrayList<T> cur, T val) {
if (cur == null) {
cur = new ArrayList<>();
}
cur.add(val);
return cur;
}
public static @Nullable <T> ArrayList<T> remove(@Nullable ArrayList<T> cur, T val) {
if (cur == null) {
return null;
}
cur.remove(val);
if (cur.isEmpty()) {
return null;
} else {
return cur;
}
}
public static <T> boolean contains(@Nullable Collection<T> cur, T val) {
return (cur != null) ? cur.contains(val) : false;
}
public static @Nullable <T> T[] trimToSize(@Nullable T[] array, int size) {
if (array == null || size == 0) {
return null;
} else if (array.length == size) {
return array;
} else {
return Arrays.copyOf(array, size);
}
}
/**
* Returns true if the two ArrayLists are equal with respect to the objects they contain.
* The objects must be in the same order and be reference equal (== not .equals()).
*/
public static <T> boolean referenceEquals(ArrayList<T> a, ArrayList<T> b) {
if (a == b) {
return true;
}
final int sizeA = a.size();
final int sizeB = b.size();
if (a == null || b == null || sizeA != sizeB) {
return false;
}
boolean diff = false;
for (int i = 0; i < sizeA && !diff; i++) {
diff |= a.get(i) != b.get(i);
}
return !diff;
}
/**
* Removes elements that match the predicate in an efficient way that alters the order of
* elements in the collection. This should only be used if order is not important.
* @param collection The ArrayList from which to remove elements.
* @param predicate The predicate that each element is tested against.
* @return the number of elements removed.
*/
public static <T> int unstableRemoveIf(@Nullable ArrayList<T> collection,
@NonNull java.util.function.Predicate<T> predicate) {
if (collection == null) {
return 0;
}
final int size = collection.size();
int leftIdx = 0;
int rightIdx = size - 1;
while (leftIdx <= rightIdx) {
// Find the next element to remove moving left to right.
while (leftIdx < size && !predicate.test(collection.get(leftIdx))) {
leftIdx++;
}
// Find the next element to keep moving right to left.
while (rightIdx > leftIdx && predicate.test(collection.get(rightIdx))) {
rightIdx--;
}
if (leftIdx >= rightIdx) {
// Done.
break;
}
Collections.swap(collection, leftIdx, rightIdx);
leftIdx++;
rightIdx--;
}
// leftIdx is now at the end.
for (int i = size - 1; i >= leftIdx; i--) {
collection.remove(i);
}
return size - leftIdx;
}
}
@@ -0,0 +1,370 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* 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.android.internal.util;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
/**
* This is a quick and dirty implementation of XmlSerializer that isn't horribly
* painfully slow like the normal one. It only does what is needed for the
* specific XML files being written with it.
*/
public class FastXmlSerializer implements XmlSerializer {
private static final String ESCAPE_TABLE[] = new String[] {
"&#0;", "&#1;", "&#2;", "&#3;", "&#4;", "&#5;", "&#6;", "&#7;", // 0-7
"&#8;", "&#9;", "&#10;", "&#11;", "&#12;", "&#13;", "&#14;", "&#15;", // 8-15
"&#16;", "&#17;", "&#18;", "&#19;", "&#20;", "&#21;", "&#22;", "&#23;", // 16-23
"&#24;", "&#25;", "&#26;", "&#27;", "&#28;", "&#29;", "&#30;", "&#31;", // 24-31
null, null, "&quot;", null, null, null, "&amp;", null, // 32-39
null, null, null, null, null, null, null, null, // 40-47
null, null, null, null, null, null, null, null, // 48-55
null, null, null, null, "&lt;", null, "&gt;", null, // 56-63
};
private static final int DEFAULT_BUFFER_LEN = 32*1024;
private static String sSpace = " ";
private final int mBufferLen;
private final char[] mText;
private int mPos;
private Writer mWriter;
private OutputStream mOutputStream;
private CharsetEncoder mCharset;
private ByteBuffer mBytes;
private boolean mIndent = false;
private boolean mInTag;
private int mNesting = 0;
private boolean mLineStart = true;
public FastXmlSerializer() {
this(DEFAULT_BUFFER_LEN);
}
/**
* Allocate a FastXmlSerializer with the given internal output buffer size. If the
* size is zero or negative, then the default buffer size will be used.
*
* @param bufferSize Size in bytes of the in-memory output buffer that the writer will use.
*/
public FastXmlSerializer(int bufferSize) {
mBufferLen = (bufferSize > 0) ? bufferSize : DEFAULT_BUFFER_LEN;
mText = new char[mBufferLen];
mBytes = ByteBuffer.allocate(mBufferLen);
}
private void append(char c) throws IOException {
int pos = mPos;
if (pos >= (mBufferLen-1)) {
flush();
pos = mPos;
}
mText[pos] = c;
mPos = pos+1;
}
private void append(String str, int i, final int length) throws IOException {
if (length > mBufferLen) {
final int end = i + length;
while (i < end) {
int next = i + mBufferLen;
append(str, i, next<end ? mBufferLen : (end-i));
i = next;
}
return;
}
int pos = mPos;
if ((pos+length) > mBufferLen) {
flush();
pos = mPos;
}
str.getChars(i, i+length, mText, pos);
mPos = pos + length;
}
private void append(char[] buf, int i, final int length) throws IOException {
if (length > mBufferLen) {
final int end = i + length;
while (i < end) {
int next = i + mBufferLen;
append(buf, i, next<end ? mBufferLen : (end-i));
i = next;
}
return;
}
int pos = mPos;
if ((pos+length) > mBufferLen) {
flush();
pos = mPos;
}
System.arraycopy(buf, i, mText, pos, length);
mPos = pos + length;
}
private void append(String str) throws IOException {
append(str, 0, str.length());
}
private void appendIndent(int indent) throws IOException {
indent *= 4;
if (indent > sSpace.length()) {
indent = sSpace.length();
}
append(sSpace, 0, indent);
}
private void escapeAndAppendString(final String string) throws IOException {
final int N = string.length();
final char NE = (char)ESCAPE_TABLE.length;
final String[] escapes = ESCAPE_TABLE;
int lastPos = 0;
int pos;
for (pos=0; pos<N; pos++) {
char c = string.charAt(pos);
if (c >= NE) continue;
String escape = escapes[c];
if (escape == null) continue;
if (lastPos < pos) append(string, lastPos, pos-lastPos);
lastPos = pos + 1;
append(escape);
}
if (lastPos < pos) append(string, lastPos, pos-lastPos);
}
private void escapeAndAppendString(char[] buf, int start, int len) throws IOException {
final char NE = (char)ESCAPE_TABLE.length;
final String[] escapes = ESCAPE_TABLE;
int end = start+len;
int lastPos = start;
int pos;
for (pos=start; pos<end; pos++) {
char c = buf[pos];
if (c >= NE) continue;
String escape = escapes[c];
if (escape == null) continue;
if (lastPos < pos) append(buf, lastPos, pos-lastPos);
lastPos = pos + 1;
append(escape);
}
if (lastPos < pos) append(buf, lastPos, pos-lastPos);
}
public XmlSerializer attribute(String namespace, String name, String value) throws IOException,
IllegalArgumentException, IllegalStateException {
append(' ');
if (namespace != null) {
append(namespace);
append(':');
}
append(name);
append("=\"");
escapeAndAppendString(value);
append('"');
mLineStart = false;
return this;
}
public void cdsect(String text) throws IOException, IllegalArgumentException,
IllegalStateException {
throw new UnsupportedOperationException();
}
public void comment(String text) throws IOException, IllegalArgumentException,
IllegalStateException {
throw new UnsupportedOperationException();
}
public void docdecl(String text) throws IOException, IllegalArgumentException,
IllegalStateException {
throw new UnsupportedOperationException();
}
public void endDocument() throws IOException, IllegalArgumentException, IllegalStateException {
flush();
}
public XmlSerializer endTag(String namespace, String name) throws IOException,
IllegalArgumentException, IllegalStateException {
mNesting--;
if (mInTag) {
append(" />\n");
} else {
if (mIndent && mLineStart) {
appendIndent(mNesting);
}
append("</");
if (namespace != null) {
append(namespace);
append(':');
}
append(name);
append(">\n");
}
mLineStart = true;
mInTag = false;
return this;
}
public void entityRef(String text) throws IOException, IllegalArgumentException,
IllegalStateException {
throw new UnsupportedOperationException();
}
private void flushBytes() throws IOException {
int position;
if ((position = mBytes.position()) > 0) {
mBytes.flip();
mOutputStream.write(mBytes.array(), 0, position);
mBytes.clear();
}
}
public void flush() throws IOException {
//Log.i("PackageManager", "flush mPos=" + mPos);
if (mPos > 0) {
if (mOutputStream != null) {
CharBuffer charBuffer = CharBuffer.wrap(mText, 0, mPos);
CoderResult result = mCharset.encode(charBuffer, mBytes, true);
while (true) {
if (result.isError()) {
throw new IOException(result.toString());
} else if (result.isOverflow()) {
flushBytes();
result = mCharset.encode(charBuffer, mBytes, true);
continue;
}
break;
}
flushBytes();
mOutputStream.flush();
} else {
mWriter.write(mText, 0, mPos);
mWriter.flush();
}
mPos = 0;
}
}
public int getDepth() {
throw new UnsupportedOperationException();
}
public boolean getFeature(String name) {
throw new UnsupportedOperationException();
}
public String getName() {
throw new UnsupportedOperationException();
}
public String getNamespace() {
throw new UnsupportedOperationException();
}
public String getPrefix(String namespace, boolean generatePrefix)
throws IllegalArgumentException {
throw new UnsupportedOperationException();
}
public Object getProperty(String name) {
throw new UnsupportedOperationException();
}
public void ignorableWhitespace(String text) throws IOException, IllegalArgumentException,
IllegalStateException {
throw new UnsupportedOperationException();
}
public void processingInstruction(String text) throws IOException, IllegalArgumentException,
IllegalStateException {
throw new UnsupportedOperationException();
}
public void setFeature(String name, boolean state) throws IllegalArgumentException,
IllegalStateException {
if (name.equals("http://xmlpull.org/v1/doc/features.html#indent-output")) {
mIndent = true;
return;
}
throw new UnsupportedOperationException();
}
public void setOutput(OutputStream os, String encoding) throws IOException,
IllegalArgumentException, IllegalStateException {
if (os == null)
throw new IllegalArgumentException();
if (true) {
try {
mCharset = Charset.forName(encoding).newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE);
} catch (IllegalCharsetNameException e) {
throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
encoding).initCause(e));
} catch (UnsupportedCharsetException e) {
throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
encoding).initCause(e));
}
mOutputStream = os;
} else {
setOutput(
encoding == null
? new OutputStreamWriter(os)
: new OutputStreamWriter(os, encoding));
}
}
public void setOutput(Writer writer) throws IOException, IllegalArgumentException,
IllegalStateException {
mWriter = writer;
}
public void setPrefix(String prefix, String namespace) throws IOException,
IllegalArgumentException, IllegalStateException {
throw new UnsupportedOperationException();
}
public void setProperty(String name, Object value) throws IllegalArgumentException,
IllegalStateException {
throw new UnsupportedOperationException();
}
public void startDocument(String encoding, Boolean standalone) throws IOException,
IllegalArgumentException, IllegalStateException {
append("<?xml version='1.0' encoding='utf-8' standalone='"
+ (standalone ? "yes" : "no") + "' ?>\n");
mLineStart = true;
}
public XmlSerializer startTag(String namespace, String name) throws IOException,
IllegalArgumentException, IllegalStateException {
if (mInTag) {
append(">\n");
}
if (mIndent) {
appendIndent(mNesting);
}
mNesting++;
append('<');
if (namespace != null) {
append(namespace);
append(':');
}
append(name);
mInTag = true;
mLineStart = false;
return this;
}
public XmlSerializer text(char[] buf, int start, int len) throws IOException,
IllegalArgumentException, IllegalStateException {
if (mInTag) {
append(">");
mInTag = false;
}
escapeAndAppendString(buf, start, len);
if (mIndent) {
mLineStart = buf[start+len-1] == '\n';
}
return this;
}
public XmlSerializer text(String text) throws IOException, IllegalArgumentException,
IllegalStateException {
if (mInTag) {
append(">");
mInTag = false;
}
escapeAndAppendString(text);
if (mIndent) {
mLineStart = text.length() > 0 && (text.charAt(text.length()-1) == '\n');
}
return this;
}
}
@@ -0,0 +1,451 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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.android.internal.util;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.text.TextUtils;
import java.util.Collection;
/**
* Simple static methods to be called at the start of your own methods to verify
* correct arguments and state.
*/
public class Preconditions {
public static void checkArgument(boolean expression) {
if (!expression) {
throw new IllegalArgumentException();
}
}
/**
* Ensures that an expression checking an argument is true.
*
* @param expression the expression to check
* @param errorMessage the exception message to use if the check fails; will
* be converted to a string using {@link String#valueOf(Object)}
* @throws IllegalArgumentException if {@code expression} is false
*/
public static void checkArgument(boolean expression, final Object errorMessage) {
if (!expression) {
throw new IllegalArgumentException(String.valueOf(errorMessage));
}
}
/**
* Ensures that an expression checking an argument is true.
*
* @param expression the expression to check
* @param messageTemplate a printf-style message template to use if the check fails; will
* be converted to a string using {@link String#format(String, Object...)}
* @param messageArgs arguments for {@code messageTemplate}
* @throws IllegalArgumentException if {@code expression} is false
*/
public static void checkArgument(boolean expression,
final String messageTemplate,
final Object... messageArgs) {
if (!expression) {
throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
}
}
/**
* Ensures that an string reference passed as a parameter to the calling
* method is not empty.
*
* @param string an string reference
* @return the string reference that was validated
* @throws IllegalArgumentException if {@code string} is empty
*/
public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string) {
if (TextUtils.isEmpty(string)) {
throw new IllegalArgumentException();
}
return string;
}
/**
* Ensures that an string reference passed as a parameter to the calling
* method is not empty.
*
* @param string an string reference
* @param errorMessage the exception message to use if the check fails; will
* be converted to a string using {@link String#valueOf(Object)}
* @return the string reference that was validated
* @throws IllegalArgumentException if {@code string} is empty
*/
public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string,
final Object errorMessage) {
if (TextUtils.isEmpty(string)) {
throw new IllegalArgumentException(String.valueOf(errorMessage));
}
return string;
}
/**
* Ensures that an object reference passed as a parameter to the calling
* method is not null.
*
* @param reference an object reference
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static @NonNull <T> T checkNotNull(final T reference) {
if (reference == null) {
throw new NullPointerException();
}
return reference;
}
/**
* Ensures that an object reference passed as a parameter to the calling
* method is not null.
*
* @param reference an object reference
* @param errorMessage the exception message to use if the check fails; will
* be converted to a string using {@link String#valueOf(Object)}
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
if (reference == null) {
throw new NullPointerException(String.valueOf(errorMessage));
}
return reference;
}
/**
* Ensures that an object reference passed as a parameter to the calling
* method is not null.
*
* @param reference an object reference
* @param messageTemplate a printf-style message template to use if the check fails; will
* be converted to a string using {@link String#format(String, Object...)}
* @param messageArgs arguments for {@code messageTemplate}
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
public static @NonNull <T> T checkNotNull(final T reference,
final String messageTemplate,
final Object... messageArgs) {
if (reference == null) {
throw new NullPointerException(String.format(messageTemplate, messageArgs));
}
return reference;
}
/**
* Ensures the truth of an expression involving the state of the calling
* instance, but not involving any parameters to the calling method.
*
* @param expression a boolean expression
* @param message exception message
* @throws IllegalStateException if {@code expression} is false
*/
public static void checkState(final boolean expression, String message) {
if (!expression) {
throw new IllegalStateException(message);
}
}
/**
* Ensures the truth of an expression involving the state of the calling
* instance, but not involving any parameters to the calling method.
*
* @param expression a boolean expression
* @throws IllegalStateException if {@code expression} is false
*/
public static void checkState(final boolean expression) {
checkState(expression, null);
}
/**
* Check the requested flags, throwing if any requested flags are outside
* the allowed set.
*
* @return the validated requested flags.
*/
public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
if ((requestedFlags & allowedFlags) != requestedFlags) {
throw new IllegalArgumentException("Requested flags 0x"
+ Integer.toHexString(requestedFlags) + ", but only 0x"
+ Integer.toHexString(allowedFlags) + " are allowed");
}
return requestedFlags;
}
/**
* Ensures that that the argument numeric value is non-negative.
*
* @param value a numeric int value
* @param errorMessage the exception message to use if the check fails
* @return the validated numeric value
* @throws IllegalArgumentException if {@code value} was negative
*/
public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
final String errorMessage) {
if (value < 0) {
throw new IllegalArgumentException(errorMessage);
}
return value;
}
/**
* Ensures that that the argument numeric value is non-negative.
*
* @param value a numeric int value
*
* @return the validated numeric value
* @throws IllegalArgumentException if {@code value} was negative
*/
public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) {
if (value < 0) {
throw new IllegalArgumentException();
}
return value;
}
/**
* Ensures that that the argument numeric value is non-negative.
*
* @param value a numeric long value
* @return the validated numeric value
* @throws IllegalArgumentException if {@code value} was negative
*/
public static long checkArgumentNonnegative(final long value) {
if (value < 0) {
throw new IllegalArgumentException();
}
return value;
}
/**
* Ensures that that the argument numeric value is non-negative.
*
* @param value a numeric long value
* @param errorMessage the exception message to use if the check fails
* @return the validated numeric value
* @throws IllegalArgumentException if {@code value} was negative
*/
public static long checkArgumentNonnegative(final long value, final String errorMessage) {
if (value < 0) {
throw new IllegalArgumentException(errorMessage);
}
return value;
}
/**
* Ensures that that the argument numeric value is positive.
*
* @param value a numeric int value
* @param errorMessage the exception message to use if the check fails
* @return the validated numeric value
* @throws IllegalArgumentException if {@code value} was not positive
*/
public static int checkArgumentPositive(final int value, final String errorMessage) {
if (value <= 0) {
throw new IllegalArgumentException(errorMessage);
}
return value;
}
/**
* Ensures that the argument floating point value is a finite number.
*
* <p>A finite number is defined to be both representable (that is, not NaN) and
* not infinite (that is neither positive or negative infinity).</p>
*
* @param value a floating point value
* @param valueName the name of the argument to use if the check fails
*
* @return the validated floating point value
*
* @throws IllegalArgumentException if {@code value} was not finite
*/
public static float checkArgumentFinite(final float value, final String valueName) {
if (Float.isNaN(value)) {
throw new IllegalArgumentException(valueName + " must not be NaN");
} else if (Float.isInfinite(value)) {
throw new IllegalArgumentException(valueName + " must not be infinite");
}
return value;
}
/**
* Ensures that the argument floating point value is within the inclusive range.
*
* <p>While this can be used to range check against +/- infinity, note that all NaN numbers
* will always be out of range.</p>
*
* @param value a floating point value
* @param lower the lower endpoint of the inclusive range
* @param upper the upper endpoint of the inclusive range
* @param valueName the name of the argument to use if the check fails
*
* @return the validated floating point value
*
* @throws IllegalArgumentException if {@code value} was not within the range
*/
public static float checkArgumentInRange(float value, float lower, float upper,
String valueName) {
if (Float.isNaN(value)) {
throw new IllegalArgumentException(valueName + " must not be NaN");
} else if (value < lower) {
throw new IllegalArgumentException(
String.format(
"%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
} else if (value > upper) {
throw new IllegalArgumentException(
String.format(
"%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
}
return value;
}
/**
* Ensures that the argument int value is within the inclusive range.
*
* @param value a int value
* @param lower the lower endpoint of the inclusive range
* @param upper the upper endpoint of the inclusive range
* @param valueName the name of the argument to use if the check fails
*
* @return the validated int value
*
* @throws IllegalArgumentException if {@code value} was not within the range
*/
public static int checkArgumentInRange(int value, int lower, int upper,
String valueName) {
if (value < lower) {
throw new IllegalArgumentException(
String.format(
"%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
} else if (value > upper) {
throw new IllegalArgumentException(
String.format(
"%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
}
return value;
}
/**
* Ensures that the argument long value is within the inclusive range.
*
* @param value a long value
* @param lower the lower endpoint of the inclusive range
* @param upper the upper endpoint of the inclusive range
* @param valueName the name of the argument to use if the check fails
*
* @return the validated long value
*
* @throws IllegalArgumentException if {@code value} was not within the range
*/
public static long checkArgumentInRange(long value, long lower, long upper,
String valueName) {
if (value < lower) {
throw new IllegalArgumentException(
String.format(
"%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
} else if (value > upper) {
throw new IllegalArgumentException(
String.format(
"%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
}
return value;
}
/**
* Ensures that the array is not {@code null}, and none of its elements are {@code null}.
*
* @param value an array of boxed objects
* @param valueName the name of the argument to use if the check fails
*
* @return the validated array
*
* @throws NullPointerException if the {@code value} or any of its elements were {@code null}
*/
public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
if (value == null) {
throw new NullPointerException(valueName + " must not be null");
}
for (int i = 0; i < value.length; ++i) {
if (value[i] == null) {
throw new NullPointerException(
String.format("%s[%d] must not be null", valueName, i));
}
}
return value;
}
/**
* Ensures that the {@link Collection} is not {@code null}, and none of its elements are
* {@code null}.
*
* @param value a {@link Collection} of boxed objects
* @param valueName the name of the argument to use if the check fails
*
* @return the validated {@link Collection}
*
* @throws NullPointerException if the {@code value} or any of its elements were {@code null}
*/
public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
final C value, final String valueName) {
if (value == null) {
throw new NullPointerException(valueName + " must not be null");
}
long ctr = 0;
for (T elem : value) {
if (elem == null) {
throw new NullPointerException(
String.format("%s[%d] must not be null", valueName, ctr));
}
++ctr;
}
return value;
}
/**
* Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
*
* @param value a {@link Collection} of boxed elements.
* @param valueName the name of the argument to use if the check fails.
* @return the validated {@link Collection}
*
* @throws NullPointerException if the {@code value} was {@code null}
* @throws IllegalArgumentException if the {@code value} was empty
*/
public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
final String valueName) {
if (value == null) {
throw new NullPointerException(valueName + " must not be null");
}
if (value.isEmpty()) {
throw new IllegalArgumentException(valueName + " is empty");
}
return value;
}
/**
* Ensures that all elements in the argument floating point array are within the inclusive range
*
* <p>While this can be used to range check against +/- infinity, note that all NaN numbers
* will always be out of range.</p>
*
* @param value a floating point array of values
* @param lower the lower endpoint of the inclusive range
* @param upper the upper endpoint of the inclusive range
* @param valueName the name of the argument to use if the check fails
*
* @return the validated floating point value
*
* @throws IllegalArgumentException if any of the elements in {@code value} were out of range
* @throws NullPointerException if the {@code value} was {@code null}
*/
public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
String valueName) {
checkNotNull(value, valueName + " must not be null");
for (int i = 0; i < value.length; ++i) {
float v = value[i];
if (Float.isNaN(v)) {
throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
} else if (v < lower) {
throw new IllegalArgumentException(
String.format("%s[%d] is out of range of [%f, %f] (too low)",
valueName, i, lower, upper));
} else if (v > upper) {
throw new IllegalArgumentException(
String.format("%s[%d] is out of range of [%f, %f] (too high)",
valueName, i, lower, upper));
}
}
return value;
}
}
File diff suppressed because it is too large Load Diff