mirror of
https://github.com/Suwayomi/Tachidesk.git
synced 2026-01-19 10:12:35 +01:00
android support! thanks to TachiWeb devs.
This commit is contained in:
@@ -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-7
|
||||
"", "	", " ", "", "", " ", "", "", // 8-15
|
||||
"", "", "", "", "", "", "", "", // 16-23
|
||||
"", "", "", "", "", "", "", "", // 24-31
|
||||
null, null, """, null, null, null, "&", 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, "<", null, ">", 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;
|
||||
}
|
||||
}
|
||||
1609
AndroidCompat/src/main/java/com/android/internal/util/XmlUtils.java
Normal file
1609
AndroidCompat/src/main/java/com/android/internal/util/XmlUtils.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
package com.f2prateek;
|
||||
//TODO Consider if we can change this package into an Android dependency
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2014 Prateek Srivastava
|
||||
|
||||
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.
|
||||
|
||||
This file may have been modified after being copied from it's original source.
|
||||
*/
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
final class BooleanAdapter implements Preference.Adapter<Boolean> {
|
||||
static final BooleanAdapter INSTANCE = new BooleanAdapter();
|
||||
|
||||
@Override public Boolean get(@NonNull String key, @NonNull SharedPreferences preferences) {
|
||||
return preferences.getBoolean(key, false);
|
||||
}
|
||||
|
||||
@Override public void set(@NonNull String key, @NonNull Boolean value,
|
||||
@NonNull SharedPreferences.Editor editor) {
|
||||
editor.putBoolean(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2014 Prateek Srivastava
|
||||
|
||||
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.
|
||||
|
||||
This file may have been modified after being copied from it's original source.
|
||||
*/
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
final class EnumAdapter<T extends Enum<T>> implements Preference.Adapter<T> {
|
||||
private final Class<T> enumClass;
|
||||
|
||||
EnumAdapter(Class<T> enumClass) {
|
||||
this.enumClass = enumClass;
|
||||
}
|
||||
|
||||
@Override public T get(@NonNull String key, @NonNull SharedPreferences preferences) {
|
||||
String value = preferences.getString(key, null);
|
||||
assert value != null; // Not called unless key is present.
|
||||
return Enum.valueOf(enumClass, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(@NonNull String key, @NonNull T value, @NonNull SharedPreferences.Editor editor) {
|
||||
editor.putString(key, value.name());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2014 Prateek Srivastava
|
||||
|
||||
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.
|
||||
|
||||
This file may have been modified after being copied from it's original source.
|
||||
*/
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
final class FloatAdapter implements Preference.Adapter<Float> {
|
||||
static final FloatAdapter INSTANCE = new FloatAdapter();
|
||||
|
||||
@Override public Float get(@NonNull String key, @NonNull SharedPreferences preferences) {
|
||||
return preferences.getFloat(key, 0f);
|
||||
}
|
||||
|
||||
@Override public void set(@NonNull String key, @NonNull Float value,
|
||||
@NonNull SharedPreferences.Editor editor) {
|
||||
editor.putFloat(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2014 Prateek Srivastava
|
||||
|
||||
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.
|
||||
|
||||
This file may have been modified after being copied from it's original source.
|
||||
*/
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
final class IntegerAdapter implements Preference.Adapter<Integer> {
|
||||
static final IntegerAdapter INSTANCE = new IntegerAdapter();
|
||||
|
||||
@Override public Integer get(@NonNull String key, @NonNull SharedPreferences preferences) {
|
||||
return preferences.getInt(key, 0);
|
||||
}
|
||||
|
||||
@Override public void set(@NonNull String key, @NonNull Integer value,
|
||||
@NonNull SharedPreferences.Editor editor) {
|
||||
editor.putInt(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2014 Prateek Srivastava
|
||||
|
||||
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.
|
||||
|
||||
This file may have been modified after being copied from it's original source.
|
||||
*/
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
final class LongAdapter implements Preference.Adapter<Long> {
|
||||
static final LongAdapter INSTANCE = new LongAdapter();
|
||||
|
||||
@Override public Long get(@NonNull String key, @NonNull SharedPreferences preferences) {
|
||||
return preferences.getLong(key, 0L);
|
||||
}
|
||||
|
||||
@Override public void set(@NonNull String key, @NonNull Long value,
|
||||
@NonNull SharedPreferences.Editor editor) {
|
||||
editor.putLong(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright 2014 Prateek Srivastava
|
||||
|
||||
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.
|
||||
|
||||
This file may have been modified after being copied from it's original source.
|
||||
*/
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
final class Preconditions {
|
||||
static void checkNotNull(Object o, String message) {
|
||||
if (o == null) {
|
||||
throw new NullPointerException(message);
|
||||
}
|
||||
}
|
||||
|
||||
private Preconditions() {
|
||||
throw new AssertionError("No instances");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
Copyright 2014 Prateek Srivastava
|
||||
|
||||
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.
|
||||
|
||||
This file has been modified after being copied from it's original source.
|
||||
*/
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import rx.Observable;
|
||||
import rx.functions.Action1;
|
||||
|
||||
/** A preference of type {@link T}. Instances can be created from {@link RxSharedPreferences}. */
|
||||
public final class Preference<T> {
|
||||
/** Stores and retrieves instances of {@code T} in {@link SharedPreferences}. */
|
||||
public interface Adapter<T> {
|
||||
/** Retrieve the value for {@code key} from {@code preferences}. */
|
||||
T get(@NonNull String key, @NonNull SharedPreferences preferences);
|
||||
|
||||
/**
|
||||
* Store non-null {@code value} for {@code key} in {@code editor}.
|
||||
* <p>
|
||||
* Note: Implementations <b>must not</b> call {@code commit()} or {@code apply()} on
|
||||
* {@code editor}.
|
||||
*/
|
||||
void set(@NonNull String key, @NonNull T value, @NonNull SharedPreferences.Editor editor);
|
||||
}
|
||||
|
||||
private final SharedPreferences preferences;
|
||||
private final String key;
|
||||
private final T defaultValue;
|
||||
private final Adapter<T> adapter;
|
||||
private final Observable<T> values;
|
||||
|
||||
Preference(SharedPreferences preferences, final String key, T defaultValue, Adapter<T> adapter,
|
||||
Observable<String> keyChanges) {
|
||||
this.preferences = preferences;
|
||||
this.key = key;
|
||||
this.defaultValue = defaultValue;
|
||||
this.adapter = adapter;
|
||||
this.values = keyChanges
|
||||
.filter(key::equals)
|
||||
.startWith("<init>") // Dummy value to trigger initial load.
|
||||
.onBackpressureLatest()
|
||||
.map(ignored -> get());
|
||||
}
|
||||
|
||||
/** The key for which this preference will store and retrieve values. */
|
||||
@NonNull
|
||||
public String key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/** The value used if none is stored. May be {@code null}. */
|
||||
@Nullable
|
||||
public T defaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current value for this preference. Returns {@link #defaultValue()} if no value is
|
||||
* set.
|
||||
*/
|
||||
@Nullable
|
||||
public T get() {
|
||||
if (!preferences.contains(key)) {
|
||||
return defaultValue;
|
||||
}
|
||||
return adapter.get(key, preferences);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this preference's stored value to {@code value}. A value of {@code null} will delete the
|
||||
* preference.
|
||||
*/
|
||||
public void set(@Nullable T value) {
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
if (value == null) {
|
||||
editor.remove(key);
|
||||
} else {
|
||||
adapter.set(key, value, editor);
|
||||
}
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
/** Returns true if this preference has a stored value. */
|
||||
public boolean isSet() {
|
||||
return preferences.contains(key);
|
||||
}
|
||||
|
||||
/** Delete the stored value for this preference, if any. */
|
||||
public void delete() {
|
||||
set(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe changes to this preference. The current value or {@link #defaultValue()} will be
|
||||
* emitted on first subscribe.
|
||||
*/
|
||||
@CheckResult @NonNull
|
||||
public Observable<T> asObservable() {
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* An action which stores a new value for this preference. Passing {@code null} will delete the
|
||||
* preference.
|
||||
*/
|
||||
@CheckResult @NonNull
|
||||
public Action1<? super T> asAction() {
|
||||
return (Action1<T>) this::set;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
Copyright 2014 Prateek Srivastava
|
||||
|
||||
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.
|
||||
|
||||
This file has been modified after being copied from it's original source.
|
||||
*/
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import rx.Observable;
|
||||
import rx.subscriptions.Subscriptions;
|
||||
|
||||
import static android.os.Build.VERSION_CODES.HONEYCOMB;
|
||||
import static com.f2prateek.rx.preferences.Preconditions.checkNotNull;
|
||||
|
||||
/** A factory for reactive {@link Preference} objects. */
|
||||
public final class RxSharedPreferences {
|
||||
private static final Float DEFAULT_FLOAT = 0f;
|
||||
private static final Integer DEFAULT_INTEGER = 0;
|
||||
private static final Boolean DEFAULT_BOOLEAN = Boolean.FALSE;
|
||||
private static final Long DEFAULT_LONG = 0L;
|
||||
|
||||
/** Create an instance of {@link RxSharedPreferences} for {@code preferences}. */
|
||||
@CheckResult @NonNull
|
||||
public static RxSharedPreferences create(@NonNull SharedPreferences preferences) {
|
||||
checkNotNull(preferences, "preferences == null");
|
||||
return new RxSharedPreferences(preferences);
|
||||
}
|
||||
|
||||
private final SharedPreferences preferences;
|
||||
private final Observable<String> keyChanges;
|
||||
|
||||
private RxSharedPreferences(final SharedPreferences preferences) {
|
||||
this.preferences = preferences;
|
||||
this.keyChanges = Observable.create((Observable.OnSubscribe<String>) subscriber -> {
|
||||
final OnSharedPreferenceChangeListener listener = (preferences1, key) -> subscriber.onNext(key);
|
||||
|
||||
preferences.registerOnSharedPreferenceChangeListener(listener);
|
||||
|
||||
subscriber.add(Subscriptions.create(() -> preferences.unregisterOnSharedPreferenceChangeListener(listener)));
|
||||
}).share();
|
||||
}
|
||||
|
||||
/** Create a boolean preference for {@code key}. Default is {@code false}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<Boolean> getBoolean(@NonNull String key) {
|
||||
return getBoolean(key, DEFAULT_BOOLEAN);
|
||||
}
|
||||
|
||||
/** Create a boolean preference for {@code key} with a default of {@code defaultValue}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<Boolean> getBoolean(@NonNull String key, @Nullable Boolean defaultValue) {
|
||||
checkNotNull(key, "key == null");
|
||||
return new Preference<>(preferences, key, defaultValue, BooleanAdapter.INSTANCE, keyChanges);
|
||||
}
|
||||
|
||||
/** Create an enum preference for {@code key}. Default is {@code null}. */
|
||||
@CheckResult @NonNull
|
||||
public <T extends Enum<T>> Preference<T> getEnum(@NonNull String key,
|
||||
@NonNull Class<T> enumClass) {
|
||||
return getEnum(key, null, enumClass);
|
||||
}
|
||||
|
||||
/** Create an enum preference for {@code key} with a default of {@code defaultValue}. */
|
||||
@CheckResult @NonNull
|
||||
public <T extends Enum<T>> Preference<T> getEnum(@NonNull String key, @Nullable T defaultValue,
|
||||
@NonNull Class<T> enumClass) {
|
||||
checkNotNull(key, "key == null");
|
||||
checkNotNull(enumClass, "enumClass == null");
|
||||
Preference.Adapter<T> adapter = new EnumAdapter<>(enumClass);
|
||||
return new Preference<>(preferences, key, defaultValue, adapter, keyChanges);
|
||||
}
|
||||
|
||||
/** Create a float preference for {@code key}. Default is {@code 0}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<Float> getFloat(@NonNull String key) {
|
||||
return getFloat(key, DEFAULT_FLOAT);
|
||||
}
|
||||
|
||||
/** Create a float preference for {@code key} with a default of {@code defaultValue}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<Float> getFloat(@NonNull String key, @Nullable Float defaultValue) {
|
||||
checkNotNull(key, "key == null");
|
||||
return new Preference<>(preferences, key, defaultValue, FloatAdapter.INSTANCE, keyChanges);
|
||||
}
|
||||
|
||||
/** Create an integer preference for {@code key}. Default is {@code 0}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<Integer> getInteger(@NonNull String key) {
|
||||
//noinspection UnnecessaryBoxing
|
||||
return getInteger(key, DEFAULT_INTEGER);
|
||||
}
|
||||
|
||||
/** Create an integer preference for {@code key} with a default of {@code defaultValue}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<Integer> getInteger(@NonNull String key, @Nullable Integer defaultValue) {
|
||||
checkNotNull(key, "key == null");
|
||||
return new Preference<>(preferences, key, defaultValue, IntegerAdapter.INSTANCE, keyChanges);
|
||||
}
|
||||
|
||||
/** Create a long preference for {@code key}. Default is {@code 0}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<Long> getLong(@NonNull String key) {
|
||||
//noinspection UnnecessaryBoxing
|
||||
return getLong(key, DEFAULT_LONG);
|
||||
}
|
||||
|
||||
/** Create a long preference for {@code key} with a default of {@code defaultValue}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<Long> getLong(@NonNull String key, @Nullable Long defaultValue) {
|
||||
checkNotNull(key, "key == null");
|
||||
return new Preference<>(preferences, key, defaultValue, LongAdapter.INSTANCE, keyChanges);
|
||||
}
|
||||
|
||||
/** Create a preference of type {@code T} for {@code key}. Default is {@code null}. */
|
||||
@CheckResult @NonNull
|
||||
public <T> Preference<T> getObject(@NonNull String key, @NonNull Preference.Adapter<T> adapter) {
|
||||
return getObject(key, null, adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a preference for type {@code T} for {@code key} with a default of {@code defaultValue}.
|
||||
*/
|
||||
@CheckResult @NonNull
|
||||
public <T> Preference<T> getObject(@NonNull String key, @Nullable T defaultValue,
|
||||
@NonNull Preference.Adapter<T> adapter) {
|
||||
checkNotNull(key, "key == null");
|
||||
checkNotNull(adapter, "adapter == null");
|
||||
return new Preference<>(preferences, key, defaultValue, adapter, keyChanges);
|
||||
}
|
||||
|
||||
/** Create a string preference for {@code key}. Default is {@code null}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<String> getString(@NonNull String key) {
|
||||
return getString(key, null);
|
||||
}
|
||||
|
||||
/** Create a string preference for {@code key} with a default of {@code defaultValue}. */
|
||||
@CheckResult @NonNull
|
||||
public Preference<String> getString(@NonNull String key, @Nullable String defaultValue) {
|
||||
checkNotNull(key, "key == null");
|
||||
return new Preference<>(preferences, key, defaultValue, StringAdapter.INSTANCE, keyChanges);
|
||||
}
|
||||
|
||||
/** Create a string set preference for {@code key}. Default is an empty set. */
|
||||
@TargetApi(HONEYCOMB)
|
||||
@CheckResult @NonNull
|
||||
public Preference<Set<String>> getStringSet(@NonNull String key) {
|
||||
return getStringSet(key, Collections.emptySet());
|
||||
}
|
||||
|
||||
/** Create a string set preference for {@code key} with a default of {@code defaultValue}. */
|
||||
@TargetApi(HONEYCOMB)
|
||||
@CheckResult @NonNull
|
||||
public Preference<Set<String>> getStringSet(@NonNull String key,
|
||||
@NonNull Set<String> defaultValue) {
|
||||
checkNotNull(key, "key == null");
|
||||
return new Preference<>(preferences, key, defaultValue, StringSetAdapter.INSTANCE, keyChanges);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
final class StringAdapter implements Preference.Adapter<String> {
|
||||
static final StringAdapter INSTANCE = new StringAdapter();
|
||||
|
||||
@Override public String get(@NonNull String key, @NonNull SharedPreferences preferences) {
|
||||
return preferences.getString(key, null);
|
||||
}
|
||||
|
||||
@Override public void set(@NonNull String key, @NonNull String value,
|
||||
@NonNull SharedPreferences.Editor editor) {
|
||||
editor.putString(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.f2prateek.rx.preferences;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.NonNull;
|
||||
import java.util.Set;
|
||||
|
||||
import static android.os.Build.VERSION_CODES.HONEYCOMB;
|
||||
|
||||
@TargetApi(HONEYCOMB)
|
||||
final class StringSetAdapter implements Preference.Adapter<Set<String>> {
|
||||
static final StringSetAdapter INSTANCE = new StringSetAdapter();
|
||||
|
||||
@Override public Set<String> get(@NonNull String key, @NonNull SharedPreferences preferences) {
|
||||
return preferences.getStringSet(key, null);
|
||||
}
|
||||
|
||||
@Override public void set(@NonNull String key, @NonNull Set<String> value,
|
||||
@NonNull SharedPreferences.Editor editor) {
|
||||
editor.putStringSet(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.pwittchen.reactivenetwork.library
|
||||
|
||||
import android.net.NetworkInfo
|
||||
|
||||
class Connectivity {
|
||||
val state = NetworkInfo.State.CONNECTED
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.github.pwittchen.reactivenetwork.library
|
||||
|
||||
import android.content.Context
|
||||
import rx.Observable
|
||||
|
||||
/**
|
||||
* Created by nulldev on 12/29/16.
|
||||
*/
|
||||
|
||||
class ReactiveNetwork {
|
||||
companion object {
|
||||
fun observeNetworkConnectivity(context: Context) = Observable.just(Connectivity())!!
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Square, Inc.
|
||||
*
|
||||
* 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.squareup.duktape;
|
||||
|
||||
import kotlin.NotImplementedError;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.io.Closeable;
|
||||
|
||||
/** A simple EMCAScript (Javascript) interpreter. */
|
||||
public final class Duktape implements Closeable, AutoCloseable {
|
||||
|
||||
private ScriptEngineManager factory = new ScriptEngineManager();
|
||||
private ScriptEngine engine = factory.getEngineByName("JavaScript");
|
||||
|
||||
/**
|
||||
* Create a new interpreter instance. Calls to this method <strong>must</strong> matched with
|
||||
* calls to {@link #close()} on the returned instance to avoid leaking native memory.
|
||||
*/
|
||||
public static Duktape create() {
|
||||
return new Duktape();
|
||||
}
|
||||
|
||||
private Duktape() {}
|
||||
|
||||
/**
|
||||
* Evaluate {@code script} and return a result. {@code fileName} will be used in error
|
||||
* reporting. Note that the result must be one of the supported Java types or the call will
|
||||
* return null.
|
||||
*
|
||||
* @throws DuktapeException if there is an error evaluating the script.
|
||||
*/
|
||||
public synchronized Object evaluate(String script, String fileName) {
|
||||
throw new NotImplementedError("Not implemented!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate {@code script} and return a result. Note that the result must be one of the
|
||||
* supported Java types or the call will return null.
|
||||
*
|
||||
* @throws DuktapeException if there is an error evaluating the script.
|
||||
*/
|
||||
public synchronized Object evaluate(String script) {
|
||||
try {
|
||||
return engine.eval(script);
|
||||
} catch (ScriptException e) {
|
||||
throw new DuktapeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides {@code object} to JavaScript as a global object called {@code name}. {@code type}
|
||||
* defines the interface implemented by {@code object} that will be accessible to JavaScript.
|
||||
* {@code type} must be an interface that does not extend any other interfaces, and cannot define
|
||||
* any overloaded methods.
|
||||
* <p>Methods of the interface may return {@code void} or any of the following supported argument
|
||||
* types: {@code boolean}, {@link Boolean}, {@code int}, {@link Integer}, {@code double},
|
||||
* {@link Double}, {@link String}.
|
||||
*/
|
||||
public synchronized <T> void set(String name, Class<T> type, T object) {
|
||||
throw new NotImplementedError("Not implemented!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches to a global JavaScript object called {@code name} that implements {@code type}.
|
||||
* {@code type} defines the interface implemented in JavaScript that will be accessible to Java.
|
||||
* {@code type} must be an interface that does not extend any other interfaces, and cannot define
|
||||
* any overloaded methods.
|
||||
* <p>Methods of the interface may return {@code void} or any of the following supported argument
|
||||
* types: {@code boolean}, {@link Boolean}, {@code int}, {@link Integer}, {@code double},
|
||||
* {@link Double}, {@link String}.
|
||||
*/
|
||||
public synchronized <T> T get(final String name, final Class<T> type) {
|
||||
throw new NotImplementedError("Not implemented!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the native resources associated with this object. You <strong>must</strong> call this
|
||||
* method for each instance to avoid leaking native memory.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void close() {}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Square, Inc.
|
||||
*
|
||||
* 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.squareup.duktape;
|
||||
|
||||
import android.support.annotation.Keep;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
// Called from native code.
|
||||
@SuppressWarnings("unused")
|
||||
// Instruct ProGuard not to strip this type.
|
||||
@Keep
|
||||
public final class DuktapeException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Duktape stack trace strings have multiple lines of the format " at func (file.ext:line)".
|
||||
* "func" is optional, but we'll omit frames without a function, since it means the frame is in
|
||||
* native code.
|
||||
*/
|
||||
private static final Pattern STACK_TRACE_PATTERN = null;
|
||||
|
||||
/** Java StackTraceElements require a class name. We don't have one in JS, so use this. */
|
||||
private static final String STACK_TRACE_CLASS_NAME = "JavaScript";
|
||||
|
||||
public DuktapeException(String detailMessage) {
|
||||
super(detailMessage);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user