diff --git a/src/main/java/com/fasterxml/jackson/core/io/CharacterEscapes.java b/src/main/java/com/fasterxml/jackson/core/io/CharacterEscapes.java index 10fee6378f..2473c69e66 100644 --- a/src/main/java/com/fasterxml/jackson/core/io/CharacterEscapes.java +++ b/src/main/java/com/fasterxml/jackson/core/io/CharacterEscapes.java @@ -1,8 +1,7 @@ package com.fasterxml.jackson.core.io; -import java.util.Arrays; - import com.fasterxml.jackson.core.SerializableString; +import com.fasterxml.jackson.core.util.ArraysCompat; /** * Abstract base class that defines interface for customizing character @@ -67,6 +66,6 @@ public abstract class CharacterEscapes public static int[] standardAsciiEscapesForJSON() { int[] esc = CharTypes.get7BitOutputEscapes(); - return Arrays.copyOf(esc, esc.length); + return ArraysCompat.copyOf(esc, esc.length); } } diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java index fba33c2680..9dcdefff67 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java @@ -1,7 +1,6 @@ package com.fasterxml.jackson.core.json; import java.io.*; -import java.util.Arrays; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.base.ParserBase; @@ -3129,7 +3128,7 @@ public static int[] growArrayBy(int[] arr, int more) if (arr == null) { return new int[more]; } - return Arrays.copyOf(arr, arr.length + more); + return ArraysCompat.copyOf(arr, arr.length + more); } /* diff --git a/src/main/java/com/fasterxml/jackson/core/sym/BytesToNameCanonicalizer.java b/src/main/java/com/fasterxml/jackson/core/sym/BytesToNameCanonicalizer.java index 3e528e99a0..7cb34afb28 100644 --- a/src/main/java/com/fasterxml/jackson/core/sym/BytesToNameCanonicalizer.java +++ b/src/main/java/com/fasterxml/jackson/core/sym/BytesToNameCanonicalizer.java @@ -3,6 +3,7 @@ import java.util.Arrays; import java.util.concurrent.atomic.AtomicReference; +import com.fasterxml.jackson.core.util.ArraysCompat; import com.fasterxml.jackson.core.util.InternCache; /** @@ -1012,7 +1013,7 @@ private int findBestBucket() private void unshareMain() { final int[] old = _mainHash; - _mainHash = Arrays.copyOf(old, old.length); + _mainHash = ArraysCompat.copyOf(old, old.length); _mainHashShared = false; } @@ -1022,7 +1023,7 @@ private void unshareCollision() if (old == null) { _collList = new Bucket[INITIAL_COLLISION_LEN]; } else { - _collList = Arrays.copyOf(old, old.length); + _collList = ArraysCompat.copyOf(old, old.length); } _collListShared = false; } @@ -1030,14 +1031,14 @@ private void unshareCollision() private void unshareNames() { final Name[] old = _mainNames; - _mainNames = Arrays.copyOf(old, old.length); + _mainNames = ArraysCompat.copyOf(old, old.length); _mainNamesShared = false; } private void expandCollision() { final Bucket[] old = _collList; - _collList = Arrays.copyOf(old, old.length * 2); + _collList = ArraysCompat.copyOf(old, old.length * 2); } /* diff --git a/src/main/java/com/fasterxml/jackson/core/sym/CharsToNameCanonicalizer.java b/src/main/java/com/fasterxml/jackson/core/sym/CharsToNameCanonicalizer.java index df70400a3d..a5643a07b0 100644 --- a/src/main/java/com/fasterxml/jackson/core/sym/CharsToNameCanonicalizer.java +++ b/src/main/java/com/fasterxml/jackson/core/sym/CharsToNameCanonicalizer.java @@ -2,6 +2,7 @@ import java.util.Arrays; +import com.fasterxml.jackson.core.util.ArraysCompat; import com.fasterxml.jackson.core.util.InternCache; /** @@ -576,9 +577,9 @@ public int calcHash(String key) private void copyArrays() { final String[] oldSyms = _symbols; - _symbols = Arrays.copyOf(oldSyms, oldSyms.length); + _symbols = ArraysCompat.copyOf(oldSyms, oldSyms.length); final Bucket[] oldBuckets = _buckets; - _buckets = Arrays.copyOf(oldBuckets, oldBuckets.length); + _buckets = ArraysCompat.copyOf(oldBuckets, oldBuckets.length); } /** diff --git a/src/main/java/com/fasterxml/jackson/core/util/ArraysCompat.java b/src/main/java/com/fasterxml/jackson/core/util/ArraysCompat.java new file mode 100644 index 0000000000..fa9add9559 --- /dev/null +++ b/src/main/java/com/fasterxml/jackson/core/util/ArraysCompat.java @@ -0,0 +1,487 @@ +package com.fasterxml.jackson.core.util; + +import java.lang.reflect.Array; + +/** + * ArraysCompat implements {@link java.util.Arrays} methods which are not available in Android 2.2 (FroYo). + */ +public class ArraysCompat { + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code false}. + * + * @param original the original array + * @param newLength the length of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + */ + public static boolean[] copyOf(boolean[] original, int newLength) { + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength); + } + + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code (byte) 0}. + * + * @param original the original array + * @param newLength the length of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + */ + public static byte[] copyOf(byte[] original, int newLength) { + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength); + } + + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code '\\u0000'}. + * + * @param original the original array + * @param newLength the length of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + */ + public static char[] copyOf(char[] original, int newLength) { + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength); + } + + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code 0.0d}. + * + * @param original the original array + * @param newLength the length of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + */ + public static double[] copyOf(double[] original, int newLength) { + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength); + } + + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code 0.0f}. + * + * @param original the original array + * @param newLength the length of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + */ + public static float[] copyOf(float[] original, int newLength) { + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength); + } + + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code 0}. + * + * @param original the original array + * @param newLength the length of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + */ + public static int[] copyOf(int[] original, int newLength) { + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength); + } + + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code 0L}. + * + * @param original the original array + * @param newLength the length of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + */ + public static long[] copyOf(long[] original, int newLength) { + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength); + } + + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code (short) 0}. + * + * @param original the original array + * @param newLength the length of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + */ + public static short[] copyOf(short[] original, int newLength) { + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength); + } + + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code null}. + * + * @param original the original array + * @param newLength the length of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + */ + public static T[] copyOf(T[] original, int newLength) { + if (original == null) { + throw new NullPointerException("original == null"); + } + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength); + } + + /** + * Copies {@code newLength} elements from {@code original} into a new array. + * If {@code newLength} is greater than {@code original.length}, the result is padded + * with the value {@code null}. + * + * @param original the original array + * @param newLength the length of the new array + * @param newType the class of the new array + * @return the new array + * @throws NegativeArraySizeException if {@code newLength < 0} + * @throws NullPointerException if {@code original == null} + * @throws ArrayStoreException if a value in {@code original} is incompatible with T + */ + public static T[] copyOf(U[] original, int newLength, Class newType) { + // We use the null pointer check in copyOfRange for exception priority compatibility. + if (newLength < 0) { + throw new NegativeArraySizeException(Integer.toString(newLength)); + } + return copyOfRange(original, 0, newLength, newType); + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code false}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + */ + public static boolean[] copyOfRange(boolean[] original, int start, int end) { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + boolean[] result = new boolean[resultLength]; + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code (byte) 0}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + */ + public static byte[] copyOfRange(byte[] original, int start, int end) { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + byte[] result = new byte[resultLength]; + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code '\\u0000'}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + */ + public static char[] copyOfRange(char[] original, int start, int end) { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + char[] result = new char[resultLength]; + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code 0.0d}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + */ + public static double[] copyOfRange(double[] original, int start, int end) { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + double[] result = new double[resultLength]; + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code 0.0f}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + */ + public static float[] copyOfRange(float[] original, int start, int end) { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + float[] result = new float[resultLength]; + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code 0}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + */ + public static int[] copyOfRange(int[] original, int start, int end) { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + int[] result = new int[resultLength]; + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code 0L}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + */ + public static long[] copyOfRange(long[] original, int start, int end) { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + long[] result = new long[resultLength]; + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code (short) 0}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + */ + public static short[] copyOfRange(short[] original, int start, int end) { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + short[] result = new short[resultLength]; + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code null}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + */ + @SuppressWarnings("unchecked") + public static T[] copyOfRange(T[] original, int start, int end) { + int originalLength = original.length; // For exception priority compatibility. + if (start > end) { + throw new IllegalArgumentException(); + } + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + T[] result = (T[]) Array.newInstance(original.getClass().getComponentType(), resultLength); + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to + * end (exclusive). The original order of elements is preserved. + * If {@code end} is greater than {@code original.length}, the result is padded + * with the value {@code null}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + * @throws ArrayStoreException if a value in {@code original} is incompatible with T + */ + @SuppressWarnings("unchecked") + public static T[] copyOfRange(U[] original, int start, int end, Class newType) { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + T[] result = (T[]) Array.newInstance(newType.getComponentType(), resultLength); + System.arraycopy(original, start, result, 0, copyLength); + return result; + } +} diff --git a/src/main/java/com/fasterxml/jackson/core/util/TextBuffer.java b/src/main/java/com/fasterxml/jackson/core/util/TextBuffer.java index 19a1b34b55..9ba08e5f8c 100644 --- a/src/main/java/com/fasterxml/jackson/core/util/TextBuffer.java +++ b/src/main/java/com/fasterxml/jackson/core/util/TextBuffer.java @@ -2,7 +2,6 @@ import java.math.BigDecimal; import java.util.ArrayList; -import java.util.Arrays; import com.fasterxml.jackson.core.io.NumberInput; @@ -578,7 +577,7 @@ public char[] expandCurrentSegment() final int len = curr.length; // Must grow by at least 1 char, no matter what int newLen = (len == MAX_SEGMENT_LEN) ? (MAX_SEGMENT_LEN+1) : Math.min(MAX_SEGMENT_LEN, len + (len >> 1)); - return (_currentSegment = Arrays.copyOf(curr, newLen)); + return (_currentSegment = ArraysCompat.copyOf(curr, newLen)); } /** @@ -593,7 +592,7 @@ public char[] expandCurrentSegment() public char[] expandCurrentSegment(int minSize) { char[] curr = _currentSegment; if (curr.length >= minSize) return curr; - _currentSegment = curr = Arrays.copyOf(curr, minSize); + _currentSegment = curr = ArraysCompat.copyOf(curr, minSize); return curr; } @@ -678,9 +677,9 @@ private char[] resultArray() } final int start = _inputStart; if (start == 0) { - return Arrays.copyOf(_inputBuffer, len); + return ArraysCompat.copyOf(_inputBuffer, len); } - return Arrays.copyOfRange(_inputBuffer, start, start+len); + return ArraysCompat.copyOfRange(_inputBuffer, start, start+len); } // nope, not shared int size = size();