String.java

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

/*
	Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
	и других спецификаций для функционирования компактных приложений на языке
	Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

	Copyright © 2016, 2019 Малик Разработчик

	Это свободная программа: вы можете перераспространять ее и/или изменять
	ее на условиях Меньшей Стандартной общественной лицензии 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;
	}
}