|
|
@@ -1,229 +1,252 @@
|
|
|
-/*
|
|
|
- * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
- * @copyright Ranides Atterwim
|
|
|
- * @license WTFPL
|
|
|
- * @url http://ranides.net/projects/assira
|
|
|
- */
|
|
|
-package net.ranides.assira.collection.arrays;
|
|
|
-
|
|
|
-import java.util.ArrayList;
|
|
|
-
|
|
|
-public final class NativeArrayAllocator {
|
|
|
-
|
|
|
- /**
|
|
|
- * This is a safe value used by {@link ArrayList} (as of Java 7) to avoid
|
|
|
- * throwing {@link OutOfMemoryError} on some JVMs. We adopt the same value.
|
|
|
- */
|
|
|
- private static final int MAX_SIZE = Integer.MAX_VALUE - 8;
|
|
|
-
|
|
|
- private NativeArrayAllocator() {
|
|
|
- // utility class
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Ensures that an array can contain the given number of entries.
|
|
|
- *
|
|
|
- * <P>If you cannot foresee whether this array will need again to be
|
|
|
- * enlarged, you should probably use
|
|
|
- * <code>grow()</code> instead.
|
|
|
- *
|
|
|
- * @param array an array.
|
|
|
- * @param length the new minimum length for this array.
|
|
|
- * @return <code>array</code>, if it contains <code>length</code> entries or
|
|
|
- * more; otherwise, an array with <code>length</code> entries whose * *
|
|
|
- * first <code>array.length</code> entries are the same as those * *
|
|
|
- * of <code>array</code>.
|
|
|
- */
|
|
|
- public static NativeArray ensureCapacity(NativeArray array, int length) {
|
|
|
- return ensureCapacity(array, length, -1);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Ensures that an array can contain the given number of entries, preserving
|
|
|
- * just a part of the array.
|
|
|
- *
|
|
|
- * @param array an array.
|
|
|
- * @param length the new minimum length for this array.
|
|
|
- * @param preserve the number of elements of the array that must be
|
|
|
- * preserved in case a new allocation is necessary.
|
|
|
- * @return <code>array</code>, if it can contain <code>length</code> entries
|
|
|
- * or more; otherwise, an array with <code>length</code> entries whose *
|
|
|
- * first <code>preserve</code> entries are the same as those * *
|
|
|
- * of <code>array</code>.
|
|
|
- */
|
|
|
- public static NativeArray ensureCapacity(NativeArray array, int length, int preserve) {
|
|
|
- int n = array.size();
|
|
|
- if(preserve < 0) {
|
|
|
- preserve = n;
|
|
|
- }
|
|
|
- if (length > n) {
|
|
|
- NativeArray target = array.allocate(length);
|
|
|
- NativeArrayUtils.copy(array, 0, target, 0, preserve);
|
|
|
- return target;
|
|
|
- }
|
|
|
- return array;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Ensures that a range given by an offset and a length fits an array.
|
|
|
- *
|
|
|
- * <P>This method may be used whenever an array range check is needed.
|
|
|
- *
|
|
|
- * @param array an array.
|
|
|
- * @param offset a start index.
|
|
|
- * @param length a length (the number of elements in the range).
|
|
|
- * @throws IllegalArgumentException if <code>length</code> is negative.
|
|
|
- * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative
|
|
|
- * or <code>offset</code>+<code>length</code> is greater than the array
|
|
|
- * length.
|
|
|
- */
|
|
|
- public static void ensureOffsetLength(NativeArray array, int offset, int length) {
|
|
|
- ensureOffsetLength(array.size(), offset, length);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Ensures that a range given by an offset and a length fits an array of
|
|
|
- * given length.
|
|
|
- *
|
|
|
- * <P>This method may be used whenever an array range check is needed.
|
|
|
- *
|
|
|
- * @param arrayLength an array length.
|
|
|
- * @param offset a start index for the fragment
|
|
|
- * @param length a length (the number of elements in the fragment).
|
|
|
- * @throws IllegalArgumentException if <code>length</code> is negative.
|
|
|
- * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative
|
|
|
- * or <code>offset</code>+<code>length</code> is greater * * than <code>arrayLength</code>.
|
|
|
- */
|
|
|
- public static void ensureOffsetLength(int arrayLength, int offset, int length) {
|
|
|
- if (offset < 0) {
|
|
|
- throw new ArrayIndexOutOfBoundsException("Offset (" + offset + ") is negative");
|
|
|
- }
|
|
|
- if (length < 0) {
|
|
|
- throw new IllegalArgumentException("Length (" + length + ") is negative");
|
|
|
- }
|
|
|
- if (offset + length > arrayLength) {
|
|
|
- throw new ArrayIndexOutOfBoundsException("Last index (" + (offset + length) + ") is greater than array length (" + arrayLength + ")");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Ensures that a range given by its first (inclusive) and last (exclusive)
|
|
|
- * elements fits an array.
|
|
|
- *
|
|
|
- * <P>This method may be used whenever an array range check is needed.
|
|
|
- *
|
|
|
- * @param array an array.
|
|
|
- * @param begin a start index (inclusive).
|
|
|
- * @param end an end index (exclusive).
|
|
|
- * @throws IllegalArgumentException if <code>from</code> is greater * *
|
|
|
- * than <code>to</code>.
|
|
|
- * @throws ArrayIndexOutOfBoundsException if <code>from</code> * *
|
|
|
- * or <code>to</code> are greater than the array length or negative.
|
|
|
- */
|
|
|
- public static void ensureFromTo(NativeArray array, int begin, int end) {
|
|
|
- ensureFromTo(array.size(), begin, end);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Ensures that a range given by its first (inclusive) and last (exclusive)
|
|
|
- * elements fits an array of given length.
|
|
|
- *
|
|
|
- * <P>This method may be used whenever an array range check is needed.
|
|
|
- *
|
|
|
- * @param arrayLength an array length.
|
|
|
- * @param begin a start index (inclusive).
|
|
|
- * @param end an end index (inclusive).
|
|
|
- * @throws IllegalArgumentException if <code>from</code> is greater * * than <code>to</code>.
|
|
|
- * @throws ArrayIndexOutOfBoundsException if <code>from</code> * * or <code>to</code> are greater than <code>arrayLength</code> or
|
|
|
- * negative.
|
|
|
- */
|
|
|
- public static void ensureFromTo(int arrayLength, int begin, int end) {
|
|
|
- if (begin < 0) {
|
|
|
- throw new ArrayIndexOutOfBoundsException("Start index (" + begin + ") is negative");
|
|
|
- }
|
|
|
- if (begin > end) {
|
|
|
- throw new IllegalArgumentException("Start index (" + begin + ") is greater than end index (" + end + ")");
|
|
|
- }
|
|
|
- if (end > arrayLength) {
|
|
|
- throw new ArrayIndexOutOfBoundsException("End index (" + end + ") is greater than array length (" + arrayLength + ")");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Grows the given array to the maximum between the given length and the
|
|
|
- * current length multiplied by two, provided that the given length is
|
|
|
- * larger than the current length.
|
|
|
- *
|
|
|
- * <P>If you want complete control on the array growth, you should probably
|
|
|
- * use
|
|
|
- * <code>ensureCapacity()</code> instead.
|
|
|
- *
|
|
|
- * @param array an array.
|
|
|
- * @param length the new minimum length for this array.
|
|
|
- * @return <code>array</code>, if it can contain <code>length</code>
|
|
|
- * entries; otherwise, an array with
|
|
|
- * max(<code>length</code>,<code>array.length</code>/φ) entries whose
|
|
|
- * first <code>array.length</code> entries are the same as those * *
|
|
|
- * of <code>array</code>.
|
|
|
- *
|
|
|
- */
|
|
|
- public static NativeArray grow(NativeArray array, int length) {
|
|
|
- return grow(array, length, -1);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Grows the given array to the maximum between the given length and the
|
|
|
- * current length multiplied by two, provided that the given length is
|
|
|
- * larger than the current length, preserving just a part of the array.
|
|
|
- *
|
|
|
- * <P>If you want complete control on the array growth, you should probably
|
|
|
- * use
|
|
|
- * <code>ensureCapacity()</code> instead.
|
|
|
- *
|
|
|
- * @param array an array.
|
|
|
- * @param length the new minimum length for this array.
|
|
|
- * @param preserve the number of elements of the array that must be
|
|
|
- * preserved in case a new allocation is necessary.
|
|
|
- * @return <code>array</code>, if it can contain <code>length</code>
|
|
|
- * entries; otherwise, an array with
|
|
|
- * max(<code>length</code>,<code>array.length</code>/φ) entries whose
|
|
|
- * first <code>preserve</code> entries are the same as those
|
|
|
- * of <code>array</code>.
|
|
|
- *
|
|
|
- */
|
|
|
- public static NativeArray grow(NativeArray array, int length, int preserve) {
|
|
|
- int n = array.size();
|
|
|
- if(preserve < 0) {
|
|
|
- preserve = n;
|
|
|
- }
|
|
|
- if (length > n) {
|
|
|
- int newLength = (int) Math.min(Math.max(2L * n, length), MAX_SIZE);
|
|
|
- NativeArray target = array.allocate(newLength);
|
|
|
- NativeArrayUtils.copy(array, 0, target, 0, preserve);
|
|
|
- return target;
|
|
|
- }
|
|
|
- return array;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Trims the given array to the given length.
|
|
|
- *
|
|
|
- * @param array an array.
|
|
|
- * @param length the new maximum length for the array.
|
|
|
- * @return <code>array</code>, if it contains <code>length</code> entries or
|
|
|
- * less; otherwise, an array with <code>length</code> entries whose entries
|
|
|
- * are the same as the first <code>length</code> entries * *
|
|
|
- * of <code>array</code>.
|
|
|
- *
|
|
|
- */
|
|
|
- public static NativeArray trim(NativeArray array, int length) {
|
|
|
- if (length >= array.size()) {
|
|
|
- return array;
|
|
|
- }
|
|
|
- NativeArray target = array.allocate(length);
|
|
|
- NativeArrayUtils.copy(array, 0, target, 0, length);
|
|
|
- return target;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
+/*
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ * @copyright Ranides Atterwim
|
|
|
+ * @license WTFPL
|
|
|
+ * @url http://ranides.net/projects/assira
|
|
|
+ */
|
|
|
+package net.ranides.assira.collection.arrays;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+
|
|
|
+public final class NativeArrayAllocator {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This is a safe value used by {@link ArrayList} (as of Java 7) to avoid
|
|
|
+ * throwing {@link OutOfMemoryError} on some JVMs. We adopt the same value.
|
|
|
+ */
|
|
|
+ private static final int MAX_SIZE = Integer.MAX_VALUE - 8;
|
|
|
+
|
|
|
+ private NativeArrayAllocator() {
|
|
|
+ // utility class
|
|
|
+ }
|
|
|
+
|
|
|
+ public static NativeArray forComponent(Class<?> component, int size) {
|
|
|
+ return NativeArray.allocate(component, size);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Creates a new array using a the given one as prototype.
|
|
|
+ *
|
|
|
+ * <P>This method returns a new array of the given length whose element are
|
|
|
+ * of the same class as of those of <code>prototype</code>.
|
|
|
+ * In case of an empty array, it tries to return {@link #EMPTY_ARRAY}, if possible.
|
|
|
+ *
|
|
|
+ * @param prototype an array that will be used to type the new one.
|
|
|
+ * @param length the length of the new array.
|
|
|
+ * @return a new array of given type and length.
|
|
|
+ */
|
|
|
+ public static NativeArray forPrototype(NativeArray prototype, int length) {
|
|
|
+ return prototype.allocate(length);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Ensures that an array can contain the given number of entries.
|
|
|
+ *
|
|
|
+ * <P>If you cannot foresee whether this array will need again to be
|
|
|
+ * enlarged, you should probably use
|
|
|
+ * <code>grow()</code> instead.
|
|
|
+ *
|
|
|
+ * @param array an array.
|
|
|
+ * @param length the new minimum length for this array.
|
|
|
+ * @return <code>array</code>, if it contains <code>length</code> entries or
|
|
|
+ * more; otherwise, an array with <code>length</code> entries whose * *
|
|
|
+ * first <code>array.length</code> entries are the same as those * *
|
|
|
+ * of <code>array</code>.
|
|
|
+ */
|
|
|
+ public static NativeArray ensureCapacity(NativeArray array, int length) {
|
|
|
+ return ensureCapacity(array, length, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Ensures that an array can contain the given number of entries, preserving
|
|
|
+ * just a part of the array.
|
|
|
+ *
|
|
|
+ * @param array an array.
|
|
|
+ * @param length the new minimum length for this array.
|
|
|
+ * @param preserve the number of elements of the array that must be
|
|
|
+ * preserved in case a new allocation is necessary.
|
|
|
+ * @return <code>array</code>, if it can contain <code>length</code> entries
|
|
|
+ * or more; otherwise, an array with <code>length</code> entries whose *
|
|
|
+ * first <code>preserve</code> entries are the same as those * *
|
|
|
+ * of <code>array</code>.
|
|
|
+ */
|
|
|
+ public static NativeArray ensureCapacity(NativeArray array, int length, int preserve) {
|
|
|
+ int n = array.size();
|
|
|
+ if(preserve < 0) {
|
|
|
+ preserve = n;
|
|
|
+ }
|
|
|
+ if (length > n) {
|
|
|
+ NativeArray target = array.allocate(length);
|
|
|
+ NativeArrayUtils.copy(array, 0, target, 0, preserve);
|
|
|
+ return target;
|
|
|
+ }
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Ensures that a range given by an offset and a length fits an array.
|
|
|
+ *
|
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
|
+ *
|
|
|
+ * @param array an array.
|
|
|
+ * @param offset a start index.
|
|
|
+ * @param length a length (the number of elements in the range).
|
|
|
+ * @throws IllegalArgumentException if <code>length</code> is negative.
|
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative
|
|
|
+ * or <code>offset</code>+<code>length</code> is greater than the array
|
|
|
+ * length.
|
|
|
+ */
|
|
|
+ public static void ensureOffsetLength(NativeArray array, int offset, int length) {
|
|
|
+ ensureOffsetLength(array.size(), offset, length);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Ensures that a range given by an offset and a length fits an array of
|
|
|
+ * given length.
|
|
|
+ *
|
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
|
+ *
|
|
|
+ * @param arrayLength an array length.
|
|
|
+ * @param offset a start index for the fragment
|
|
|
+ * @param length a length (the number of elements in the fragment).
|
|
|
+ * @throws IllegalArgumentException if <code>length</code> is negative.
|
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative
|
|
|
+ * or <code>offset</code>+<code>length</code> is greater * * than <code>arrayLength</code>.
|
|
|
+ */
|
|
|
+ public static void ensureOffsetLength(int arrayLength, int offset, int length) {
|
|
|
+ if (offset < 0) {
|
|
|
+ throw new ArrayIndexOutOfBoundsException("Offset (" + offset + ") is negative");
|
|
|
+ }
|
|
|
+ if (length < 0) {
|
|
|
+ throw new IllegalArgumentException("Length (" + length + ") is negative");
|
|
|
+ }
|
|
|
+ if (offset + length > arrayLength) {
|
|
|
+ throw new ArrayIndexOutOfBoundsException("Last index (" + (offset + length) + ") is greater than array length (" + arrayLength + ")");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Ensures that a range given by its first (inclusive) and last (exclusive)
|
|
|
+ * elements fits an array.
|
|
|
+ *
|
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
|
+ *
|
|
|
+ * @param array an array.
|
|
|
+ * @param begin a start index (inclusive).
|
|
|
+ * @param end an end index (exclusive).
|
|
|
+ * @throws IllegalArgumentException if <code>from</code> is greater * *
|
|
|
+ * than <code>to</code>.
|
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>from</code> * *
|
|
|
+ * or <code>to</code> are greater than the array length or negative.
|
|
|
+ */
|
|
|
+ public static void ensureFromTo(NativeArray array, int begin, int end) {
|
|
|
+ ensureFromTo(array.size(), begin, end);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Ensures that a range given by its first (inclusive) and last (exclusive)
|
|
|
+ * elements fits an array of given length.
|
|
|
+ *
|
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
|
+ *
|
|
|
+ * @param arrayLength an array length.
|
|
|
+ * @param begin a start index (inclusive).
|
|
|
+ * @param end an end index (inclusive).
|
|
|
+ * @throws IllegalArgumentException if <code>from</code> is greater * * than <code>to</code>.
|
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>from</code> * * or <code>to</code> are greater than <code>arrayLength</code> or
|
|
|
+ * negative.
|
|
|
+ */
|
|
|
+ public static void ensureFromTo(int arrayLength, int begin, int end) {
|
|
|
+ if (begin < 0) {
|
|
|
+ throw new ArrayIndexOutOfBoundsException("Start index (" + begin + ") is negative");
|
|
|
+ }
|
|
|
+ if (begin > end) {
|
|
|
+ throw new IllegalArgumentException("Start index (" + begin + ") is greater than end index (" + end + ")");
|
|
|
+ }
|
|
|
+ if (end > arrayLength) {
|
|
|
+ throw new ArrayIndexOutOfBoundsException("End index (" + end + ") is greater than array length (" + arrayLength + ")");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static NativeArray resize(NativeArray array, int size) {
|
|
|
+ return NativeArrayUtils.copy(array, 0, array.allocate(size), 0, Math.min(size, array.size()));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Grows the given array to the maximum between the given length and the
|
|
|
+ * current length multiplied by two, provided that the given length is
|
|
|
+ * larger than the current length.
|
|
|
+ *
|
|
|
+ * <P>If you want complete control on the array growth, you should probably
|
|
|
+ * use
|
|
|
+ * <code>ensureCapacity()</code> instead.
|
|
|
+ *
|
|
|
+ * @param array an array.
|
|
|
+ * @param length the new minimum length for this array.
|
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
|
+ * entries; otherwise, an array with
|
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) entries whose
|
|
|
+ * first <code>array.length</code> entries are the same as those * *
|
|
|
+ * of <code>array</code>.
|
|
|
+ *
|
|
|
+ */
|
|
|
+ public static NativeArray grow(NativeArray array, int length) {
|
|
|
+ return grow(array, length, -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Grows the given array to the maximum between the given length and the
|
|
|
+ * current length multiplied by two, provided that the given length is
|
|
|
+ * larger than the current length, preserving just a part of the array.
|
|
|
+ *
|
|
|
+ * <P>If you want complete control on the array growth, you should probably
|
|
|
+ * use
|
|
|
+ * <code>ensureCapacity()</code> instead.
|
|
|
+ *
|
|
|
+ * @param array an array.
|
|
|
+ * @param length the new minimum length for this array.
|
|
|
+ * @param preserve the number of elements of the array that must be
|
|
|
+ * preserved in case a new allocation is necessary.
|
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
|
+ * entries; otherwise, an array with
|
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) entries whose
|
|
|
+ * first <code>preserve</code> entries are the same as those
|
|
|
+ * of <code>array</code>.
|
|
|
+ *
|
|
|
+ */
|
|
|
+ public static NativeArray grow(NativeArray array, int length, int preserve) {
|
|
|
+ int n = array.size();
|
|
|
+ if(preserve < 0) {
|
|
|
+ preserve = n;
|
|
|
+ }
|
|
|
+ if (length > n) {
|
|
|
+ int newLength = (int) Math.min(Math.max(2L * n, length), MAX_SIZE);
|
|
|
+ NativeArray target = array.allocate(newLength);
|
|
|
+ NativeArrayUtils.copy(array, 0, target, 0, preserve);
|
|
|
+ return target;
|
|
|
+ }
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Trims the given array to the given length.
|
|
|
+ *
|
|
|
+ * @param array an array.
|
|
|
+ * @param length the new maximum length for the array.
|
|
|
+ * @return <code>array</code>, if it contains <code>length</code> entries or
|
|
|
+ * less; otherwise, an array with <code>length</code> entries whose entries
|
|
|
+ * are the same as the first <code>length</code> entries * *
|
|
|
+ * of <code>array</code>.
|
|
|
+ *
|
|
|
+ */
|
|
|
+ public static NativeArray trim(NativeArray array, int length) {
|
|
|
+ if (length >= array.size()) {
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+ NativeArray target = array.allocate(length);
|
|
|
+ NativeArrayUtils.copy(array, 0, target, 0, length);
|
|
|
+ return target;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|