5 // Alan Tam Siu Lung (Tam@SiuLung.com)
15 internal class CP950 : DbcsEncoding
17 // Magic number used by Windows for the Big5 code page.
18 private const int BIG5_CODE_PAGE = 950;
21 public CP950() : base(BIG5_CODE_PAGE) {
24 internal override DbcsConvert GetConvert ()
26 return Big5Convert.Convert;
29 // Get the bytes that result from encoding a character buffer.
30 public unsafe override int GetBytesImpl (char* chars, int charCount,
31 byte* bytes, int byteCount)
33 DbcsConvert convert = GetConvert ();
37 EncoderFallbackBuffer buffer = null;
40 int origIndex = byteIndex;
41 while (charCount-- > 0) {
42 char c = chars[charIndex++];
43 if (c <= 0x80 || c == 0xFF) { // ASCII
44 bytes[byteIndex++] = (byte)c;
47 byte b1 = convert.u2n[((int)c) * 2 + 1];
48 byte b2 = convert.u2n[((int)c) * 2];
49 if (b1 == 0 && b2 == 0) {
51 HandleFallback (ref buffer, chars,
52 ref charIndex, ref charCount,
53 bytes, ref byteIndex, ref byteCount);
55 bytes[byteIndex++] = (byte)'?';
58 bytes[byteIndex++] = b1;
59 bytes[byteIndex++] = b2;
62 return byteIndex - origIndex;
65 // Get the characters that result from decoding a byte buffer.
66 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
67 char[] chars, int charIndex)
70 DbcsConvert convert = GetConvert ();
72 base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
73 int origIndex = charIndex;
75 while (byteCount-- > 0) {
76 int b = bytes[byteIndex++];
78 if (b <= 0x80 || b == 0xFF) { // ASCII
79 chars[charIndex++] = (char)b;
80 } else if (b < 0xA1 || b >= 0xFA) {
81 // incorrect first byte.
82 chars[charIndex++] = '?';
83 byteCount--; // cut one more byte.
89 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
90 char c1 = ord < 0 || ord > convert.n2u.Length ?
92 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
94 chars[charIndex++] = '?';
96 chars[charIndex++] = c1;
100 chars[charIndex++] = '?';
102 return charIndex - origIndex;
105 return GetDecoder ().GetChars (bytes, byteIndex, byteCount, chars, charIndex);
108 // Get a decoder that handles a rolling Big5 state.
109 public override Decoder GetDecoder()
111 return new CP950Decoder(GetConvert ());
114 // Get the mail body name for this encoding.
115 public override String BodyName
117 get { return "big5"; }
120 // Get the human-readable name for this encoding.
121 public override String EncodingName
123 get { return "Chinese Traditional (Big5)"; }
126 // Get the mail agent header name for this encoding.
127 public override String HeaderName
129 get { return "big5"; }
132 // Get the IANA-preferred Web name for this encoding.
133 public override String WebName
135 get { return "big5"; }
139 // Get the Windows code page represented by this object.
140 public override int WindowsCodePage
142 get { return BIG5_PAGE; }
146 // Decoder that handles a rolling Big5 state.
147 private sealed class CP950Decoder : DbcsDecoder
150 public CP950Decoder(DbcsConvert convert) : base(convert) {}
151 int last_byte_count, last_byte_conv;
153 public override int GetCharCount (byte[] bytes, int index, int count)
155 return GetCharCount (bytes, index, count, false);
161 int GetCharCount (byte[] bytes, int index, int count, bool refresh)
163 CheckRange (bytes, index, count);
165 int lastByte = last_byte_count;
168 while (count-- > 0) {
169 int b = bytes[index++];
171 if (b <= 0x80 || b == 0xFF) { // ASCII
173 } else if (b < 0xA1 || b >= 0xFA) {
174 // incorrect first byte.
176 count--; // cut one more byte.
182 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
183 char c1 = ord < 0 || ord > convert.n2u.Length ?
185 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
199 last_byte_count = lastByte;
204 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
205 char[] chars, int charIndex)
207 return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false);
213 int GetChars(byte[] bytes, int byteIndex, int byteCount,
214 char[] chars, int charIndex, bool refresh)
216 CheckRange (bytes, byteIndex, byteCount, chars, charIndex);
218 int origIndex = charIndex;
219 int lastByte = last_byte_conv;
221 while (byteCount-- > 0) {
222 int b = bytes[byteIndex++];
224 if (b <= 0x80 || b == 0xFF) { // ASCII
225 chars[charIndex++] = (char)b;
226 } else if (b < 0xA1 || b >= 0xFA) {
227 // incorrect first byte.
228 chars[charIndex++] = '?';
229 byteCount--; // cut one more byte.
235 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
236 char c1 = ord < 0 || ord > convert.n2u.Length ?
238 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
240 chars[charIndex++] = '?';
242 chars[charIndex++] = c1;
248 chars [charIndex++] = '?';
250 last_byte_conv = lastByte;
252 return charIndex - origIndex;
258 internal class ENCbig5 : CP950