StringBuilder.avt

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

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    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"));
        }
    }
}