/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package avt.lang;
import avt.io.charset.*;
import avt.lang.array.*;
import avt.lang.math.*;
import avt.lang.table.*;
import platform.dependent.*;
import platform.independent.streamformat.*;
public final class String(Object, CharSequence, DataHolder, Comparable, Cloneable, Measureable, CharArray)
{
private static byte[] created;
private static String[] constants;
private static String empty;
private static Mutex poolOperation;
private static HashValueTable poolTable;
public static String valueOf(boolean src) { return src ? "true" : "false"; }
public static String valueOf(char src) { return new String(src); }
public static native String valueOf(byte src);
public static native String valueOf(short src);
public static native String valueOf(int src);
public static native String valueOf(long src);
public static native String valueOf(float src);
public static native String valueOf(double src);
public static native String valueOf(real 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) return null;
int beginIndex = 0;
int formLength = form.length;
StringBuilder result = new StringBuilder();
label0: for(int endIndex = 0, int dataLength = data == null ? -1 : 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 isExpForm = false;
boolean significandAll = false;
boolean significandSign = false;
boolean orderSign = true;
boolean leadZeroOutput = false;
int significandDigits = 1;
int orderDigits = 0;
int leadZeroWidth = 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 == '0')
{
leadZeroOutput = true;
if(++formIndex >= formLength) break label0;
if((formChar = form[formIndex]) < '0' || formChar > '9')
{
result + form.substring(beginIndex, endIndex = formIndex + 1);
continue label0;
}
leadZeroWidth = formChar - '0';
if(++formIndex >= formLength) break label0;
if((formChar = form[formIndex]) >= '0' && formChar <= '9')
{
leadZeroWidth = (leadZeroWidth * 10) + (formChar - '0');
if(++formIndex >= formLength) break label0;
formChar = form[formIndex];
}
} else
{
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];
}
if(significandDigits++ < 1)
{
result + form.substring(beginIndex, endIndex = formIndex + 1);
continue label0;
}
if(formChar == 'A' || formChar == 'a')
{
significandAll = true;
if(++formIndex >= formLength) break label0;
formChar = form[formIndex];
}
}
if((isExpForm = 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 fieldWidth = 0;
if(formChar == ':')
{
if(++formIndex >= formLength) break label0;
if((formChar = form[formIndex]) < '0' || formChar > '9')
{
result + form.substring(beginIndex, endIndex = formIndex + 1);
continue label0;
}
fieldWidth = formChar - '0';
do
{
if(++formIndex >= formLength) break label0;
if((formChar = form[formIndex]) < '0' || formChar > '9') break;
int digit = formChar - '0';
if((fieldWidth *= 10) > (1024 - digit))
{
result + form.substring(beginIndex, endIndex = formIndex + 1);
continue label0;
}
fieldWidth += digit;
} while(true);
}
if(formChar != '%')
{
result + form.substring(beginIndex, endIndex = formIndex + 1);
continue label0;
}
if(dataLength < 0)
{
throw new NullPointerException(package.getResourceString("null-pointer.format-data"));
}
if(dataIndex < 0 || dataIndex >= dataLength)
{
throw new ArrayIndexOutOfBoundsException(package.getResourceString("out-of-bounds.array-index.format-data"));
}
Object dataComponent = data[dataIndex];
if(dataComponent == null)
{
throw new NullPointerException(package.getResourceString("null-pointer.format-data.component"));
}
String formatted;
if(isString)
{
formatted = dataComponent.toString();
} else
{
if(!(dataComponent instanceof Numeric))
{
throw new ClassCastException(package.getResourceString("class-cast.format-data")) { source = dataComponent.getClass(), destination = Numeric.class };
}
Numeric dataNumeric = (Numeric) dataComponent;
if(isReal)
{
formatted = Real.toString(
dataNumeric.asReal(), significandDigits <= 1 ? RealRepresenter.MAX_SIGNIFICAND_DIGITS : significandDigits, orderDigits,
significandAll, orderDigits > 0, isExpForm, significandSign, orderSign
);
} else
{
long number = dataNumeric.asLong();
formatted = leadZeroOutput ? Long.toLeadZeroString(number, leadZeroWidth) : Long.toString(number);
if(significandSign && number >= 0) formatted = "+" + formatted;
}
}
int formattedWidth = formatted.length;
if(fieldWidth > formattedWidth) for(int count = fieldWidth - formattedWidth; count-- > 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 void initialize() {
int length = getConstantCount();
created = new byte[length + 7 >> 3];
constants = new String[length];
empty = new String();
poolOperation = Runtime.getInstance().newMutex();
(poolTable = new HashValueTable()).append(empty.hashCodeAsLong2(), empty);
}
package static void clean() {
if(poolTable != null)
{
boolean cleaning = true;
Mutex operation = poolOperation;
RemoveWeakValueState state = new RemoveWeakValueState();
do
{
operation.lock();
try
{
for(int count = 0x0400; count-- > 0; ) if(!poolTable.removeWeakValue(state))
{
cleaning = false;
break;
}
} finally
{
operation.unlock();
}
} while(cleaning);
}
}
package static String getConstant(int index) {
if(index < 0 || index >= constants.length)
{
return null;
}
String result;
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))).intern();
}
catch(Throwable exception)
{
result = empty;
}
constants[index] = result;
}
if(result.fldLength <= 0 && getConstantLength(index) > 0)
{
Runtime.getInstance().throwOutOfMemoryError();
}
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 boolean fldIsHashAsInt032Computed;
private boolean fldIsHashAsInt064Computed;
private boolean fldIsHashAsInt128Computed;
private int fldHashAsInt032;
private long fldHashAsInt064;
private long2 fldHashAsInt128;
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 length = fldLength = src.length;
if(length <= 0) return;
if(src instanceof StringBuilder)
{
src = ((StringBuilder) src).fldContent;
}
if(src instanceof char[])
{
Array.copy((char[]) src, 0, fldChars = new char[length], 0, length);
}
else if(!(src instanceof String))
{
char[] chars = fldChars = new char[length];
for(int chi = 0; chi < length; chi++) chars[chi] = src[chi];
}
else
{
String anot = (String) src;
fldOffset = anot.fldOffset;
fldChars = anot.fldChars;
}
}
public (CharArray src, int offset, int length) {
if(src == null) return;
int2 bounds = Array.intersectBounds(src, offset, length);
if((length = fldLength = bounds[1]) <= 0) return;
if(src instanceof StringBuilder)
{
src = ((StringBuilder) src).fldContent;
}
if(src instanceof char[])
{
Array.copy((char[]) src, bounds[0], fldChars = new char[length], 0, length);
}
else if(!(src instanceof String))
{
char[] chars = fldChars = new char[length];
for(int chi = 0, int chj = bounds[0]; chi < length; chi++, chj++) chars[chi] = src[chj];
}
else
{
String anot = (String) src;
fldOffset = anot.fldOffset + bounds[0];
fldChars = anot.fldChars;
}
}
public (ByteArray src) {
if(src == null) return;
fldLength = (fldChars = Charset.getDefault().decode(src)).length;
}
public (ByteArray src, int offset, int length) {
if(src == null) return;
int2 bounds = Array.intersectBounds(src, offset, length);
fldLength = (fldChars = Charset.getDefault().decode(src, bounds[0], bounds[1])).length;
}
public (ByteArray src, Charset charset) {
if(src == null) return;
fldLength = (fldChars = (charset != null ? charset : Charset.getDefault()).decode(src)).length;
}
public (ByteArray src, int offset, int length, Charset charset) {
if(src == null) return;
int2 bounds = Array.intersectBounds(src, offset, length);
fldLength = (fldChars = (charset != null ? charset : Charset.getDefault()).decode(src, bounds[0], bounds[1])).length;
}
private (int offset, int length, char[] chars) {
fldOffset = offset;
fldLength = length;
fldChars = chars;
}
public boolean equals(Object anot) {
if(anot == this) return true;
if(anot instanceof String)
{
int thisLength = fldLength;
String astr = (String) anot;
if(thisLength == astr.fldLength)
{
int thisOffset = this.fldOffset;
int anotOffset = astr.fldOffset;
char[] thisChars = this.fldChars;
char[] anotChars = astr.fldChars;
if(thisChars == anotChars && thisOffset == anotOffset || thisLength <= 0 || Array.offsetOfNonEqual(thisChars, thisOffset, anotChars, anotOffset, thisLength) == INDEFINITE) return true;
}
}
return false;
}
public int hashCode() {
if(fldIsHashAsInt032Computed) return fldHashAsInt032;
int result = 0i;
for(char[] chars = fldChars, int offset = fldOffset, int length = fldLength, int mult = 1; length-- > 0; mult *= 31)
{
result += mult * (int) chars[offset++];
}
fldHashAsInt032 = result;
fldIsHashAsInt032Computed = true;
return result;
}
public long hashCodeAsLong() {
if(fldIsHashAsInt064Computed) return fldHashAsInt064;
long result = 0L;
for(char[] chars = fldChars, int offset = fldOffset, int length = fldLength, long mult = 1; length-- > 0; mult *= 31)
{
result += mult * (long) chars[offset++];
}
fldHashAsInt064 = result;
fldIsHashAsInt064Computed = true;
return result;
}
public long2 hashCodeAsLong2() {
if(fldIsHashAsInt128Computed) return fldHashAsInt128;
long2 result = 0L;
for(char[] chars = fldChars, int offset = fldOffset, int length = fldLength, long2 mult = 1; length-- > 0; mult = Int128.mul(mult, 31))
{
result = Int128.add(result, Int128.mul(mult, (long2) chars[offset++]));
}
fldHashAsInt128 = result;
fldIsHashAsInt128Computed = true;
return result;
}
public String toString() { return this; }
public void getChars(int beginIndex, int endIndex, MutableCharArray dst, int offset) {
int length = fldLength;
if((beginIndex | endIndex) < 0 || beginIndex > length || endIndex > length || beginIndex > endIndex)
{
throw new StringIndexOutOfBoundsException(package.getResourceString("out-of-bounds.string-index"));
}
if(dst == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "dst" }));
}
Array.checkBounds(dst, offset, length = endIndex - beginIndex);
if(dst instanceof StringBuilder)
{
dst = ((StringBuilder) dst).fldContent;
}
if(dst instanceof char[])
{
Array.copy(fldChars, fldOffset + beginIndex, (char[]) dst, offset, length);
return;
}
for(char[] chars = fldChars, beginIndex += fldOffset; length-- > 0; ) dst[offset++] = chars[beginIndex++];
}
public char[] toCharArray() {
int length = fldLength;
char[] result = new char[length];
Array.copy(fldChars, fldOffset, result, 0, length);
return result;
}
public String join(CharSequence anot) {
if(anot == null) return this;
int anotLength = anot.length;
if(anotLength <= 0) return this;
int thisLength = fldLength;
int resultLength = anotLength + thisLength;
if(resultLength < 0)
{
throw new BufferTooLargeError(package.getResourceString("!error.buffer-too-large"));
}
char[] resultChars = new char[resultLength];
Array.copy(fldChars, fldOffset, resultChars, 0, thisLength);
anot.getChars(0, anotLength, resultChars, thisLength);
return new String(resultChars, 0, resultLength);
}
public String join(CharSequence[] seqs) {
if(seqs == null) return this;
int seqsLength = seqs.length;
if(seqsLength <= 0) return this;
int thisLength = fldLength;
int resultLength = thisLength;
int[] seqsLengths = new int[seqsLength];
CharSequence[] seqsCopy = new CharSequence[seqsLength];
for(int index = 0; index < seqsLength; index++)
{
Measureable seq = seqsCopy[index] = seqs[index];
int anotLength = seq == null ? 0 : seq.length;
if(anotLength < 0) anotLength = 0;
if((resultLength += anotLength) < 0)
{
throw new BufferTooLargeError(package.getResourceString("!error.buffer-too-large"));
}
seqsLengths[index] = anotLength;
}
char[] resultChars = new char[resultLength];
Array.copy(fldChars, fldOffset, resultChars, 0, thisLength);
for(int resultPosition = thisLength, int index = 0; index < seqsLength; index++)
{
int anotLength = seqsLengths[index];
if(anotLength > 0)
{
seqsCopy[index].getChars(0, anotLength, resultChars, resultPosition);
resultPosition += anotLength;
}
}
return new String(resultChars, 0, resultLength);
}
public String subsequence(int beginIndex) {
int length = fldLength;
if(beginIndex < 0 || beginIndex > length)
{
throw new StringIndexOutOfBoundsException(package.getResourceString("out-of-bounds.string-index"));
}
return beginIndex == length ? "" : beginIndex == 0 ? this : new String(fldOffset + beginIndex, length - beginIndex, fldChars);
}
public String subsequence(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"));
}
return beginIndex == endIndex ? "" : beginIndex == endIndex - length ? this : new String(fldOffset + beginIndex, endIndex - beginIndex, fldChars);
}
public boolean isEmpty() { return fldLength <= 0; }
public int compareTo(Comparable anot) {
if(anot == this) return EQUALS;
if(anot instanceof String)
{
String astr = (String) anot;
int thisLength = fldLength;
int anotLength = astr.fldLength;
if(anotLength <= 0) return thisLength;
if(thisLength <= 0) return -anotLength;
int thisOffset = fldOffset;
int anotOffset = astr.fldOffset;
char[] thisChars = fldChars;
char[] anotChars = astr.fldChars;
int nonEqualOffset = Array.offsetOfNonEqual(thisChars, thisOffset, anotChars, anotOffset, thisLength < anotLength ? thisLength : anotLength);
return nonEqualOffset < 0 ? thisLength - anotLength : thisChars[thisOffset + nonEqualOffset] - anotChars[anotOffset + nonEqualOffset];
}
return INDEFINITE;
}
public String clone() { return new String(fldOffset, fldLength, fldChars); }
public boolean contentEquals(CharArray array) {
int thisLength = fldLength;
if(array == null || array.length < thisLength)
{
return false;
}
if(thisLength <= 0)
{
return true;
}
if(array instanceof StringBuilder)
{
array = ((StringBuilder) array).fldContent;
}
if(array instanceof char[])
{
return Array.offsetOfNonEqual(fldChars, fldOffset, (char[]) array, 0, thisLength) == INDEFINITE;
}
if(array instanceof String)
{
String anot = (String) array;
return Array.offsetOfNonEqual(fldChars, fldOffset, anot.fldChars, anot.fldOffset, thisLength) == INDEFINITE;
}
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 - thisLength)
{
return false;
}
if(thisLength <= 0)
{
return true;
}
if(array instanceof StringBuilder)
{
array = ((StringBuilder) array).fldContent;
}
if(array instanceof char[])
{
return Array.offsetOfNonEqual(fldChars, fldOffset, (char[]) array, offset, thisLength) == INDEFINITE;
}
if(array instanceof String)
{
String anot = (String) array;
return Array.offsetOfNonEqual(fldChars, fldOffset, anot.fldChars, anot.fldOffset + offset, thisLength) == INDEFINITE;
}
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;
if(array instanceof StringBuilder)
{
array = ((StringBuilder) array).fldContent;
}
if(array instanceof char[])
{
char[] astr = (char[]) array;
char first = astr[0];
while((thisOffset = Array.indexOf(first, thisChars, thisOffset, thisLimit - thisOffset) + 1) > 0)
{
if(length <= 0 || Array.offsetOfNonEqual(thisChars, thisOffset, astr, 1, length) == INDEFINITE) return true;
if(thisOffset >= thisLimit) break;
}
}
else if(array instanceof String)
{
String astr = (String) array;
int anotOffset = astr.fldOffset;
char[] anotChars = astr.fldChars;
char first = anotChars[anotOffset++];
while((thisOffset = Array.indexOf(first, thisChars, thisOffset, thisLimit - thisOffset) + 1) > 0)
{
if(length <= 0 || Array.offsetOfNonEqual(thisChars, thisOffset, anotChars, anotOffset, length) == INDEFINITE) return true;
if(thisOffset >= thisLimit) break;
}
}
else
{
char first = array[0];
while((thisOffset = Array.indexOf(first, thisChars, thisOffset, thisLimit - thisOffset) + 1) > 0)
{
label0:
{
for(int chi = thisOffset, int chj = 0; chj < length; ) if(thisChars[chi++] != array[++chj]) break label0;
return true;
}
if(thisOffset >= thisLimit) break;
}
}
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;
int thisOffset = fldOffset;
int thisLimit = thisOffset + fldLength - --length;
if(thisOffset >= thisLimit) return false;
char[] thisChars = fldChars;
offset = bounds[0];
if(array instanceof StringBuilder)
{
array = ((StringBuilder) array).fldContent;
}
if(array instanceof char[])
{
char[] astr = (char[]) array;
char first = astr[offset++];
while((thisOffset = Array.indexOf(first, thisChars, thisOffset, thisLimit - thisOffset) + 1) > 0)
{
if(length <= 0 || Array.offsetOfNonEqual(thisChars, thisOffset, astr, offset, length) == INDEFINITE) return true;
if(thisOffset >= thisLimit) break;
}
}
else if(array instanceof String)
{
String astr = (String) array;
int anotOffset = astr.fldOffset + offset;
char[] anotChars = astr.fldChars;
char first = anotChars[anotOffset++];
while((thisOffset = Array.indexOf(first, thisChars, thisOffset, thisLimit - thisOffset) + 1) > 0)
{
if(length <= 0 || Array.offsetOfNonEqual(thisChars, thisOffset, anotChars, anotOffset, length) == INDEFINITE) return true;
if(thisOffset >= thisLimit) break;
}
}
else
{
char first = array[offset];
while((thisOffset = Array.indexOf(first, thisChars, thisOffset, thisLimit - thisOffset) + 1) > 0)
{
label0:
{
for(int chi = thisOffset, int chj = offset, int count = length; count-- > 0; ) if(thisChars[chi++] != array[++chj]) break label0;
return true;
}
if(thisOffset >= thisLimit) break;
}
}
return false;
}
public boolean equalsIgnoreCase(String anot) {
int thisLength = fldLength;
return anot != null && thisLength == anot.fldLength && regionMatches(0, anot, 0, thisLength, true);
}
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;
}
return length <= 0 || Array.offsetOfNonEqual(fldChars, fldOffset + thisOffset, anot.fldChars, anot.fldOffset + anotOffset, length) == INDEFINITE;
}
public boolean regionMatches(int thisOffset, String anot, int anotOffset, int length, boolean isIgnoreCase) {
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;
int nonEqualOffset;
do
{
if(length <= 0 || (nonEqualOffset = Array.offsetOfNonEqual(thisChars, thisOffset, anotChars, anotOffset, length)) == INDEFINITE) return true;
thisOffset += nonEqualOffset;
anotOffset += nonEqualOffset;
thisChar = thisChars[thisOffset++];
anotChar = anotChars[anotOffset++];
length -= 1 + nonEqualOffset;
} while(isIgnoreCase && (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(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "suffix" }));
}
int anotLength = suffix.fldLength;
int offset = fldLength - anotLength;
if(offset < 0) return false;
return anotLength <= 0 || Array.offsetOfNonEqual(fldChars, fldOffset + offset, suffix.fldChars, suffix.fldOffset, anotLength) == INDEFINITE;
}
public boolean startsWith(String prefix) {
if(prefix == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "prefix" }));
}
int anotLength = prefix.fldLength;
if(fldLength < anotLength) return false;
return anotLength <= 0 || Array.offsetOfNonEqual(fldChars, fldOffset, prefix.fldChars, prefix.fldOffset, anotLength) == INDEFINITE;
}
public boolean startsWith(String prefix, int offset) {
if(prefix == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "prefix" }));
}
int anotLength = prefix.fldLength;
if(offset < 0 || offset > fldLength - anotLength) return false;
return anotLength <= 0 || Array.offsetOfNonEqual(fldChars, fldOffset + offset, prefix.fldChars, prefix.fldOffset, anotLength) == INDEFINITE;
}
public int indexOf(int character) {
if(character < 0 || character > 0xffff) return -1;
int length = fldLength;
if(length <= 0) return -1;
int offset = fldOffset;
int index = Array.indexOf(character, fldChars, offset, length);
return index < 0 ? -1 : index - offset;
}
public int indexOf(int character, int startFromIndex) {
if(character < 0 || character > 0xffff) return -1;
int length = fldLength;
if(startFromIndex < 0) startFromIndex = 0;
if(startFromIndex >= length) return -1;
int offset = fldOffset;
int index = Array.indexOf(character, fldChars, offset + startFromIndex, length - startFromIndex);
return index < 0 ? -1 : index - offset;
}
public int indexOf(String string) { return indexOf(string, 0); }
public int indexOf(String string, int startFromIndex) {
if(string == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "string" }));
}
int anotLength = string.fldLength;
int thisLength = fldLength - anotLength;
if(startFromIndex < 0) startFromIndex = 0;
if(startFromIndex > thisLength++) return -1;
if(anotLength-- <= 0) return startFromIndex;
int anotOffset = string.fldOffset;
int thisOffset = fldOffset;
char[] anotChars = string.fldChars;
char[] thisChars = fldChars;
char first = anotChars[anotOffset++];
do
{
int thisIndex = Array.indexOf(first, thisChars, thisOffset + startFromIndex, thisLength - startFromIndex);
if(thisIndex < 0) break;
startFromIndex = thisIndex++ - thisOffset;
if(anotLength <= 0 || Array.offsetOfNonEqual(thisChars, thisIndex, anotChars, anotOffset, anotLength) == INDEFINITE) return startFromIndex;
} while(++startFromIndex < thisLength);
return -1;
}
public int indexOfNon(int character) {
int length = fldLength;
if(length <= 0) return -1;
if(character < 0 || character > 0xffff) return 0;
int offset = fldOffset;
int index = Array.indexOfNon(character, fldChars, offset, length);
return index < 0 ? -1 : index - offset;
}
public int indexOfNon(int character, int startFromIndex) {
int length = fldLength;
if(startFromIndex < 0) startFromIndex = 0;
if(startFromIndex >= length) return -1;
if(character < 0 || character > 0xffff) return startFromIndex;
int offset = fldOffset;
int index = Array.indexOfNon(character, fldChars, offset + startFromIndex, length - startFromIndex);
return index < 0 ? -1 : index - offset;
}
public int lastIndexOf(int character) {
if(character < 0 || character > 0xffff) return -1;
int length = fldLength;
if(length <= 0) return -1;
int offset = fldOffset;
int index = Array.lastIndexOf(character, fldChars, offset + length - 1, length);
return index < 0 ? -1 : index - offset;
}
public int lastIndexOf(int character, int startFromIndex) {
if(character < 0 || character > 0xffff) return -1;
int length = fldLength;
if(startFromIndex >= length) startFromIndex = length - 1;
if(startFromIndex < 0) return -1;
int offset = fldOffset;
int index = Array.lastIndexOf(character, fldChars, offset + startFromIndex, startFromIndex + 1);
return index < 0 ? -1 : index - offset;
}
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.format(package.getResourceString("null-pointer.argument"), new Object[] { "string" }));
}
int anotLength = string.fldLength;
int thisLength = fldLength - anotLength;
if(startFromIndex > thisLength++) startFromIndex = thisLength - 1;
if(startFromIndex < 0) return -1;
if(anotLength-- <= 0) return startFromIndex;
int anotOffset = string.fldOffset;
int thisOffset = fldOffset;
char[] anotChars = string.fldChars;
char[] thisChars = fldChars;
char first = anotChars[anotOffset++];
do
{
int thisIndex = Array.lastIndexOf(first, thisChars, thisOffset + startFromIndex, startFromIndex + 1);
if(thisIndex < 0) break;
startFromIndex = thisIndex++ - thisOffset;
if(anotLength <= 0 || Array.offsetOfNonEqual(thisChars, thisIndex, anotChars, anotOffset, anotLength) == INDEFINITE) return startFromIndex;
} while(--startFromIndex >= 0);
return -1;
}
public int lastIndexOfNon(int character) {
int length = fldLength;
if(length <= 0) return -1;
if(character < 0 || character > 0xffff) return length - 1;
int offset = fldOffset;
int index = Array.lastIndexOfNon(character, fldChars, offset + length - 1, length);
return index < 0 ? -1 : index - offset;
}
public int lastIndexOfNon(int character, int startFromIndex) {
int length = fldLength;
if(startFromIndex >= length) startFromIndex = length - 1;
if(startFromIndex < 0) return -1;
if(character < 0 || character > 0xffff) return -1;
int offset = fldOffset;
int index = Array.lastIndexOfNon(character, fldChars, offset + startFromIndex, startFromIndex + 1);
return index < 0 ? -1 : index - offset;
}
public int compareToIgnoreCase(String anot) {
if(anot == this) return EQUALS;
if(anot != null)
{
int thisLength = fldLength;
int anotLength = anot.fldLength;
if(anotLength <= 0) return thisLength;
if(thisLength <= 0) return -anotLength;
int thisOffset = fldOffset;
int anotOffset = anot.fldOffset;
char[] thisChars = fldChars;
char[] anotChars = anot.fldChars;
int nonEqualOffset = Array.offsetOfNonEqual(thisChars, thisOffset, anotChars, anotOffset, thisLength < anotLength ? thisLength : anotLength);
return nonEqualOffset < 0 ? thisLength - anotLength : Char.compareIgnoreCase(thisChars[thisOffset + nonEqualOffset], anotChars[anotOffset + nonEqualOffset]);
}
return INDEFINITE;
}
public int compareToLexicographically(String anot) {
if(anot == this) return EQUALS;
if(anot != null)
{
int thisLength = fldLength;
int anotLength = anot.fldLength;
if(anotLength <= 0) return thisLength;
if(thisLength <= 0) return -anotLength;
int thisOffset = fldOffset;
int anotOffset = anot.fldOffset;
char[] thisChars = fldChars;
char[] anotChars = anot.fldChars;
int nonEqualOffset = Array.offsetOfNonEqual(thisChars, thisOffset, anotChars, anotOffset, thisLength < anotLength ? thisLength : anotLength);
return nonEqualOffset < 0 ? thisLength - anotLength : Char.compareLexicographically(thisChars[thisOffset + nonEqualOffset], anotChars[anotOffset + nonEqualOffset]);
}
return INDEFINITE;
}
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 {
Charset charset = Charset.get(charsetName);
int length = fldLength;
return length <= 0 ? new byte[0] : charset.encode(fldChars, fldOffset, length);
}
public String[] split() {
int boundsLength = 0;
int2[] boundsData = new int2[0x0fi];
int thisLength = fldLength;
char[] thisChars = fldChars;
for(int beginIndex = fldOffset, int thisLimit = beginIndex + thisLength; beginIndex <= thisLimit; )
{
int endIndex0 = beginIndex >= thisLimit ? beginIndex : Array.indexOf('\n', thisChars, beginIndex, thisLimit - beginIndex);
int endIndex1 = beginIndex >= thisLimit ? beginIndex : Array.indexOf('\r', thisChars, beginIndex, thisLimit - beginIndex);
if(endIndex0 < 0) endIndex0 = thisLimit;
if(endIndex1 < 0) endIndex1 = thisLimit;
int endIndex = endIndex0 < endIndex1 ? endIndex0 : endIndex1;
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(beginIndex < thisLimit && thisChars[endIndex] == '\r' && thisChars[beginIndex] == '\n') beginIndex++;
}
String[] result = new String[boundsLength];
while(boundsLength-- > 0)
{
int2 substringBounds = boundsData[boundsLength];
int substringLength = substringBounds[1];
result[boundsLength] = substringLength <= 0 ? "" : substringLength == thisLength ? this : new String(substringBounds[0], substringLength, thisChars);
}
return result;
}
public String trim() {
int beginIndex = fldOffset;
int endIndex = beginIndex + fldLength - 1;
int chi = beginIndex;
int chj = endIndex;
char[] chars = fldChars;
while(chi <= chj && chars[chi] <= '\u0020') chi++;
while(chi <= chj && chars[chj] <= '\u0020') chj--;
return chi > chj ? "" : chi == beginIndex && chj == endIndex ? this : new String(chi, chj - chi + 1, chars);
}
public String intern() {
boolean multiThreaded = Runtime.getInstance().multiThreaded;
long2 hash = hashCodeAsLong2();
Mutex operation = poolOperation;
if(multiThreaded) operation.lock();
try
{
String canonical = (String) poolTable.get(hash, this);
if(canonical != null) return canonical;
poolTable.append(hash, this);
} finally
{
if(multiThreaded) operation.unlock();
}
return this;
}
public String toLowerCase() {
int thisOffset = fldOffset;
int thisLength = fldLength;
char[] thisChars = fldChars;
int chi = thisOffset;
label0:
{
for(int thisLimit = thisOffset + thisLength; chi < thisLimit; chi++)
{
char character = thisChars[chi];
if(character != Char.toLowerCase(character)) break label0;
}
return this;
}
char[] resultChars = new char[thisLength];
for(int chj = chi - thisOffset, Array.copy(thisChars, thisOffset, resultChars, 0, chj); chj < thisLength; chi++, chj++)
{
resultChars[chj] = Char.toLowerCase(thisChars[chi]);
}
return new String(0, thisLength, resultChars);
}
public String toUpperCase() {
int thisOffset = fldOffset;
int thisLength = fldLength;
char[] thisChars = fldChars;
int chi = thisOffset;
label0:
{
for(int thisLimit = thisOffset + thisLength; chi < thisLimit; chi++)
{
char character = thisChars[chi];
if(character != Char.toUpperCase(character)) break label0;
}
return this;
}
char[] resultChars = new char[thisLength];
for(int chj = chi - thisOffset, Array.copy(thisChars, thisOffset, resultChars, 0, chj); chj < thisLength; chi++, chj++)
{
resultChars[chj] = Char.toUpperCase(thisChars[chi]);
}
return new String(0, thisLength, resultChars);
}
public native String substring(int beginIndex);
public native String substring(int beginIndex, int endIndex);
public String replaceAll(char oldCharacter, char newCharacter) {
int thisLength = fldLength;
if(thisLength <= 0 || oldCharacter == newCharacter) return this;
int thisOffset = fldOffset;
char[] thisChars = fldChars;
int chi = Array.indexOf(oldCharacter, thisChars, thisOffset, thisLength);
if(chi < 0) return this;
char[] resultChars = new char[thisLength];
for(int chj = chi - thisOffset, Array.copy(thisChars, thisOffset, resultChars, 0, chj); chj < thisLength; chi++, chj++)
{
char character = thisChars[chi];
resultChars[chj] = character != oldCharacter ? character : newCharacter;
}
return new String(0, thisLength, resultChars);
}
public String replaceAll(String oldString, String newString) {
if(oldString == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "oldString" }));
}
if(newString == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "newString" }));
}
int thisLength = fldLength;
int oldLength = oldString.fldLength;
if(thisLength <= 0 || oldLength <= 0 || oldString.equals(newString)) return this;
int indexLength = 0;
int[] indexData = new int[0x1fi];
for(int thisIndex = 0; (thisIndex = indexOf(oldString, thisIndex)) >= 0; thisIndex += oldLength)
{
if(indexLength == indexData.length)
{
Array.copy(indexData, 0, indexData = new int[indexLength << 1 | 1], 0, indexLength);
}
indexData[indexLength++] = thisIndex;
}
if(indexLength <= 0) return this;
int newLength = newString.fldLength;
long longResultLength = (long) thisLength + (long) indexLength * (long) (newLength - oldLength);
if(longResultLength > (long) Int.MAX_VALUE || longResultLength < 0L)
{
throw new BufferTooLargeError(package.getResourceString("!error.buffer-too-large"));
}
int newOffset = newString.fldOffset;
char[] newChars = newString.fldChars;
int thisEnd = thisLength;
int thisOffset = fldOffset;
char[] thisChars = fldChars;
int resultEnd = (int) longResultLength;
int resultLength = resultEnd;
char[] resultChars = new char[resultLength];
while(indexLength-- > 0)
{
int thisBegin = indexData[indexLength] + oldLength;
int copyLength = thisEnd - thisBegin;
int resultBegin = resultEnd - copyLength;
thisEnd = thisBegin - oldLength;
Array.copy(thisChars, thisOffset + thisBegin, resultChars, resultBegin, copyLength);
Array.copy(newChars, newOffset, resultChars, resultEnd = resultBegin - newLength, newLength);
}
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(thisLength <= 0 || oldCharacter == newCharacter) return this;
if(startFromIndex < 0) startFromIndex = 0;
if(startFromIndex >= thisLength) return this;
int thisOffset = fldOffset;
char[] thisChars = fldChars;
int thisIndex = Array.indexOf(oldCharacter, thisChars, thisOffset + startFromIndex, thisLength - startFromIndex);
if(thisIndex < 0) return this;
char[] resultChars = new char[thisLength];
Array.copy(thisChars, thisOffset, resultChars, 0, thisLength);
resultChars[thisIndex - 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(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "oldString" }));
}
if(newString == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "newString" }));
}
int thisLength = fldLength;
int oldLength = oldString.fldLength;
if(thisLength <= 0 || oldLength <= 0 || oldString.equals(newString)) return this;
int thisIndex = indexOf(oldString, startFromIndex);
if(thisIndex < 0) return this;
int newLength = newString.fldLength;
int resultLength = thisLength + (newLength - oldLength);
if(resultLength < 0)
{
throw new BufferTooLargeError(package.getResourceString("!error.buffer-too-large"));
}
int thisOffset = fldOffset;
char[] thisChars = fldChars;
char[] resultChars = new char[resultLength];
Array.copy(thisChars, thisOffset, resultChars, 0, thisIndex);
Array.copy(newString.fldChars, newString.fldOffset, resultChars, thisIndex, newLength);
Array.copy(thisChars, thisOffset + thisIndex + oldLength, resultChars, thisIndex += newLength, resultLength - thisIndex);
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(thisLength <= 0 || oldCharacter == newCharacter) return this;
if(startFromIndex >= thisLength) startFromIndex = thisLength - 1;
if(startFromIndex < 0) return this;
int thisOffset = fldOffset;
char[] thisChars = fldChars;
int thisIndex = Array.lastIndexOf(oldCharacter, thisChars, thisOffset + startFromIndex, startFromIndex + 1);
if(thisIndex < 0) return this;
char[] resultChars = new char[thisLength];
Array.copy(thisChars, thisOffset, resultChars, 0, thisLength);
resultChars[thisIndex - 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(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "oldString" }));
}
if(newString == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "newString" }));
}
int thisLength = fldLength;
int oldLength = oldString.fldLength;
if(thisLength <= 0 || oldLength <= 0 || oldString.equals(newString)) return this;
int thisIndex = lastIndexOf(oldString, startFromIndex);
if(thisIndex < 0) return this;
int newLength = newString.fldLength;
int resultLength = thisLength + (newLength - oldLength);
if(resultLength < 0)
{
throw new BufferTooLargeError(package.getResourceString("!error.buffer-too-large"));
}
int thisOffset = fldOffset;
char[] thisChars = fldChars;
char[] resultChars = new char[resultLength];
Array.copy(thisChars, thisOffset, resultChars, 0, thisIndex);
Array.copy(newString.fldChars, newString.fldOffset, resultChars, thisIndex, newLength);
Array.copy(thisChars, thisOffset + thisIndex + oldLength, resultChars, thisIndex += newLength, resultLength - thisIndex);
return new String(0, resultLength, resultChars);
}
public int length { read = fldLength }
public char operator [](int index) {
if(index < 0 || index >= fldLength)
{
throw new StringIndexOutOfBoundsException(package.getResourceString("out-of-bounds.string-index"));
}
return fldChars[fldOffset + index];
}
public String operator +(char anot) {
int thisLength = fldLength;
if(thisLength <= 0) return new String(anot);
int resultLength = thisLength + 1;
if(resultLength < 0)
{
throw new BufferTooLargeError(package.getResourceString("!error.buffer-too-large"));
}
char[] resultChars = new char[resultLength];
Array.copy(fldChars, fldOffset, resultChars, 0, thisLength);
resultChars[thisLength] = anot;
return new String(0, resultLength, resultChars);
}
public String operator +(String anot) {
if(anot == null)
{
throw new NullPointerException(String.format(package.getResourceString("null-pointer.argument"), new Object[] { "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(package.getResourceString("!error.buffer-too-large"));
}
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);
}
public String operator +`(char anot) {
int thisLength = fldLength;
if(thisLength <= 0) return new String(anot);
int resultLength = thisLength + 1;
if(resultLength < 0)
{
throw new BufferTooLargeError(package.getResourceString("!error.buffer-too-large"));
}
char[] resultChars = new char[resultLength];
resultChars[0] = anot;
Array.copy(fldChars, fldOffset, resultChars, 1, thisLength);
return new String(0, resultLength, resultChars);
}
}