/*
	Реализация спецификаций 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.io;

public class DataInputStream extends InputStream
		implements DataInput
{
	public static String readUTF(DataInput stream)
			throws IOException
	{
		int i;
		int b1;
		int b2;
		int b3;
		int strlen;
		int length;
		char[] result;
		byte[] b;
		if(stream == null)
		{
			throw new NullPointerException("DataInputStream.readUTF: " +
					"параметр stream равен нулевой ссылке.");
		}
		if((length = stream.readUnsignedShort()) == 0)
		{
			return "";
		}
		strlen = 0;
		result = new char[length];
		stream.readFully(b = new byte[length]);
		for(i = 0; i < length; )
		{
			switch((b1 = b[i] & 0xff) >> 4)
			{
			default:
				throw new UTFDataFormatException("DataInputStream.readUTF: " +
						"ошибка в данных, закодированных кодировкой UTF-8.");
			case 0x00:
			case 0x01:
			case 0x02:
			case 0x03:
			case 0x04:
			case 0x05:
			case 0x06:
			case 0x07:
				i++;
				result[strlen++] = (char) b1;
				break;
			case 0x0c:
			case 0x0d:
				if((i += 2) > length ||
						((b2 = b[i - 1]) & 0xc0) != 0x80)
				{
					throw new UTFDataFormatException("DataInputStream.readUTF: " +
							"ошибка в данных, закодированных кодировкой UTF-8.");
				}
				result[strlen++] = (char) (((b1 & 0x1f) << 6) | (b2 & 0x3f));
				break;
			case 0x0e:
				if((i += 3) > length ||
						((b2 = b[i - 2]) & 0xc0) != 0x80 ||
						((b3 = b[i - 1]) & 0xc0) != 0x80)
				{
					throw new UTFDataFormatException("DataInputStream.readUTF: " +
							"ошибка в данных, закодированных кодировкой UTF-8.");
				}
				result[strlen++] = (char) (((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f));
				break;
			}
		}
		return new String(result, 0, strlen);
	}


	protected InputStream in;

	public DataInputStream(InputStream stream)
	{
		this.in = stream;
	}

	public void close()
			throws IOException
	{
		in.close();
	}

	public void reset()
			throws IOException
	{
		in.reset();
	}

	public void mark(int readLimit)
	{
		in.mark(readLimit);
	}

	public boolean markSupported()
	{
		return in.markSupported();
	}

	public int read()
			throws IOException
	{
		return in.read();
	}

	public int available()
			throws IOException
	{
		return in.available();
	}

	public long skip(long bytesCount)
			throws IOException
	{
		return in.skip(bytesCount);
	}

	public final int read(byte[] dst)
			throws IOException
	{
		return in.read(dst);
	}

	public final int read(byte[] dst, int offset, int length)
			throws IOException
	{
		return in.read(dst, offset, length);
	}

	public final void readFully(byte[] dst)
			throws IOException
	{
		int length;
		int p;
		int c;
		if(dst == null)
		{
			throw new NullPointerException("DataInputStream.readFully: " +
					"параметр dst равен нулевой ссылке.");
		}
		for(length = dst.length, p = 0; p < length; p += c)
		{
			if((c = read(dst, p, length - p)) < 0)
			{
				throw new EOFException("DataInputStream: " +
						"достигнут конец данных.");
			}
		}
	}

	public final void readFully(byte[] dst, int offset, int length)
			throws IOException
	{
		int lim;
		int len;
		int p;
		int c;
		if(dst == null)
		{
			throw new NullPointerException("DataInputStream.readFully: " +
					"параметр dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) ||
				lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("DataInputStream.readFully: " +
					"индекс выходит из диапазона.");
		}
		for(p = 0; p < length; p += c)
		{
			if((c = read(dst, offset + p, length - p)) < 0)
			{
				throw new EOFException("DataInputStream: " +
						"достигнут конец данных.");
			}
		}
	}

	public final boolean readBoolean()
			throws IOException
	{
		return readUnsignedByte() != 0;
	}

	public final char readChar()
			throws IOException
	{
		return (char) readUnsignedShort();
	}

	public final float readFloat()
			throws IOException
	{
		return Float.intBitsToFloat(readInt());
	}

	public final double readDouble()
			throws IOException
	{
		return Double.longBitsToDouble(readLong());
	}

	public final byte readByte()
			throws IOException
	{
		return (byte) readUnsignedByte();
	}

	public final short readShort()
			throws IOException
	{
		return (short) readUnsignedShort();
	}

	public final int readUnsignedByte()
			throws IOException
	{
		int b;
		if((b = read()) < 0)
		{
			throw new EOFException("DataInputStream: " +
					"достигнут конец данных.");
		}
		return b;
	}

	public final int readUnsignedShort()
			throws IOException
	{
		int b1 = read();
		int b2 = read();
		if((b1 | b2) < 0)
		{
			throw new EOFException("DataInputStream: " +
					"достигнут конец данных.");
		}
		return (b1 << 8) | b2;
	}

	public final int readInt()
			throws IOException
	{
		int b1 = read();
		int b2 = read();
		int b3 = read();
		int b4 = read();
		if((b1 | b2 | b3 | b4) < 0)
		{
			throw new EOFException("DataInputStream: " +
					"достигнут конец данных.");
		}
		return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
	}

	public final long readLong()
			throws IOException
	{
		int b1 = read();
		int b2 = read();
		int b3 = read();
		int b4 = read();
		int b5 = read();
		int b6 = read();
		int b7 = read();
		int b8 = read();
		if((b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8) < 0)
		{
			throw new EOFException("DataInputStream: " +
					"достигнут конец данных.");
		}
		return ((((long) b1) << 56) | (((long) b2) << 48) |
				(((long) b3) << 40) | (((long) b4) << 32) |
				(((long) b5) << 24) | (((long) b6) << 16) |
				(((long) b7) << 8) | ((long) b8));
	}

	public final String readUTF()
			throws IOException
	{
		return readUTF(this);
	}

	public final int skipBytes(int bytesCount)
			throws IOException
	{
		int skiped;
		int result = 0;
		while(result < bytesCount && (skiped = (int) skip((long) (bytesCount - result))) > 0)
		{
			result += skiped;
		}
		return result;
	}
}
