//
// I18N.CJK.DBCSEncoding
//
// Author:
//   Alan Tam Siu Lung (Tam@SiuLung.com)
//

using System;
using System.Text;

namespace C1.C1Zip
{
	internal abstract class DBCSEncoding : Encoding
	{
		public DBCSEncoding()
		{
		}

		internal abstract DBCSConvert GetConvert ();

		// Get the number of bytes needed to encode a character buffer.
		public override int GetByteCount(char[] chars, int index, int count)
		{
			if (chars == null)
				throw new ArgumentNullException("chars");
			if (index < 0 || index > chars.Length)
				throw new ArgumentOutOfRangeException("index", Strings.GetString("ArgRange_Array"));
			if (count < 0 || index + count > chars.Length)
				throw new ArgumentOutOfRangeException("count", Strings.GetString("ArgRange_Array"));
			byte[] buffer = new byte[count * 2];
			return GetBytes(chars, index, count, buffer, 0);
		}
		
		// Get the number of characters needed to decode a byte buffer.
		public override int GetCharCount(byte[] bytes, int index, int count)
		{
			if (bytes == null)
				throw new ArgumentNullException("bytes");
			if (index < 0 || index > bytes.Length)
				throw new ArgumentOutOfRangeException("index", Strings.GetString("ArgRange_Array"));
			if (count < 0 || index + count > bytes.Length)
				throw new ArgumentOutOfRangeException("count", Strings.GetString("ArgRange_Array"));
			char[] buffer = new char[count];
			return GetChars(bytes, index, count, buffer, 0);
		}
		
		// Get the characters that result from decoding a byte buffer.
		public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
					     char[] chars, int charIndex)
		{
			if (bytes == null)
				throw new ArgumentNullException("bytes");
			if (chars == null)
				throw new ArgumentNullException("chars");
			if (byteIndex < 0 || byteIndex > bytes.Length)
				throw new ArgumentOutOfRangeException("byteIndex", Strings.GetString("ArgRange_Array"));
			if (byteCount < 0 || byteIndex + byteCount > bytes.Length)
				throw new ArgumentOutOfRangeException("byteCount", Strings.GetString("ArgRange_Array"));
			if (charIndex < 0 || charIndex > chars.Length)
				throw new ArgumentOutOfRangeException("charIndex", Strings.GetString("ArgRange_Array"));
			return 0; // For subclasses to implement
		}
		
		// Get the maximum number of bytes needed to encode a
		// specified number of characters.
		public override int GetMaxByteCount(int charCount)
		{
			if (charCount < 0)
				throw new ArgumentOutOfRangeException("charCount", Strings.GetString("ArgRange_NonNegative"));
			return charCount * 2;
		}
		
		// Get the maximum number of characters needed to decode a
		// specified number of bytes.
		public override int GetMaxCharCount(int byteCount)
		{
			if (byteCount < 0) {
				throw new ArgumentOutOfRangeException("byteCount", Strings.GetString("ArgRange_NonNegative"));
			}
			return byteCount;
		}
		
		// Decoder that handles a rolling state.
		internal abstract class DBCSDecoder : Decoder
		{
			protected DBCSConvert convert;
			
			// Constructor.
			public DBCSDecoder(DBCSConvert convert)
			{
				this.convert = convert;
			}
			
			internal void CheckRange (byte[] bytes, int index, int count)
			{
				if (bytes == null)
					throw new ArgumentNullException("bytes");
				if (index < 0 || index > bytes.Length)
					throw new ArgumentOutOfRangeException("index", Strings.GetString("ArgRange_Array"));
				if (count < 0 || count > (bytes.Length - index))
					throw new ArgumentOutOfRangeException("count", Strings.GetString("ArgRange_Array"));
			}

			internal void CheckRange (byte[] bytes, int byteIndex, int byteCount,
						     char[] chars, int charIndex)
			{
				if (bytes == null)
					throw new ArgumentNullException("bytes");
				if (chars == null)
					throw new ArgumentNullException("chars");
				if (byteIndex < 0 || byteIndex > bytes.Length)
					throw new ArgumentOutOfRangeException("byteIndex", Strings.GetString("ArgRange_Array"));
				if (byteCount < 0 || byteIndex + byteCount > bytes.Length)
					throw new ArgumentOutOfRangeException("byteCount", Strings.GetString("ArgRange_Array"));
				if (charIndex < 0 || charIndex > chars.Length)
					throw new ArgumentOutOfRangeException("charIndex", Strings.GetString("ArgRange_Array"));
			}
		}
	}
}
