/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии 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;
}
}