Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7abdcf1e authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka
Browse files

Implement ResizableIntArray.fill

Change-Id: I570641bc2f32d016c247db6c065a138d8235ab8c
parent 19ac19e5
Loading
Loading
Loading
Loading
+49 −20
Original line number Diff line number Diff line
@@ -28,38 +28,49 @@ public class ResizableIntArray {
    }

    public int get(final int index) {
        if (index < 0 || index >= mLength) {
            throw new ArrayIndexOutOfBoundsException("length=" + mLength + "; index=" + index);
        }
        if (index < mLength) {
            return mArray[index];
        }
        throw new ArrayIndexOutOfBoundsException("length=" + mLength + "; index=" + index);
    }

    public void add(final int index, final int val) {
        if (mLength < index + 1) {
        if (index < mLength) {
            mArray[index] = val;
        } else {
            mLength = index;
            add(val);
        } else {
            mArray[index] = val;
        }
    }

    public void add(final int val) {
        final int nextLength = mLength + 1;
        ensureCapacity(nextLength);
        mArray[mLength] = val;
        mLength = nextLength;
        final int currentLength = mLength;
        ensureCapacity(currentLength + 1);
        mArray[currentLength] = val;
        mLength = currentLength + 1;
    }

    /**
     * Calculate the new capacity of {@code mArray}.
     * @param minimumCapacity the minimum capacity that the {@code mArray} should have.
     * @return the new capacity that the {@code mArray} should have. Returns zero when there is no
     * need to expand {@code mArray}.
     */
    private int calculateCapacity(final int minimumCapacity) {
        final int currentCapcity = mArray.length;
        if (currentCapcity < minimumCapacity) {
            final int nextCapacity = currentCapcity * 2;
            // The following is the same as return Math.max(minimumCapacity, nextCapacity);
            return minimumCapacity > nextCapacity ? minimumCapacity : nextCapacity;
        }
        return 0;
    }

    private void ensureCapacity(final int minimumCapacity) {
        if (mArray.length < minimumCapacity) {
            final int nextCapacity = mArray.length * 2;
            // The following is the same as newLength =
            // Math.max(minimumCapacity, nextCapacity);
            final int newLength = minimumCapacity > nextCapacity
                    ? minimumCapacity
                    : nextCapacity;
        final int newCapacity = calculateCapacity(minimumCapacity);
        if (newCapacity > 0) {
            // TODO: Implement primitive array pool.
            mArray = Arrays.copyOf(mArray, newLength);
            mArray = Arrays.copyOf(mArray, newCapacity);
        }
    }

@@ -89,17 +100,35 @@ public class ResizableIntArray {
    }

    public void copy(final ResizableIntArray ip) {
        // TODO: Avoid useless coping of values.
        ensureCapacity(ip.mLength);
        final int newCapacity = calculateCapacity(ip.mLength);
        if (newCapacity > 0) {
            // TODO: Implement primitive array pool.
            mArray = new int[newCapacity];
        }
        System.arraycopy(ip.mArray, 0, mArray, 0, ip.mLength);
        mLength = ip.mLength;
    }

    public void append(final ResizableIntArray src, final int startPos, final int length) {
        if (length == 0) {
            return;
        }
        final int currentLength = mLength;
        final int newLength = currentLength + length;
        ensureCapacity(newLength);
        System.arraycopy(src.mArray, startPos, mArray, currentLength, length);
        mLength = newLength;
    }

    public void fill(final int value, final int startPos, final int length) {
        if (startPos < 0 || length < 0) {
            throw new IllegalArgumentException("startPos=" + startPos + "; length=" + length);
        }
        final int endPos = startPos + length;
        ensureCapacity(endPos);
        Arrays.fill(mArray, startPos, endPos, value);
        if (mLength < endPos) {
            mLength = endPos;
        }
    }
}
+89 −8
Original line number Diff line number Diff line
@@ -37,8 +37,12 @@ public class ResizableIntArrayTests extends AndroidTestCase {
        for (int i = 0; i < limit; i++) {
            src.add(i);
            assertEquals("length after add " + i, i + 1, src.getLength());
            if (i == DEFAULT_CAPACITY) array2 = src.getPrimitiveArray();
            if (i == DEFAULT_CAPACITY * 2) array3 = src.getPrimitiveArray();
            if (i == DEFAULT_CAPACITY) {
                array2 = src.getPrimitiveArray();
            }
            if (i == DEFAULT_CAPACITY * 2) {
                array3 = src.getPrimitiveArray();
            }
            if (i < DEFAULT_CAPACITY) {
                assertSame("array after add " + i, array, src.getPrimitiveArray());
            } else if (i < DEFAULT_CAPACITY * 2) {
@@ -110,7 +114,9 @@ public class ResizableIntArrayTests extends AndroidTestCase {
        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
            src.add(i);
            assertEquals("length after add " + i, i + 1, src.getLength());
            if (i == smallerLength) array3 = src.getPrimitiveArray();
            if (i == smallerLength) {
                array3 = src.getPrimitiveArray();
            }
            if (i < smallerLength) {
                assertSame("array after add " + i, array2, src.getPrimitiveArray());
            } else if (i < smallerLength * 2) {
@@ -133,11 +139,13 @@ public class ResizableIntArrayTests extends AndroidTestCase {
        assertEquals("length after larger setLength", largerLength, src.getLength());
        assertNotSame("array after larger setLength", array, array2);
        assertEquals("array length after larger setLength", largerLength, array2.length);
        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
            assertEquals("value at " + i, i, src.get(i));
        for (int i = 0; i < largerLength; i++) {
            final int v = src.get(i);
            if (i < DEFAULT_CAPACITY) {
                assertEquals("value at " + i, i, v);
            } else {
                assertEquals("value at " + i, 0, v);
            }
        for (int i = DEFAULT_CAPACITY; i < largerLength; i++) {
            assertEquals("value at " + i, 0, src.get(i));
        }

        final int smallerLength = DEFAULT_CAPACITY / 2;
@@ -236,6 +244,79 @@ public class ResizableIntArrayTests extends AndroidTestCase {
                src.getPrimitiveArray(), 0, dst.getPrimitiveArray(), dstLen + srcLen, srcLen);
    }

    public void testFill() {
        final int srcLen = DEFAULT_CAPACITY;
        final ResizableIntArray src = new ResizableIntArray(srcLen);
        for (int i = 0; i < srcLen; i++) {
            src.add(i);
        }
        final int[] array = src.getPrimitiveArray();

        final int startPos = srcLen / 3;
        final int length = srcLen / 3;
        final int endPos = startPos + length;
        assertTrue(startPos >= 1);
        final int value = 123;
        try {
            src.fill(value, -1, length);
            fail("fill from -1 shouldn't succeed");
        } catch (IllegalArgumentException e) {
            // success
        }
        try {
            src.fill(value, startPos, -1);
            fail("fill negative length shouldn't succeed");
        } catch (IllegalArgumentException e) {
            // success
        }

        src.fill(value, startPos, length);
        assertEquals("length after fill", srcLen, src.getLength());
        assertSame("array after fill", array, src.getPrimitiveArray());
        for (int i = 0; i < srcLen; i++) {
            final int v = src.get(i);
            if (i >= startPos && i < endPos) {
                assertEquals("new values after fill at " + i, value, v);
            } else {
                assertEquals("unmodified values after fill at " + i, i, v);
            }
        }

        final int length2 = srcLen * 2 - startPos;
        final int largeEnd = startPos + length2;
        assertTrue(largeEnd > srcLen);
        final int value2 = 456;
        src.fill(value2, startPos, length2);
        assertEquals("length after large fill", largeEnd, src.getLength());
        assertNotSame("array after large fill", array, src.getPrimitiveArray());
        for (int i = 0; i < largeEnd; i++) {
            final int v = src.get(i);
            if (i >= startPos && i < largeEnd) {
                assertEquals("new values after large fill at " + i, value2, v);
            } else {
                assertEquals("unmodified values after large fill at " + i, i, v);
            }
        }

        final int startPos2 = largeEnd + length2;
        final int endPos2 = startPos2 + length2;
        final int value3 = 789;
        src.fill(value3, startPos2, length2);
        assertEquals("length after disjoint fill", endPos2, src.getLength());
        for (int i = 0; i < endPos2; i++) {
            final int v = src.get(i);
            if (i >= startPos2 && i < endPos2) {
                assertEquals("new values after disjoint fill at " + i, value3, v);
            } else if (i >= startPos && i < largeEnd) {
                assertEquals("unmodified values after disjoint fill at " + i, value2, v);
            } else if (i < startPos) {
                assertEquals("unmodified values after disjoint fill at " + i, i, v);
            } else {
                assertEquals("gap values after disjoint fill at " + i, 0, v);
            }
        }
    }

    private static void assertArrayEquals(String message, int[] expecteds, int expectedPos,
            int[] actuals, int actualPos, int length) {
        if (expecteds == null && actuals == null) {