//
// Author:
// Alan Tam Siu Lung (Tam@SiuLung.com)
+// Atsushi Enomoto <atsushi@ximian.com>
//
using System;
namespace I18N.CJK
{
+ [Serializable]
internal class CP950 : DbcsEncoding
{
// Magic number used by Windows for the Big5 code page.
// Constructor.
public CP950() : base(BIG5_CODE_PAGE) {
- convert = Big5Convert.Convert;
}
-
+
+ internal override DbcsConvert GetConvert ()
+ {
+ return DbcsConvert.Big5;
+ }
+
+#if !DISABLE_UNSAFE
// Get the bytes that result from encoding a character buffer.
- public override int GetBytes(char[] chars, int charIndex, int charCount,
- byte[] bytes, int byteIndex)
+ public unsafe override int GetByteCountImpl (char* chars, int count)
{
- // 00 00 - FF FF
- base.GetBytes(chars, charIndex, charCount, bytes, byteIndex);
+ DbcsConvert convert = GetConvert ();
+ int index = 0;
+ int length = 0;
+
+ while (count-- > 0) {
+ char c = chars[index++];
+ if (c <= 0x80 || c == 0xFF) { // ASCII
+ length++;
+ continue;
+ }
+ byte b1 = convert.u2n[((int)c) * 2 + 1];
+ byte b2 = convert.u2n[((int)c) * 2];
+ if (b1 == 0 && b2 == 0) {
+ // FIXME: handle fallback for GetByteCountImpl().
+ length++;
+ }
+ else
+ length += 2;
+ }
+ return length;
+ }
+
+ // Get the bytes that result from encoding a character buffer.
+ public unsafe override int GetBytesImpl (char* chars, int charCount,
+ byte* bytes, int byteCount)
+ {
+ DbcsConvert convert = GetConvert ();
+ int charIndex = 0;
+ int byteIndex = 0;
+ int end = charCount;
+ EncoderFallbackBuffer buffer = null;
+
int origIndex = byteIndex;
- while (charCount-- > 0) {
- char c = chars[charIndex++];
+ for (int i = charIndex; i < end; i++, charCount--)
+ {
+ char c = chars[i];
if (c <= 0x80 || c == 0xFF) { // ASCII
bytes[byteIndex++] = (byte)c;
continue;
byte b1 = convert.u2n[((int)c) * 2 + 1];
byte b2 = convert.u2n[((int)c) * 2];
if (b1 == 0 && b2 == 0) {
- bytes[byteIndex++] = (byte)'?';
+ HandleFallback (ref buffer, chars,
+ ref i, ref charCount,
+ bytes, ref byteIndex, ref byteCount, null);
} else {
bytes[byteIndex++] = b1;
bytes[byteIndex++] = b2;
}
return byteIndex - origIndex;
}
-
+#else
+ // Get the bytes that result from encoding a character buffer.
+ public override int GetByteCount(char[] chars, int index, int count)
+ {
+ DbcsConvert convert = GetConvert();
+ int length = 0;
+
+ while (count-- > 0)
+ {
+ char c = chars[index++];
+ if (c <= 0x80 || c == 0xFF)
+ { // ASCII
+ length++;
+ continue;
+ }
+ byte b1 = convert.u2n[((int)c) * 2 + 1];
+ byte b2 = convert.u2n[((int)c) * 2];
+ if (b1 == 0 && b2 == 0)
+ {
+ // FIXME: handle fallback for GetByteCountImpl().
+ length++;
+ }
+ else
+ length += 2;
+ }
+ return length;
+ }
+
+ // Get the bytes that result from encoding a character buffer.
+ public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ {
+ int byteCount = bytes.Length;
+ int end = charIndex + charCount;
+
+ DbcsConvert convert = GetConvert();
+ EncoderFallbackBuffer buffer = null;
+
+ int origIndex = byteIndex;
+ for (int i = charIndex; i < end; i++, charCount--)
+ {
+ char c = chars[i];
+ if (c <= 0x80 || c == 0xFF)
+ { // ASCII
+ bytes[byteIndex++] = (byte)c;
+ continue;
+ }
+ byte b1 = convert.u2n[((int)c) * 2 + 1];
+ byte b2 = convert.u2n[((int)c) * 2];
+ if (b1 == 0 && b2 == 0)
+ {
+ HandleFallback (ref buffer, chars, ref i, ref charCount,
+ bytes, ref byteIndex, ref byteCount, null);
+ }
+ else
+ {
+ bytes[byteIndex++] = b1;
+ bytes[byteIndex++] = b2;
+ }
+ }
+ return byteIndex - origIndex;
+ }
+#endif
// Get the characters that result from decoding a byte buffer.
public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
char[] chars, int charIndex)
{
+ /*
+ DbcsConvert convert = GetConvert ();
// A1 40 - FA FF
base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
int origIndex = charIndex;
if (lastByte == 0) {
if (b <= 0x80 || b == 0xFF) { // ASCII
chars[charIndex++] = (char)b;
- continue;
} else if (b < 0xA1 || b >= 0xFA) {
- continue;
+ // incorrect first byte.
+ chars[charIndex++] = '?';
+ byteCount--; // cut one more byte.
} else {
lastByte = b;
- continue;
}
+ continue;
}
int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
- char c1 = (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
+ char c1 = ord < 0 || ord > convert.n2u.Length ?
+ '\0' :
+ (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
if (c1 == 0)
chars[charIndex++] = '?';
else
chars[charIndex++] = c1;
lastByte = 0;
}
+ if (lastByte != 0)
+ chars[charIndex++] = '?';
+
return charIndex - origIndex;
+ */
+
+ return GetDecoder ().GetChars (bytes, byteIndex, byteCount, chars, charIndex);
}
// Get a decoder that handles a rolling Big5 state.
public override Decoder GetDecoder()
{
- return new CP950Decoder(convert);
+ return new CP950Decoder(GetConvert ());
}
// Get the mail body name for this encoding.
{
// Constructor.
public CP950Decoder(DbcsConvert convert) : base(convert) {}
-
+ int last_byte_count, last_byte_conv;
+
+ public override int GetCharCount (byte[] bytes, int index, int count)
+ {
+ return GetCharCount (bytes, index, count, false);
+ }
+
+ public override
+ int GetCharCount (byte[] bytes, int index, int count, bool refresh)
+ {
+ CheckRange (bytes, index, count);
+
+ int lastByte = last_byte_count;
+ last_byte_count = 0;
+ int length = 0;
+ while (count-- > 0) {
+ int b = bytes[index++];
+ if (lastByte == 0) {
+ if (b <= 0x80 || b == 0xFF) { // ASCII
+ length++;
+ } else if (b < 0xA1 || b >= 0xFA) {
+ // incorrect first byte.
+ length++;
+ count--; // cut one more byte.
+ } else {
+ lastByte = b;
+ }
+ continue;
+ }
+ int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
+ char c1 = ord < 0 || ord > convert.n2u.Length ?
+ '\0' :
+ (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
+ if (c1 == 0)
+ // FIXME: fallback
+ length++;
+ else
+ length++;
+ lastByte = 0;
+ }
+
+ if (lastByte != 0) {
+ if (refresh)
+ // FIXME: fallback
+ length++;
+ else
+ last_byte_count = lastByte;
+ }
+ return length;
+ }
+
public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
char[] chars, int charIndex)
{
- base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
+ return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false);
+ }
+
+ public override
+ int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex, bool refresh)
+ {
+ CheckRange (bytes, byteIndex, byteCount, chars, charIndex);
+
int origIndex = charIndex;
+ int lastByte = last_byte_conv;
+ last_byte_conv = 0;
while (byteCount-- > 0) {
int b = bytes[byteIndex++];
if (lastByte == 0) {
if (b <= 0x80 || b == 0xFF) { // ASCII
chars[charIndex++] = (char)b;
- continue;
} else if (b < 0xA1 || b >= 0xFA) {
- continue;
+ // incorrect first byte.
+ chars[charIndex++] = '?';
+ byteCount--; // cut one more byte.
} else {
lastByte = b;
- continue;
}
+ continue;
}
int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
- char c1 = (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
- if (c1 == 0) {
+ char c1 = ord < 0 || ord > convert.n2u.Length ?
+ '\0' :
+ (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
+ if (c1 == 0)
chars[charIndex++] = '?';
- } else {
+ else
chars[charIndex++] = c1;
- }
lastByte = 0;
}
+
+ if (lastByte != 0) {
+ if (refresh)
+ chars [charIndex++] = '?';
+ else
+ last_byte_conv = lastByte;
+ }
return charIndex - origIndex;
}
}
}
+ [Serializable]
internal class ENCbig5 : CP950
{
public ENCbig5() {}