/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package avt.lang;
import avt.lang.array.*;
import platform.independent.streamformat.*;
public class StringBuilder(Object, MutableDataHolder, Cloneable, CharSequence, DataHolder, Measureable, MutableMeasureable, ResizeableCharArray, MutableCharArray, CharArray)
{
protected int fldLength;
protected char[] fldContent;
public () {
fldContent = new char[0x3fi];
}
public (int initialCapacity) {
fldContent = new char[initialCapacity <= 1 ? 1 : initialCapacity];
}
protected (int length, char[] content) {
fldLength = length;
fldContent = content;
}
public void clear() { setLength(0); }
public StringBuilder clone() { return new StringBuilder(fldLength, fldContent.clone()); }
public StringBuilder join(CharSequence anot) {
if(anot != null)
{
appendArray(anot, 0, anot.length);
}
return this;
}
public StringBuilder join(CharSequence[] seqs) {
if(seqs != null) for(int length = seqs.length, int index = 0; index < length; index++)
{
CharArray anot = seqs[index];
if(anot != null) appendArray(anot, 0, anot.length);
}
return this;
}
public StringBuilder subsequence(int beginIndex) {
int endIndex = fldLength;
checkBounds(beginIndex, endIndex);
deleteTails(beginIndex, endIndex, false);
return this;
}
public StringBuilder subsequence(int beginIndex, int endIndex) {
checkBounds(beginIndex, endIndex);
deleteTails(beginIndex, endIndex, false);
return this;
}
public void ensureCapacity(int minCapacity) {
if(minCapacity >= 0)
{
char[] content = fldContent;
int curCapacity = content.length;
if(minCapacity > curCapacity)
{
int newCapacity = curCapacity >= (Int.MAX_VALUE >> 1) ? Int.MAX_VALUE : curCapacity << 1 | 1;
if(minCapacity > newCapacity) newCapacity = minCapacity;
Array.copy(content, 0, fldContent = new char[newCapacity], 0, curCapacity);
}
}
}
public StringBuilder reverse() {
reverseContent();
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) {
CharArray array = src instanceof CharArray ? (CharArray) src : String.valueOf(src);
appendArray(array, 0, array.length);
return this;
}
public StringBuilder append(CharArray src, int offset, int length) {
if(src == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
}
Array.checkBounds(src, offset, length);
appendArray(src, offset, length);
return this;
}
public StringBuilder appendf(String form, ObjectArray data) {
if(form == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "form" }));
}
String array = String.format(form, data);
appendArray(array, 0, array.length);
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) {
CharArray array = src instanceof CharArray ? (CharArray) src : String.valueOf(src);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder insert(int index, CharArray src, int offset, int length) {
if(src == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
}
Array.checkBounds(src, offset, length);
insertArray(index, src, offset, length);
return this;
}
public StringBuilder insertf(int index, String form, ObjectArray data) {
if(form == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "form" }));
}
String array = String.format(form, data);
insertArray(index, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, boolean src) {
checkBounds(beginIndex, endIndex);
String array = String.valueOf(src);
replaceArray(beginIndex, endIndex, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, char src) {
checkBounds(beginIndex, endIndex);
replaceChar(beginIndex, endIndex, src);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, byte src) {
checkBounds(beginIndex, endIndex);
String array = String.valueOf(src);
replaceArray(beginIndex, endIndex, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, short src) {
checkBounds(beginIndex, endIndex);
String array = String.valueOf(src);
replaceArray(beginIndex, endIndex, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, int src) {
checkBounds(beginIndex, endIndex);
String array = String.valueOf(src);
replaceArray(beginIndex, endIndex, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, long src) {
checkBounds(beginIndex, endIndex);
String array = String.valueOf(src);
replaceArray(beginIndex, endIndex, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, float src) {
checkBounds(beginIndex, endIndex);
String array = String.valueOf(src);
replaceArray(beginIndex, endIndex, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, double src) {
checkBounds(beginIndex, endIndex);
String array = String.valueOf(src);
replaceArray(beginIndex, endIndex, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, real src) {
checkBounds(beginIndex, endIndex);
String array = String.valueOf(src);
replaceArray(beginIndex, endIndex, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, Object src) {
checkBounds(beginIndex, endIndex);
CharArray array = src instanceof CharArray ? (CharArray) src : String.valueOf(src);
replaceArray(beginIndex, endIndex, array, 0, array.length);
return this;
}
public StringBuilder replace(int beginIndex, int endIndex, CharArray src, int offset, int length) {
checkBounds(beginIndex, endIndex);
if(src == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "src" }));
}
Array.checkBounds(src, offset, length);
replaceArray(beginIndex, endIndex, src, offset, length);
return this;
}
public StringBuilder replacef(int beginIndex, int endIndex, String form, ObjectArray data) {
checkBounds(beginIndex, endIndex);
if(form == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "form" }));
}
String array = String.format(form, data);
replaceArray(beginIndex, endIndex, 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 deleteTailSpaces() {
int chi = 0;
int chj = fldLength - 1;
char[] content = fldContent;
while(chi <= chj && content[chi] <= '\u0020') chi++;
while(chi <= chj && content[chj] <= '\u0020') chj--;
deleteTails(chi, chj + 1, false);
return this;
}
public StringBuilder trimTailSpaces() {
int chi = 0;
int chj = fldLength - 1;
char[] content = fldContent;
while(chi <= chj && content[chi] <= '\u0020') chi++;
while(chi <= chj && content[chj] <= '\u0020') chj--;
deleteTails(chi, chj + 1, true);
return this;
}
public StringBuilder trimToLength() {
deleteTails(0, fldLength, true);
return this;
}
public StringBuilder trimToSubsequence(int beginIndex) {
int endIndex = fldLength;
checkBounds(beginIndex, endIndex);
deleteTails(beginIndex, endIndex, true);
return this;
}
public StringBuilder trimToSubsequence(int beginIndex, int endIndex) {
checkBounds(beginIndex, endIndex);
deleteTails(beginIndex, endIndex, true);
return this;
}
public String displayString() { return new String(fldContent, 0, fldLength); }
public final String toString() { return new String(fldContent, 0, fldLength); }
public final void getChars(int beginIndex, int endIndex, MutableCharArray dst, int offset) {
checkBounds(beginIndex, endIndex);
if(dst == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "dst" }));
}
int length = endIndex - beginIndex;
Array.checkBounds(dst, offset, length);
if(dst instanceof StringBuilder)
{
dst = ((StringBuilder) dst).fldContent;
}
if(dst instanceof char[])
{
Array.copy(fldContent, beginIndex, (char[]) dst, offset, length);
return;
}
for(char[] content = fldContent; length-- > 0; ) dst[offset++] = content[beginIndex++];
}
public final void copyInto(MutableCharArray dst, int offset) { getChars(0, fldLength, dst, offset); }
public final char[] toCharArray() {
int length = fldLength;
char[] result = new char[length];
Array.copy(fldContent, 0, result, 0, length);
return result;
}
public final boolean isEmpty() { return fldLength <= 0; }
public final int indexOf(int character) {
int length = fldLength;
return 0 >= length || character < 0 || character > 0xffff ? -1 : Array.indexOf(character, fldContent, 0, length);
}
public final int indexOf(int character, int startFromIndex) {
int length = fldLength;
if(startFromIndex < 0) startFromIndex = 0;
return startFromIndex >= length || character < 0 || character > 0xffff ? -1 : Array.indexOf(character, fldContent, startFromIndex, length - startFromIndex);
}
public final int indexOf(CharSequence string) { return indexOf(string, 0); }
public final int indexOf(CharSequence string, int startFromIndex) {
if(string == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "string" }));
}
int anotLength = string.length;
int thisLength = fldLength - anotLength;
if(startFromIndex < 0) startFromIndex = 0;
if(startFromIndex > thisLength++) return -1;
if(anotLength-- <= 0) return startFromIndex;
char[] anotContent = string instanceof StringBuilder ? ((StringBuilder) string).fldContent : string.toCharArray();
char[] thisContent = fldContent;
char first = anotContent[0];
do
{
int thisIndex = Array.indexOf(first, thisContent, startFromIndex, thisLength - startFromIndex);
if(thisIndex < 0) break;
startFromIndex = thisIndex++;
if(anotLength <= 0 || Array.offsetOfNonEqual(thisContent, thisIndex, anotContent, 1, anotLength) == Comparable.INDEFINITE) return startFromIndex;
} while(++startFromIndex < thisLength);
return -1;
}
public final int indexOfNon(int character) {
int length = fldLength;
return 0 >= length ? -1 : character < 0 || character > 0xffff ? 0 : Array.indexOfNon(character, fldContent, 0, length);
}
public final int indexOfNon(int character, int startFromIndex) {
int length = fldLength;
if(startFromIndex < 0) startFromIndex = 0;
return startFromIndex >= length ? -1 : character < 0 || character > 0xffff ? startFromIndex : Array.indexOfNon(character, fldContent, startFromIndex, length - startFromIndex);
}
public final int lastIndexOf(int character) {
int length = fldLength - 1;
return length < 0 || character < 0 || character > 0xffff ? -1 : Array.lastIndexOf(character, fldContent, length++, length);
}
public final int lastIndexOf(int character, int startFromIndex) {
int length = fldLength;
if(startFromIndex >= length) startFromIndex = length - 1;
return startFromIndex < 0 || character < 0 || character > 0xffff ? -1 : Array.lastIndexOf(character, fldContent, startFromIndex++, startFromIndex);
}
public final int lastIndexOf(CharSequence string) { return lastIndexOf(string, Int.MAX_VALUE); }
public final int lastIndexOf(CharSequence string, int startFromIndex) {
if(string == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "string" }));
}
int anotLength = string.length;
int thisLength = fldLength - anotLength;
if(startFromIndex > thisLength++) startFromIndex = thisLength - 1;
if(startFromIndex < 0) return -1;
if(anotLength-- <= 0) return startFromIndex;
char[] anotContent = string instanceof StringBuilder ? ((StringBuilder) string).fldContent : string.toCharArray();
char[] thisContent = fldContent;
char first = anotContent[0];
do
{
int thisIndex = Array.lastIndexOf(first, thisContent, startFromIndex, startFromIndex + 1);
if(thisIndex < 0) break;
startFromIndex = thisIndex++;
if(anotLength <= 0 || Array.offsetOfNonEqual(thisContent, thisIndex, anotContent, 1, anotLength) == Comparable.INDEFINITE) return startFromIndex;
} while(--startFromIndex >= 0);
return -1;
}
public final int lastIndexOfNon(int character) {
int length = fldLength - 1;
return length < 0 ? -1 : character < 0 || character > 0xffff ? length : Array.lastIndexOfNon(character, fldContent, length++, length);
}
public final int lastIndexOfNon(int character, int startFromIndex) {
int length = fldLength;
if(startFromIndex >= length) startFromIndex = length - 1;
return startFromIndex < 0 ? -1 : character < 0 || character > 0xffff ? startFromIndex : Array.lastIndexOfNon(character, fldContent, startFromIndex++, startFromIndex);
}
public final int length { read = fldLength, write = setLength }
public final int capacity { read = fldContent.length }
public void operator []=(int index, char component) {
checkIndex(index);
writeChar(index, component);
}
public final char operator [](int index) {
checkIndex(index);
return fldContent[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 setLength(int newLength) {
if(newLength < 0)
{
throw new NegativeArrayLengthException(package.getResourceString("negative-array-length"));
}
int curLength = fldLength;
char[] content = fldContent;
if(newLength > content.length) content = madeLarger(newLength);
if(newLength > curLength) Array.fill(content, curLength, newLength - curLength, '\0');
fldLength = newLength;
}
protected void reverseContent() {
int length = fldLength;
char[] content = fldContent;
for(int chi = length >> 1, int chj = length - chi; chi-- > 0; chj++)
{
char chr = content[chi];
content[chi] = content[chj];
content[chj] = chr;
}
}
protected void writeChar(int index, char src) {
fldContent[index] = src;
}
protected void appendChar(char src) {
int length = fldLength;
char[] content = madeLarger(length + 1);
content[length++] = src;
fldLength = length;
}
protected void appendArray(CharArray src, int offset, int length) {
int curLength = fldLength;
int newLength = curLength + length;
char[] content = madeLarger(newLength);
if(src instanceof char[])
{
Array.copy((char[]) src, offset, content, curLength, length);
}
else if(src instanceof CharSequence)
{
((CharSequence) src).getChars(offset, offset + length, content, curLength);
}
else
{
while(length-- > 0) content[curLength++] = src[offset++];
}
fldLength = newLength;
}
protected void insertChar(int index, char src) {
int length = fldLength;
char[] content = madeLarger(length + 1);
if(index < 0) index = 0;
if(index > length) index = length;
Array.copy(content, index, content, index + 1, length++ - index);
content[index] = src;
fldLength = length;
}
protected void insertArray(int index, CharArray src, int offset, int length) {
int curLength = fldLength;
int newLength = curLength + length;
char[] content = madeLarger(newLength);
if(index < 0) index = 0;
if(index > curLength) index = curLength;
Array.copy(content, index, content, index + length, curLength - index);
if(src instanceof char[])
{
Array.copy((char[]) src, offset, content, index, length);
}
else if(src instanceof CharSequence)
{
((CharSequence) src).getChars(offset, offset + length, content, index);
}
else
{
while(length-- > 0) content[index++] = src[offset++];
}
fldLength = newLength;
}
protected void replaceChar(int beginIndex, int endIndex, char src) {
int curLength = fldLength;
int newLength = curLength - beginIndex + endIndex + 1;
char[] content = madeLarger(newLength);
Array.copy(content, endIndex, content, beginIndex + 1, curLength - endIndex);
content[beginIndex] = src;
fldLength = newLength;
}
protected void replaceArray(int beginIndex, int endIndex, CharArray src, int offset, int length) {
int curLength = fldLength;
int newLength = curLength - beginIndex + endIndex + length;
char[] content = madeLarger(newLength);
Array.copy(content, endIndex, content, beginIndex + length, curLength - endIndex);
if(src instanceof char[])
{
Array.copy((char[]) src, offset, content, beginIndex, length);
}
else if(src instanceof CharSequence)
{
((CharSequence) src).getChars(offset, offset + length, content, beginIndex);
}
else
{
while(length-- > 0) content[beginIndex++] = src[offset++];
}
fldLength = newLength;
}
protected void deletePortion(int beginIndex, int endIndex) {
int count = endIndex - beginIndex;
int curLength = fldLength;
int newLength = curLength - count;
if(count > 0)
{
char[] content = fldContent;
Array.copy(content, endIndex, content, beginIndex, curLength - endIndex);
}
fldLength = newLength;
}
protected void deleteTails(int beginIndex, int endIndex, boolean isTrim) {
int newLength = endIndex - beginIndex;
char[] content = fldContent;
if(!isTrim)
{
if(beginIndex > 0) Array.copy(content, beginIndex, content, 0, newLength);
fldLength = newLength;
}
else if(beginIndex > 0 || endIndex < content.length)
{
Array.copy(content, beginIndex, fldContent = new char[newLength], 0, newLength);
fldLength = newLength;
}
}
protected char[] madeLarger(int minCapacity) {
if(minCapacity < 0)
{
throw new BufferTooLargeError(package.getResourceString("!error.buffer-too-large"));
}
char[] content = fldContent;
int curCapacity = content.length;
if(minCapacity > curCapacity)
{
int newCapacity = curCapacity >= (Int.MAX_VALUE >> 1) ? Int.MAX_VALUE : curCapacity << 1 | 1;
if(minCapacity > newCapacity) newCapacity = minCapacity;
Array.copy(content, 0, fldContent = content = new char[newCapacity], 0, curCapacity);
}
return content;
}
protected final void checkBounds(int beginIndex, int endIndex) {
int length = fldLength;
if((beginIndex | endIndex) < 0 || beginIndex > length || endIndex > length || beginIndex > endIndex)
{
throw new StringIndexOutOfBoundsException(package.getResourceString("out-of-bounds.string-index"));
}
}
protected final void checkIndex(int index) {
if(index < 0 || index >= fldLength)
{
throw new StringIndexOutOfBoundsException(package.getResourceString("out-of-bounds.string-index"));
}
}
}