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;
30 // Get the bytes that result from encoding a character buffer.
31 public unsafe override int GetByteCountImpl (char* chars, int count)
33 DbcsConvert convert = GetConvert ();
37 EncoderFallbackBuffer buffer = null;
41 char c = chars[index++];
42 if (c <= 0x80 || c == 0xFF) { // ASCII
46 byte b1 = convert.u2n[((int)c) * 2 + 1];
47 byte b2 = convert.u2n[((int)c) * 2];
48 if (b1 == 0 && b2 == 0) {
50 // FIXME: handle fallback for GetByteCountImpl().
62 // Get the bytes that result from encoding a character buffer.
63 public unsafe override int GetBytesImpl (char* chars, int charCount,
64 byte* bytes, int byteCount)
66 DbcsConvert convert = GetConvert ();
70 EncoderFallbackBuffer buffer = null;
73 int origIndex = byteIndex;
74 while (charCount-- > 0) {
75 char c = chars[charIndex++];
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,
85 ref charIndex, ref charCount,
86 bytes, ref byteIndex, ref byteCount);
88 bytes[byteIndex++] = (byte)'?';
91 bytes[byteIndex++] = b1;
92 bytes[byteIndex++] = b2;
95 return byteIndex - origIndex;
98 // Get the characters that result from decoding a byte buffer.
99 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
100 char[] chars, int charIndex)
103 DbcsConvert convert = GetConvert ();
105 base.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
106 int origIndex = charIndex;
108 while (byteCount-- > 0) {
109 int b = bytes[byteIndex++];
111 if (b <= 0x80 || b == 0xFF) { // ASCII
112 chars[charIndex++] = (char)b;
113 } else if (b < 0xA1 || b >= 0xFA) {
114 // incorrect first byte.
115 chars[charIndex++] = '?';
116 byteCount--; // cut one more byte.
122 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
123 char c1 = ord < 0 || ord > convert.n2u.Length ?
125 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
127 chars[charIndex++] = '?';
129 chars[charIndex++] = c1;
133 chars[charIndex++] = '?';
135 return charIndex - origIndex;
138 return GetDecoder ().GetChars (bytes, byteIndex, byteCount, chars, charIndex);
141 // Get a decoder that handles a rolling Big5 state.
142 public override Decoder GetDecoder()
144 return new CP950Decoder(GetConvert ());
147 // Get the mail body name for this encoding.
148 public override String BodyName
150 get { return "big5"; }
153 // Get the human-readable name for this encoding.
154 public override String EncodingName
156 get { return "Chinese Traditional (Big5)"; }
159 // Get the mail agent header name for this encoding.
160 public override String HeaderName
162 get { return "big5"; }
165 // Get the IANA-preferred Web name for this encoding.
166 public override String WebName
168 get { return "big5"; }
172 // Get the Windows code page represented by this object.
173 public override int WindowsCodePage
175 get { return BIG5_PAGE; }
179 // Decoder that handles a rolling Big5 state.
180 private sealed class CP950Decoder : DbcsDecoder
183 public CP950Decoder(DbcsConvert convert) : base(convert) {}
184 int last_byte_count, last_byte_conv;
186 public override int GetCharCount (byte[] bytes, int index, int count)
188 return GetCharCount (bytes, index, count, false);
194 int GetCharCount (byte[] bytes, int index, int count, bool refresh)
196 CheckRange (bytes, index, count);
198 int lastByte = last_byte_count;
201 while (count-- > 0) {
202 int b = bytes[index++];
204 if (b <= 0x80 || b == 0xFF) { // ASCII
206 } else if (b < 0xA1 || b >= 0xFA) {
207 // incorrect first byte.
209 count--; // cut one more byte.
215 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
216 char c1 = ord < 0 || ord > convert.n2u.Length ?
218 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
232 last_byte_count = lastByte;
237 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
238 char[] chars, int charIndex)
240 return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false);
246 int GetChars(byte[] bytes, int byteIndex, int byteCount,
247 char[] chars, int charIndex, bool refresh)
249 CheckRange (bytes, byteIndex, byteCount, chars, charIndex);
251 int origIndex = charIndex;
252 int lastByte = last_byte_conv;
254 while (byteCount-- > 0) {
255 int b = bytes[byteIndex++];
257 if (b <= 0x80 || b == 0xFF) { // ASCII
258 chars[charIndex++] = (char)b;
259 } else if (b < 0xA1 || b >= 0xFA) {
260 // incorrect first byte.
261 chars[charIndex++] = '?';
262 byteCount--; // cut one more byte.
268 int ord = ((lastByte - 0xA1) * 191 + b - 0x40) * 2;
269 char c1 = ord < 0 || ord > convert.n2u.Length ?
271 (char)(convert.n2u[ord] + convert.n2u[ord + 1] * 256);
273 chars[charIndex++] = '?';
275 chars[charIndex++] = c1;
281 chars [charIndex++] = '?';
283 last_byte_conv = lastByte;
285 return charIndex - origIndex;
291 internal class ENCbig5 : CP950