/*
Исходный код среды исполнения ПВТ-ОО.
Этот исходный код является частью проекта ПВТ-ОО.
Copyright © 2021 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
*/
package avt.lang;
import avt.lang.array.*;
import platform.independent.streamformat.*;
public class StringBuilder(Object, MutableDataHolder, CharSequence, Cloneable, DataHolder, Measureable, MutableCharArray, CharArray)
{
protected int fldLength;
protected char[] fldChars;
public () { fldChars = new char[63]; }
public (int initialCapacity) { fldChars = new char[initialCapacity <= 1 ? 1 : initialCapacity]; }
protected (char[] chars, int length) {
fldLength = length;
fldChars = chars;
}
public String toString() { return new String(fldChars, 0, fldLength); }
public void clear() { fldLength = 0; }
public void getChars(int beginIndex, int endIndex, MutableCharArray dst, int offset) {
checkBounds(beginIndex, endIndex);
if(dst == null)
{
throw new NullPointerException("аргумент dst равен нулевой ссылке");
}
int length = endIndex - beginIndex;
Array.checkBounds(dst, offset, length);
copyChars(beginIndex, dst, offset, length);
}
public StringBuilder subsequence(int beginIndex, int endIndex) {
checkBounds(beginIndex, endIndex);
int length = endIndex - beginIndex;
char[] chars = new char[length];
copyChars(beginIndex, chars, 0, length);
return new StringBuilder(chars, length);
}
public StringBuilder subsequence(int beginIndex) { return subsequence(beginIndex, fldLength); }
public StringBuilder clone() { return subsequence(0, fldLength); }
public boolean isEmpty() { return fldLength <= 0; }
public int indexOf(int character) { return findForward(character, 0); }
public int indexOf(int character, int startFromIndex) { return findForward(character, startFromIndex); }
public int indexOf(String string) { return findForward(string, 0); }
public int indexOf(String string, int startFromIndex) { return findForward(string, startFromIndex); }
public int lastIndexOf(int character) { return findBackward(character, Int.MAX_VALUE); }
public int lastIndexOf(int character, int startFromIndex) { return findBackward(character, startFromIndex); }
public int lastIndexOf(String string) { return findBackward(string, Int.MAX_VALUE); }
public int lastIndexOf(String string, int startFromIndex) { return findBackward(string, startFromIndex); }
public StringBuilder trimToLength() {
trim();
return this;
}
public StringBuilder insert(int index, boolean src) {
String array = String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, char src) {
insertChar(index, src);
return this;
}
public StringBuilder insert(int index, byte src) {
String array = String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, short src) {
String array = String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, int src) {
String array = String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, long src) {
String array = String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, float src) {
String array = String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, double src) {
String array = String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, real src) {
String array = String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, Object src) {
String array = String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, CharArray src, int offset, int length) {
Array.checkBounds(src, offset, length);
insertArray(index, src, offset, length);
return this;
}
public StringBuilder insertf(int index, String form, ObjectArray data) {
String array = String.format(form, data);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder delete(int beginIndex, int endIndex) {
checkBounds(beginIndex, endIndex);
deletePortion(beginIndex, endIndex);
return this;
}
public StringBuilder delete(int index) {
checkIndex(index);
deletePortion(index, index + 1);
return this;
}
public StringBuilder append(boolean src) {
String array = String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(char src) {
appendChar(src);
return this;
}
public StringBuilder append(byte src) {
String array = String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(short src) {
String array = String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(int src) {
String array = String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(long src) {
String array = String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(float src) {
String array = String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(double src) {
String array = String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(real src) {
String array = String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(Object src) {
String array = String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(CharArray src, int offset, int length) {
Array.checkBounds(src, offset, length);
appendArray(src, offset, length);
return this;
}
public StringBuilder appendf(String form, ObjectArray data) {
String array = String.format(form, data);
appendArray(array, 0, array.length);
return this;
}
public String displayString() { return toString(); }
public int length { read = fldLength, write = setLength }
public final int capacity { read = getCapacity }
public void operator []=(int index, char character) {
checkIndex(index);
fldChars[index] = character;
}
public char operator [](int index) {
checkIndex(index);
return fldChars[index];
}
public final StringBuilder operator +(boolean src) { return append(src); }
public final StringBuilder operator +(char src) { return append(src); }
public final StringBuilder operator +(byte src) { return append(src); }
public final StringBuilder operator +(short src) { return append(src); }
public final StringBuilder operator +(int src) { return append(src); }
public final StringBuilder operator +(long src) { return append(src); }
public final StringBuilder operator +(float src) { return append(src); }
public final StringBuilder operator +(double src) { return append(src); }
public final StringBuilder operator +(real src) { return append(src); }
public final StringBuilder operator +(Object src) { return append(src); }
protected void trim() {
int length = fldLength;
char[] chars = fldChars;
if(length < chars.length)
{
Array.copy(chars, 0, fldChars = new char[length], 0, length);
}
}
protected void setLength(int newLength) {
if(newLength < 0)
{
throw new NegativeArrayLengthException("длина не может быть отрицательной");
}
int curLength = fldLength;
char[] chars = fldChars;
if(newLength > chars.length) chars = madeLarger(newLength);
if(newLength > curLength) Array.fill(chars, curLength, newLength - curLength, '\0');
fldLength = newLength;
}
protected void copyChars(int index, MutableCharArray dst, int offset, int length) {
if(dst instanceof char[])
{
Array.copy(fldChars, index, (char[]) dst, offset, length);
return;
}
for(char[] chars = fldChars; length-- > 0; ) dst[offset++] = chars[index++];
}
protected void insertChar(int index, char src) {
int thisLength = fldLength;
char[] thisChars = madeLarger(thisLength + 1);
if(index < 0) index = 0;
if(index > thisLength) index = thisLength;
Array.copy(thisChars, index, thisChars, index + 1, thisLength++ - index);
thisChars[index] = src;
fldLength = thisLength;
}
protected void insertArray(int index, CharArray src, int offset, int length) {
int thisLength = fldLength;
int newLength = thisLength + length;
char[] thisChars = madeLarger(newLength);
if(index < 0) index = 0;
if(index > thisLength) index = thisLength;
Array.copy(thisChars, index, thisChars, index + length, thisLength - index);
if(src instanceof char[])
{
Array.copy((char[]) src, offset, thisChars, index, length);
}
else if(src instanceof CharSequence)
{
((CharSequence) src).getChars(offset, offset + length, thisChars, index);
}
else
{
while(length-- > 0) thisChars[index++] = src[offset++];
}
fldLength = newLength;
}
protected void appendChar(char src) {
int length = fldLength;
char[] chars = madeLarger(length + 1);
chars[length++] = src;
fldLength = length;
}
protected void appendArray(CharArray src, int offset, int length) {
int thisLength = fldLength;
int newLength = thisLength + length;
char[] thisChars = madeLarger(newLength);
if(src instanceof char[])
{
Array.copy((char[]) src, offset, thisChars, thisLength, length);
}
else if(src instanceof CharSequence)
{
((CharSequence) src).getChars(offset, offset + length, thisChars, thisLength);
}
else
{
while(length-- > 0) thisChars[thisLength++] = src[offset++];
}
fldLength = newLength;
}
protected void deletePortion(int beginIndex, int endIndex) {
int count = endIndex - beginIndex;
int thisLength = fldLength;
char[] thisChars = fldChars;
Array.copy(thisChars, endIndex, thisChars, beginIndex, thisLength - endIndex);
fldLength = thisLength - count;
}
protected int findForward(int character, int startFromIndex) {
int thisLength = fldLength;
if(startFromIndex < 0) startFromIndex = 0;
return startFromIndex >= thisLength ? -1 : Array.indexOf(character, fldChars, startFromIndex, thisLength - startFromIndex);
}
protected int findForward(String string, int startFromIndex) {
int anotLength;
if(string == null || (anotLength = string.length) <= 0) return startFromIndex;
if(startFromIndex < 0) startFromIndex = 0;
int thisLength = fldLength;
int limit = thisLength - anotLength + 1;
if(startFromIndex < limit)
{
int character = string[0];
char[] thisChars = fldChars;
do
{
if((startFromIndex = Array.indexOf(character, thisChars, startFromIndex, limit - startFromIndex)) < 0) break;
if(string.contentEquals(thisChars, startFromIndex)) return startFromIndex;
} while(++startFromIndex < limit);
}
return -1;
}
protected int findBackward(int character, int startFromIndex) {
int thisLength = fldLength;
if(startFromIndex >= thisLength) startFromIndex = thisLength - 1;
return startFromIndex < 0 ? -1 : Array.lastIndexOf(character, fldChars, startFromIndex, startFromIndex + 1);
}
protected int findBackward(String string, int startFromIndex) {
int anotLength;
if(string == null || (anotLength = string.length) <= 0) return startFromIndex;
int thisLength = fldLength;
int limit = thisLength - anotLength;
if(startFromIndex > limit) startFromIndex = limit;
if(startFromIndex >= 0)
{
int character = string[0];
char[] thisChars = fldChars;
do
{
if((startFromIndex = Array.lastIndexOf(character, thisChars, startFromIndex, startFromIndex + 1)) < 0) break;
if(string.contentEquals(thisChars, startFromIndex)) return startFromIndex;
} while(--startFromIndex >= 0);
}
return -1;
}
protected final void checkBounds(int beginIndex, int endIndex) {
int thisLength = length;
if((beginIndex | endIndex) < 0 || beginIndex > thisLength || endIndex > thisLength || beginIndex > endIndex)
{
throw new StringIndexOutOfBoundsException("индекс символа строки выходит из диапазона");
}
}
protected final void checkIndex(int index) {
if(index < 0 || index >= length)
{
throw new StringIndexOutOfBoundsException("индекс символа строки выходит из диапазона");
}
}
private int getCapacity() { return fldChars.length; }
private char[] madeLarger(int minimumCapacity) {
if(minimumCapacity < 0)
{
throw new BufferTooLargeError("объём буфера очень велик");
}
char[] chars = fldChars;
int currentCapacity = chars.length;
if(minimumCapacity > currentCapacity)
{
int newCapacity = currentCapacity >= (Int.MAX_VALUE >> 1) ? Int.MAX_VALUE : (currentCapacity << 1) + 1;
if(newCapacity < minimumCapacity) newCapacity = minimumCapacity;
Array.copy(chars, 0, fldChars = chars = new char[newCapacity], 0, currentCapacity);
}
return chars;
}
}