SquirrelJME/SquirrelJME

View on GitHub
modules/cldc-compact/src/main/java/cc/squirreljme/runtime/cldc/util/IntegerList.java

Summary

Maintainability
A
0 mins
Test Coverage
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the Mozilla Public License Version 2.0.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.cldc.util;

import cc.squirreljme.runtime.cldc.debug.Debugging;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.RandomAccess;

/**
 * This is a list of integers which is backed by a primitive array rather than
 * boxed types.
 *
 * @since 2017/11/26
 */
public final class IntegerList
    extends AbstractList<Integer>
    implements RandomAccess
{
    /** The array growing size. */
    private static final int _GROW_SIZE =
        8;
    
    /** The internal integer list. */
    private volatile int[] _values;
    
    /** The number of values in the list. */
    private volatile int _size;
    
    /**
     * Initializes an empty list.
     *
     * @since 2017/11/26
     */
    public IntegerList()
    {
    }
    
    /**
     * Initializes a list using the given collection of integers.
     *
     * @param __v The collection to source values from.
     * @throws NullPointerException On null arguments.
     * @since 2017/11/26
     */
    public IntegerList(Collection<Integer> __v)
        throws NullPointerException
    {
        if (__v == null)
            throw new NullPointerException("NARG");
        
        // Iterate through collections
        int n = __v.size(), i = 0;
        int[] values = new int[n];
        for (Integer v : __v)
            values[i++] = v;
        
        // Set
        this._values = values;
        this._size = n;
    }
    
    /**
     * Initializes a list using the given integer values from an array.
     *
     * @param __v The array of integers to use for values.
     * @throws NullPointerException On null arguments.
     * @since 2017/11/26
     */
    public IntegerList(int... __v)
        throws NullPointerException
    {
        if (__v == null)
            throw new NullPointerException("NARG");
        
        // Defensive copy
        __v = __v.clone();
        
        // Simple set
        this._values = __v;
        this._size = __v.length;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public boolean add(Integer __a)
        throws NullPointerException
    {
        if (__a == null)
            throw new NullPointerException("NARG");
        
        return this.addInteger(__a);
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public void add(int __i, Integer __v)
        throws NullPointerException
    {
        if (__v == null)
            throw new NullPointerException("NARG");
        
        this.addInteger(__i, __v);
    }
    
    /**
     * Adds the specified integer to the list.
     *
     * @param __v The value to add.
     * @return {@code true} if the list has changed.
     * @since 2017/11/26
     */
    public boolean addInteger(int __v)
    {
        this.addInteger(this._size, __v);
        return true;
    }
    
    /**
     * Adds the specified integer to the list at the specified position.
     *
     * @param __i The index to add the value at.
     * @param __v The value to add.
     * @throws IndexOutOfBoundsException If the index to add it outside of
     * the array bounds.
     * @since 2017/11/26
     */
    public void addInteger(int __i, int __v)
        throws IndexOutOfBoundsException
    {
        if (__i < 0 || __i > this._size)
            throw new IndexOutOfBoundsException("IOOB");
        
        // Existing values
        boolean realloced = false;
        int[] values = this._values;
        int nvalues = (values == null ? 0 : values.length),
            size = this._size;
        
        // Need a larger array?
        if ((realloced = (size + 1 > nvalues)))
            if (values == null)
                values = new int[IntegerList._GROW_SIZE];
            else
                values = Arrays.copyOf(values,
                    nvalues + IntegerList._GROW_SIZE);
        
        // Move all values up
        for (int o = size; o > __i; o++)
            values[o] = values[o - 1];
        
        // Set this index
        values[__i] = __v;
        size++;
        
        // Store new values
        if (realloced)
            this._values = values;
        this._size = size;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public void clear()
    {
        this._values = null;
        this._size = 0;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public boolean contains(Object __a)
    {
        // Only contains integers
        if (!(__a instanceof Integer))
            return false;
        
        return this.containsInteger((Integer)__a);
    }
    
    /**
     * Checks if the list contains the specified integer.
     *
     * @param __v The value to check.
     * @return {@code true} if the list contains the given integer.
     * @since 2017/11/26
     */
    public boolean containsInteger(int __v)
    {
        return this.indexOfInteger(__v) >= 0;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public Integer get(int __i)
        throws IndexOutOfBoundsException
    {
        return this.getInteger(__i);
    }
    
    /**
     * Obtains the integer at the given index.
     *
     * @param __i The index to get.
     * @return The integer at the given index.
     * @throws IndexOutOfBoundsException If the index is not within bounds.
     * @since 2017/11/26
     */
    public int getInteger(int __i)
        throws IndexOutOfBoundsException
    {
        if (__i < 0 || __i >= this._size)
            throw new IndexOutOfBoundsException("IOOB");
        
        return this._values[__i];
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public int indexOf(Object __a)
    {
        // Will never contain non-integers
        if (!(__a instanceof Integer))
            return -1;
        
        return this.indexOfInteger((Integer)__a);
    }
    
    /**
     * Returns the index which contains the specified integer.
     *
     * @param __v The value to search for.
     * @return The index of the specified integer or {@code -1} if the list
     * contains no such value.
     * @since 2017/11/26
     */
    public int indexOfInteger(int __v)
    {
        int[] values = this._values;
        for (int i = 0, n = values.length; i < n; i++)
            if (values[i] == __v)
                return i;
        return -1;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public boolean isEmpty()
    {
        return this._size == 0;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public int lastIndexOf(Object __a)
    {
        // Will never contain non-integers
        if (!(__a instanceof Integer))
            return -1;
        
        return this.lastIndexOfInteger((Integer)__a);
    }
    
    /**
     * Returns the index which contains the specified integer starting from
     * the end of the list.
     *
     * @param __v The value to search for.
     * @return The index of the specified integer or {@code -1} if the list
     * contains no such value.
     * @since 2017/11/26
     */
    public int lastIndexOfInteger(int __v)
    {
        int[] values = this._values;
        for (int n = values.length, i = n - 1; i >= 0; i--)
            if (values[i] == __v)
                return i;
        return -1;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public boolean remove(Object __a)
    {
        // Will never contain non-integers
        if (!(__a instanceof Integer))
            return false;
        
        int dx = this.indexOf(__a);
        if (dx < 0)
            return false;
        
        this.remove(dx);
        return true;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public Integer remove(int __a)
    {
        throw Debugging.todo();
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public Integer set(int __i, Integer __v)
        throws NullPointerException
    {
        if (__v == null)
            throw new NullPointerException("NARG");
        
        return this.setInteger(__i, __v);
    }
    
    /**
     * Sets the integer at the specified index to the given value.
     *
     * @param __i The index to set.
     * @param __v The value to set.
     * @return The old value.
     * @throws IndexOutOfBoundsException If the index is not within bounds.
     * @since 2017/11/26
     */
    public int setInteger(int __i, int __v)
        throws IndexOutOfBoundsException
    {
        if (__i < 0 || __i >= this._size)
            throw new IndexOutOfBoundsException("IOOB");
        
        int[] values = this._values;
        int rv = values[__i];
        values[__i] = __v;
        return rv;
    }
    
    /**
     * {@inheritDoc}
     * @since 2017/11/26
     */
    @Override
    public int size()
    {
        return this._size;
    }
    
    /**
     * Converts the integer list to an integer array.
     *
     * @return This list as an integer array.
     * @since 2017/11/26
     */
    public int[] toIntegerArray()
    {
        int[] values = this._values;
        int size = this._size;
        
        // Values would not be allocated
        if (size == 0)
            return new int[0];
        
        // Copy values
        int[] rv = new int[size];
        System.arraycopy(values, 0, rv, 0, size);
        return rv;
    }
}