/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package java.lang;
import java.io.*;
import malik.emulator.i18n.*;
public final class String extends Object
{
public static void checkBound(String method, int stringLength, int offset, int length) throws StringIndexOutOfBoundsException {
int lim;
if((lim = offset + length) > stringLength || lim < offset || offset > stringLength || offset < 0)
{
throw new StringIndexOutOfBoundsException(method != null ? method.concat(": индекс выходит из диапазона.") : "Индекс выходит из диапазона.", true);
}
}
public static String valueOf(boolean value) {
return value ? "true" : "false";
}
public static String valueOf(char value) {
return new String(value);
}
public static String valueOf(float value) {
return Float.toString(value);
}
public static String valueOf(double value) {
return Double.toString(value);
}
public static String valueOf(int value) {
return Integer.toString(value, 10);
}
public static String valueOf(long value) {
return Long.toString(value, 10);
}
public static String valueOf(char[] src) {
int len;
if((len = src == null ? 0 : src.length) > 0)
{
MalikSystem.arraycopyf_short(src, 0, src = new char[len], 0, len);
} else
{
src = null;
}
return new String(0, len, src);
}
public static String valueOf(char[] src, int offset, int length) {
if(src == null)
{
throw new NullPointerException("String.valueOf: аргумент src равен нулевой ссылке.");
}
Array.checkBound("String.valueOf", src.length, offset, length);
if(length > 0)
{
MalikSystem.arraycopyf_short(src, offset, src = new char[length], 0, length);
} else
{
src = null;
}
return new String(0, length, src);
}
public static String valueOf(Object value) {
return value == null ? "null" : value.toString();
}
private final int offset;
private final int length;
private final char[] chars;
public String() {
this.offset = 0;
this.length = 0;
this.chars = null;
}
public String(char[] src) {
int len;
if(src == null)
{
throw new NullPointerException("String: аргумент src равен нулевой ссылке.");
}
if((len = src.length) > 0)
{
MalikSystem.arraycopyf_short(src, 0, src = new char[len], 0, len);
} else
{
src = null;
}
this.offset = 0;
this.length = len;
this.chars = src;
}
public String(char[] src, int offset, int length) {
if(src == null)
{
throw new NullPointerException("String: аргумент src равен нулевой ссылке.");
}
Array.checkBound("String", src.length, offset, length);
if(length > 0)
{
MalikSystem.arraycopyf_short(src, offset, src = new char[length], 0, length);
} else
{
src = null;
}
this.offset = 0;
this.length = length;
this.chars = src;
}
public String(byte[] src) {
int len;
char[] chars = src != null ? Helper.byteToCharArray(src, 0, src.length) : null;
if((len = chars == null ? 0 : chars.length) <= 0) chars = null;
this.offset = 0;
this.length = len;
this.chars = chars;
}
public String(byte[] src, String encoding) throws UnsupportedEncodingException {
int len;
char[] chars = src != null ? Helper.byteToCharArray(src, 0, src.length, encoding) : null;
if((len = chars == null ? 0 : chars.length) <= 0) chars = null;
this.offset = 0;
this.length = len;
this.chars = chars;
}
public String(byte[] src, int offset, int length) {
int len;
long bounds;
char[] chars;
offset = (int) (bounds = Array.intersectBound(src == null ? 0 : src.length, offset, length));
length = (int) (bounds >> 32);
chars = src != null ? Helper.byteToCharArray(src, offset, length) : null;
if((len = chars == null ? 0 : chars.length) <= 0) chars = null;
this.offset = 0;
this.length = len;
this.chars = chars;
}
public String(byte[] src, int offset, int length, String encoding) throws UnsupportedEncodingException {
int len;
long bounds;
char[] chars;
offset = (int) (bounds = Array.intersectBound(src == null ? 0 : src.length, offset, length));
length = (int) (bounds >> 32);
chars = src != null ? Helper.byteToCharArray(src, offset, length, encoding) : null;
if((len = chars == null ? 0 : chars.length) <= 0) chars = null;
this.offset = 0;
this.length = len;
this.chars = chars;
}
public String(StringBuffer source) {
if(source == null)
{
throw new NullPointerException("String: аргумент buffer равен нулевой ссылке.");
}
synchronized(source.monitor())
{
this.offset = 0;
this.length = source.length();
this.chars = source.content();
source.setShared();
}
}
public String(String source) {
if(source == null)
{
this.offset = 0;
this.length = 0;
this.chars = null;
return;
}
this.offset = source.offset;
this.length = source.length;
this.chars = source.chars;
}
private String(char source) {
this.offset = 0;
this.length = 1;
this.chars = new char[] { source };
}
private String(int offset, int length, char[] chars) {
this.offset = offset;
this.length = length;
this.chars = chars;
}
public boolean equals(Object anot) {
int len;
String s;
return anot == this || anot instanceof String && (len = length) == (s = (String) anot).length && (offset == s.offset && chars == s.chars || regionMatches(false, 0, s, 0, len));
}
public int hashCode() {
int result = 0;
char[] c = chars;
for(int ofs, e = 1, i = (ofs = offset) + length; i-- > ofs; e *= 31) result += e * c[i];
return result;
}
public String toString() {
return this;
}
public void getChars(int beginIndex, int endIndex, char[] dst, int offset) {
int lim;
int len;
int length;
if((beginIndex | endIndex) < 0 || beginIndex > (len = this.length) || endIndex > len || beginIndex > endIndex)
{
throw new StringIndexOutOfBoundsException("String.getChars: индекс выходит из диапазона.");
}
if(dst == null)
{
throw new NullPointerException("String.getChars: аргумент dst равен нулевой ссылке.");
}
if((lim = offset + (length = endIndex - beginIndex)) > (len = dst.length) || lim < offset || offset > len || offset < 0)
{
throw new ArrayIndexOutOfBoundsException("String.getChars: индекс выходит из диапазона.");
}
if(length > 0) MalikSystem.arraycopyf_short(this.chars, this.offset + beginIndex, dst, offset, length);
}
public boolean regionMatches(boolean ignoreCase, int thisOffset, String anot, int anotOffset, int length) {
char c1;
char c2;
int lim;
int len;
char[] thisChars;
char[] anotChars;
if(
anot == null ||
(lim = thisOffset + length) > (len = this.length) || lim < thisOffset || thisOffset > len || thisOffset < 0 ||
(lim = anotOffset + length) > (len = anot.length) || lim < anotOffset || anotOffset > len || anotOffset < 0
) return false;
thisOffset += this.offset;
anotOffset += anot.offset;
thisChars = this.chars;
anotChars = anot.chars;
do
{
do
{
if(length-- <= 0) return true;
} while((c1 = thisChars[thisOffset++]) == (c2 = anotChars[anotOffset++]));
if(!ignoreCase) break;
} while(Character.toUpperCase(c1) == Character.toUpperCase(c2) || Character.toLowerCase(c1) == Character.toLowerCase(c2));
return false;
}
public boolean equalsIgnoreCase(String anot) {
int length;
return anot != null && (length = this.length) == anot.length && regionMatches(true, 0, anot, 0, length);
}
public boolean endsWith(String suffix) {
if(suffix == null)
{
throw new NullPointerException("String.endsWith: аргумент suffix равен нулевой ссылке.");
}
return startsWith(suffix, this.length - suffix.length);
}
public boolean startsWith(String prefix) {
if(prefix == null)
{
throw new NullPointerException("String.startsWith: аргумент prefix равен нулевой ссылке.");
}
return startsWith(prefix, 0);
}
public boolean startsWith(String prefix, int offset) {
int i;
char[] thisChars;
char[] anotChars;
if(prefix == null)
{
throw new NullPointerException("String.startsWith: аргумент prefix равен нулевой ссылке.");
}
if(offset < 0 || offset > this.length - (i = prefix.length)) return false;
thisChars = this.chars;
anotChars = prefix.chars;
for(int thisOffset = this.offset + offset, anotOffset = prefix.offset; i-- > 0; ) if(thisChars[thisOffset++] != anotChars[anotOffset++]) return false;
return true;
}
public char charAt(int index) {
if(index < 0 || index >= length)
{
throw new StringIndexOutOfBoundsException("String.charAt: аргумент index выходит из диапазона.");
}
return chars[offset + index];
}
public int length() {
return length;
}
public int compareTo(String anot) {
int lengthDiff;
int thisLength;
int anotLength;
int thisOffset;
int anotOffset;
char[] thisChars;
char[] anotChars;
if(anot == null)
{
throw new NullPointerException("String.compareTo: аргумент anot равен нулевой ссылке.");
}
lengthDiff = (thisLength = this.length) - (anotLength = anot.length);
thisOffset = this.offset;
anotOffset = anot.offset;
thisChars = this.chars;
anotChars = anot.chars;
for(int i = 0, j = 0; i < thisLength && j < anotLength; i++, j++)
{
int c1 = thisChars[thisOffset++];
int c2 = anotChars[anotOffset++];
int characterDiff;
if((characterDiff = c1 - c2) != 0) return characterDiff;
}
return lengthDiff;
}
public int indexOf(int character) {
int ofs;
int len;
int result;
return
0 >= (len = length) || character < Character.MIN_VALUE || character > Character.MAX_VALUE ||
(result = MalikSystem.arrayfindf_short(chars, (ofs = offset), character) - ofs) >= len ? -1 : result
;
}
public int indexOf(int character, int startFromIndex) {
int ofs;
int len;
int result;
if(startFromIndex < 0) startFromIndex = 0;
return
startFromIndex >= (len = length) || character < Character.MIN_VALUE || character > Character.MAX_VALUE ||
(result = MalikSystem.arrayfindf_short(chars, (ofs = offset) + startFromIndex, character) - ofs) >= len ? -1 : result
;
}
public int indexOf(String string) {
return indexOf(string, 0);
}
public int indexOf(String string, int startFromIndex) {
char first;
int len;
int lim;
int thisOffset;
int anotOffset;
char[] thisChars;
char[] anotChars;
if(string == null)
{
throw new NullPointerException("String.indexOf: аргумент string равен нулевой ссылке.");
}
if(startFromIndex < 0) startFromIndex = 0;
if(startFromIndex > (lim = this.length - (len = string.length))) return -1;
if(len <= 0) return startFromIndex;
thisChars = this.chars;
thisOffset = this.offset + startFromIndex;
first = (anotChars = string.chars)[anotOffset = string.offset];
do
{
label0: if(thisChars[thisOffset] == first)
{
for(int i = thisOffset, j = anotOffset, k = len; k-- > 1; ) if(thisChars[++i] != anotChars[++j]) break label0;
return startFromIndex;
}
thisOffset++;
} while(++startFromIndex <= lim);
return -1;
}
public int lastIndexOf(int character) {
int ofs;
int result;
int startFromIndex = length - 1;
return
startFromIndex < 0 || character < Character.MIN_VALUE || character > Character.MAX_VALUE ||
(result = MalikSystem.arrayfindb_short(chars, (ofs = offset) + startFromIndex, character) - ofs) < 0 ? -1 : result
;
}
public int lastIndexOf(int character, int startFromIndex) {
int ofs;
int len;
int result;
if(startFromIndex >= (len = length)) startFromIndex = len - 1;
return
startFromIndex < 0 || character < Character.MIN_VALUE || character > Character.MAX_VALUE ||
(result = MalikSystem.arrayfindb_short(chars, (ofs = offset) + startFromIndex, character) - ofs) < 0 ? -1 : result
;
}
public char[] toCharArray() {
int len;
char[] result = new char[len = length];
if(len > 0) MalikSystem.arraycopyf_short(chars, offset, result, 0, len);
return result;
}
public byte[] getBytes() {
return Helper.charToByteArray(chars, offset, length);
}
public byte[] getBytes(String encoding) throws UnsupportedEncodingException {
return Helper.charToByteArray(chars, offset, length, encoding);
}
public String trim() {
int o1;
int o2;
int ofs1 = o1 = offset;
int ofs2 = o2 = length + ofs1 - 1;
char[] c = chars;
for(; ofs2 >= ofs1 && c[ofs2] <= '\u0020'; ofs2--);
for(; ofs1 <= ofs2 && c[ofs1] <= '\u0020'; ofs1++);
return ofs1 > ofs2 ? "" : o1 == ofs1 && o2 == ofs2 ? this : new String(ofs1, ofs2 - ofs1 + 1, c);
}
public String intern() {
String result;
return (result = StringPool.intern(this)) != this ? result : (String) Memory.intern(this);
}
public String toLowerCase() {
int i;
int j;
int ofs;
int len;
int lim = (ofs = offset) + (len = length);
char[] c = chars;
char[] r;
for(i = ofs; i < lim; i++)
{
char ci;
if((ci = c[i]) != Character.toLowerCase(ci)) break;
}
if(i >= lim) return this;
for(MalikSystem.arraycopyf_short(c, ofs, r = new char[len], 0, j = i - ofs); j < len; i++, j++) r[j] = Character.toLowerCase(c[i]);
return new String(0, len, r);
}
public String toUpperCase() {
int i;
int j;
int ofs;
int len;
int lim = (ofs = offset) + (len = length);
char[] c = chars;
char[] r;
for(i = ofs; i < lim; i++)
{
char ci;
if((ci = c[i]) != Character.toUpperCase(ci)) break;
}
if(i >= lim) return this;
for(MalikSystem.arraycopyf_short(c, ofs, r = new char[len], 0, j = i - ofs); j < len; i++, j++) r[j] = Character.toUpperCase(c[i]);
return new String(0, len, r);
}
public String substring(int beginIndex) {
int len;
if(beginIndex < 0 || beginIndex > (len = length))
{
throw new StringIndexOutOfBoundsException("String.substring: аргумент beginIndex выходит из диапазона.");
}
return beginIndex == len ? "" : beginIndex == 0 ? this : new String(offset + beginIndex, len - beginIndex, chars);
}
public String substring(int beginIndex, int endIndex) {
int len;
if((beginIndex | endIndex) < 0 || beginIndex > (len = this.length) || endIndex > len || beginIndex > endIndex)
{
throw new StringIndexOutOfBoundsException("String.substring: индекс выходит из диапазона.");
}
return beginIndex == endIndex ? "" : endIndex - beginIndex == len ? this : new String(offset + beginIndex, endIndex - beginIndex, chars);
}
public String replace(char oldCharacter, char newCharacter) {
int i;
int j;
int ofs;
int len;
int lim;
char[] c;
char[] r;
if(oldCharacter == newCharacter || (len = length) <= 0) return this;
lim = (ofs = offset) + len;
c = chars;
if((i = MalikSystem.arrayfindf_short(c, ofs, oldCharacter)) >= lim) return this;
for(MalikSystem.arraycopyf_short(c, ofs, r = new char[len], 0, j = i - ofs); j < len; i++, j++)
{
char ci;
r[j] = (ci = c[i]) != oldCharacter ? ci : newCharacter;
}
return new String(0, len, r);
}
public String concat(String anot) {
int len;
int len1;
int len2;
char[] r;
if(anot == null)
{
throw new NullPointerException("String.concat: аргумент anot равен нулевой ссылке.");
}
if((len2 = anot.length) <= 0) return this;
if((len1 = this.length) <= 0) return anot;
r = new char[len = len1 + len2];
MalikSystem.arraycopyf_short(this.chars, this.offset, r, 0, len1);
MalikSystem.arraycopyf_short(anot.chars, anot.offset, r, len1, len2);
return new String(0, len, r);
}
int getCharsAddress() {
return length > 0 ? chars.getArrayAddress() + (offset << 1) : 0;
}
}