5 // Alan Tam Siu Lung (Tam@SiuLung.com)
6 // Atsushi Enomoto <atsushi@ximian.com>
16 internal class CP950 : DbcsEncoding
18 // Magic number used by Windows for the Big5 code page.
19 private const int BIG5_CODE_PAGE = 950;
22 public CP950() : base(BIG5_CODE_PAGE) {
25 internal override DbcsConvert GetConvert ()
27 return DbcsConvert.Big5;
31 // Get the bytes that result from encoding a character buffer.
32 public unsafe override int GetByteCountImpl (char* chars, int count)
34 DbcsConvert convert = GetConvert ();
39 char c = chars[index++];
40 if (c <= 0x80 || c == 0xFF) { // ASCII
44 byte b1 = convert.u2n[((int)c) * 2 + 1];
45 byte b2 = convert.u2n[((int)c) * 2];
46 if (b1 == 0 && b2 == 0) {
48 // FIXME: handle fallback for GetByteCountImpl().
60 // Get the bytes that result from encoding a character buffer.
61 public unsafe override int GetBytesImpl (char* chars, int charCount,
62 byte* bytes, int byteCount)
64 DbcsConvert convert = GetConvert ();
69 EncoderFallbackBuffer buffer = null;
72 int origIndex = byteIndex;
73 for (int i = charIndex; i < end; i++, charCount--)
76 if (c <= 0x80 || c == 0xFF) { // ASCII
77 bytes[byteIndex++] = (byte)c;
80 byte b1 = convert.u2n[((int)c) * 2 + 1];
81 byte b2 = convert.u2n[((int)c) * 2];
82 if (b1 == 0 && b2 == 0) {
84 HandleFallback (ref buffer, chars,
86 bytes, ref byteIndex, ref byteCount, null);
88 bytes[byteIndex++] = (byte)'?';
91 bytes[byteIndex++] = b1;
92 bytes[byteIndex++] = b2;
95 return byteIndex - origIndex;
98 // Get the bytes that result from encoding a character buffer.
99 public override int GetByteCount(char[] chars, int index, int count)
101 DbcsConvert convert = GetConvert();
106 char c = chars[index++];
107 if (c <= 0x80 || c == 0xFF)
112 byte b1 = convert.u2n[((int)c) * 2 + 1];
113 byte b2 = convert.u2n[((int)c) * 2];
114 if (b1 == 0 && b2 == 0)
117 // FIXME: handle fallback for GetByteCountImpl().
129 // Get the bytes that result from encoding a character buffer.
130 public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
132 int byteCount = bytes.Length;
133 int end = charIndex + charCount;
135 DbcsConvert convert = GetConvert();
137 EncoderFallbackBuffer buffer = null;
140 int origIndex = byteIndex;
141 for (int i = charIndex; i < end; i++, charCount--)
144 if (c <= 0x80 || c == 0xFF)
146 bytes[byteIndex++] = (byte)c;
149 byte b1 = convert.u2n[((int)c) * 2 + 1];
150 byte b2 = convert.u2n[((int)c) * 2];
151 if (b1 == 0 && b2 == 0)
154 HandleFallback (ref buffer, chars, ref i, ref charCount,
155 bytes, ref byteIndex, ref byteCount, null);
157 bytes[byteIndex++] = (byte)'?';
162 bytes[byteIndex++] = b1;
163 bytes[byteIndex++] = b2;
166 return byteIndex - origIndex;
169 // Get the characters that result from decoding a byte buffer.
170 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
171 char[] chars, int charIndex)
174 DbcsConvert convert = GetConvert ();
176 base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
177 int origIndex = charIndex;
179 while (byteCount-- > 0) {
180 int b = bytes[byteIndex++];
182 if (b <= 0x80 || b == 0xFF) { // ASCII
183 chars[charIndex++] = (char)b;
184 } else if (b < 0xA1 || b >= 0xFA) {
185 // incorrect first byte.
186 chars[charIndex++] = '?';
187 byteCount--; // cut one more byte.
193 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
194 char c1 = ord < 0 || ord > convert.n2u.Length ?
196 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
198 chars[charIndex++] = '?';
200 chars[charIndex++] = c1;
204 chars[charIndex++] = '?';
206 return charIndex - origIndex;
209 return GetDecoder ().GetChars (bytes, byteIndex, byteCount, chars, charIndex);
212 // Get a decoder that handles a rolling Big5 state.
213 public override Decoder GetDecoder()
215 return new CP950Decoder(GetConvert ());
218 // Get the mail body name for this encoding.
219 public override String BodyName
221 get { return "big5"; }
224 // Get the human-readable name for this encoding.
225 public override String EncodingName
227 get { return "Chinese Traditional (Big5)"; }
230 // Get the mail agent header name for this encoding.
231 public override String HeaderName
233 get { return "big5"; }
236 // Get the IANA-preferred Web name for this encoding.
237 public override String WebName
239 get { return "big5"; }
243 // Get the Windows code page represented by this object.
244 public override int WindowsCodePage
246 get { return BIG5_PAGE; }
250 // Decoder that handles a rolling Big5 state.
251 private sealed class CP950Decoder : DbcsDecoder
254 public CP950Decoder(DbcsConvert convert) : base(convert) {}
255 int last_byte_count, last_byte_conv;
257 public override int GetCharCount (byte[] bytes, int index, int count)
259 return GetCharCount (bytes, index, count, false);
265 int GetCharCount (byte[] bytes, int index, int count, bool refresh)
267 CheckRange (bytes, index, count);
269 int lastByte = last_byte_count;
272 while (count-- > 0) {
273 int b = bytes[index++];
275 if (b <= 0x80 || b == 0xFF) { // ASCII
277 } else if (b < 0xA1 || b >= 0xFA) {
278 // incorrect first byte.
280 count--; // cut one more byte.
286 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
287 char c1 = ord < 0 || ord > convert.n2u.Length ?
289 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
303 last_byte_count = lastByte;
308 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
309 char[] chars, int charIndex)
311 return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false);
317 int GetChars(byte[] bytes, int byteIndex, int byteCount,
318 char[] chars, int charIndex, bool refresh)
320 CheckRange (bytes, byteIndex, byteCount, chars, charIndex);
322 int origIndex = charIndex;
323 int lastByte = last_byte_conv;
325 while (byteCount-- > 0) {
326 int b = bytes[byteIndex++];
328 if (b <= 0x80 || b == 0xFF) { // ASCII
329 chars[charIndex++] = (char)b;
330 } else if (b < 0xA1 || b >= 0xFA) {
331 // incorrect first byte.
332 chars[charIndex++] = '?';
333 byteCount--; // cut one more byte.
339 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
340 char c1 = ord < 0 || ord > convert.n2u.Length ?
342 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
344 chars[charIndex++] = '?';
346 chars[charIndex++] = c1;
352 chars [charIndex++] = '?';
354 last_byte_conv = lastByte;
356 return charIndex - origIndex;
362 internal class ENCbig5 : CP950