Merge pull request #1396 from jwestfall69/dgvrc-clear-speedup
[mono.git] / mcs / class / I18N / CJK / CP936.cs
1 //
2 // I18N.CJK.CP936.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // (new implementation based on CP950.)
8 //
9
10 using System;
11 using System.Text;
12 using I18N.Common;
13
14 namespace I18N.CJK
15 {
16         [Serializable]
17         internal class CP936 : DbcsEncoding
18         {
19                 // Magic number used by Windows for the Gb2312 code page.
20                 private const int GB2312_CODE_PAGE = 936;
21                 
22                 // Constructor.
23                 public CP936() : base(GB2312_CODE_PAGE) {
24                 }
25
26                 internal override DbcsConvert GetConvert ()
27                 {
28                         return DbcsConvert.Gb2312;
29                 }
30
31 #if !DISABLE_UNSAFE
32                 // Get the bytes that result from encoding a character buffer.
33                 public unsafe override int GetByteCountImpl (char* chars, int count)
34                 {
35                         return GetBytesImpl(chars, count, null, 0);
36                 }
37
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)
40                 {
41                         DbcsConvert gb2312 = GetConvert ();
42                         int charIndex = 0;
43                         int byteIndex = 0;
44                         int end = charCount;
45 #if NET_2_0
46                         EncoderFallbackBuffer buffer = null;
47 #endif
48
49                         int origIndex = byteIndex;
50                         for (int i = charIndex; i < end; i++, charCount--) {
51                                 char c = chars[i];
52                                 if (c <= 0x80 || c == 0xFF) { // ASCII
53                                         int offset = byteIndex++;
54                                         if (bytes != null) bytes[offset] = (byte)c;
55                                         continue;
56                                 }
57                                 byte b1 = gb2312.u2n[((int)c) * 2 + 1];
58                                 byte b2 = gb2312.u2n[((int)c) * 2];
59                                 if (b1 == 0 && b2 == 0) {
60 #if NET_2_0
61                                         HandleFallback (ref buffer, chars,
62                                                 ref i, ref charCount,
63                                                 bytes, ref byteIndex, ref byteCount, null);
64 #else
65                                         int offset = byteIndex++;
66                                         if (bytes != null) bytes[offset] = (byte)'?';
67 #endif
68                                 } else {
69                                         if (bytes != null)
70                                         {
71                                                 bytes[byteIndex++] = b1;
72                                                 bytes[byteIndex++] = b2;
73                                         }
74                                         else
75                                         {
76                                                 byteIndex += 2;
77                                         }
78                                 }
79                         }
80                         return byteIndex - origIndex;
81                 }
82 #else
83                 protected int GetBytesInternal(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
84                 {
85                         int origIndex = byteIndex;
86                         int end = charIndex + charCount;
87                         int byteCount = bytes != null ? bytes.Length : 0;
88
89                         DbcsConvert gb2312 = GetConvert();
90 #if NET_2_0
91                         EncoderFallbackBuffer buffer = null;
92 #endif
93                         for (int i = charIndex; i < end; i++, charCount--)
94                         {
95                                 char c = chars[i];
96                                 if (c <= 0x80 || c == 0xFF)
97                                 { // ASCII
98                                         int offset = byteIndex++;
99                                         if (bytes != null) bytes[offset] = (byte)c;
100                                         continue;
101                                 }
102                                 byte b1 = gb2312.u2n[((int)c) * 2 + 1];
103                                 byte b2 = gb2312.u2n[((int)c) * 2];
104                                 if (b1 == 0 && b2 == 0)
105                                 {
106 #if NET_2_0
107                                         HandleFallback (ref buffer, chars, ref i, ref charCount,
108                                                 bytes, ref byteIndex, ref byteCount, null);
109 #else
110                                         int offset = byteIndex++;
111                                         if (bytes != null) bytes[] = (byte)'?';
112 #endif
113                                 }
114                                 else
115                                 {
116                                         if (bytes != null)
117                                         {
118                                                 bytes[byteIndex++] = b1;
119                                                 bytes[byteIndex++] = b2;
120                                         }
121                                         else
122                                         {
123                                                 byteIndex += 2;
124                                         }
125                                 }
126                         }
127                         return byteIndex - origIndex;
128                 }
129
130                 // Get the bytes that result from encoding a character buffer.
131                 public override int GetByteCount(char[] chars, int index, int count)
132                 {
133                         return GetBytes(chars, index, count, null, 0);
134                 }
135
136                 // Get the bytes that result from encoding a character buffer.
137                 public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
138                 {
139                         return GetBytesInternal(chars, charIndex, charCount, bytes, byteIndex);
140                 }
141 #endif
142                 // Get the characters that result from decoding a byte buffer.
143                 public override int GetCharCount (byte [] bytes, int index, int count)
144                 {
145                         return GetDecoder ().GetCharCount (bytes, index, count);
146                 }
147
148                 // Get the characters that result from decoding a byte buffer.
149                 public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
150                                              char[] chars, int charIndex)
151                 {
152                         return GetDecoder ().GetChars (
153                                 bytes, byteIndex, byteCount, chars, charIndex);
154                 }
155                 
156                 // Get a decoder that handles a rolling Gb2312 state.
157                 public override Decoder GetDecoder()
158                 {
159                         return new CP936Decoder(GetConvert ());
160                 }
161                 
162                 // Get the mail body name for this encoding.
163                 public override String BodyName
164                 {
165                         get { return("gb2312"); }
166                 }
167                 
168                 // Get the human-readable name for this encoding.
169                 public override String EncodingName
170                 {
171                         get { return("Chinese Simplified (GB2312)"); }
172                 }
173                 
174                 // Get the mail agent header name for this encoding.
175                 public override String HeaderName
176                 {
177                         get { return("gb2312"); }
178                 }
179                 
180                 // Determine if this encoding can be displayed in a Web browser.
181                 public override bool IsBrowserDisplay
182                 {
183                         get { return(true); }
184                 }
185                 
186                 // Determine if this encoding can be saved from a Web browser.
187                 public override bool IsBrowserSave
188                 {
189                         get { return(true); }
190                 }
191                 
192                 // Determine if this encoding can be displayed in a mail/news agent.
193                 public override bool IsMailNewsDisplay
194                 {
195                         get { return(true); }
196                 }
197                 
198                 // Determine if this encoding can be saved from a mail/news agent.
199                 public override bool IsMailNewsSave
200                 {
201                         get { return(true); }
202                 }
203                 
204                 // Get the IANA-preferred Web name for this encoding.
205                 public override String WebName
206                 {
207                         get { return("gb2312"); }
208                 }
209         }
210
211         // Decoder that handles a rolling Gb2312 state.
212         sealed class CP936Decoder : DbcsEncoding.DbcsDecoder
213         {
214                 // Constructor.
215                 public CP936Decoder (DbcsConvert convert)
216                         : base (convert)
217                 {
218                 }
219
220                 int last_byte_count, last_byte_bytes;
221
222                 // Get the characters that result from decoding a byte buffer.
223                 public override int GetCharCount (byte [] bytes, int index, int count)
224                 {
225                         return GetCharCount (bytes, index, count, false);
226                 }
227
228 #if NET_2_0
229                 public override
230 #endif
231                 int GetCharCount (byte [] bytes, int index, int count, bool refresh)
232                 {
233                         CheckRange (bytes, index, count);
234
235                         int lastByte = last_byte_count;
236                         last_byte_count = 0;
237                         int length = 0;
238                         while (count-- > 0) {
239                                 int b = bytes [index++];
240                                 if (lastByte == 0) {
241                                         if (b <= 0x80 || b == 0xFF) { // ASCII
242                                                 length++;
243                                                 continue;
244                                         } else {
245                                                 lastByte = b;
246                                                 continue;
247                                         }
248                                 }
249                                 length++;
250                                 lastByte = 0;
251                         }
252
253                         if (lastByte != 0) {
254                                 if (refresh) {
255                                         length++;
256                                         last_byte_count = 0;
257                                 }
258                                 else
259                                         last_byte_count = lastByte;
260                         }
261
262                         return length;
263                 }
264
265                 public override int GetChars (byte[] bytes, int byteIndex, int byteCount,
266                                              char[] chars, int charIndex)
267                 {
268                         return GetChars (bytes, byteIndex, byteCount, chars, charIndex, false);
269                 }
270
271 #if NET_2_0
272                 public override
273 #endif
274                 int GetChars (byte [] bytes, int byteIndex, int byteCount,
275                               char [] chars, int charIndex, bool refresh)
276                 {
277                         CheckRange (bytes, byteIndex, byteCount, chars, charIndex);
278
279                         int origIndex = charIndex;
280                         int lastByte = last_byte_bytes;
281                         last_byte_bytes = 0;
282                         while (byteCount-- > 0) {
283                                 int b = bytes[byteIndex++];
284                                 if (lastByte == 0) {
285                                         if (b <= 0x80 || b == 0xFF) { // ASCII
286                                                 chars[charIndex++] = (char)b;
287                                                 continue;
288                                         } else if (b < 0x81 || b >= 0xFF) {
289                                                 continue;
290                                         } else {
291                                                 lastByte = b;
292                                                 continue;
293                                         }
294                                 }
295                                 int ord = ((lastByte - 0x81) * 191 + b - 0x40) * 2;
296                                 char c1 = ord < 0 || ord >= convert.n2u.Length ?
297                                         '\0' : (char) (convert.n2u[ord] + convert.n2u[ord + 1] * 256);
298                                 if (c1 == 0)
299                                         chars[charIndex++] = '?';
300                                 else
301                                         chars[charIndex++] = c1;
302                                 lastByte = 0;
303                         }
304
305                         if (lastByte != 0) {
306                                 if (refresh) {
307                                         // FIXME: handle fallback
308                                         chars [charIndex++] = '?';
309                                         last_byte_bytes = 0;
310                                 }
311                                 else
312                                         last_byte_bytes = lastByte;
313                         }
314
315                         return charIndex - origIndex;
316                 }
317         }
318         
319         [Serializable]
320         internal class ENCgb2312 : CP936
321         {
322                 public ENCgb2312(): base () {}
323         }
324 }