5 // Atsushi Enomoto <atsushi@ximian.com>
7 // (new implementation based on CP950.)
17 internal class CP936 : DbcsEncoding
19 // Magic number used by Windows for the Gb2312 code page.
20 private const int GB2312_CODE_PAGE = 936;
23 public CP936() : base(GB2312_CODE_PAGE) {
26 internal override DbcsConvert GetConvert ()
28 return DbcsConvert.Gb2312;
32 // Get the bytes that result from encoding a character buffer.
33 public unsafe override int GetByteCountImpl (char* chars, int count)
35 return GetBytesImpl(chars, count, null, 0);
38 // Get the bytes that result from encoding a character buffer.
39 public unsafe override int GetBytesImpl (char* chars, int charCount, byte* bytes, int byteCount)
41 DbcsConvert gb2312 = GetConvert ();
45 EncoderFallbackBuffer buffer = null;
47 int origIndex = byteIndex;
48 for (int i = charIndex; i < end; i++, charCount--) {
50 if (c <= 0x80 || c == 0xFF) { // ASCII
51 int offset = byteIndex++;
52 if (bytes != null) bytes[offset] = (byte)c;
55 byte b1 = gb2312.u2n[((int)c) * 2 + 1];
56 byte b2 = gb2312.u2n[((int)c) * 2];
57 if (b1 == 0 && b2 == 0) {
58 HandleFallback (ref buffer, chars,
60 bytes, ref byteIndex, ref byteCount, null);
64 bytes[byteIndex++] = b1;
65 bytes[byteIndex++] = b2;
73 return byteIndex - origIndex;
76 protected int GetBytesInternal(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
78 int origIndex = byteIndex;
79 int end = charIndex + charCount;
80 int byteCount = bytes != null ? bytes.Length : 0;
82 DbcsConvert gb2312 = GetConvert();
83 EncoderFallbackBuffer buffer = null;
84 for (int i = charIndex; i < end; i++, charCount--)
87 if (c <= 0x80 || c == 0xFF)
89 int offset = byteIndex++;
90 if (bytes != null) bytes[offset] = (byte)c;
93 byte b1 = gb2312.u2n[((int)c) * 2 + 1];
94 byte b2 = gb2312.u2n[((int)c) * 2];
95 if (b1 == 0 && b2 == 0)
97 HandleFallback (ref buffer, chars, ref i, ref charCount,
98 bytes, ref byteIndex, ref byteCount, null);
104 bytes[byteIndex++] = b1;
105 bytes[byteIndex++] = b2;
113 return byteIndex - origIndex;
116 // Get the bytes that result from encoding a character buffer.
117 public override int GetByteCount(char[] chars, int index, int count)
119 return GetBytes(chars, index, count, null, 0);
122 // Get the bytes that result from encoding a character buffer.
123 public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
125 return GetBytesInternal(chars, charIndex, charCount, bytes, byteIndex);
128 // Get the characters that result from decoding a byte buffer.
129 public override int GetCharCount (byte [] bytes, int index, int count)
131 return GetDecoder ().GetCharCount (bytes, index, count);
134 // Get the characters that result from decoding a byte buffer.
135 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
136 char[] chars, int charIndex)
138 return GetDecoder ().GetChars (
139 bytes, byteIndex, byteCount, chars, charIndex);
142 // Get a decoder that handles a rolling Gb2312 state.
143 public override Decoder GetDecoder()
145 return new CP936Decoder(GetConvert ());
148 // Get the mail body name for this encoding.
149 public override String BodyName
151 get { return("gb2312"); }
154 // Get the human-readable name for this encoding.
155 public override String EncodingName
157 get { return("Chinese Simplified (GB2312)"); }
160 // Get the mail agent header name for this encoding.
161 public override String HeaderName
163 get { return("gb2312"); }
166 // Determine if this encoding can be displayed in a Web browser.
167 public override bool IsBrowserDisplay
169 get { return(true); }
172 // Determine if this encoding can be saved from a Web browser.
173 public override bool IsBrowserSave
175 get { return(true); }
178 // Determine if this encoding can be displayed in a mail/news agent.
179 public override bool IsMailNewsDisplay
181 get { return(true); }
184 // Determine if this encoding can be saved from a mail/news agent.
185 public override bool IsMailNewsSave
187 get { return(true); }
190 // Get the IANA-preferred Web name for this encoding.
191 public override String WebName
193 get { return("gb2312"); }
197 // Decoder that handles a rolling Gb2312 state.
198 sealed class CP936Decoder : DbcsEncoding.DbcsDecoder
201 public CP936Decoder (DbcsConvert convert)
206 int last_byte_count, last_byte_bytes;
208 // Get the characters that result from decoding a byte buffer.
209 public override int GetCharCount (byte [] bytes, int index, int count)
211 return GetCharCount (bytes, index, count, false);
215 int GetCharCount (byte [] bytes, int index, int count, bool refresh)
217 CheckRange (bytes, index, count);
219 int lastByte = last_byte_count;
222 while (count-- > 0) {
223 int b = bytes [index++];
225 if (b <= 0x80 || b == 0xFF) { // ASCII
243 last_byte_count = lastByte;
249 public override int GetChars (byte[] bytes, int byteIndex, int byteCount,
250 char[] chars, int charIndex)
252 return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false);
256 int GetChars (byte [] bytes, int byteIndex, int byteCount,
257 char [] chars, int charIndex, bool refresh)
259 CheckRange (bytes, byteIndex, byteCount, chars, charIndex);
261 int origIndex = charIndex;
262 int lastByte = last_byte_bytes;
264 while (byteCount-- > 0) {
265 int b = bytes[byteIndex++];
267 if (b <= 0x80 || b == 0xFF) { // ASCII
268 chars[charIndex++] = (char)b;
270 } else if (b < 0x81 || b >= 0xFF) {
277 int ord = ((lastByte - 0x81) * 191 + b - 0x40) * 2;
278 char c1 = ord < 0 || ord >= convert.n2u.Length ?
279 '\0' : (char) (convert.n2u[ord] + convert.n2u[ord + 1] * 256);
281 chars[charIndex++] = '?';
283 chars[charIndex++] = c1;
289 // FIXME: handle fallback
290 chars [charIndex++] = '?';
294 last_byte_bytes = lastByte;
297 return charIndex - origIndex;
302 internal class ENCgb2312 : CP936
304 public ENCgb2312(): base () {}