From 5b7608d1549989d92dd159392c19d9ba8ce0e62e Mon Sep 17 00:00:00 2001
From: beradrian
Date: Thu, 7 May 2015 09:50:41 +0300
Subject: [PATCH 1/4] consistent treatment for negative indices for swap method
---
.../org/apache/commons/lang3/ArrayUtils.java | 384 ++++++++++++------
.../apache/commons/lang3/ArrayUtilsTest.java | 121 +++---
2 files changed, 311 insertions(+), 194 deletions(-)
diff --git a/src/main/java/org/apache/commons/lang3/ArrayUtils.java b/src/main/java/org/apache/commons/lang3/ArrayUtils.java
index 0afe0e406..177a0ba2c 100644
--- a/src/main/java/org/apache/commons/lang3/ArrayUtils.java
+++ b/src/main/java/org/apache/commons/lang3/ArrayUtils.java
@@ -1854,24 +1854,25 @@ public static void reverse(final short[] array, final int startIndexInclusive, f
*
* There is no special handling for multi-dimensional arrays.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
*
* Examples:
*
* - ArrayUtils.swap(["1", "2", "3"], 0, 2) -> ["3", "2", "1"]
* - ArrayUtils.swap(["1", "2", "3"], 0, 0) -> ["1", "2", "3"]
* - ArrayUtils.swap(["1", "2", "3"], 1, 0) -> ["2", "1", "3"]
- * - ArrayUtils.swap(["1", "2", "3"], 0, 5) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap(["1", "2", "3"], 0, 5) -> ["1", "2", "3"]
+ * - ArrayUtils.swap(["1", "2", "3"], -1, 1) -> ["2", "1", "3"]
*
*
*
* @param array the array to swap, may be {@code null}
* @param offset1 the index of the first element to swap
* @param offset2 the index of the second element to swap
- * @throws ArrayIndexOutOfBoundsException if one of the indices is out of range
*/
public static void swap(final Object[] array, int offset1, int offset2) {
- if (array == null) {
+ if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
@@ -1880,24 +1881,27 @@ public static void swap(final Object[] array, int offset1, int offset2) {
/**
* Swaps two elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * There is no special handling for multi-dimensional arrays.
+ *
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
*
* Examples:
*
* - ArrayUtils.swap([true, false, true], 0, 2) -> [true, false, true]
* - ArrayUtils.swap([true, false, true], 0, 0) -> [true, false, true]
* - ArrayUtils.swap([true, false, true], 1, 0) -> [false, true, true]
- * - ArrayUtils.swap([true, false, true], 0, 5) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([true, false, true], 0, 5) -> [true, false, true]
+ * - ArrayUtils.swap([true, false, true], -1, 1) -> [false, true, true]
*
*
*
* @param array the array to swap, may be {@code null}
* @param offset1 the index of the first element to swap
* @param offset2 the index of the second element to swap
- * @throws ArrayIndexOutOfBoundsException if one of the indices is out of range
*/
public static void swap(final long[] array, int offset1, int offset2) {
- if (array == null) {
+ if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
@@ -1906,24 +1910,25 @@ public static void swap(final long[] array, int offset1, int offset2) {
/**
* Swaps two elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
* - ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
* - ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * - ArrayUtils.swap([1, 2, 3], 0, 5) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * - ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
*
*
*
* @param array the array to swap, may be {@code null}
* @param offset1 the index of the first element to swap
* @param offset2 the index of the second element to swap
- * @throws ArrayIndexOutOfBoundsException if one of the indices is out of range
*/
public static void swap(final int[] array, int offset1, int offset2) {
- if (array == null) {
+ if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
@@ -1932,24 +1937,25 @@ public static void swap(final int[] array, int offset1, int offset2) {
/**
* Swaps two elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
* - ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
* - ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * - ArrayUtils.swap([1, 2, 3], 0, 5) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * - ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
*
*
*
* @param array the array to swap, may be {@code null}
* @param offset1 the index of the first element to swap
* @param offset2 the index of the second element to swap
- * @throws ArrayIndexOutOfBoundsException if one of the indices is out of range
*/
public static void swap(final short[] array, int offset1, int offset2) {
- if (array == null) {
+ if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
@@ -1958,24 +1964,25 @@ public static void swap(final short[] array, int offset1, int offset2) {
/**
* Swaps two elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
* - ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
* - ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * - ArrayUtils.swap([1, 2, 3], 0, 5) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * - ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
*
*
*
* @param array the array to swap, may be {@code null}
* @param offset1 the index of the first element to swap
* @param offset2 the index of the second element to swap
- * @throws ArrayIndexOutOfBoundsException if one of the indices is out of range
*/
public static void swap(final char[] array, int offset1, int offset2) {
- if (array == null) {
+ if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
@@ -1984,24 +1991,25 @@ public static void swap(final char[] array, int offset1, int offset2) {
/**
* Swaps two elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
* - ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
* - ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * - ArrayUtils.swap([1, 2, 3], 0, 5) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * - ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
*
*
*
* @param array the array to swap, may be {@code null}
* @param offset1 the index of the first element to swap
* @param offset2 the index of the second element to swap
- * @throws ArrayIndexOutOfBoundsException if one of the indices is out of range
*/
public static void swap(final byte[] array, int offset1, int offset2) {
- if (array == null) {
+ if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
@@ -2010,24 +2018,25 @@ public static void swap(final byte[] array, int offset1, int offset2) {
/**
* Swaps two elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
* - ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
* - ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * - ArrayUtils.swap([1, 2, 3], 0, 5) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * - ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
*
*
*
* @param array the array to swap, may be {@code null}
* @param offset1 the index of the first element to swap
* @param offset2 the index of the second element to swap
- * @throws ArrayIndexOutOfBoundsException if one of the indices is out of range
*/
public static void swap(final double[] array, int offset1, int offset2) {
- if (array == null) {
+ if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
@@ -2036,24 +2045,25 @@ public static void swap(final double[] array, int offset1, int offset2) {
/**
* Swaps two elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
* - ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
* - ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * - ArrayUtils.swap([1, 2, 3], 0, 5) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * - ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
*
*
*
* @param array the array to swap, may be {@code null}
* @param offset1 the index of the first element to swap
* @param offset2 the index of the second element to swap
- * @throws ArrayIndexOutOfBoundsException if one of the indices is out of range
*/
public static void swap(final float[] array, int offset1, int offset2) {
- if (array == null) {
+ if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
@@ -2062,24 +2072,25 @@ public static void swap(final float[] array, int offset1, int offset2) {
/**
* Swaps two elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
*
- * Examples:
+ *
Examples:
*
* - ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
* - ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
* - ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
- * - ArrayUtils.swap([1, 2, 3], 0, 5) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * - ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
*
*
*
* @param array the array to swap, may be {@code null}
* @param offset1 the index of the first element to swap
* @param offset2 the index of the second element to swap
- * @throws ArrayIndexOutOfBoundsException if one of the indices is out of range
*/
public static void swap(final boolean[] array, int offset1, int offset2) {
- if (array == null) {
+ if (array == null || array.length == 0) {
return;
}
swap(array, offset1, offset2, 1);
@@ -2088,45 +2099,61 @@ public static void swap(final boolean[] array, int offset1, int offset2) {
/**
* Swaps a series of elements in the given array.
*
- * This method does nothing for a {@code null} input array.
- *
- * Examples:
- *
- * - ArrayUtils.swap(["1", "2", "3", "4"], 0, 2, 1) -> ["3", "2", "1", "4"]
- * - ArrayUtils.swap(["1", "2", "3", "4"], 0, 0, 1) -> ["1", "2", "3", "4"]
- * - ArrayUtils.swap(["1", "2", "3", "4"], 2, 0, 2) -> ["3", "4", "1", "2"]
- * - ArrayUtils.swap(["1", "2", "3", "4"], 0, 3, 3) -> ArrayOutOfBoundsException
- *
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ * If any of the sub-arrays to swap falls outside of the given array,
+ * then the swap is stopped at the end of the array and as many as possible elements are swapped.
*
*
- * @param array the array to swap, may be {@code null}
- * @param offset1 the index of the first element in the series to swap
- * @param offset2 the index of the second element in the series to swap
- * @param len the number of elements to swap starting with the given indices
- * @throws ArrayIndexOutOfBoundsException if one of the indices (plus the length of the series to swap) is out of range
- */
- public static void swap(final boolean[] array, int offset1, int offset2, int len) {
- if (array == null) {
- return;
- }
- for (int i = 0; i < len; i++) {
- boolean aux = array[offset1 + i];
- array[offset1 + i] = array[offset2 + i];
- array[offset2 + i] = aux;
- }
- }
-
- /**
- * Swaps a series of elements in the given array.
- *
- * This method does nothing for a {@code null} input array.
- *
* Examples:
*
* - ArrayUtils.swap([true, false, true, false], 0, 2, 1) -> [true, false, true, false]
* - ArrayUtils.swap([true, false, true, false], 0, 0, 1) -> [true, false, true, false]
* - ArrayUtils.swap([true, false, true, false], 0, 2, 2) -> [true, false, true, false]
- * - ArrayUtils.swap([true, false, true, false], 0, 5, 3) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([true, false, true, false], -3, 2, 2) -> [true, false, true, false]
+ * - ArrayUtils.swap([true, false, true, false], 0, 3, 3) -> [false, false, true, true]
+ *
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ */
+ public static void swap(final boolean[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ boolean aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+ }
+
+ /**
+ * Swaps a series of elements in the given array.
+ *
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ * If any of the sub-arrays to swap falls outside of the given array,
+ * then the swap is stopped at the end of the array and as many as possible elements are swapped.
+ *
+ *
+ * Examples:
+ *
+ * - ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
+ * - ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
+ * - ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
+ * - ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
*
*
*
@@ -2134,31 +2161,42 @@ public static void swap(final boolean[] array, int offset1, int offset2, int le
* @param offset1 the index of the first element in the series to swap
* @param offset2 the index of the second element in the series to swap
* @param len the number of elements to swap starting with the given indices
- * @throws ArrayIndexOutOfBoundsException if one of the indices (plus the length of the series to swap) is out of range
*/
public static void swap(final byte[] array, int offset1, int offset2, int len) {
- if (array == null) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
return;
}
- for (int i = 0; i < len; i++) {
- byte aux = array[offset1 + i];
- array[offset1 + i] = array[offset2 + i];
- array[offset2 + i] = aux;
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ byte aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
}
}
/**
* Swaps a series of elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ * If any of the sub-arrays to swap falls outside of the given array,
+ * then the swap is stopped at the end of the array and as many as possible elements are swapped.
+ *
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
*
*
*
@@ -2166,30 +2204,41 @@ public static void swap(final byte[] array, int offset1, int offset2, int len)
* @param offset1 the index of the first element in the series to swap
* @param offset2 the index of the second element in the series to swap
* @param len the number of elements to swap starting with the given indices
- * @throws ArrayIndexOutOfBoundsException if one of the indices (plus the length of the series to swap) is out of range
*/
public static void swap(final char[] array, int offset1, int offset2, int len) {
- if (array == null) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
return;
}
- for (int i = 0; i < len; i++) {
- char aux = array[offset1 + i];
- array[offset1 + i] = array[offset2 + i];
- array[offset2 + i] = aux;
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ char aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
}
}
/**
* Swaps a series of elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ * If any of the sub-arrays to swap falls outside of the given array,
+ * then the swap is stopped at the end of the array and as many as possible elements are swapped.
+ *
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
*
*
*
@@ -2197,30 +2246,41 @@ public static void swap(final char[] array, int offset1, int offset2, int len)
* @param offset1 the index of the first element in the series to swap
* @param offset2 the index of the second element in the series to swap
* @param len the number of elements to swap starting with the given indices
- * @throws ArrayIndexOutOfBoundsException if one of the indices (plus the length of the series to swap) is out of range
*/
public static void swap(final double[] array, int offset1, int offset2, int len) {
- if (array == null) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
return;
}
- for (int i = 0; i < len; i++) {
- double aux = array[offset1 + i];
- array[offset1 + i] = array[offset2 + i];
- array[offset2 + i] = aux;
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ double aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
}
}
/**
* Swaps a series of elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ * If any of the sub-arrays to swap falls outside of the given array,
+ * then the swap is stopped at the end of the array and as many as possible elements are swapped.
+ *
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
*
*
*
@@ -2228,30 +2288,42 @@ public static void swap(final double[] array, int offset1, int offset2, int len
* @param offset1 the index of the first element in the series to swap
* @param offset2 the index of the second element in the series to swap
* @param len the number of elements to swap starting with the given indices
- * @throws ArrayIndexOutOfBoundsException if one of the indices (plus the length of the series to swap) is out of range
*/
public static void swap(final float[] array, int offset1, int offset2, int len) {
- if (array == null) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
return;
}
- for (int i = 0; i < len; i++) {
- float aux = array[offset1 + i];
- array[offset1 + i] = array[offset2 + i];
- array[offset2 + i] = aux;
+ if (offset1 < 0) {
+ offset1 = 0;
}
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ float aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+
}
/**
* Swaps a series of elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ * If any of the sub-arrays to swap falls outside of the given array,
+ * then the swap is stopped at the end of the array and as many as possible elements are swapped.
+ *
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
*
*
*
@@ -2259,30 +2331,41 @@ public static void swap(final float[] array, int offset1, int offset2, int len)
* @param offset1 the index of the first element in the series to swap
* @param offset2 the index of the second element in the series to swap
* @param len the number of elements to swap starting with the given indices
- * @throws ArrayIndexOutOfBoundsException if one of the indices (plus the length of the series to swap) is out of range
*/
public static void swap(final int[] array, int offset1, int offset2, int len) {
- if (array == null) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
return;
}
- for (int i = 0; i < len; i++) {
- int aux = array[offset1 + i];
- array[offset1 + i] = array[offset2 + i];
- array[offset2 + i] = aux;
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ int aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
}
}
/**
* Swaps a series of elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ * If any of the sub-arrays to swap falls outside of the given array,
+ * then the swap is stopped at the end of the array and as many as possible elements are swapped.
+ *
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
*
*
*
@@ -2290,30 +2373,41 @@ public static void swap(final int[] array, int offset1, int offset2, int len) {
* @param offset1 the index of the first element in the series to swap
* @param offset2 the index of the second element in the series to swap
* @param len the number of elements to swap starting with the given indices
- * @throws ArrayIndexOutOfBoundsException if one of the indices (plus the length of the series to swap) is out of range
*/
public static void swap(final long[] array, int offset1, int offset2, int len) {
- if (array == null) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
return;
}
- for (int i = 0; i < len; i++) {
- long aux = array[offset1 + i];
- array[offset1 + i] = array[offset2 + i];
- array[offset2 + i] = aux;
- }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ long aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
}
/**
* Swaps a series of elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ * If any of the sub-arrays to swap falls outside of the given array,
+ * then the swap is stopped at the end of the array and as many as possible elements are swapped.
+ *
*
* Examples:
*
- * - ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
- * - ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
- * - ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap(["1", "2", "3", "4"], 0, 2, 1) -> ["3", "2", "1", "4"]
+ * - ArrayUtils.swap(["1", "2", "3", "4"], 0, 0, 1) -> ["1", "2", "3", "4"]
+ * - ArrayUtils.swap(["1", "2", "3", "4"], 2, 0, 2) -> ["3", "4", "1", "2"]
+ * - ArrayUtils.swap(["1", "2", "3", "4"], -3, 2, 2) -> ["3", "4", "1", "2"]
+ * - ArrayUtils.swap(["1", "2", "3", "4"], 0, 3, 3) -> ["4", "2", "3", "1"]
*
*
*
@@ -2321,30 +2415,41 @@ public static void swap(final long[] array, int offset1, int offset2, int len)
* @param offset1 the index of the first element in the series to swap
* @param offset2 the index of the second element in the series to swap
* @param len the number of elements to swap starting with the given indices
- * @throws ArrayIndexOutOfBoundsException if one of the indices (plus the length of the series to swap) is out of range
*/
public static void swap(final Object[] array, int offset1, int offset2, int len) {
- if (array == null) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
return;
}
- for (int i = 0; i < len; i++) {
- Object aux = array[offset1 + i];
- array[offset1 + i] = array[offset2 + i];
- array[offset2 + i] = aux;
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ Object aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
}
}
/**
* Swaps a series of elements in the given array.
*
- * This method does nothing for a {@code null} input array.
+ * This method does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ * If any of the sub-arrays to swap falls outside of the given array,
+ * then the swap is stopped at the end of the array and as many as possible elements are swapped.
+ *
*
* Examples:
*
* - ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
* - ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
- * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> ArrayOutOfBoundsException
+ * - ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * - ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
*
*
*
@@ -2352,16 +2457,25 @@ public static void swap(final Object[] array, int offset1, int offset2, int len
* @param offset1 the index of the first element in the series to swap
* @param offset2 the index of the second element in the series to swap
* @param len the number of elements to swap starting with the given indices
- * @throws ArrayIndexOutOfBoundsException if one of the indices (plus the length of the series to swap) is out of range
*/
public static void swap(final short[] array, int offset1, int offset2, int len) {
- if (array == null) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
return;
}
- for (int i = 0; i < len; i++) {
- short aux = array[offset1 + i];
- array[offset1 + i] = array[offset2 + i];
- array[offset2 + i] = aux;
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ if (offset1 == offset2) {
+ return;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ short aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
}
}
diff --git a/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java b/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java
index be3e11960..b0217193b 100644
--- a/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java
@@ -2142,18 +2142,18 @@ public void testSwapCharRange() {
assertEquals(4, array[1]);
assertEquals(1, array[2]);
assertEquals(2, array[3]);
- }
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapCharOutOfRange() {
- char[] array = new char[] {1, 2, 3};
+ array = new char[] {1, 2, 3};
ArrayUtils.swap(array, 0, 3);
- }
-
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapCharOutOfRangeLen() {
- char[] array = new char[] {1, 2, 3};
+ assertEquals(1, array[0]);
+ assertEquals(2, array[1]);
+ assertEquals(3, array[2]);
+
+ array = new char[] {1, 2, 3};
ArrayUtils.swap(array, 0, 2, 2);
+ assertEquals(3, array[0]);
+ assertEquals(2, array[1]);
+ assertEquals(1, array[2]);
}
@Test
@@ -2173,18 +2173,18 @@ public void testSwapFloatRange() {
assertEquals(4, array[1], 0);
assertEquals(1, array[2], 0);
assertEquals(2, array[3], 0);
- }
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapFloatOutOfRange() {
- float[] array = new float[] {1, 2, 3};
+ array = new float[] {1, 2, 3};
ArrayUtils.swap(array, 0, 3);
- }
-
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapFloatOutOfRangeLen() {
- float[] array = new float[] {1, 2, 3};
+ assertEquals(1, array[0], 0);
+ assertEquals(2, array[1], 0);
+ assertEquals(3, array[2], 0);
+
+ array = new float[] {1, 2, 3};
ArrayUtils.swap(array, 0, 2, 2);
+ assertEquals(3, array[0], 0);
+ assertEquals(2, array[1], 0);
+ assertEquals(1, array[2], 0);
}
@Test
@@ -2204,18 +2204,18 @@ public void testSwapDoubleRange() {
assertEquals(4, array[1], 0);
assertEquals(1, array[2], 0);
assertEquals(2, array[3], 0);
- }
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapDoubleOutOfRange() {
- double[] array = new double[] {1, 2, 3};
+ array = new double[] {1, 2, 3};
ArrayUtils.swap(array, 0, 3);
- }
-
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapDoubleOutOfRangeLen() {
- double[] array = new double[] {1, 2, 3};
+ assertEquals(1, array[0], 0);
+ assertEquals(2, array[1], 0);
+ assertEquals(3, array[2], 0);
+
+ array = new double[] {1, 2, 3};
ArrayUtils.swap(array, 0, 2, 2);
+ assertEquals(3, array[0], 0);
+ assertEquals(2, array[1], 0);
+ assertEquals(1, array[2], 0);
}
@Test
@@ -2235,6 +2235,18 @@ public void testSwapIntRange() {
assertEquals(4, array[1]);
assertEquals(1, array[2]);
assertEquals(2, array[3]);
+
+ array = new int[] {1, 2, 3};
+ ArrayUtils.swap(array, 3, 0);
+ assertEquals(1, array[0]);
+ assertEquals(2, array[1]);
+ assertEquals(3, array[2]);
+
+ array = new int[] {1, 2, 3};
+ ArrayUtils.swap(array, 0, 2, 2);
+ assertEquals(3, array[0]);
+ assertEquals(2, array[1]);
+ assertEquals(1, array[2]);
}
@Test
@@ -2249,18 +2261,6 @@ public void testSwapIntExchangedOffsets() {
assertArrayEquals(new int[] {2, 3, 1}, array);
}
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapIntOutOfRange() {
- int[] array = new int[] {1, 2, 3};
- ArrayUtils.swap(array, 0, 3);
- }
-
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapIntOutOfRangeLen() {
- int[] array = new int[] {1, 2, 3};
- ArrayUtils.swap(array, 0, 2, 2);
- }
-
@Test
public void testSwapLong() {
long[] array = new long[] {1, 2, 3};
@@ -2278,18 +2278,18 @@ public void testSwapLongRange() {
assertEquals(4, array[1]);
assertEquals(1, array[2]);
assertEquals(2, array[3]);
- }
-
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapLongOutOfRange() {
- long[] array = new long[] {1, 2, 3};
+
+ array = new long[] {1, 2, 3};
ArrayUtils.swap(array, 0, 3);
- }
-
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapLongOutOfRangeLen() {
- long[] array = new long[] {1, 2, 3};
+ assertEquals(1, array[0]);
+ assertEquals(2, array[1]);
+ assertEquals(3, array[2]);
+
+ array = new long[] {1, 2, 3};
ArrayUtils.swap(array, 0, 2, 2);
+ assertEquals(3, array[0]);
+ assertEquals(2, array[1]);
+ assertEquals(1, array[2]);
}
@Test
@@ -2309,18 +2309,21 @@ public void testSwapObjectRange() {
assertEquals("4", array[1]);
assertEquals("1", array[2]);
assertEquals("2", array[3]);
- }
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapObjectOutOfRange() {
- String[] array = new String[] {"1", "2", "3"};
- ArrayUtils.swap(array, 0, 3);
- }
+ array = new String[] {"1", "2", "3", "4"};
+ ArrayUtils.swap(array, -1, 2, 3);
+ assertEquals("3", array[0]);
+ assertEquals("4", array[1]);
+ assertEquals("1", array[2]);
+ assertEquals("2", array[3]);
- @Test(expected = ArrayIndexOutOfBoundsException.class)
- public void testSwapObjectOutOfRangeLen() {
- String[] array = new String[] {"1", "2", "3"};
- ArrayUtils.swap(array, 0, 2, 2);
+ array = new String[] {"1", "2", "3", "4", "5"};
+ ArrayUtils.swap(array, -3, 2, 3);
+ assertEquals("3", array[0]);
+ assertEquals("4", array[1]);
+ assertEquals("5", array[2]);
+ assertEquals("2", array[3]);
+ assertEquals("1", array[4]);
}
//-----------------------------------------------------------------------
From e79a590e0cdabd93883aca964db2a862ff3f8490 Mon Sep 17 00:00:00 2001
From: beradrian
Date: Thu, 7 May 2015 11:31:28 +0300
Subject: [PATCH 2/4] new test case explanations about algorithm
---
.../org/apache/commons/lang3/ArrayUtils.java | 18 ++++++++++++++++++
.../apache/commons/lang3/ArrayUtilsTest.java | 7 +++++++
2 files changed, 25 insertions(+)
diff --git a/src/main/java/org/apache/commons/lang3/ArrayUtils.java b/src/main/java/org/apache/commons/lang3/ArrayUtils.java
index 177a0ba2c..20ff85dc9 100644
--- a/src/main/java/org/apache/commons/lang3/ArrayUtils.java
+++ b/src/main/java/org/apache/commons/lang3/ArrayUtils.java
@@ -2650,6 +2650,8 @@ public static void shift(final boolean[] array, int startIndexInclusive, int end
if (offset < 0) {
offset += n;
}
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
while (n > 1 && offset > 0) {
int n_offset = n - offset;
@@ -2708,6 +2710,8 @@ public static void shift(final byte[] array, int startIndexInclusive, int endInd
if (offset < 0) {
offset += n;
}
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
while (n > 1 && offset > 0) {
int n_offset = n - offset;
@@ -2766,6 +2770,8 @@ public static void shift(final char[] array, int startIndexInclusive, int endInd
if (offset < 0) {
offset += n;
}
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
while (n > 1 && offset > 0) {
int n_offset = n - offset;
@@ -2824,6 +2830,8 @@ public static void shift(final double[] array, int startIndexInclusive, int endI
if (offset < 0) {
offset += n;
}
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
while (n > 1 && offset > 0) {
int n_offset = n - offset;
@@ -2882,6 +2890,8 @@ public static void shift(final float[] array, int startIndexInclusive, int endIn
if (offset < 0) {
offset += n;
}
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
while (n > 1 && offset > 0) {
int n_offset = n - offset;
@@ -2940,6 +2950,8 @@ public static void shift(final int[] array, int startIndexInclusive, int endInde
if (offset < 0) {
offset += n;
}
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
while (n > 1 && offset > 0) {
int n_offset = n - offset;
@@ -2997,6 +3009,8 @@ public static void shift(final long[] array, int startIndexInclusive, int endInd
if (offset < 0) {
offset += n;
}
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
while (n > 1 && offset > 0) {
int n_offset = n - offset;
@@ -3054,6 +3068,8 @@ public static void shift(final Object[] array, int startIndexInclusive, int endI
if (offset < 0) {
offset += n;
}
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
while (n > 1 && offset > 0) {
int n_offset = n - offset;
@@ -3112,6 +3128,8 @@ public static void shift(final short[] array, int startIndexInclusive, int endIn
if (offset < 0) {
offset += n;
}
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
while (n > 1 && offset > 0) {
int n_offset = n - offset;
diff --git a/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java b/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java
index b0217193b..cdd21fd13 100644
--- a/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java
@@ -2484,6 +2484,13 @@ public void testShiftShort() {
assertEquals(4, array[1]);
assertEquals(1, array[2]);
assertEquals(2, array[3]);
+ array = new short[] {1, 2, 3, 4, 5};
+ ArrayUtils.shift(array, 2);
+ assertEquals(4, array[0]);
+ assertEquals(5, array[1]);
+ assertEquals(1, array[2]);
+ assertEquals(2, array[3]);
+ assertEquals(3, array[4]);
}
@Test
From c885a32e24662cbbe9fb6b8a0bc3c8dacf3288b5 Mon Sep 17 00:00:00 2001
From: Benedikt Ritter
Date: Thu, 7 May 2015 20:29:53 +0200
Subject: [PATCH 3/4] Add LANG-1122 to changes.xml
---
src/changes/changes.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 27a7f5ce5..5e9efaf9d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -22,6 +22,7 @@
+ Inconsistent behavior of swap for malformed inputs
TypeUtils.ParameterizedType#equals doesn't work with wildcard types
Add rotate(string, int) method to StringUtils
StringUtils.repeat('z', -1) throws NegativeArraySizeException
From 35096beed02221413948ed840bdd33c8e3c921d1 Mon Sep 17 00:00:00 2001
From: Benedikt Ritter
Date: Thu, 7 May 2015 20:30:09 +0200
Subject: [PATCH 4/4] Add Adrian Ber to the list of contributors
---
pom.xml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/pom.xml b/pom.xml
index 3d8090993..e8af806ec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -478,6 +478,9 @@
MichaĆ Kordas
+
+ Adrian Ber
+