/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.lib.cvsclient.io;

import java.io.*;

/**
 * @author Thomas Singer
 */
public final class Utf8InputStreamReader extends AbstractInputStreamReader {

	// Setup ==================================================================

	public Utf8InputStreamReader(InputStream inputStream) {
		super(inputStream);
	}

	// Implemented ============================================================

	@Override
	protected int readChar(InputStream inputStream) throws IOException {
		final int value1 = inputStream.read();
		if (value1 < 0) {
			return -1;
		}

		final int byte1 = value1 & 0xFF;
		if (byte1 < 0x80) {
			return byte1;
		}

		// two bytes
		if ((byte1 & 0xE0) == 0xC0) {
			final int value2 = inputStream.read();
			if (value2 < 0) {
				throw new EncodingException("Unexpected eof while reading " + Integer.toHexString(byte1));
			}

			final int byte2 = value2 & 0xFF;
			if ((byte2 & 0xC0) != 0x80) {
				throw new EncodingException("Invalid second unicode character " + Integer.toHexString(byte1) + " " + Integer.toHexString(byte2));
			}

			return byte2 & 0x3F | ((byte1 & 0x1F) << 6);
		}

		// three bytes
		if ((byte1 & 0xF0) != 0xE0) {
			throw new EncodingException("Invalid first unicode character " + Integer.toHexString(byte1));
		}

		final int value2 = inputStream.read();
		if (value2 < 0) {
			throw new EncodingException("Unexpected eof while reading " + Integer.toHexString(byte1));
		}

		final int byte2 = value2 & 0xFF;
		if ((byte2 & 0xC0) != 0x80) {
			throw new EncodingException("Invalid second unicode character " + Integer.toHexString(byte1) + " " + Integer.toHexString(byte2));
		}

		final int value3 = inputStream.read();
		if (value3 < 0) {
			throw new EncodingException("Unexpected eof while reading " + Integer.toHexString(byte1) + " " + Integer.toHexString(byte2));
		}

		final int byte3 = value3 & 0xFF;
		if ((byte3 & 0xC0) != 0x80) {
			throw new EncodingException("Invalid second unicode character " + Integer.toHexString(byte1) + " " + Integer.toHexString(byte2) + " " + Integer.toHexString(byte3));
		}

		return byte3 & 0x3F | ((byte2 & 0x3F) << 6) | ((byte1 & 0x0F) << 12);
	}
}
