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
;
31 // Get the bytes that result from encoding a character buffer.
32 public unsafe override int GetByteCountImpl (
33 char* chars
, int count
)
35 DbcsConvert gb2312
= GetConvert ();
39 char c
= chars
[index
++];
40 if (c
<= 0x80 || c
== 0xFF) { // ASCII
44 byte b1
= gb2312
.u2n
[((int)c
) * 2 + 1];
45 byte b2
= gb2312
.u2n
[((int)c
) * 2];
46 if (b1
== 0 && b2
== 0) {
48 // FIXME: handle fallback for GetByteCount().
59 // Get the bytes that result from encoding a character buffer.
60 public unsafe override int GetBytesImpl (char* chars
, int charCount
,
61 byte* bytes
, int byteCount
)
63 DbcsConvert gb2312
= GetConvert ();
67 EncoderFallbackBuffer buffer
= null;
70 int origIndex
= byteIndex
;
71 while (charCount
-- > 0) {
72 char c
= chars
[charIndex
++];
73 if (c
<= 0x80 || c
== 0xFF) { // ASCII
74 bytes
[byteIndex
++] = (byte)c
;
77 byte b1
= gb2312
.u2n
[((int)c
) * 2 + 1];
78 byte b2
= gb2312
.u2n
[((int)c
) * 2];
79 if (b1
== 0 && b2
== 0) {
81 HandleFallback (ref buffer
, chars
,
82 ref charIndex
, ref charCount
,
83 bytes
, ref byteIndex
, ref byteCount
);
85 bytes
[byteIndex
++] = (byte)'?';
88 bytes
[byteIndex
++] = b1
;
89 bytes
[byteIndex
++] = b2
;
92 return byteIndex
- origIndex
;
95 // Get the characters that result from decoding a byte buffer.
96 public override int GetCharCount (byte [] bytes
, int index
, int count
)
98 return GetDecoder ().GetCharCount (bytes
, index
, count
);
101 // Get the characters that result from decoding a byte buffer.
102 public override int GetChars(byte[] bytes
, int byteIndex
, int byteCount
,
103 char[] chars
, int charIndex
)
105 return GetDecoder ().GetChars (
106 bytes
, byteIndex
, byteCount
, chars
, charIndex
);
109 // Get a decoder that handles a rolling Gb2312 state.
110 public override Decoder
GetDecoder()
112 return new CP936Decoder(GetConvert ());
115 // Get the mail body name for this encoding.
116 public override String BodyName
118 get { return("gb2312"); }
121 // Get the human-readable name for this encoding.
122 public override String EncodingName
124 get { return("Chinese Simplified (GB2312)"); }
127 // Get the mail agent header name for this encoding.
128 public override String HeaderName
130 get { return("gb2312"); }
133 // Determine if this encoding can be displayed in a Web browser.
134 public override bool IsBrowserDisplay
136 get { return(true); }
139 // Determine if this encoding can be saved from a Web browser.
140 public override bool IsBrowserSave
142 get { return(true); }
145 // Determine if this encoding can be displayed in a mail/news agent.
146 public override bool IsMailNewsDisplay
148 get { return(true); }
151 // Determine if this encoding can be saved from a mail/news agent.
152 public override bool IsMailNewsSave
154 get { return(true); }
157 // Get the IANA-preferred Web name for this encoding.
158 public override String WebName
160 get { return("gb2312"); }
164 // Decoder that handles a rolling Gb2312 state.
165 sealed class CP936Decoder
: DbcsEncoding
.DbcsDecoder
168 public CP936Decoder (DbcsConvert convert
)
173 int last_byte_count
, last_byte_bytes
;
175 // Get the characters that result from decoding a byte buffer.
176 public override int GetCharCount (byte [] bytes
, int index
, int count
)
178 return GetCharCount (bytes
, index
, count
, false);
184 int GetCharCount (byte [] bytes
, int index
, int count
, bool refresh
)
186 CheckRange (bytes
, index
, count
);
188 int lastByte
= last_byte_count
;
191 while (count
-- > 0) {
192 int b
= bytes
[index
++];
194 if (b
<= 0x80 || b
== 0xFF) { // ASCII
212 last_byte_count
= lastByte
;
218 public override int GetChars (byte[] bytes
, int byteIndex
, int byteCount
,
219 char[] chars
, int charIndex
)
221 return GetChars (bytes
, byteIndex
, byteCount
, chars
, charIndex
, false);
227 int GetChars (byte [] bytes
, int byteIndex
, int byteCount
,
228 char [] chars
, int charIndex
, bool refresh
)
230 CheckRange (bytes
, byteIndex
, byteCount
, chars
, charIndex
);
232 int origIndex
= charIndex
;
233 int lastByte
= last_byte_bytes
;
235 while (byteCount
-- > 0) {
236 int b
= bytes
[byteIndex
++];
238 if (b
<= 0x80 || b
== 0xFF) { // ASCII
239 chars
[charIndex
++] = (char)b
;
241 } else if (b
< 0x81 || b
>= 0xFF) {
248 int ord
= ((lastByte
- 0x81) * 191 + b
- 0x40) * 2;
249 char c1
= ord
< 0 || ord
>= convert
.n2u
.Length
?
250 '\0' : (char) (convert
.n2u
[ord
] + convert
.n2u
[ord
+ 1] * 256);
252 chars
[charIndex
++] = '?';
254 chars
[charIndex
++] = c1
;
260 // FIXME: handle fallback
261 chars
[charIndex
++] = '?';
265 last_byte_bytes
= lastByte
;
268 return charIndex
- origIndex
;
273 internal class ENCgb2312
: CP936
275 public ENCgb2312(): base () {}