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