String.avt

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

/*
    Исходный код среды исполнения ПВТ-ОО.

    Этот исходный код является частью проекта ПВТ-ОО.

    Copyright © 2021 Малик Разработчик

    Это свободная программа: вы можете перераспространять её и/или
    изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она может быть полезна,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <http://www.gnu.org/licenses/>.
*/

package avt.lang;

import avt.io.charset.*;
import avt.lang.array.*;
import avt.math.*;
import platform.independent.streamformat.*;

/* Нужен также тип String32 c символами типа int */

public final class String(Object, CharSequence, Cloneable, DataHolder, Comparable, Measureable, CharArray)
{
    private static byte[] created;
    private static String[] constants;
    private static String empty;

    public static String valueOf(boolean src) { return src ? "true" : "false"; }

    public static String valueOf(char src) { return new String(src); }

    public static String valueOf(byte src) { return Byte.toString(src); }

    public static String valueOf(short src) { return Short.toString(src); }

    public static String valueOf(int src) { return Int.toString(src); }

    public static String valueOf(long src) { return Long.toString(src); }

    public static String valueOf(float src) { return Float.toString(src); }

    public static String valueOf(double src) { return Double.toString(src); }

    public static String valueOf(real src) { return Real.toString(src); }

    public static String valueOf(Object src) { return src == null ? "null" : src.toString(); }

    public static String valueOf(CharArray src, int offset, int length) { return new String(src, offset, length); }

    public static String format(String form, ObjectArray data) {
		if(form == null)
		{
			throw new NullPointerException("аргумент form равен нулевой ссылке");
		}
		if(data == null)
		{
			throw new NullPointerException("аргумент data равен нулевой ссылке");
		}
		StringBuilder result = new StringBuilder();
		int beginIndex = 0;
		label0: for(int endIndex = 0, int formLength = form.length, int dataLength = data.length; (endIndex = form.indexOf('%', beginIndex)) >= 0; beginIndex = endIndex)
		{
			result + form.substring(beginIndex, endIndex);
			int formIndex = (beginIndex = endIndex) + 1;
			if(formIndex >= formLength) break label0;
			char formChar = form[formIndex];
			if(formChar == '%')
			{
				endIndex = formIndex + 1;
				result + '%';
				continue label0;
			}
			if(formChar < '0' || formChar > '9')
			{
				result + form.substring(beginIndex, endIndex = formIndex + 1);
				continue label0;
			}
			int dataIndex = formChar - '0';
			do
			{
				if(++formIndex >= formLength) break label0;
				if((formChar = form[formIndex]) < '0' || formChar > '9') break;
				int digit = formChar - '0';
				if((dataIndex *= 10) > Int.MAX_VALUE - digit)
				{
					result + form.substring(beginIndex, endIndex = formIndex + 1);
					continue label0;
				}
				dataIndex += digit;
			} while(true);
			boolean isReal = false;
			boolean isString = true;
			boolean expForm = false;
			boolean significandAll = false;
			boolean significandSign = false;
			boolean orderSign = true;
			int significandDigits = 1;
			int orderDigits = 0;
			if(formChar == '|')
			{
				isString = false;
				if(++formIndex >= formLength) break label0;
				if((formChar = form[formIndex]) == '+')
				{
					significandSign = true;
					if(++formIndex >= formLength) break label0;
					formChar = form[formIndex];
				}
				if(formChar != '1')
				{
					result + form.substring(beginIndex, endIndex = formIndex + 1);
					continue label0;
				}
				if(++formIndex >= formLength) break label0;
				if((formChar = form[formIndex]) == '.')
				{
					isReal = true;
					if(++formIndex >= formLength) break label0;
					if((formChar = form[formIndex]) < '0' || formChar > '9')
					{
						result + form.substring(beginIndex, endIndex = formIndex + 1);
						continue label0;
					}
					significandDigits = formChar - '0';
					if(++formIndex >= formLength) break label0;
					if((formChar = form[formIndex]) >= '0' && formChar <= '9')
					{
						significandDigits = significandDigits * 10 + (formChar - '0');
						if(++formIndex >= formLength) break label0;
						formChar = form[formIndex];
					}
					significandDigits++;
					if(formChar == 'A' || formChar == 'a')
					{
						significandAll = true;
						if(++formIndex >= formLength) break label0;
						formChar = form[formIndex];
					}
				}
				if((expForm = formChar == 'E') || formChar == 'e')
				{
					isReal = true;
					if(++formIndex >= formLength) break label0;
					if((formChar = form[formIndex]) != '+')
					{
						orderSign = false;
					} else
					{
						if(++formIndex >= formLength) break label0;
						formChar = form[formIndex];
					}
					if(formChar < '0' || formChar > '4')
					{
						result + form.substring(beginIndex, endIndex = formIndex + 1);
						continue label0;
					}
					orderDigits = formChar - '0';
					if(++formIndex >= formLength) break label0;
					formChar = form[formIndex];
				}
			}
			int minimumLength = 0;
			if(formChar == ':')
			{
				if(++formIndex >= formLength) break label0;
				if((formChar = form[formIndex]) < '0' || formChar > '9')
				{
					result + form.substring(beginIndex, endIndex = formIndex + 1);
					continue label0;
				}
				minimumLength = formChar - '0';
				do
				{
					if(++formIndex >= formLength) break label0;
					if((formChar = form[formIndex]) < '0' || formChar > '9') break;
					int digit = formChar - '0';
					if((minimumLength *= 10) > 1024 - digit)
					{
						result + form.substring(beginIndex, endIndex = formIndex + 1);
						continue label0;
					}
					minimumLength += digit;
				} while(true);
			}
			if(formChar != '%')
			{
				result + form.substring(beginIndex, endIndex = formIndex + 1);
				continue label0;
			}
			if(dataIndex < 0 || dataIndex >= dataLength)
			{
				throw new ArrayIndexOutOfBoundsException("индекс элемента массива данных выходит из диапазона");
			}
			Object dataElement = data[dataIndex];
			if(dataElement == null)
			{
				throw new NullPointerException("элемент массива данных равен нулевой ссылке");
			}
			String formatted;
			if(isString)
			{
				formatted = dataElement.toString();
			} else
			{
				if(!(dataElement instanceof Numeric))
				{
					throw new ClassCastException("элемент массива данных не является числом") { source = dataElement.getClass(), destination = Numeric.class };
				}
				Numeric dataNumber = (Numeric) dataElement;
				if(isReal)
				{
					formatted = Real.toString(dataNumber.asReal(), significandDigits < 2 ? RealRepresenter.MAX_SIGNIFICAND_DIGITS : significandDigits, orderDigits, significandAll, orderDigits >= 1, expForm, significandSign, orderSign);
				} else
				{
					long number = dataNumber.asLong();
					formatted = number < 0L || !significandSign ? Long.toString(number) : "+" + Long.toString(number);
				}
			}
			int formattedLength = formatted.length;
			if(formattedLength < minimumLength) for(int i = minimumLength - formattedLength; i-- > 0; ) result + ' ';
			endIndex = formIndex + 1;
			result + formatted;
		}
		return (result + form.substring(beginIndex)).toString();
	}

    public static String decode(ByteArray src, String charsetName) throws UnsupportedCharsetNameException {
        char[] chars = Charset.get(charsetName).decode(src);
        return new String(0, chars.length, chars);
    }

    public static String decode(ByteArray src, int offset, int length, String charsetName) throws UnsupportedCharsetNameException {
        char[] chars = Charset.get(charsetName).decode(src, offset, length);
        return new String(0, chars.length, chars);
    }

    package static String getConstant(int index) {
        if(constants == null)
        {
            int count = getConstantCount();
            created = new byte[count + 7 >> 3];
            constants = new String[count];
            empty = new String();
        }
        String result = null;
        if(index >= 0 && index < constants.length)
        {
            if(isConstantCreated(index))
            {
                while((result = constants[index]) == null) Thread.yield();
            } else
            {
                int length = getConstantLength(index);
                try
                {
                    result = length == 0 ? empty : new String(0, length, (char[]) char[].class.newArrayAt(getConstantPointer(index), length));
                }
                catch(Throwable e)
                {
                    result = empty;
                }
                constants[index] = result;
            }
        }
        return result;
    }

    private static native boolean isConstantCreated(int index);

    private static native int getConstantCount();

    private static native int getConstantLength(int index);

    private static native long getConstantPointer(int index);


    private final int fldOffset;
    private final int fldLength;
    private final char[] fldChars;

    public () {  }

    public (char src) {
        fldLength = 1;
        fldChars = new char[] { src };
    }

    public (CharArray src) {
        if(src == null) return;
        int thisLength = fldLength = src.length;
        if(thisLength <= 0) return;
        if(src instanceof char[])
        {
            Array.copy((char[]) src, 0, fldChars = new char[thisLength], 0, thisLength);
        }
        else if(src instanceof String)
        {
            String anot = (String) src;
            fldOffset = anot.fldOffset;
            fldChars = anot.fldChars;
        }
        else
        {
            char[] thisChars = fldChars = new char[thisLength];
            for(int i = 0; i < thisLength; i++) thisChars[i] = src[i];
        }
    }

    public (CharArray src, int offset, int length) {
        if(src == null) return;
        int2 bounds = Array.intersectBounds(src, offset, length);
        int thisLength = fldLength = bounds[1];
        if(thisLength <= 0) return;
        if(src instanceof char[])
        {
            Array.copy((char[]) src, bounds[0], fldChars = new char[thisLength], 0, thisLength);
        }
        else if(src instanceof String)
        {
            String anot = (String) src;
            fldOffset = anot.fldOffset + bounds[0];
            fldChars = anot.fldChars;
        }
        else
        {
            char[] thisChars = fldChars = new char[thisLength];
            for(int i = 0, int j = bounds[0]; i < thisLength; i++, j++) thisChars[i] = src[j];
        }
    }

    public (ByteArray src) {
        if(src == null) return;
        char[] thisChars = Charset.getDefault().decode(src);
        int thisLength = fldLength = thisChars.length;
        if(thisLength > 0) Array.copy(thisChars, 0, fldChars = new char[thisLength], 0, thisLength);
    }

    public (ByteArray src, int offset, int length) {
        if(src == null) return;
        int2 bounds = Array.intersectBounds(src, offset, length);
        char[] thisChars = Charset.getDefault().decode(src, bounds[0], bounds[1]);
        int thisLength = fldLength = thisChars.length;
        if(thisLength > 0) Array.copy(thisChars, 0, fldChars = new char[thisLength], 0, thisLength);
    }

    public (ByteArray src, Charset charset) {
        if(src == null) return;
        char[] thisChars = (charset == null ? Charset.getDefault() : charset).decode(src);
        int thisLength = fldLength = thisChars.length;
        if(thisLength > 0) Array.copy(thisChars, 0, fldChars = new char[thisLength], 0, thisLength);
    }

    public (ByteArray src, int offset, int length, Charset charset) {
        if(src == null) return;
        int2 bounds = Array.intersectBounds(src, offset, length);
        char[] thisChars = (charset == null ? Charset.getDefault() : charset).decode(src, bounds[0], bounds[1]);
        int thisLength = fldLength = thisChars.length;
        if(thisLength > 0) Array.copy(thisChars, 0, fldChars = new char[thisLength], 0, thisLength);
    }

    private (int offset, int length, char[] chars) {
        fldOffset = offset;
        fldLength = length;
        fldChars = chars;
    }

    public boolean equals(Object anot) {
        if(anot == this) return true;
        label0: if(anot instanceof String)
        {
            with((String) anot)
            {
                int thisLength = this.fldLength;
                if(thisLength != fldLength) break label0;
                int anotOffset = fldOffset;
                char[] anotChars = fldChars;
                int thisOffset = this.fldOffset;
                char[] thisChars = this.fldChars;
                if(thisChars != anotChars || thisOffset != anotOffset)
                {
                    while(thisLength-- > 0)
                    {
                        if(thisChars[thisOffset++] != anotChars[anotOffset++]) break label0;
                    }
                }
            }
            return true;
        }
        return false;
    }

    public int hashCode() {
        int result = 0;
        for(char[] thisChars = fldChars, int thisOffset = fldOffset, int thisLength = fldLength, int e = 1; thisLength-- > 0; e *= 31)
        {
            result += e * (int) thisChars[thisOffset++];
        }
        return result;
    }

    public long hashCodeAsLong() {
        long result = 0L;
        for(char[] thisChars = fldChars, int thisOffset = fldOffset, int thisLength = fldLength, long e = 1L; thisLength-- > 0; e *= 31L)
        {
            result += e * (long) thisChars[thisOffset++];
        }
        return result;
    }

    public long2 hashCodeAsLong2() {
        long2 result = 0L;
        for(char[] thisChars = fldChars, int thisOffset = fldOffset, int thisLength = fldLength, long2 e = 1L; thisLength-- > 0; e = Int128.mul(e, 31L))
        {
            result = Int128.add(result, Int128.mul(e, (long2) thisChars[thisOffset++]));
        }
        return result;
    }

    public String toString() { return this; }

    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);
        if(dst instanceof char[])
        {
            Array.copy(fldChars, fldOffset + beginIndex, (char[]) dst, offset, length);
            return;
        }
        for(char[] thisChars = fldChars, int thisOffset = fldOffset + beginIndex; length-- > 0; ) dst[offset++] = thisChars[thisOffset++];
    }

    public char[] toCharArray() {
        int thisLength = fldLength;
        char[] result = new char[thisLength];
        Array.copy(fldChars, fldOffset, result, 0, thisLength);
        return result;
    }

    public String subsequence(int beginIndex, int endIndex) { return substring(beginIndex, endIndex); }

    public String subsequence(int beginIndex) { return substring(beginIndex, fldLength); }

    public String clone() { return new String(fldOffset, fldLength, fldChars); }

    public boolean isEmpty() { return fldLength <= 0; }

    public int compareTo(Comparable anot) {
        if(anot == this) return EQUALS;
        if(anot instanceof String)
        {
            with((String) anot)
            {
                int anotOffset = fldOffset;
                int anotLength = fldLength;
                char[] anotChars = fldChars;
                int thisOffset = this.fldOffset;
                int thisLength = this.fldLength;
                char[] thisChars = this.fldChars;
                if(thisChars != anotChars || thisOffset != anotOffset || thisLength != anotLength)
                {
                    for(int minLength = thisLength > anotLength ? anotLength : thisLength; minLength-- > 0; )
                    {
                        char thisChar = thisChars[thisOffset++];
                        char anotChar = anotChars[anotOffset++];
                        if(thisChar != anotChar) return thisChar - anotChar;
                    }
                    if(thisLength > anotLength) return 0x00010000;
                    if(thisLength < anotLength) return 0xffff0000;
                }
            }
            return EQUALS;
        }
        return INDEFINITE;
    }

    public boolean contentEquals(CharArray array) {
        int thisLength = fldLength;
        if(array == null || array.length < thisLength) return false;
        for(char[] thisChars = fldChars, int thisOffset = fldOffset, int offset = 0; thisLength-- > 0; )
        {
            if(thisChars[thisOffset++] != array[offset++]) return false;
        }
        return true;
    }

    public boolean contentEquals(CharArray array, int offset) {
        int thisLength = fldLength;
        if(array == null || offset < 0 || offset > array.length - fldLength) return false;
        for(char[] thisChars = fldChars, int thisOffset = fldOffset; thisLength-- > 0; )
        {
            if(thisChars[thisOffset++] != array[offset++]) return false;
        }
        return true;
    }

    public boolean contains(CharArray array) {
        if(array == null) return false;
        int length = array.length;
        if(length <= 0) return true;
        int thisOffset = fldOffset;
        int thisLimit = thisOffset + fldLength - length;
        if(thisOffset > thisLimit) return false;
        char[] thisChars = fldChars;
        char first = array[0];
        do
        {
            label0: if(thisChars[thisOffset++] == first)
            {
                for(int i = thisOffset, int j = 1; j < length; )
                {
                    if(thisChars[i++] != array[j++]) break label0;
                }
                return true;
            }
        } while(thisOffset <= thisLimit);
        return false;
    }

    public boolean contains(CharArray array, int offset, int length) {
        if(array == null) return false;
        int2 bounds = Array.intersectBounds(array, offset, length);
        if((length = bounds[1]) <= 0) return true;
        offset = bounds[0];
        int thisOffset = fldOffset;
        int thisLimit = thisOffset + fldLength - length;
        if(thisOffset > thisLimit) return false;
        char[] thisChars = fldChars;
        char first = array[offset++];
        do
        {
            label0: if(thisChars[thisOffset++] == first)
            {
                for(int i = thisOffset, int j = offset, int k = length; k-- > 0; )
                {
                    if(thisChars[i++] != array[j++]) break label0;
                }
                return true;
            }
        } while(thisOffset <= thisLimit);
        return false;
    }

    public boolean equalsIgnoreCase(String anot) {
        int thisLength = fldLength;
        return anot != null && thisLength == anot.fldLength && regionMatches(true, 0, anot, 0, thisLength);
    }

    public boolean regionMatches(int thisOffset, String anot, int anotOffset, int length) {
        if(anot == null) return false;
        int lim = thisOffset + length;
        int len = fldLength;
        if(lim > len || lim < thisOffset || thisOffset > len || thisOffset < 0 || (lim = anotOffset + length) > (len = anot.fldLength) || lim < anotOffset || anotOffset > len || anotOffset < 0) return false;
        thisOffset += fldOffset;
        anotOffset += anot.fldOffset;
        char[] thisChars = fldChars;
        char[] anotChars = anot.fldChars;
        do
        {
            if(length-- <= 0) return true;
        } while(thisChars[thisOffset++] == anotChars[anotOffset++]);
        return false;
    }

    public boolean regionMatches(boolean ignoreCase, int thisOffset, String anot, int anotOffset, int length) {
        if(anot == null) return false;
        int lim = thisOffset + length;
        int len = fldLength;
        if(lim > len || lim < thisOffset || thisOffset > len || thisOffset < 0 || (lim = anotOffset + length) > (len = anot.fldLength) || lim < anotOffset || anotOffset > len || anotOffset < 0) return false;
        thisOffset += fldOffset;
        anotOffset += anot.fldOffset;
        char[] thisChars = fldChars;
        char[] anotChars = anot.fldChars;
        char thisChar;
        char anotChar;
        do
        {
            do
            {
                if(length-- <= 0) return true;
            } while((thisChar = thisChars[thisOffset++]) == (anotChar = anotChars[anotOffset++]));
            if(!ignoreCase) break;
        } while(Char.toUpperCase(thisChar) == Char.toUpperCase(anotChar) || Char.toLowerCase(thisChar) == Char.toLowerCase(anotChar));
        return false;
    }

    public boolean endsWith(String suffix) {
        if(suffix == null)
        {
            throw new NullPointerException("аргумент suffix равен нулевой ссылке");
        }
        return startsWith(suffix, fldLength - suffix.fldLength);
    }

    public boolean startsWith(String prefix) {
        if(prefix == null)
        {
            throw new NullPointerException("аргумент prefix равен нулевой ссылке");
        }
        return startsWith(prefix, 0);
    }

    public boolean startsWith(String prefix, int offset) {
        if(prefix == null)
        {
            throw new NullPointerException("аргумент prefix равен нулевой ссылке");
        }
        int anotLength = prefix.fldLength;
        if(offset < 0 || offset > fldLength - anotLength) return false;
        for(char[] thisChars = fldChars, char[] anotChars = prefix.fldChars, int i = fldOffset + offset, int j = prefix.fldOffset; anotLength-- > 0; i++, j++)
        {
            if(thisChars[i] != anotChars[j]) return false;
        }
        return true;
    }

    public int indexOf(int character) {
        if(character < 0 || character >= 0xffff) return -1;
        int thisLength = fldLength;
        if(thisLength <= 0) return -1;
        int thisOffset = fldOffset;
        int index = Array.indexOf(character, fldChars, thisOffset, thisLength);
        return index < 0 ? -1 : index - thisOffset;
    }

    public int indexOf(int character, int startFromIndex) {
        if(character < 0 || character >= 0xffff) return -1;
        int thisLength = fldLength;
        if(startFromIndex < 0) startFromIndex = 0;
        if(startFromIndex >= thisLength) return -1;
        int thisOffset = fldOffset;
        int index = Array.indexOf(character, fldChars, thisOffset + startFromIndex, thisLength - startFromIndex);
        return index < 0 ? -1 : index - thisOffset;
    }

    public int indexOf(String string) { return indexOf(string, 0); }

    public int indexOf(String string, int startFromIndex) {
        if(string == null)
        {
            throw new NullPointerException("аргумент string равен нулевой ссылке");
        }
        int thisOffset = fldOffset;
        int anotLength = string.fldLength;
        int thisLimit = fldLength - anotLength;
        if(startFromIndex < 0) startFromIndex = 0;
        if(startFromIndex > thisLimit) return -1;
        if(anotLength <= 0) return startFromIndex;
        char[] thisChars = fldChars;
        int anotOffset = string.fldOffset;
        char[] anotChars = string.fldChars;
        char first = anotChars[anotOffset++];
        thisOffset += startFromIndex;
        do
        {
            label0: if(thisChars[thisOffset++] == first)
            {
                for(int i = thisOffset, int j = anotOffset, int k = anotLength; k-- > 1; i++, j++)
                {
                    if(thisChars[i] != anotChars[j]) break label0;
                }
                return startFromIndex;
            }
        } while(++startFromIndex <= thisLimit);
        return -1;
    }

    public int lastIndexOf(int character) {
        int thisLength = fldLength;
        if(thisLength <= 0) return -1;
        int thisOffset = fldOffset;
        int index = Array.lastIndexOf(character, fldChars, thisOffset + thisLength - 1, thisLength);
        return index < 0 ? -1 : index - thisOffset;
    }

    public int lastIndexOf(int character, int startFromIndex) {
        int thisLength = fldLength;
        if(startFromIndex >= thisLength) startFromIndex = thisLength - 1;
        if(startFromIndex < 0) return -1;
        int thisOffset = fldOffset;
        int index = Array.lastIndexOf(character, fldChars, thisOffset + startFromIndex, startFromIndex + 1);
        return index < 0 ? -1 : index - thisOffset;
    }

    public int lastIndexOf(String string) { return lastIndexOf(string, Int.MAX_VALUE); }

    public int lastIndexOf(String string, int startFromIndex) {
        if(string == null)
        {
            throw new NullPointerException("аргумент string равен нулевой ссылке");
        }
        int thisOffset = fldOffset;
        int anotLength = string.fldLength;
        int thisLimit = fldLength - anotLength;
        if(startFromIndex > thisLimit) startFromIndex = thisLimit;
        if(startFromIndex < 0) return -1;
        if(anotLength <= 0) return startFromIndex;
        char[] thisChars = fldChars;
        int anotOffset = string.fldOffset;
        char[] anotChars = string.fldChars;
        char first = anotChars[anotOffset++];
        thisOffset += startFromIndex;
        do
        {
            label0: if(thisChars[thisOffset--] == first)
            {
                for(int i = thisOffset, int j = anotOffset, int k = anotLength; k-- > 1; i++, j++)
                {
                    if(thisChars[i] != anotChars[j]) break label0;
                }
                return startFromIndex;
            }
        } while(--startFromIndex >= 0);
        return -1;
    }

    public int compareToIgnoreCase(String anot) {
        if(anot == this) return EQUALS;
        int thisOffset = fldOffset;
        int thisLength = fldLength;
        char[] thisChars = fldChars;
        int anotOffset = anot.fldOffset;
        int anotLength = anot.fldLength;
        char[] anotChars = anot.fldChars;
        if(thisChars != anotChars || thisOffset != anotOffset || thisLength != anotLength)
        {
            for(int minLength = thisLength > anotLength ? anotLength : thisLength; minLength-- > 0; )
            {
                char thisChar = Char.toUpperCase(thisChars[thisOffset++]);
                char anotChar = Char.toUpperCase(anotChars[anotOffset++]);
                if(thisChar != anotChar) return thisChar - anotChar;
            }
            if(thisLength > anotLength) return 0x00010000;
            if(thisLength < anotLength) return 0xffff0000;
        }
        return EQUALS;
    }

    public byte[] toByteArray() {
        int length = fldLength;
        return length <= 0 ? new byte[0] : Charset.getDefault().encode(fldChars, fldOffset, length);
    }

    public byte[] toByteArray(Charset charset) {
        int length = fldLength;
        return length <= 0 ? new byte[0] : (charset != null ? charset : Charset.getDefault()).encode(fldChars, fldOffset, length);
    }

    public byte[] toByteArray(String charsetName) throws UnsupportedCharsetNameException {
        int length = fldLength;
        Charset charset = Charset.get(charsetName);
        return length <= 0 ? new byte[0] : charset.encode(fldChars, fldOffset, length);
    }

    public String[] split() {
        int boundsLength = 0;
        int2[] boundsData = new int2[15];
        int thisLength = fldLength;
        char[] thisChars = fldChars;
        for(int beginIndex = fldOffset, int thisLimit = beginIndex + thisLength; beginIndex <= thisLimit; )
        {
            char character = '\0';
            int endIndex = beginIndex;
            while(endIndex < thisLimit && (character = thisChars[endIndex]) != '\n' && character != '\r') endIndex++;
            if(boundsLength == boundsData.length)
            {
                Array.copy(boundsData, 0, boundsData = new int2[(boundsLength << 1) + 1], 0, boundsLength);
            }
            boundsData[boundsLength++] = new int2 { beginIndex, endIndex - beginIndex };
            beginIndex = endIndex + 1;
            if(character == '\r' && beginIndex < thisLimit && thisChars[beginIndex] == '\n') beginIndex++;
        }
        String[] result = new String[boundsLength];
        while(boundsLength-- > 0)
        {
            int2 bounds = boundsData[boundsLength];
            int resultLength = bounds[1];
            result[boundsLength] = resultLength == 0 ? "" : resultLength == thisLength ? this : new String(bounds[0], resultLength, thisChars);
        }
        return result;
    }

    public String trim() {
        int beginIndex = fldOffset;
        int endIndex = beginIndex + fldLength - 1;
        int i = beginIndex;
        int j = endIndex;
        char[] thisChars = fldChars;
        while(i <= j && thisChars[i] <= '\u0020') i++;
        while(i <= j && thisChars[j] <= '\u0020') j--;
        return i > j ? "" : i == beginIndex && j == endIndex ? this : new String(i, j - i + 1, thisChars);
    }

    public String intern() {
        for(int i = constants.length; i-- > 0; )
        {
            String string = constants[i];
            if(string != null && equals(string)) return string;
        }
        return Runtime.getInstance().intern(this);
    }

    public String toLowerCase() {
        int thisOffset = fldOffset;
        int thisLength = fldLength;
        char[] thisChars = fldChars;
        int i = thisOffset;
        label0:
        {
            for(int thisLimit = thisOffset + thisLength; i < thisLimit; i++)
            {
                char character = thisChars[i];
                if(character != Char.toLowerCase(character)) break label0;
            }
            return this;
        }
        char[] resultChars = new char[thisLength];
        for(int j = i - thisOffset, Array.copy(thisChars, thisOffset, resultChars, 0, j); j < thisLength; i++, j++)
        {
            resultChars[j] = Char.toLowerCase(thisChars[i]);
        }
        return new String(0, thisLength, resultChars);
    }

    public String toUpperCase() {
        int thisOffset = fldOffset;
        int thisLength = fldLength;
        char[] thisChars = fldChars;
        int i = thisOffset;
        label0:
        {
            for(int thisLimit = thisOffset + thisLength; i < thisLimit; i++)
            {
                char character = thisChars[i];
                if(character != Char.toUpperCase(character)) break label0;
            }
            return this;
        }
        char[] resultChars = new char[thisLength];
        for(int j = i - thisOffset, Array.copy(thisChars, thisOffset, resultChars, 0, j); j < thisLength; i++, j++)
        {
            resultChars[j] = Char.toUpperCase(thisChars[i]);
        }
        return new String(0, thisLength, resultChars);
    }

    public String substring(int beginIndex) {
        int thisLength = fldLength;
        if(beginIndex < 0 || beginIndex > thisLength)
        {
            throw new StringIndexOutOfBoundsException("индекс символа строки выходит из диапазона");
        }
        return beginIndex == thisLength ? "" : beginIndex == 0 ? this : new String(fldOffset + beginIndex, thisLength - beginIndex, fldChars);
    }

    public String substring(int beginIndex, int endIndex) {
        int thisLength = fldLength;
        if((beginIndex | endIndex) < 0 || beginIndex > thisLength || endIndex > thisLength || beginIndex > endIndex)
        {
            throw new StringIndexOutOfBoundsException("индекс символа строки выходит из диапазона");
        }
        int resultLength = endIndex - beginIndex;
        return resultLength == 0 ? "" : resultLength == thisLength ? this : new String(fldOffset + beginIndex, resultLength, fldChars);
    }

    public String replace(char oldCharacter, char newCharacter) {
        int thisLength = fldLength;
        if(thisLength <= 0 || oldCharacter == newCharacter) return this;
        int thisOffset = fldOffset;
        char[] thisChars = fldChars;
        int i = Array.indexOf(oldCharacter, thisChars, thisOffset, thisLength);
        if(i < 0) return this;
        char[] resultChars = new char[thisLength];
        for(int j = i - thisOffset, Array.copy(thisChars, thisOffset, resultChars, 0, j); j < thisLength; i++, j++)
        {
            char character = thisChars[i];
            resultChars[j] = (char) (character != oldCharacter ? character : newCharacter);
        }
        return new String(0, thisLength, resultChars);
    }

    public String replace(String oldString, String newString) {
        if(oldString == null)
        {
            throw new NullPointerException("аргумент oldString равен нулевой ссылке");
        }
        if(newString == null)
        {
            throw new NullPointerException("аргумент newString равен нулевой ссылке");
        }
        int thisLength = fldLength;
        int oldLength = oldString.fldLength;
        if(oldLength <= 0 || thisLength <= 0 || oldString.equals(newString)) return this;
        int indexLength = 0;
        int[] indexData = new int[31];
        for(int index = 0; (index = indexOf(oldString, index)) >= 0; index += oldLength)
        {
            if(indexLength == indexData.length)
            {
                Array.copy(indexData, 0, indexData = new int[(indexLength << 1) + 1], 0, length);
            }
            indexData[indexLength++] = index;
        }
        if(indexLength <= 0) return this;
        int newLength = newString.fldLength;
        long longLength = (long) thisLength + (long) indexLength * (long) (newLength - oldLength);
        if(longLength > (long) Int.MAX_VALUE || longLength < 0L)
        {
            throw new BufferTooLargeError("объём буфера очень велик");
        }
        int thisEnd = thisLength;
        int thisOffset = fldOffset;
        char[] thisChars = fldChars;
        int resultEnd = (int) longLength;
        int resultLength = resultEnd;
        char[] resultChars = new char[resultLength];
        int newOffset = newString.fldOffset;
        char[] newChars = newString.fldChars;
        while(indexLength-- > 0)
        {
            int thisBegin = indexData[indexLength] + oldLength;
            int copyLength = thisEnd - thisBegin;
            int resultBegin = resultEnd - copyLength;
            Array.copy(thisChars, thisOffset + thisBegin, resultChars, resultBegin, copyLength);
            Array.copy(newChars, newOffset, resultChars, resultEnd = resultBegin - newLength, newLength);
            thisEnd = thisBegin - oldLength;
        }
        Array.copy(thisChars, thisOffset, resultChars, 0, thisEnd);
        return new String(0, resultLength, resultChars);
    }

    public String replaceFirst(char oldCharacter, char newCharacter) { return replaceFirst(oldCharacter, newCharacter, 0); }

    public String replaceFirst(char oldCharacter, char newCharacter, int startFromIndex) {
        int thisLength = fldLength;
        if(startFromIndex < 0) startFromIndex = 0;
        if(startFromIndex >= thisLength) return this;
        int thisOffset = fldOffset;
        char[] thisChars = fldChars;
        int index = Array.indexOf(oldCharacter, thisChars, thisOffset + startFromIndex, thisLength - startFromIndex);
        if(index < 0) return this;
        char[] resultChars = new char[thisLength];
        Array.copy(thisChars, thisOffset, resultChars, 0, thisLength);
        resultChars[index - thisOffset] = newCharacter;
        return new String(0, thisLength, resultChars);
    }

    public String replaceFirst(String oldString, String newString) { return replaceFirst(oldString, newString, 0); }

    public String replaceFirst(String oldString, String newString, int startFromIndex) {
        if(oldString == null)
        {
            throw new NullPointerException("аргумент oldString равен нулевой ссылке");
        }
        if(newString == null)
        {
            throw new NullPointerException("аргумент newString равен нулевой ссылке");
        }
        int thisLength = fldLength;
        int oldLength = oldString.fldLength;
        if(oldLength <= 0 || thisLength <= 0 || oldString.equals(newString)) return this;
        int index = indexOf(oldString, startFromIndex);
        if(index < 0) return this;
        int newLength = newString.fldLength;
        int resultLength = thisLength + (newLength - oldLength);
        if(resultLength < 0)
        {
            throw new BufferTooLargeError("объём буфера очень велик");
        }
        int thisOffset = fldOffset;
        char[] thisChars = fldChars;
        char[] resultChars = new char[resultLength];
        Array.copy(thisChars, thisOffset, resultChars, 0, index);
        Array.copy(newString.fldChars, newString.fldOffset, resultChars, index, newLength);
        Array.copy(thisChars, thisOffset + index + oldLength, resultChars, index += newLength, resultLength - index);
        return new String(0, resultLength, resultChars);
    }

    public String replaceLast(char oldCharacter, char newCharacter) { return replaceLast(oldCharacter, newCharacter, Int.MAX_VALUE); }

    public String replaceLast(char oldCharacter, char newCharacter, int startFromIndex) {
        int thisLength = fldLength;
        if(startFromIndex >= thisLength) startFromIndex = thisLength - 1;
        if(startFromIndex < 0) return this;
        int thisOffset = fldOffset;
        char[] thisChars = fldChars;
        int index = Array.lastIndexOf(oldCharacter, thisChars, thisOffset + startFromIndex, startFromIndex + 1);
        if(index < 0) return this;
        char[] resultChars = new char[thisLength];
        Array.copy(thisChars, thisOffset, resultChars, 0, thisLength);
        resultChars[index - thisOffset] = newCharacter;
        return new String(0, thisLength, resultChars);
    }

    public String replaceLast(String oldString, String newString) { return replaceLast(oldString, newString, Int.MAX_VALUE); }

    public String replaceLast(String oldString, String newString, int startFromIndex) {
        if(oldString == null)
        {
            throw new NullPointerException("аргумент oldString равен нулевой ссылке");
        }
        if(newString == null)
        {
            throw new NullPointerException("аргумент newString равен нулевой ссылке");
        }
        int thisLength = fldLength;
        int oldLength = oldString.fldLength;
        if(oldLength <= 0 || thisLength <= 0 || oldString.equals(newString)) return this;
        int index = lastIndexOf(oldString, startFromIndex);
        if(index < 0) return this;
        int newLength = newString.fldLength;
        int resultLength = thisLength + (newLength - oldLength);
        if(resultLength < 0)
        {
            throw new BufferTooLargeError("объём буфера очень велик");
        }
        int thisOffset = fldOffset;
        char[] thisChars = fldChars;
        char[] resultChars = new char[resultLength];
        Array.copy(thisChars, thisOffset, resultChars, 0, index);
        Array.copy(newString.fldChars, newString.fldOffset, resultChars, index, newLength);
        Array.copy(thisChars, thisOffset + index + oldLength, resultChars, index += newLength, resultLength - index);
        return new String(0, resultLength, resultChars);
    }

    public int length { read = fldLength }

    public char operator [](int index) {
        if(index < 0 || index >= fldLength)
        {
            throw new StringIndexOutOfBoundsException("индекс символа строки выходит из диапазона");
        }
        return fldChars[fldOffset + index];
    }

    public String operator +(String anot) {
        if(anot == null)
        {
            throw new NullPointerException("аргумент anot равен нулевой ссылке");
        }
        int anotLength = anot.fldLength;
        if(anotLength <= 0) return this;
        int thisLength = fldLength;
        if(thisLength <= 0) return anot;
        int resultLength = thisLength + anotLength;
        if(resultLength < 0)
        {
            throw new BufferTooLargeError("объём буфера очень велик");
        }
        char[] resultChars = new char[resultLength];
        Array.copy(fldChars, fldOffset, resultChars, 0, thisLength);
        Array.copy(anot.fldChars, anot.fldOffset, resultChars, thisLength, anotLength);
        return new String(0, resultLength, resultChars);
    }

    private void checkBounds(int beginIndex, int endIndex) {
        int thisLength = fldLength;
        if((beginIndex | endIndex) < 0 || beginIndex > thisLength || endIndex > thisLength || beginIndex > endIndex)
        {
            throw new StringIndexOutOfBoundsException("индекс символа строки выходит из диапазона");
        }
    }
}