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) {
47 // FIXME: handle fallback for GetByteCountImpl().
56 // Get the bytes that result from encoding a character buffer.
57 public unsafe override int GetBytesImpl (char* chars, int charCount,
58 byte* bytes, int byteCount)
60 DbcsConvert convert = GetConvert ();
64 EncoderFallbackBuffer buffer = null;
66 int origIndex = byteIndex;
67 for (int i = charIndex; i < end; i++, charCount--)
70 if (c <= 0x80 || c == 0xFF) { // ASCII
71 bytes[byteIndex++] = (byte)c;
74 byte b1 = convert.u2n[((int)c) * 2 + 1];
75 byte b2 = convert.u2n[((int)c) * 2];
76 if (b1 == 0 && b2 == 0) {
77 HandleFallback (ref buffer, chars,
79 bytes, ref byteIndex, ref byteCount, null);
81 bytes[byteIndex++] = b1;
82 bytes[byteIndex++] = b2;
85 return byteIndex - origIndex;
88 // Get the bytes that result from encoding a character buffer.
89 public override int GetByteCount(char[] chars, int index, int count)
91 DbcsConvert convert = GetConvert();
96 char c = chars[index++];
97 if (c <= 0x80 || c == 0xFF)
102 byte b1 = convert.u2n[((int)c) * 2 + 1];
103 byte b2 = convert.u2n[((int)c) * 2];
104 if (b1 == 0 && b2 == 0)
106 // FIXME: handle fallback for GetByteCountImpl().
115 // Get the bytes that result from encoding a character buffer.
116 public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
118 int byteCount = bytes.Length;
119 int end = charIndex + charCount;
121 DbcsConvert convert = GetConvert();
122 EncoderFallbackBuffer buffer = null;
124 int origIndex = byteIndex;
125 for (int i = charIndex; i < end; i++, charCount--)
128 if (c <= 0x80 || c == 0xFF)
130 bytes[byteIndex++] = (byte)c;
133 byte b1 = convert.u2n[((int)c) * 2 + 1];
134 byte b2 = convert.u2n[((int)c) * 2];
135 if (b1 == 0 && b2 == 0)
137 HandleFallback (ref buffer, chars, ref i, ref charCount,
138 bytes, ref byteIndex, ref byteCount, null);
142 bytes[byteIndex++] = b1;
143 bytes[byteIndex++] = b2;
146 return byteIndex - origIndex;
149 // Get the characters that result from decoding a byte buffer.
150 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
151 char[] chars, int charIndex)
154 DbcsConvert convert = GetConvert ();
156 base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
157 int origIndex = charIndex;
159 while (byteCount-- > 0) {
160 int b = bytes[byteIndex++];
162 if (b <= 0x80 || b == 0xFF) { // ASCII
163 chars[charIndex++] = (char)b;
164 } else if (b < 0xA1 || b >= 0xFA) {
165 // incorrect first byte.
166 chars[charIndex++] = '?';
167 byteCount--; // cut one more byte.
173 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
174 char c1 = ord < 0 || ord > convert.n2u.Length ?
176 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
178 chars[charIndex++] = '?';
180 chars[charIndex++] = c1;
184 chars[charIndex++] = '?';
186 return charIndex - origIndex;
189 return GetDecoder ().GetChars (bytes, byteIndex, byteCount, chars, charIndex);
192 // Get a decoder that handles a rolling Big5 state.
193 public override Decoder GetDecoder()
195 return new CP950Decoder(GetConvert ());
198 // Get the mail body name for this encoding.
199 public override String BodyName
201 get { return "big5"; }
204 // Get the human-readable name for this encoding.
205 public override String EncodingName
207 get { return "Chinese Traditional (Big5)"; }
210 // Get the mail agent header name for this encoding.
211 public override String HeaderName
213 get { return "big5"; }
216 // Get the IANA-preferred Web name for this encoding.
217 public override String WebName
219 get { return "big5"; }
223 // Get the Windows code page represented by this object.
224 public override int WindowsCodePage
226 get { return BIG5_PAGE; }
230 // Decoder that handles a rolling Big5 state.
231 private sealed class CP950Decoder : DbcsDecoder
234 public CP950Decoder(DbcsConvert convert) : base(convert) {}
235 int last_byte_count, last_byte_conv;
237 public override int GetCharCount (byte[] bytes, int index, int count)
239 return GetCharCount (bytes, index, count, false);
243 int GetCharCount (byte[] bytes, int index, int count, bool refresh)
245 CheckRange (bytes, index, count);
247 int lastByte = last_byte_count;
250 while (count-- > 0) {
251 int b = bytes[index++];
253 if (b <= 0x80 || b == 0xFF) { // ASCII
255 } else if (b < 0xA1 || b >= 0xFA) {
256 // incorrect first byte.
258 count--; // cut one more byte.
264 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
265 char c1 = ord < 0 || ord > convert.n2u.Length ?
267 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
281 last_byte_count = lastByte;
286 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
287 char[] chars, int charIndex)
289 return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false);
293 int GetChars(byte[] bytes, int byteIndex, int byteCount,
294 char[] chars, int charIndex, bool refresh)
296 CheckRange (bytes, byteIndex, byteCount, chars, charIndex);
298 int origIndex = charIndex;
299 int lastByte = last_byte_conv;
301 while (byteCount-- > 0) {
302 int b = bytes[byteIndex++];
304 if (b <= 0x80 || b == 0xFF) { // ASCII
305 chars[charIndex++] = (char)b;
306 } else if (b < 0xA1 || b >= 0xFA) {
307 // incorrect first byte.
308 chars[charIndex++] = '?';
309 byteCount--; // cut one more byte.
315 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
316 char c1 = ord < 0 || ord > convert.n2u.Length ?
318 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
320 chars[charIndex++] = '?';
322 chars[charIndex++] = c1;
328 chars [charIndex++] = '?';
330 last_byte_conv = lastByte;
332 return charIndex - origIndex;
338 internal class ENCbig5 : CP950