/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
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;
}
}