StringBuffer.java

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

/*
	Реализация спецификаций 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.lang;

public final class StringBuffer extends Object
{
	private boolean shared;
	private int length;
	private char[] chars;
	private final Object monitor;

	public StringBuffer()
	{
		this.chars = new char[16];
		this.monitor = new Object();
	}

	public StringBuffer(int initialCapacity)
	{
		if(initialCapacity < 0)
		{
			throw new NegativeArraySizeException("StringBuffer: аргумент initialCapacity не может быть отрицательным.");
		}
		this.chars = new char[initialCapacity];
		this.monitor = new Object();
	}

	public StringBuffer(String initialContent)
	{
		int length;
		char[] chars;
		if(initialContent != null)
		{
			length = initialContent.length();
			initialContent.getChars(0, length, chars = new char[length + 16], 0);
		} else
		{
			length = 0;
			chars = new char[16];
		}
		this.length = length;
		this.chars = chars;
		this.monitor = new Object();
	}

	public String toString()
	{
		return new String(this);
	}

	public void ensureCapacity(int minimumCapacity)
	{
		synchronized(monitor)
		{
			if(minimumCapacity > chars.length)
			{
				madeLarger(minimumCapacity);
			}
		}
	}

	public void setLength(int length)
	{
		if(length < 0)
		{
			throw new IndexOutOfBoundsException("StringBuffer.setLength: аргумент length не может быть отрицательным.");
		}
		synchronized(monitor)
		{
			int len;
			char[] c;
			if(length > (c = chars).length)
			{
				c = madeLarger(length);
			}
			len = this.length;
			this.length = length;
			if(length > len)
			{
				MalikSystem.arrayfill_short(c, len, length - len, 0);
			}
			else if(length < len && shared)
			{
				if(length > 0)
				{
					copy();
				} else
				{
					chars = new char[16];
					shared = false;
				}
			}
		}
	}

	public void setCharAt(int index, char character)
	{
		int error = 0;
		synchronized(monitor)
		{
			label0:
			{
				if(index < 0 || index >= length)
				{
					error = 1;
					break label0;
				}
				(shared ? copy() : chars)[index] = character;
			}
		}
		if(error == 1)
		{
			throw new StringIndexOutOfBoundsException("StringBuffer.setCharAt: аргумент index выходит из диапазона.");
		}
	}

	public void getChars(int beginIndex, int endIndex, char[] dst, int offset)
	{
		int error = 0;
		synchronized(monitor)
		{
			label0:
			{
				int lim;
				int len;
				int length;
				if((beginIndex | endIndex) < 0 || beginIndex > (len = this.length) || endIndex > len || beginIndex > endIndex)
				{
					error = 1;
					break label0;
				}
				if(dst == null)
				{
					error = 2;
					break label0;
				}
				if((lim = offset + (length = endIndex - beginIndex)) > (len = dst.length) || lim < offset || offset > len || offset < 0)
				{
					error = 3;
					break label0;
				}
				if(length > 0)
				{
					MalikSystem.arraycopyf_short(chars, beginIndex, dst, offset, length);
				}
			}
		}
		switch(error)
		{
		case 1:
			throw new StringIndexOutOfBoundsException("StringBuffer.getChars: индекс выходит из диапазона.");
		case 2:
			throw new NullPointerException("StringBuffer.getChars: аргумент dst равен нулевой ссылке.");
		case 3:
			throw new ArrayIndexOutOfBoundsException("StringBuffer.getChars: индекс выходит из диапазона.");
		}
	}

	public char charAt(int index)
	{
		char result;
		int error = 0;
		synchronized(monitor)
		{
			label0:
			{
				if(index < 0 || index >= length)
				{
					error = 1;
					result = 0;
					break label0;
				}
				result = chars[index];
			}
		}
		if(error == 1)
		{
			throw new StringIndexOutOfBoundsException("StringBuffer.charAt: аргумент index выходит из диапазона.");
		}
		return result;
	}

	public int length()
	{
		return length;
	}

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

	public StringBuffer insert(int position, boolean value)
	{
		return insert(position, value ? "true" : "false");
	}

	public StringBuffer insert(int position, char value)
	{
		int error = 0;
		synchronized(monitor)
		{
			label0:
			{
				int len;
				int newlen;
				char[] c;
				if(position < 0 || position > (len = length))
				{
					error = 1;
					break label0;
				}
				if((newlen = len + 1) > (c = chars).length)
				{
					c = madeLarger(newlen);
				}
				if(len > position)
				{
					if(shared) c = copy();
					MalikSystem.arraycopyb_short(c, len, c, newlen, len - position);
				}
				c[position] = value;
				length = newlen;
			}
		}
		if(error == 1)
		{
			throw new StringIndexOutOfBoundsException("StringBuffer.insert: аргумент position выходит из диапазона.");
		}
		return this;
	}

	public StringBuffer insert(int position, float value)
	{
		return insert(position, Float.toString(value));
	}

	public StringBuffer insert(int position, double value)
	{
		return insert(position, Double.toString(value));
	}

	public StringBuffer insert(int position, int value)
	{
		return insert(position, Integer.toString(value, 10));
	}

	public StringBuffer insert(int position, long value)
	{
		return insert(position, Long.toString(value, 10));
	}

	public StringBuffer insert(int position, char[] src)
	{
		int error;
		int length;
		if((length = src == null ? 0 : src.length) <= 0)
		{
			return this;
		}
		error = 0;
		synchronized(monitor)
		{
			label0:
			{
				int len;
				int newlen;
				char[] c;
				if(position < 0 || position > (len = this.length))
				{
					error = 1;
					break label0;
				}
				if(length <= 0)
				{
					break label0;
				}
				if((newlen = len + length) > (c = chars).length)
				{
					c = madeLarger(newlen);
				}
				if(len > position)
				{
					if(shared) c = copy();
					MalikSystem.arraycopyb_short(c, len, c, newlen, len - position);
				}
				MalikSystem.arraycopyf_short(src, 0, c, position, length);
				this.length = newlen;
			}
		}
		if(error == 1)
		{
			throw new StringIndexOutOfBoundsException("StringBuffer.insert: аргумент position выходит из диапазона.");
		}
		return this;
	}

	public StringBuffer insert(int position, String value)
	{
		int length;
		int error = 0;
		if(value == null) value = "null";
		length = value.length();
		synchronized(monitor)
		{
			label0:
			{
				int len;
				int newlen;
				char[] c;
				if(position < 0 || position > (len = this.length))
				{
					error = 1;
					break label0;
				}
				if(length <= 0)
				{
					break label0;
				}
				if((newlen = len + length) > (c = chars).length)
				{
					c = madeLarger(newlen);
				}
				if(len > position)
				{
					if(shared) c = copy();
					MalikSystem.arraycopyb_short(c, len, c, newlen, len - position);
				}
				value.getChars(0, length, c, position);
				this.length = newlen;
			}
		}
		if(error == 1)
		{
			throw new StringIndexOutOfBoundsException("StringBuffer.insert: аргумент position выходит из диапазона.");
		}
		return this;
	}

	public StringBuffer insert(int position, Object value)
	{
		return insert(position, value == null ? "null" : value.toString());
	}

	public StringBuffer append(boolean value)
	{
		return append(value ? "true" : "false");
	}

	public StringBuffer append(char value)
	{
		synchronized(monitor)
		{
			int len;
			int newlen;
			char[] c;
			if((newlen = (len = length) + 1) > (c = chars).length)
			{
				c = madeLarger(newlen);
			}
			c[len] = value;
			length = newlen;
		}
		return this;
	}

	public StringBuffer append(float value)
	{
		return append(Float.toString(value));
	}

	public StringBuffer append(double value)
	{
		return append(Double.toString(value));
	}

	public StringBuffer append(int value)
	{
		return append(Integer.toString(value, 10));
	}

	public StringBuffer append(long value)
	{
		return append(Long.toString(value, 10));
	}

	public StringBuffer append(char[] src)
	{
		return src == null ? this : append(src, 0, src.length);
	}

	public StringBuffer append(char[] src, int offset, int length)
	{
		long bounds;
		if(src == null) return this;
		offset = (int) (bounds = Array.intersectBound(src.length, offset, length));
		length = (int) (bounds >> 32);
		synchronized(monitor)
		{
			int len;
			int newlen;
			char[] c;
			if((newlen = (len = this.length) + length) > (c = chars).length)
			{
				c = madeLarger(newlen);
			}
			if(length > 0)
			{
				MalikSystem.arraycopyf_short(src, offset, c, len, length);
				this.length = newlen;
			}
		}
		return this;
	}

	public StringBuffer append(String value)
	{
		int length;
		if(value == null) value = "null";
		length = value.length();
		synchronized(monitor)
		{
			int len;
			int newlen;
			char[] c;
			if((newlen = (len = this.length) + length) > (c = chars).length)
			{
				c = madeLarger(newlen);
			}
			if(length > 0)
			{
				value.getChars(0, length, c, len);
				this.length = newlen;
			}
		}
		return this;
	}

	public StringBuffer append(Object value)
	{
		return append(value == null ? "null" : value.toString());
	}

	public StringBuffer deleteCharAt(int index)
	{
		int error = 0;
		synchronized(monitor)
		{
			label0:
			{
				int cnt;
				int len;
				char[] c;
				if(index < 0 || index >= (len = length))
				{
					error = 1;
					break label0;
				}
				c = shared ? copy() : chars;
				if((cnt = --len - index) > 0)
				{
					MalikSystem.arraycopyf_short(c, index + 1, c, index, cnt);
				}
				length = len;
			}
		}
		if(error == 1)
		{
			throw new StringIndexOutOfBoundsException("StringBuffer.deleteCharAt: аргумент index выходит из диапазона.");
		}
		return this;
	}

	public StringBuffer delete(int beginIndex, int endIndex)
	{
		int error = 0;
		synchronized(monitor)
		{
			label0:
			{
				int cnt;
				int len;
				char[] c;
				if(endIndex > (len = length))
				{
					endIndex = len;
				}
				if((beginIndex | endIndex) < 0 || beginIndex > endIndex)
				{
					error = 1;
					break label0;
				}
				if((cnt = endIndex - beginIndex) <= 0)
				{
					break label0;
				}
				c = shared ? copy() : chars;
				if(len > endIndex)
				{
					MalikSystem.arraycopyf_short(c, endIndex, c, beginIndex, len - endIndex);
				}
				length = len - cnt;
			}
		}
		if(error == 1)
		{
			throw new StringIndexOutOfBoundsException("StringBuffer.delete: индекс выходит из диапазона.");
		}
		return this;
	}

	public StringBuffer reverse()
	{
		synchronized(monitor)
		{
			int len = length;
			char[] c = shared ? copy() : chars;
			for(int i = len >> 1, j = len - i; i-- > 0; j++)
			{
				char ci = c[i];
				c[i] = c[j];
				c[j] = ci;
			}
		}
		return this;
	}

	void setShared()
	{
		shared = true;
	}

	char[] content()
	{
		return chars;
	}

	Object monitor()
	{
		return monitor;
	}

	private char[] copy()
	{
		char[] result;
		MalikSystem.arraycopyf_short(result = chars, 0, result = chars = new char[result.length], 0, length);
		shared = false;
		return result;
	}

	private char[] madeLarger(int neededCharacters)
	{
		int capacity;
		char[] result;
		if((capacity = ((result = chars).length + 1) << 1) <= 0)
		{
			capacity = Integer.MAX_VALUE;
		}
		else if(capacity < neededCharacters)
		{
			capacity = neededCharacters;
		}
		MalikSystem.arraycopyf_short(result, 0, result = chars = new char[capacity], 0, length);
		shared = false;
		return result;
	}
}