/*
	Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
	и других спецификаций для функционирования компактных приложений на языке
	Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

	Copyright © 2016, 2019 Малик Разработчик

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

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

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


package java.util;

public class Vector extends Object
{
	private class Enumerator extends Object
			implements Enumeration
	{
		private int index;

		Enumerator()
		{
		}

		public boolean hasMoreElements()
		{
			return index < (Vector.this).elementCount;
		}

		public Object nextElement()
		{
			int i;
			int error;
			Vector thisVector;
			Object result;
			error = 0;
			synchronized((thisVector = Vector.this).getMonitor())
			{
				label0:
				{
					if((i = index) >= thisVector.elementCount)
					{
						error = 1;
						result = null;
						break label0;
					}
					index = i + 1;
					result = thisVector.elementData[i];
				}
			}
			if(error == 1)
			{
				throw new NoSuchElementException("Vector: " +
						"больше не осталось элементов для перечисления.");
			}
			return result;
		}
	}

	protected int capacityIncrement;
	protected int elementCount;
	protected Object[] elementData;
	private Object lock;

	public Vector()
	{
		this(15, 0);
	}

	public Vector(int initialCapacity)
	{
		this(initialCapacity, 0);
	}

	public Vector(int initialCapacity, int capacityIncrement)
	{
		if(initialCapacity < 0)
		{
			throw new IllegalArgumentException("Vector: " +
					"параметр initialCapacity не может быть отрицательным.");
		}
		this.capacityIncrement = capacityIncrement;
		this.elementData = new Object[initialCapacity];
		this.lock = new Object();
	}

	public String toString()
	{
		int i;
		int c;
		Object[] d;
		StringBuffer result = new StringBuffer('[');
		synchronized(lock)
		{
			c = elementCount - 1;
			d = elementData;
			for(i = 0; i <= c; i++)
			{
				result.append(d[i]);
				if(i < c)
				{
					result.append(", ");
				}
			}
		}
		return result.append(']').toString();
	}

	public void trimToSize()
	{
		int c;
		Object[] d;
		synchronized(lock)
		{
			if((c = elementCount) < (d = elementData).length)
			{
				Array.copy(d, 0, elementData = new Object[c], 0, c);
			}
		}
	}

	public void copyInto(Object[] dst)
	{
		int i;
		Object[] d;
		if(dst == null)
		{
			throw new NullPointerException("Vector.copyInto: " +
					"параметр dst равен нулевой ссылке.");
		}
		synchronized(lock)
		{
			for(d = elementData, i = elementCount; i-- > 0; dst[i] = d[i]);
		}
	}

	public void ensureCapacity(int minimumCapacity)
	{
		synchronized(lock)
		{
			if(minimumCapacity > elementData.length)
			{
				ensureCapacityHelper(minimumCapacity);
			}
		}
	}

	public void removeAllElements()
	{
		int i;
		Object[] d;
		synchronized(lock)
		{
			for(d = elementData, i = elementCount; i-- > 0; d[i] = null);
			elementCount = 0;
		}
	}

	public void removeElementAt(int index)
	{
		int i;
		int c;
		int error;
		Object[] d;
		error = 0;
		synchronized(lock)
		{
			label0:
			{
				if(index > (c = elementCount - 1) || index < 0)
				{
					error = 1;
					break label0;
				}
				d = elementData;
				if((i = c - index) > 0)
				{
					Array.copy(d, index + 1, d, index, i);
				}
				d[elementCount = c] = null;
			}
		}
		if(error == 1)
		{
			throw new ArrayIndexOutOfBoundsException(index);
		}
	}

	public void insertElementAt(Object element, int index)
	{
		int i;
		int c;
		int error;
		Object[] d;
		error = 0;
		synchronized(lock)
		{
			label0:
			{
				if(index > (c = elementCount) || index < 0)
				{
					error = 1;
					break label0;
				}
				if(c == (d = elementData).length)
				{
					d = ensureCapacityHelper(c + 1);
				}
				if((i = c - index) > 0)
				{
					Array.copy(d, index, d, index + 1, i);
				}
				d[index] = element;
				elementCount = c + 1;
			}
		}
		if(error == 1)
		{
			throw new ArrayIndexOutOfBoundsException(index);
		}
	}

	public void addElement(Object element)
	{
		int c;
		Object[] d;
		synchronized(lock)
		{
			if((c = elementCount) == (d = elementData).length)
			{
				d = ensureCapacityHelper(c + 1);
			}
			d[c] = element;
			elementCount = c + 1;
		}
	}

	public void setElementAt(Object element, int index)
	{
		int error = 0;
		synchronized(lock)
		{
			label0:
			{
				if(index >= elementCount || index < 0)
				{
					error = 1;
					break label0;
				}
				elementData[index] = element;
			}
		}
		if(error == 1)
		{
			throw new ArrayIndexOutOfBoundsException(index);
		}
	}

	public void setSize(int newSize)
	{
		int i;
		int c;
		Object[] d;
		synchronized(lock)
		{
			if(newSize > (d = elementData).length)
			{
				d = ensureCapacityHelper(newSize);
			}
			if(newSize >= (c = elementCount))
			{
				for(i = newSize; i-- > c; d[i] = null);
			} else
			{
				for(i = c; i-- > newSize; d[i] = null);
			}
			elementCount = newSize;
		}
	}

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

	public boolean contains(Object element)
	{
		boolean result;
		int i;
		Object[] d;
		synchronized(lock)
		{
			label0:
			{
				d = elementData;
				if(element == null)
				{
					for(i = elementCount; i-- > 0; )
					{
						if(d[i] != null)
						{
							continue;
						}
						result = true;
						break label0;
					}
				} else
				{
					for(i = elementCount; i-- > 0; )
					{
						if(!element.equals(d[i]))
						{
							continue;
						}
						result = true;
						break label0;
					}
				}
				result = false;
			}
		}
		return result;
	}

	public boolean removeElement(Object element)
	{
		boolean result;
		int index;
		int i;
		int c;
		Object[] d;
		synchronized(lock)
		{
			label0:
			{
				label1:
				{
					c = elementCount;
					d = elementData;
					if(element == null)
					{
						for(i = 0; i < c; i++)
						{
							if(d[i] != null)
							{
								continue;
							}
							result = true;
							break label1;
						}
					} else
					{
						for(i = 0; i < c; i++)
						{
							if(!element.equals(d[i]))
							{
								continue;
							}
							result = true;
							break label1;
						}
					}
					result = false;
					break label0;
				}
				if((i = (--c) - (index = i)) > 0)
				{
					Array.copy(d, index + 1, d, index, i);
				}
				d[elementCount = c] = null;
			}
		}
		return result;
	}

	public int capacity()
	{
		return elementData.length;
	}

	public int size()
	{
		return elementCount;
	}

	public int indexOf(Object element)
	{
		int result;
		int i;
		int c;
		Object[] d;
		synchronized(lock)
		{
			label0:
			{
				c = elementCount;
				d = elementData;
				if(element == null)
				{
					for(i = 0; i < c; i++)
					{
						if(d[i] != null)
						{
							continue;
						}
						result = i;
						break label0;
					}
				} else
				{
					for(i = 0; i < c; i++)
					{
						if(!element.equals(d[i]))
						{
							continue;
						}
						result = i;
						break label0;
					}
				}
				result = -1;
			}
		}
		return result;
	}

	public int indexOf(Object element, int fromIndex)
	{
		int result;
		int i;
		int c;
		Object[] d;
		if(fromIndex < 0)
		{
			fromIndex = 0;
		}
		synchronized(lock)
		{
			label0:
			{
				c = elementCount;
				d = elementData;
				if(element == null)
				{
					for(i = fromIndex; i < c; i++)
					{
						if(d[i] != null)
						{
							continue;
						}
						result = i;
						break label0;
					}
				} else
				{
					for(i = fromIndex; i < c; i++)
					{
						if(!element.equals(d[i]))
						{
							continue;
						}
						result = i;
						break label0;
					}
				}
				result = -1;
			}
		}
		return result;
	}

	public int lastIndexOf(Object element)
	{
		int result;
		int i;
		Object[] d;
		synchronized(lock)
		{
			label0:
			{
				d = elementData;
				if(element == null)
				{
					for(i = elementCount; i-- > 0; )
					{
						if(d[i] != null)
						{
							continue;
						}
						result = i;
						break label0;
					}
				} else
				{
					for(i = elementCount; i-- > 0; )
					{
						if(!element.equals(d[i]))
						{
							continue;
						}
						result = i;
						break label0;
					}
				}
				result = -1;
			}
		}
		return result;
	}

	public int lastIndexOf(Object element, int fromIndex)
	{
		int i;
		int result;
		int error;
		Object[] d;
		error = 0;
		synchronized(lock)
		{
			label0:
			{
				if((fromIndex++) >= elementCount)
				{
					error = 1;
					result = 0;
					break label0;
				}
				d = elementData;
				if(element == null)
				{
					for(i = fromIndex; i-- > 0; )
					{
						if(d[i] != null)
						{
							continue;
						}
						result = i;
						break label0;
					}
				} else
				{
					for(i = fromIndex; i-- > 0; )
					{
						if(!element.equals(d[i]))
						{
							continue;
						}
						result = i;
						break label0;
					}
				}
				result = -1;
			}
		}
		if(error == 1)
		{
			throw new ArrayIndexOutOfBoundsException(fromIndex);
		}
		return result;
	}

	public Object firstElement()
	{
		int error;
		Object result;
		error = 0;
		synchronized(lock)
		{
			label0:
			{
				if(elementCount <= 0)
				{
					error = 1;
					result = null;
					break label0;
				}
				result = elementData[0];
			}
		}
		if(error == 1)
		{
			throw new NoSuchElementException("Vector.firstElement: " +
					"вектор не содержит элементов.");
		}
		return result;
	}

	public Object lastElement()
	{
		int c;
		int error;
		Object result;
		error = 0;
		synchronized(lock)
		{
			label0:
			{
				if((c = elementCount) <= 0)
				{
					error = 1;
					result = null;
					break label0;
				}
				result = elementData[c - 1];
			}
		}
		if(error == 1)
		{
			throw new NoSuchElementException("Vector.lastElement: " +
					"вектор не содержит элементов.");
		}
		return result;
	}

	public Object elementAt(int index)
	{
		int error;
		Object result;
		error = 0;
		synchronized(lock)
		{
			label0:
			{
				if(index >= elementCount || index < 0)
				{
					error = 1;
					result = null;
					break label0;
				}
				result = elementData[index];
			}
		}
		if(error == 1)
		{
			throw new ArrayIndexOutOfBoundsException(index);
		}
		return result;
	}

	public Enumeration elements()
	{
		return this.new Enumerator();
	}

	final Object getMonitor()
	{
		return lock;
	}

	private Object[] ensureCapacityHelper(int minimumCapacity)
	{
		int i;
		int oc;
		int nc;
		Object[] result;
		oc = (result = elementData).length;
		if((nc = (i = capacityIncrement) <= 0 ? (oc << 1) + 1 : oc + i) < minimumCapacity)
		{
			nc = minimumCapacity;
		}
		Array.copy(result, 0, result = elementData = new Object[nc], 0, elementCount);
		return result;
	}
}
