Vector.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024, 2026 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package avt.util;

import avt.lang.array.*;
import platform.independent.streamformat.*;

public class Vector(Object, MutableDataHolder, DataHolder, Cloneable, Measureable, MutableMeasureable, ResizeableObjectArray, MutableObjectArray, ObjectArray)
{
    protected int fldLength;
    protected Object[] fldElements;

    public () { fldElements = new Object[0x3f]; }

    public (int initialCapacity) { fldElements = new Object[initialCapacity <= 1 ? 1 : initialCapacity]; }

    protected (int length, Object[] elements) {
        fldLength = length;
        fldElements = elements;
    }

    public String toString() {
        StringBuilder result = (new StringBuilder()).append("[ ");
        for(Object[] elements = fldElements, int length = fldLength, int index = 0; index < length; index++)
        {
            if(index > 0) result.append(", ");
            result.append(elements[index]);
        }
        return result.append(" ]").toString();
    }

    public void clear() { setLength(0); }

    public boolean isEmpty() { return fldLength <= 0; }

    public Vector clone() { return new Vector(fldLength, fldElements.clone()); }

    public void getElements(int beginIndex, int endIndex, MutableObjectArray dst, int offset) {
        checkBounds(beginIndex, endIndex);
        if(dst == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "dst" }));
        }
        int length = endIndex - beginIndex;
        Array.checkBounds(dst, offset, length);
        if(dst instanceof Vector) dst = ((Vector) dst).fldElements;
        if(dst instanceof Object[])
        {
            Array.copyRefs(fldElements, beginIndex, (Object[]) dst, offset, length);
            return;
        }
        for(Object[] elements = fldElements; length-- > 0; ) dst[offset++] = elements[beginIndex++];
    }

    public void copyInto(MutableObjectArray dst, int offset) {
        if(dst == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "dst" }));
        }
        int length = fldLength;
        Array.checkBounds(dst, offset, length);
        if(dst instanceof Vector) dst = ((Vector) dst).fldElements;
        if(dst instanceof Object[])
        {
            Array.copyRefs(fldElements, 0, (Object[]) dst, offset, length);
            return;
        }
        for(Object[] elements = fldElements, int index = 0; length-- > 0; ) dst[offset++] = elements[index++];
    }

    public void ensureCapacity(int minCapacity) {
        if(minCapacity < 0) return;
        Object[] elements = fldElements;
        int curCapacity = elements.length;
        if(minCapacity <= curCapacity) return;
        int newCapacity = curCapacity >= (Int.MAX_VALUE >> 1) ? Int.MAX_VALUE : curCapacity << 1 | 1;
        if(minCapacity > newCapacity) newCapacity = minCapacity;
        Array.copy(elements, 0, fldElements = new Object[newCapacity], 0, curCapacity);
    }

    public boolean contains(Object obj) {
        if(obj == null)
        {
            int length = fldLength;
            return length > 0 && Array.indexOf(null, fldElements, 0, length) >= 0;
        }
        for(Object[] elements = fldElements, int index = fldLength; index-- > 0; ) if(obj.equals(elements[index])) return true;
        return false;
    }

    public int indexOf(Object obj, int startFromIndex) {
        int length = fldLength;
        if(startFromIndex < 0) startFromIndex = 0;
        if(startFromIndex < length)
        {
            if(obj == null) return Array.indexOf(null, fldElements, startFromIndex, length - startFromIndex);
            for(Object[] elements = fldElements, int index = startFromIndex; index < length; index++) if(obj.equals(elements[index])) return index;
        }
        return -1;
    }

    public int indexOfNon(Object obj, int startFromIndex) {
        int length = fldLength;
        if(startFromIndex < 0) startFromIndex = 0;
        if(startFromIndex < length)
        {
            if(obj == null) return Array.indexOfNon(null, fldElements, startFromIndex, length - startFromIndex);
            for(Object[] elements = fldElements, int index = startFromIndex; index < length; index++) if(!obj.equals(elements[index])) return index;
        }
        return -1;
    }

    public int lastIndexOf(Object obj, int startFromIndex) {
        int length = fldLength;
        if(startFromIndex >= length) startFromIndex = length - 1;
        if(startFromIndex >= 0)
        {
            if(obj == null) return Array.lastIndexOf(null, fldElements, startFromIndex, 0);
            for(Object[] elements = fldElements, int index = startFromIndex; index >= 0; index--) if(obj.equals(elements[index])) return index;
        }
        return -1;
    }

    public int lastIndexOfNon(Object obj, int startFromIndex) {
        int length = fldLength;
        if(startFromIndex >= length) startFromIndex = length - 1;
        if(startFromIndex >= 0)
        {
            if(obj == null) return Array.lastIndexOfNon(null, fldElements, startFromIndex, 0);
            for(Object[] elements = fldElements, int index = startFromIndex; index >= 0; index--) if(!obj.equals(elements[index])) return index;
        }
        return -1;
    }

    public int insert(int index, Object src) { return insertElement(index, src); }

    public int inserta(int index, ObjectArray src) {
        if(src == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
        }
        return insertArray(index, src, 0, src.length);
    }

    public int inserta(int index, ObjectArray src, int offset, int length) {
        if(src == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
        }
        Array.checkBounds(src, offset, length);
        return insertArray(index, src, offset, length);
    }

    public int insertf(int index, String form, ObjectArray data) { return insertElement(index, String.format(form, data)); }

    public int replace(int beginIndex, int endIndex, Object src) {
        checkBounds(beginIndex, endIndex);
        return replaceElement(beginIndex, endIndex, src);
    }

    public int replacea(int beginIndex, int endIndex, ObjectArray src) {
        checkBounds(beginIndex, endIndex);
        if(src == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
        }
        return replaceArray(beginIndex, endIndex, src, 0, src.length);
    }

    public int replacea(int beginIndex, int endIndex, ObjectArray src, int offset, int length) {
        checkBounds(beginIndex, endIndex);
        if(src == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
        }
        Array.checkBounds(src, offset, length);
        return replaceArray(beginIndex, endIndex, src, offset, length);
    }

    public int replacef(int beginIndex, int endIndex, String form, ObjectArray data) {
        checkBounds(beginIndex, endIndex);
        return replaceElement(beginIndex, endIndex, String.format(form, data));
    }

    public Object[] toObjectArray() {
        int length = fldLength;
        Object[] result = new Object[length];
        Array.copy(fldElements, 0, result, 0, length);
        return result;
    }

    public Vector append(Object src) {
        appendElement(src);
        return this;
    }

    public Vector appenda(ObjectArray src) {
        if(src == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
        }
        appendArray(src, 0, src.length);
        return this;
    }

    public Vector appenda(ObjectArray src, int offset, int length) {
        if(src == null)
        {
            throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
        }
        Array.checkBounds(src, offset, length);
        appendArray(src, offset, length);
        return this;
    }

    public Vector appendf(String form, ObjectArray data) {
        appendElement(String.format(form, data));
        return this;
    }

    public Vector reverse() {
        reverseElements();
        return this;
    }

    public Vector delete(int index) {
        checkIndex(index);
        deletePortion(index, index + 1);
        return this;
    }

    public Vector delete(int beginIndex, int endIndex) {
        checkBounds(beginIndex, endIndex);
        deletePortion(beginIndex, endIndex);
        return this;
    }

    public Vector trimToLength() {
        deleteTails(0, fldLength, true);
        return this;
    }

    public Vector trimToSubvector(int beginIndex) {
        int endIndex = fldLength;
        checkBounds(beginIndex, endIndex);
        deleteTails(beginIndex, endIndex, true);
        return this;
    }

    public Vector trimToSubvector(int beginIndex, int endIndex) {
        checkBounds(beginIndex, endIndex);
        deleteTails(beginIndex, endIndex, true);
        return this;
    }

    public Vector subvector(int beginIndex) {
        int endIndex = fldLength;
        checkBounds(beginIndex, endIndex);
        deleteTails(beginIndex, endIndex, false);
        return this;
    }

    public Vector subvector(int beginIndex, int endIndex) {
        checkBounds(beginIndex, endIndex);
        deleteTails(beginIndex, endIndex, false);
        return this;
    }

    public Enumeration enumerate() { return new ArrayEnumeration(fldElements, 0, fldLength); }

    public Enumeration enumerateBackward() { return new ArrayEnumeration(fldElements, 0, fldLength, true); }

    public final int indexOf(Object obj) { return indexOf(obj, 0); }

    public final int indexOfNon(Object obj) { return indexOfNon(obj, 0); }

    public final int lastIndexOf(Object obj) { return lastIndexOf(obj, Int.MAX_VALUE); }

    public final int lastIndexOfNon(Object obj) { return lastIndexOfNon(obj, Int.MAX_VALUE); }

    public int length { read = fldLength, write = setLength }

    public int capacity { read = fldElements.length }

    public void operator []=(int index, Object component) {
        checkIndex(index);
        setElement(index, component);
    }

    public Object operator [](int index) {
        checkIndex(index);
        return fldElements[index];
    }

    protected void checkIndex(int index) {
        if(index < 0 || index >= fldLength)
        {
            throw new VectorIndexOutOfBoundsException(package.getResourceString("out-of-bounds.vector-index"));
        }
    }

    protected void checkBounds(int beginIndex, int endIndex) {
        int length = fldLength;
        if((beginIndex | endIndex) < 0 || beginIndex > length || endIndex > length || beginIndex > endIndex)
        {
            throw new VectorIndexOutOfBoundsException(package.getResourceString("out-of-bounds.vector-index"));
        }
    }

    protected void reverseElements() {
        for(Object[] elements = fldElements, int length = fldLength, int eli = length >> 1, int elj = length - eli; eli-- > 0; elj++)
        {
            Object obj = elements[eli];
            elements[eli] = elements[elj];
            elements[elj] = obj;
        }
    }

    protected void setLength(int newLength) {
        if(newLength < 0)
        {
            throw new NegativeArrayLengthException(package.getResourceString("negative-array-length"));
        }
        int curLength = fldLength;
        Object[] elements = fldElements;
        if(newLength > elements.length) elements = madeLarger(newLength);
        if(newLength > curLength) Array.fill(elements, curLength, newLength - curLength, null);
        fldLength = newLength;
    }

    protected void setElement(int index, Object src) { fldElements[index] = src; }

    protected void deletePortion(int beginIndex, int endIndex) {
        int count = endIndex - beginIndex;
        int curLength = fldLength;
        int newLength = curLength - count;
        if(count > 0)
        {
            Object[] elements = fldElements;
            Array.copy(elements, endIndex, elements, beginIndex, curLength - endIndex);
        }
        fldLength = newLength;
    }

    protected void deleteTails(int beginIndex, int endIndex, boolean isTrim) {
        int newLength = endIndex - beginIndex;
        Object[] elements = fldElements;
        if(!isTrim)
        {
            if(beginIndex > 0) Array.copy(elements, beginIndex, elements, 0, newLength);
            fldLength = newLength;
            return;
        }
        if(beginIndex > 0 || endIndex < elements.length)
        {
            Array.copy(elements, beginIndex, fldElements = new Object[newLength], 0, newLength);
            fldLength = newLength;
        }
    }

    protected void appendElement(Object src) {
        int length = fldLength;
        Object[] elements = madeLarger(length + 1);
        elements[length++] = src;
        fldLength = length;
    }

    protected void appendArray(ObjectArray src, int offset, int length) {
        int curLength = fldLength;
        int newLength = curLength + length;
        Object[] elements = madeLarger(newLength);
        if(src instanceof Vector) src = ((Vector) src).fldElements;
        if(src instanceof Object[])
        {
            Array.copy((Object[]) src, offset, elements, curLength, length);
        } else
        {
            while(length-- > 0) elements[curLength++] = src[offset++];
        }
        fldLength = newLength;
    }

    protected int insertElement(int index, Object src) {
        int length = fldLength;
        Object[] elements = madeLarger(length + 1);
        if(index < 0) index = 0;
        if(index > length) index = length;
        int result = index + 1;
        Array.copy(elements, index, elements, result, length++ - index);
        elements[index] = src;
        fldLength = length;
        return result;
    }

    protected int insertArray(int index, ObjectArray src, int offset, int length) {
        int curLength = fldLength;
        int newLength = curLength + length;
        Object[] elements = madeLarger(newLength);
        if(index < 0) index = 0;
        if(index > curLength) index = curLength;
        int result = index + length;
        Array.copy(elements, index, elements, result, curLength - index);
        if(src instanceof Vector) src = ((Vector) src).fldElements;
        if(src instanceof Object[])
        {
            Array.copy((Object[]) src, offset, elements, index, length);
        } else
        {
            while(length-- > 0) elements[index++] = src[offset++];
        }
        fldLength = newLength;
        return result;
    }

    protected int replaceElement(int beginIndex, int endIndex, Object src) {
        int result = beginIndex + 1;
        int curLength = fldLength;
        int newLength = curLength - endIndex + result;
        Object[] elements = madeLarger(newLength);
        Array.copy(elements, endIndex, elements, result, curLength - endIndex);
        elements[beginIndex] = src;
        fldLength = newLength;
        return result;
    }

    protected int replaceArray(int beginIndex, int endIndex, ObjectArray src, int offset, int length) {
        int result = beginIndex + length;
        int curLength = fldLength;
        int newLength = curLength - endIndex + result;
        Object[] elements = madeLarger(newLength);
        Array.copy(elements, endIndex, elements, result, curLength - endIndex);
        if(src instanceof Vector) src = ((Vector) src).fldElements;
        if(src instanceof Object[])
        {
            Array.copy((Object[]) src, offset, elements, beginIndex, length);
        } else
        {
            while(length-- > 0) elements[beginIndex++] = src[offset++];
        }
        fldLength = newLength;
        return result;
    }

    protected Object[] madeLarger(int minCapacity) {
        if(minCapacity < 0)
        {
            throw new BufferTooLargeError(package.getResourceString("!error.buffer-too-large"));
        }
        Object[] elements = fldElements;
        int curCapacity = elements.length;
        if(minCapacity > curCapacity)
        {
            int newCapacity = curCapacity >= (Int.MAX_VALUE >> 1) ? Int.MAX_VALUE : curCapacity << 1 | 1;
            if(minCapacity > newCapacity) newCapacity = minCapacity;
            Array.copy(elements, 0, fldElements = elements = new Object[newCapacity], 0, curCapacity);
        }
        return elements;
    }
}