Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / text / asciiencoding.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 namespace System.Text
7 {
8     using System;
9     using System.Runtime.Serialization;
10     using System.Security.Permissions;
11     using System.Diagnostics.Contracts;
12
13     // ASCIIEncoding
14     //
15     // Note that ASCIIEncoding is optomized with no best fit and ? for fallback.
16     // It doesn't come in other flavors.
17     //
18     // Note: ASCIIEncoding is the only encoding that doesn't do best fit (windows has best fit).
19     //
20     // Note: IsAlwaysNormalized remains false because 1/2 the code points are unassigned, so they'd
21     //       use fallbacks, and we cannot guarantee that fallbacks are normalized.
22     //
23
24     [Serializable]
25 [System.Runtime.InteropServices.ComVisible(true)]
26     public class ASCIIEncoding : Encoding
27     {
28
29         public ASCIIEncoding() : base(Encoding.CodePageASCII)
30         {
31         }
32
33         internal override void SetDefaultFallbacks()
34         {
35             // For ASCIIEncoding we just use default replacement fallback
36             this.encoderFallback = EncoderFallback.ReplacementFallback;
37             this.decoderFallback = DecoderFallback.ReplacementFallback;
38         }
39
40         //
41         // WARNING: GetByteCount(string chars), GetBytes(string chars,...), and GetString(byte[] byteIndex...)
42         // WARNING: have different variable names than EncodingNLS.cs, so this can't just be cut & pasted,
43         // WARNING: or it'll break VB's way of calling these.
44         //
45         // The following methods are copied from EncodingNLS.cs.
46         // Unfortunately EncodingNLS.cs is internal and we're public, so we have to reimpliment them here.
47         // These should be kept in sync for the following classes:
48         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
49         //
50
51         // Returns the number of bytes required to encode a range of characters in
52         // a character array.
53         //
54         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
55         // So if you fix this, fix the others.  Currently those include:
56         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
57         // parent method is safe
58
59         [System.Security.SecuritySafeCritical]  // auto-generated
60         public override unsafe int GetByteCount(char[] chars, int index, int count)
61         {
62             // Validate input parameters
63             if (chars == null)
64                 throw new ArgumentNullException("chars",
65                       Environment.GetResourceString("ArgumentNull_Array"));
66
67             if (index < 0 || count < 0)
68                 throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"),
69                       Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
70
71             if (chars.Length - index < count)
72                 throw new ArgumentOutOfRangeException("chars",
73                       Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
74             Contract.EndContractBlock();
75
76             // If no input, return 0, avoid fixed empty array problem
77             if (chars.Length == 0)
78                 return 0;
79
80             // Just call the pointer version
81             fixed (char* pChars = chars)
82                 return GetByteCount(pChars + index, count, null);
83         }
84
85         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
86         // So if you fix this, fix the others.  Currently those include:
87         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
88         // parent method is safe
89
90         [System.Security.SecuritySafeCritical]  // auto-generated
91         public override unsafe int GetByteCount(String chars)
92         {
93             // Validate input
94             if (chars==null)
95                 throw new ArgumentNullException("chars");
96             Contract.EndContractBlock();
97
98             fixed (char* pChars = chars)
99                 return GetByteCount(pChars, chars.Length, null);
100         }
101
102         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
103         // So if you fix this, fix the others.  Currently those include:
104         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
105
106         [System.Security.SecurityCritical]  // auto-generated
107         [CLSCompliant(false)]
108         [System.Runtime.InteropServices.ComVisible(false)]
109         public override unsafe int GetByteCount(char* chars, int count)
110         {
111             // Validate Parameters
112             if (chars == null)
113                 throw new ArgumentNullException("chars",
114                     Environment.GetResourceString("ArgumentNull_Array"));
115
116             if (count < 0)
117                 throw new ArgumentOutOfRangeException("count",
118                     Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
119             Contract.EndContractBlock();
120
121             // Call it with empty encoder
122             return GetByteCount(chars, count, null);
123         }
124
125         // Parent method is safe.
126         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
127         // So if you fix this, fix the others.  Currently those include:
128         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
129
130         [System.Security.SecuritySafeCritical]  // auto-generated
131         public override unsafe int GetBytes(String chars, int charIndex, int charCount,
132                                               byte[] bytes, int byteIndex)
133         {
134             if (chars == null || bytes == null)
135                 throw new ArgumentNullException((chars == null ? "chars" : "bytes"),
136                       Environment.GetResourceString("ArgumentNull_Array"));
137
138             if (charIndex < 0 || charCount < 0)
139                 throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"),
140                       Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
141
142             if (chars.Length - charIndex < charCount)
143                 throw new ArgumentOutOfRangeException("chars",
144                       Environment.GetResourceString("ArgumentOutOfRange_IndexCount"));
145
146             if (byteIndex < 0 || byteIndex > bytes.Length)
147                 throw new ArgumentOutOfRangeException("byteIndex",
148                     Environment.GetResourceString("ArgumentOutOfRange_Index"));
149             Contract.EndContractBlock();
150
151             int byteCount = bytes.Length - byteIndex;
152
153             // Fixed doesn't like empty byte arrays
154             if (bytes.Length == 0)
155                 bytes = new byte[1];
156
157             fixed (char* pChars = chars)
158                 fixed ( byte* pBytes = bytes)
159                     return GetBytes(pChars + charIndex, charCount,
160                                     pBytes + byteIndex, byteCount, null);
161         }
162
163         // Encodes a range of characters in a character array into a range of bytes
164         // in a byte array. An exception occurs if the byte array is not large
165         // enough to hold the complete encoding of the characters. The
166         // GetByteCount method can be used to determine the exact number of
167         // bytes that will be produced for a given range of characters.
168         // Alternatively, the GetMaxByteCount method can be used to
169         // determine the maximum number of bytes that will be produced for a given
170         // number of characters, regardless of the actual character values.
171         //
172         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
173         // So if you fix this, fix the others.  Currently those include:
174         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
175         // parent method is safe
176
177         [System.Security.SecuritySafeCritical]  // auto-generated
178         public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
179                                                byte[] bytes, int byteIndex)
180         {
181             // Validate parameters
182             if (chars == null || bytes == null)
183                 throw new ArgumentNullException((chars == null ? "chars" : "bytes"),
184                       Environment.GetResourceString("ArgumentNull_Array"));
185
186             if (charIndex < 0 || charCount < 0)
187                 throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"),
188                       Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
189
190             if (chars.Length - charIndex < charCount)
191                 throw new ArgumentOutOfRangeException("chars",
192                       Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
193
194             if (byteIndex < 0 || byteIndex > bytes.Length)
195                 throw new ArgumentOutOfRangeException("byteIndex",
196                      Environment.GetResourceString("ArgumentOutOfRange_Index"));
197             Contract.EndContractBlock();
198
199             // If nothing to encode return 0, avoid fixed problem
200             if (chars.Length == 0)
201                 return 0;
202
203             // Just call pointer version
204             int byteCount = bytes.Length - byteIndex;
205
206             // Fixed doesn't like empty byte arrays
207             if (bytes.Length == 0)
208                 bytes = new byte[1];
209
210             fixed (char* pChars = chars)
211                 fixed (byte* pBytes = bytes)
212                     // Remember that byteCount is # to decode, not size of array.
213                     return GetBytes(pChars + charIndex, charCount,
214                                     pBytes + byteIndex, byteCount, null);
215         }
216
217         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
218         // So if you fix this, fix the others.  Currently those include:
219         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
220
221         [System.Security.SecurityCritical]  // auto-generated
222         [CLSCompliant(false)]
223         [System.Runtime.InteropServices.ComVisible(false)]
224         public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
225         {
226             // Validate Parameters
227             if (bytes == null || chars == null)
228                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
229                     Environment.GetResourceString("ArgumentNull_Array"));
230
231             if (charCount < 0 || byteCount < 0)
232                 throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"),
233                     Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
234             Contract.EndContractBlock();
235
236             return GetBytes(chars, charCount, bytes, byteCount, null);
237         }
238
239         // Returns the number of characters produced by decoding a range of bytes
240         // in a byte array.
241         //
242         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
243         // So if you fix this, fix the others.  Currently those include:
244         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
245         // parent method is safe
246
247         [System.Security.SecuritySafeCritical]  // auto-generated
248         public override unsafe int GetCharCount(byte[] bytes, int index, int count)
249         {
250             // Validate Parameters
251             if (bytes == null)
252                 throw new ArgumentNullException("bytes",
253                     Environment.GetResourceString("ArgumentNull_Array"));
254
255             if (index < 0 || count < 0)
256                 throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"),
257                     Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
258
259             if (bytes.Length - index < count)
260                 throw new ArgumentOutOfRangeException("bytes",
261                     Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
262             Contract.EndContractBlock();
263
264             // If no input just return 0, fixed doesn't like 0 length arrays
265             if (bytes.Length == 0)
266                 return 0;
267
268             // Just call pointer version
269             fixed (byte* pBytes = bytes)
270                 return GetCharCount(pBytes + index, count, null);
271         }
272
273         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
274         // So if you fix this, fix the others.  Currently those include:
275         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
276
277         [System.Security.SecurityCritical]  // auto-generated
278         [CLSCompliant(false)]
279         [System.Runtime.InteropServices.ComVisible(false)]
280         public override unsafe int GetCharCount(byte* bytes, int count)
281         {
282             // Validate Parameters
283             if (bytes == null)
284                 throw new ArgumentNullException("bytes",
285                     Environment.GetResourceString("ArgumentNull_Array"));
286
287             if (count < 0)
288                 throw new ArgumentOutOfRangeException("count",
289                     Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
290             Contract.EndContractBlock();
291
292             return GetCharCount(bytes, count, null);
293         }
294
295         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
296         // So if you fix this, fix the others.  Currently those include:
297         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
298         // parent method is safe
299
300         [System.Security.SecuritySafeCritical]  // auto-generated
301         public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
302                                               char[] chars, int charIndex)
303         {
304             // Validate Parameters
305             if (bytes == null || chars == null)
306                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
307                     Environment.GetResourceString("ArgumentNull_Array"));
308
309             if (byteIndex < 0 || byteCount < 0)
310                 throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"),
311                     Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
312
313             if ( bytes.Length - byteIndex < byteCount)
314                 throw new ArgumentOutOfRangeException("bytes",
315                     Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
316
317             if (charIndex < 0 || charIndex > chars.Length)
318                 throw new ArgumentOutOfRangeException("charIndex",
319                     Environment.GetResourceString("ArgumentOutOfRange_Index"));
320             Contract.EndContractBlock();
321
322             // If no input, return 0 & avoid fixed problem
323             if (bytes.Length == 0)
324                 return 0;
325
326             // Just call pointer version
327             int charCount = chars.Length - charIndex;
328
329             // Fixed doesn't like empty char arrays
330             if (chars.Length == 0)
331                 chars = new char[1];
332
333             fixed (byte* pBytes = bytes)
334                 fixed (char* pChars = chars)
335                     // Remember that charCount is # to decode, not size of array
336                     return GetChars(pBytes + byteIndex, byteCount,
337                                     pChars + charIndex, charCount, null);
338         }
339
340         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
341         // So if you fix this, fix the others.  Currently those include:
342         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
343
344         [System.Security.SecurityCritical]  // auto-generated
345         [CLSCompliant(false)]
346         [System.Runtime.InteropServices.ComVisible(false)]
347         public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
348         {
349             // Validate Parameters
350             if (bytes == null || chars == null)
351                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
352                     Environment.GetResourceString("ArgumentNull_Array"));
353
354             if (charCount < 0 || byteCount < 0)
355                 throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"),
356                     Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
357             Contract.EndContractBlock();
358
359             return GetChars(bytes, byteCount, chars, charCount, null);
360         }
361
362         // Returns a string containing the decoded representation of a range of
363         // bytes in a byte array.
364         //
365         // All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
366         // So if you fix this, fix the others.  Currently those include:
367         // EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
368         // parent method is safe
369
370         [System.Security.SecuritySafeCritical]  // auto-generated
371         public override unsafe String GetString(byte[] bytes, int byteIndex, int byteCount)
372         {
373             // Validate Parameters
374             if (bytes == null)
375                 throw new ArgumentNullException("bytes",
376                     Environment.GetResourceString("ArgumentNull_Array"));
377
378             if (byteIndex < 0 || byteCount < 0)
379                 throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"),
380                     Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
381
382
383             if (bytes.Length - byteIndex < byteCount)
384                 throw new ArgumentOutOfRangeException("bytes",
385                     Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
386             Contract.EndContractBlock();
387
388             // Avoid problems with empty input buffer
389             if (bytes.Length == 0) return String.Empty;
390
391             fixed (byte* pBytes = bytes)
392                 return String.CreateStringFromEncoding(
393                     pBytes + byteIndex, byteCount, this);
394         }
395
396         //
397         // End of standard methods copied from EncodingNLS.cs
398         //
399
400         // GetByteCount
401         // Note: We start by assuming that the output will be the same as count.  Having
402         // an encoder or fallback may change that assumption
403         [System.Security.SecurityCritical]  // auto-generated
404         internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
405         {
406             // Just need to ASSERT, this is called by something else internal that checked parameters already
407             Contract.Assert(charCount >= 0, "[ASCIIEncoding.GetByteCount]count is negative");
408             Contract.Assert(chars != null, "[ASCIIEncoding.GetByteCount]chars is null");
409
410             // Assert because we shouldn't be able to have a null encoder.
411             Contract.Assert(encoderFallback != null, "[ASCIIEncoding.GetByteCount]Attempting to use null fallback encoder");
412
413             char charLeftOver = (char)0;
414             EncoderReplacementFallback fallback = null;
415
416             // Start by assuming default count, then +/- for fallback characters
417             char* charEnd = chars + charCount;
418
419             // For fallback we may need a fallback buffer, we know we aren't default fallback.
420             EncoderFallbackBuffer fallbackBuffer = null;
421
422             if (encoder != null)
423             {
424                 charLeftOver = encoder.charLeftOver;
425                 Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
426                     "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
427
428                 fallback = encoder.Fallback as EncoderReplacementFallback;
429
430                 // We mustn't have left over fallback data when counting
431                 if (encoder.InternalHasFallbackBuffer)
432                 {
433                     // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
434                     fallbackBuffer = encoder.FallbackBuffer;
435                     if (fallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
436                         throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
437                         this.EncodingName, encoder.Fallback.GetType()));
438
439                     // Set our internal fallback interesting things.
440                     fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
441                 }
442
443                 // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
444                 Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
445                     encoder.FallbackBuffer.Remaining == 0,
446                     "[ASCIICodePageEncoding.GetByteCount]Expected empty fallback buffer");
447 //                if (encoder.InternalHasFallbackBuffer && encoder.FallbackBuffer.Remaining > 0)
448 //                    throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
449 //                    this.EncodingName, encoder.Fallback.GetType()));
450             }
451             else
452             {
453                 fallback = this.EncoderFallback as EncoderReplacementFallback;
454             }
455
456             // If we have an encoder AND we aren't using default fallback,
457             // then we may have a complicated count.
458             if (fallback != null && fallback.MaxCharCount == 1)
459             {
460                 // Replacement fallback encodes surrogate pairs as two ?? (or two whatever), so return size is always
461                 // same as input size.
462                 // Note that no existing SBCS code pages map code points to supplimentary characters, so this is easy.
463
464                 // We could however have 1 extra byte if the last call had an encoder and a funky fallback and
465                 // if we don't use the funky fallback this time.
466
467                 // Do we have an extra char left over from last time?
468                 if (charLeftOver > 0)
469                     charCount++;
470
471                 return (charCount);
472             }
473
474             // Count is more complicated if you have a funky fallback
475             // For fallback we may need a fallback buffer, we know we're not default fallback
476             int byteCount = 0;
477
478             // We may have a left over character from last time, try and process it.
479             if (charLeftOver > 0)
480             {
481                 Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
482                 Contract.Assert(encoder != null, "[ASCIIEncoding.GetByteCount]Expected encoder");
483
484                 // Since left over char was a surrogate, it'll have to be fallen back.
485                 // Get Fallback
486                 fallbackBuffer = encoder.FallbackBuffer;
487                 fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
488
489                 // This will fallback a pair if *chars is a low surrogate
490                 fallbackBuffer.InternalFallback(charLeftOver, ref chars);
491             }
492
493             // Now we may have fallback char[] already from the encoder
494
495             // Go ahead and do it, including the fallback.
496             char ch;
497             while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
498                     chars < charEnd)
499             {
500
501                 // First unwind any fallback
502                 if (ch == 0)
503                 {
504                     // No fallback, just get next char
505                     ch = *chars;
506                     chars++;
507                 }
508
509                 // Check for fallback, this'll catch surrogate pairs too.
510                 // no chars >= 0x80 are allowed.
511                 if (ch > 0x7f)
512                 {
513                     if (fallbackBuffer == null)
514                     {
515                         // Initialize the buffer
516                         if (encoder == null)
517                             fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
518                         else
519                             fallbackBuffer = encoder.FallbackBuffer;
520                         fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, false);
521                     }
522
523                     // Get Fallback
524                     fallbackBuffer.InternalFallback(ch, ref chars);
525                     continue;
526                 }
527
528                 // We'll use this one
529                 byteCount++;
530             }
531
532             Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
533                 "[ASCIIEncoding.GetByteCount]Expected Empty fallback buffer");
534
535             return byteCount;
536         }
537
538         [System.Security.SecurityCritical]  // auto-generated
539         internal override unsafe int GetBytes(char* chars, int charCount,
540                                                 byte* bytes, int byteCount, EncoderNLS encoder)
541         {
542             // Just need to ASSERT, this is called by something else internal that checked parameters already
543             Contract.Assert(bytes != null, "[ASCIIEncoding.GetBytes]bytes is null");
544             Contract.Assert(byteCount >= 0, "[ASCIIEncoding.GetBytes]byteCount is negative");
545             Contract.Assert(chars != null, "[ASCIIEncoding.GetBytes]chars is null");
546             Contract.Assert(charCount >= 0, "[ASCIIEncoding.GetBytes]charCount is negative");
547
548             // Assert because we shouldn't be able to have a null encoder.
549             Contract.Assert(encoderFallback != null, "[ASCIIEncoding.GetBytes]Attempting to use null encoder fallback");
550
551             // Get any left over characters
552             char charLeftOver = (char)0;
553             EncoderReplacementFallback fallback = null;
554
555             // For fallback we may need a fallback buffer, we know we aren't default fallback.
556             EncoderFallbackBuffer fallbackBuffer = null;
557
558             // prepare our end
559             char* charEnd = chars + charCount;
560             byte* byteStart = bytes;
561             char* charStart = chars;
562
563             if (encoder != null)
564             {
565                 charLeftOver = encoder.charLeftOver;
566                 fallback = encoder.Fallback as EncoderReplacementFallback;
567
568                 // We mustn't have left over fallback data when counting
569                 if (encoder.InternalHasFallbackBuffer)
570                 {
571                     // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
572                     fallbackBuffer = encoder.FallbackBuffer;
573                     if (fallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
574                         throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
575                         this.EncodingName, encoder.Fallback.GetType()));
576
577                     // Set our internal fallback interesting things.
578                     fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
579                 }
580
581                 Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
582                     "[ASCIIEncoding.GetBytes]leftover character should be high surrogate");
583
584                 // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
585                 Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
586                     encoder.FallbackBuffer.Remaining == 0,
587                     "[ASCIICodePageEncoding.GetBytes]Expected empty fallback buffer");
588 //                if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer &&
589 //                  encoder.FallbackBuffer.Remaining > 0)
590 //                  throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
591 //                        this.EncodingName, encoder.Fallback.GetType()));
592             }
593             else
594             {
595                 fallback = this.EncoderFallback as EncoderReplacementFallback;
596             }
597
598
599             // See if we do the fast default or slightly slower fallback
600             if (fallback != null && fallback.MaxCharCount == 1)
601             {
602                 // Fast version
603                 char cReplacement = fallback.DefaultString[0];
604
605                 // Check for replacements in range, otherwise fall back to slow version.
606                 if (cReplacement <= (char)0x7f)
607                 {
608                     // We should have exactly as many output bytes as input bytes, unless there's a left
609                     // over character, in which case we may need one more.
610                     // If we had a left over character will have to add a ?  (This happens if they had a funky
611                     // fallback last time, but not this time.) (We can't spit any out though
612                     // because with fallback encoder each surrogate is treated as a seperate code point)
613                     if (charLeftOver > 0)
614                     {
615                         // Have to have room
616                         // Throw even if doing no throw version because this is just 1 char,
617                         // so buffer will never be big enough
618                         if (byteCount == 0)
619                             ThrowBytesOverflow(encoder, true);
620
621                         // This'll make sure we still have more room and also make sure our return value is correct.
622                         *(bytes++) = (byte)cReplacement;
623                         byteCount--;                // We used one of the ones we were counting.
624                     }
625
626                     // This keeps us from overrunning our output buffer
627                     if (byteCount < charCount)
628                     {
629                         // Throw or make buffer smaller?
630                         ThrowBytesOverflow(encoder, byteCount < 1);
631
632                         // Just use what we can
633                         charEnd = chars + byteCount;
634                     }
635
636                     // We just do a quick copy
637                     while (chars < charEnd)
638                     {
639                         char ch2 = *(chars++);
640                         if (ch2 >= 0x0080) *(bytes++) = (byte)cReplacement;
641                         else *(bytes++) = unchecked((byte)(ch2));
642                     }
643
644                     // Clear encoder
645                     if (encoder != null)
646                     {
647                         encoder.charLeftOver = (char)0;
648                         encoder.m_charsUsed = (int)(chars-charStart);
649                     }
650
651                     return (int)(bytes - byteStart);
652                 }
653             }
654
655             // Slower version, have to do real fallback.
656
657             // prepare our end
658             byte* byteEnd = bytes + byteCount;
659
660             // We may have a left over character from last time, try and process it.
661             if (charLeftOver > 0)
662             {
663                 // Initialize the buffer
664                 Contract.Assert(encoder != null,
665                     "[ASCIIEncoding.GetBytes]Expected non null encoder if we have surrogate left over");
666                 fallbackBuffer = encoder.FallbackBuffer;
667                 fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
668
669                 // Since left over char was a surrogate, it'll have to be fallen back.
670                 // Get Fallback
671                 // This will fallback a pair if *chars is a low surrogate
672                 fallbackBuffer.InternalFallback(charLeftOver, ref chars);
673             }
674
675             // Now we may have fallback char[] already from the encoder
676
677             // Go ahead and do it, including the fallback.
678             char ch;
679             while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
680                     chars < charEnd)
681             {
682                 // First unwind any fallback
683                 if (ch == 0)
684                 {
685                     // No fallback, just get next char
686                     ch = *chars;
687                     chars++;
688                 }
689
690                 // Check for fallback, this'll catch surrogate pairs too.
691                 // All characters >= 0x80 must fall back.
692                 if (ch > 0x7f)
693                 {
694                     // Initialize the buffer
695                     if (fallbackBuffer == null)
696                     {
697                         if (encoder == null)
698                             fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
699                         else
700                             fallbackBuffer = encoder.FallbackBuffer;
701                         fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
702                     }
703
704                     // Get Fallback
705                     fallbackBuffer.InternalFallback(ch, ref chars);
706
707                     // Go ahead & continue (& do the fallback)
708                     continue;
709                 }
710
711                 // We'll use this one
712                 // Bounds check
713                 if (bytes >= byteEnd)
714                 {
715                     // didn't use this char, we'll throw or use buffer
716                     if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false)
717                     {
718                         Contract.Assert(chars > charStart || bytes == byteStart,
719                             "[ASCIIEncoding.GetBytes]Expected chars to have advanced already.");
720                         chars--;                                        // don't use last char
721                     }
722                     else
723                         fallbackBuffer.MovePrevious();
724
725                     // Are we throwing or using buffer?
726                     ThrowBytesOverflow(encoder, bytes == byteStart);    // throw?
727                     break;                                              // don't throw, stop
728                 }
729
730                 // Go ahead and add it
731                 *bytes = unchecked((byte)ch);
732                 bytes++;
733             }
734
735             // Need to do encoder stuff
736             if (encoder != null)
737             {
738                 // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases
739                 if (fallbackBuffer != null && !fallbackBuffer.bUsedEncoder)
740                     // Clear it in case of MustFlush
741                     encoder.charLeftOver = (char)0;
742
743                 // Set our chars used count
744                 encoder.m_charsUsed = (int)(chars - charStart);
745             }
746
747             Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 ||
748                 (encoder != null && !encoder.m_throwOnOverflow ),
749                 "[ASCIIEncoding.GetBytes]Expected Empty fallback buffer at end");
750
751             return (int)(bytes - byteStart);
752         }
753
754         // This is internal and called by something else,
755         [System.Security.SecurityCritical]  // auto-generated
756         internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
757         {
758             // Just assert, we're called internally so these should be safe, checked already
759             Contract.Assert(bytes != null, "[ASCIIEncoding.GetCharCount]bytes is null");
760             Contract.Assert(count >= 0, "[ASCIIEncoding.GetCharCount]byteCount is negative");
761
762             // ASCII doesn't do best fit, so don't have to check for it, find out which decoder fallback we're using
763             DecoderReplacementFallback fallback = null;
764
765             if (decoder == null)
766                 fallback = this.DecoderFallback as DecoderReplacementFallback;
767             else
768             {
769                 fallback = decoder.Fallback as DecoderReplacementFallback;
770                 Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
771                     decoder.FallbackBuffer.Remaining == 0,
772                     "[ASCIICodePageEncoding.GetCharCount]Expected empty fallback buffer");
773             }
774
775             if (fallback != null && fallback.MaxCharCount == 1)
776             {
777                 // Just return length, SBCS stay the same length because they don't map to surrogate
778                 // pairs and we don't have a decoder fallback.
779
780                 return count;
781             }
782
783             // Only need decoder fallback buffer if not using default replacement fallback, no best fit for ASCII
784             DecoderFallbackBuffer fallbackBuffer = null;
785
786             // Have to do it the hard way.
787             // Assume charCount will be == count
788             int charCount = count;
789             byte[] byteBuffer = new byte[1];
790
791             // Do it our fast way
792             byte* byteEnd = bytes + count;
793
794             // Quick loop
795             while (bytes < byteEnd)
796             {
797                 // Faster if don't use *bytes++;
798                 byte b = *bytes;
799                 bytes++;
800
801                 // If unknown we have to do fallback count
802                 if (b >= 0x80)
803                 {
804                     if (fallbackBuffer == null)
805                     {
806                         if (decoder == null)
807                             fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
808                         else
809                             fallbackBuffer = decoder.FallbackBuffer;
810                         fallbackBuffer.InternalInitialize(byteEnd - count, null);
811                     }
812
813                     // Use fallback buffer
814                     byteBuffer[0] = b;
815                     charCount--;            // Have to unreserve the one we already allocated for b
816                     charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
817                 }
818             }
819
820             // Fallback buffer must be empty
821             Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
822                 "[ASCIIEncoding.GetCharCount]Expected Empty fallback buffer");
823
824             // Converted sequence is same length as input
825             return charCount;
826         }
827
828         [System.Security.SecurityCritical]  // auto-generated
829         internal override unsafe int GetChars(byte* bytes, int byteCount,
830                                                 char* chars, int charCount, DecoderNLS decoder)
831         {
832             // Just need to ASSERT, this is called by something else internal that checked parameters already
833             Contract.Assert(bytes != null, "[ASCIIEncoding.GetChars]bytes is null");
834             Contract.Assert(byteCount >= 0, "[ASCIIEncoding.GetChars]byteCount is negative");
835             Contract.Assert(chars != null, "[ASCIIEncoding.GetChars]chars is null");
836             Contract.Assert(charCount >= 0, "[ASCIIEncoding.GetChars]charCount is negative");
837
838             // Do it fast way if using ? replacement fallback
839             byte* byteEnd = bytes + byteCount;
840             byte* byteStart = bytes;
841             char* charStart = chars;
842
843             // Note: ASCII doesn't do best fit, but we have to fallback if they use something > 0x7f
844             // Only need decoder fallback buffer if not using ? fallback.
845             // ASCII doesn't do best fit, so don't have to check for it, find out which decoder fallback we're using
846             DecoderReplacementFallback fallback = null;
847
848             if (decoder == null)
849                 fallback = this.DecoderFallback as DecoderReplacementFallback;
850             else
851             {
852                 fallback = decoder.Fallback as DecoderReplacementFallback;
853                 Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
854                     decoder.FallbackBuffer.Remaining == 0,
855                     "[ASCIICodePageEncoding.GetChars]Expected empty fallback buffer");
856             }
857
858             if (fallback != null && fallback.MaxCharCount == 1)
859             {
860                 // Try it the fast way
861                 char replacementChar = fallback.DefaultString[0];
862
863                 // Need byteCount chars, otherwise too small buffer
864                 if (charCount < byteCount)
865                 {
866                     // Need at least 1 output byte, throw if must throw
867                     ThrowCharsOverflow(decoder, charCount < 1);
868
869                     // Not throwing, use what we can
870                     byteEnd = bytes + charCount;
871                 }
872
873                 // Quick loop, just do '?' replacement because we don't have fallbacks for decodings.
874                 while (bytes < byteEnd)
875                 {
876                     byte b = *(bytes++);
877                     if (b >= 0x80)
878                         // This is an invalid byte in the ASCII encoding.
879                         *(chars++) = replacementChar;
880                     else
881                         *(chars++) = unchecked((char)b);
882                 }
883
884                 // bytes & chars used are the same
885                 if (decoder != null)
886                     decoder.m_bytesUsed = (int)(bytes - byteStart);
887                 return (int)(chars - charStart);
888             }
889
890             // Slower way's going to need a fallback buffer
891             DecoderFallbackBuffer fallbackBuffer = null;
892             byte[] byteBuffer = new byte[1];
893             char*   charEnd = chars + charCount;
894
895             // Not quite so fast loop
896             while (bytes < byteEnd)
897             {
898                 // Faster if don't use *bytes++;
899                 byte b = *(bytes);
900                 bytes++;
901
902                 if (b >= 0x80)
903                 {
904                     // This is an invalid byte in the ASCII encoding.
905                     if (fallbackBuffer == null)
906                     {
907                         if (decoder == null)
908                             fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
909                         else
910                             fallbackBuffer = decoder.FallbackBuffer;
911                         fallbackBuffer.InternalInitialize(byteEnd - byteCount, charEnd);
912                     }
913
914                     // Use fallback buffer
915                     byteBuffer[0] = b;
916
917                     // Note that chars won't get updated unless this succeeds
918                     if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
919                     {
920                         // May or may not throw, but we didn't get this byte
921                         Contract.Assert(bytes > byteStart || chars == charStart,
922                             "[ASCIIEncoding.GetChars]Expected bytes to have advanced already (fallback case)");
923                         bytes--;                                            // unused byte
924                         fallbackBuffer.InternalReset();                     // Didn't fall this back
925                         ThrowCharsOverflow(decoder, chars == charStart);    // throw?
926                         break;                                              // don't throw, but stop loop
927                     }
928                 }
929                 else
930                 {
931                     // Make sure we have buffer space
932                     if (chars >= charEnd)
933                     {
934                         Contract.Assert(bytes > byteStart || chars == charStart,
935                             "[ASCIIEncoding.GetChars]Expected bytes to have advanced already (normal case)");
936                         bytes--;                                            // unused byte
937                         ThrowCharsOverflow(decoder, chars == charStart);    // throw?
938                         break;                                              // don't throw, but stop loop
939                     }
940
941                     *(chars) = unchecked((char)b);
942                     chars++;
943                 }
944             }
945
946             // Might have had decoder fallback stuff.
947             if (decoder != null)
948                 decoder.m_bytesUsed = (int)(bytes - byteStart);
949
950             // Expect Empty fallback buffer for GetChars
951             Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
952                 "[ASCIIEncoding.GetChars]Expected Empty fallback buffer");
953
954             return (int)(chars - charStart);
955         }
956
957
958         public override int GetMaxByteCount(int charCount)
959         {
960             if (charCount < 0)
961                throw new ArgumentOutOfRangeException("charCount",
962                     Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
963             Contract.EndContractBlock();
964
965             // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
966             long byteCount = (long)charCount + 1;
967
968             if (EncoderFallback.MaxCharCount > 1)
969                 byteCount *= EncoderFallback.MaxCharCount;
970
971             // 1 to 1 for most characters.  Only surrogates with fallbacks have less.
972
973             if (byteCount > 0x7fffffff)
974                 throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
975             return (int)byteCount;
976         }
977
978
979         public override int GetMaxCharCount(int byteCount)
980         {
981             if (byteCount < 0)
982                throw new ArgumentOutOfRangeException("byteCount",
983                     Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
984             Contract.EndContractBlock();
985
986             // Just return length, SBCS stay the same length because they don't map to surrogate
987             long charCount = (long)byteCount;
988
989             // 1 to 1 for most characters.  Only surrogates with fallbacks have less, unknown fallbacks could be longer.
990             if (DecoderFallback.MaxCharCount > 1)
991                 charCount *= DecoderFallback.MaxCharCount;
992
993             if (charCount > 0x7fffffff)
994                 throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
995
996             return (int)charCount;
997         }
998
999         // True if and only if the encoding only uses single byte code points.  (Ie, ASCII, 1252, etc)
1000
1001         [System.Runtime.InteropServices.ComVisible(false)]
1002         public override bool IsSingleByte
1003         {
1004             get
1005             {
1006                 return true;
1007             }
1008         }
1009
1010         [System.Runtime.InteropServices.ComVisible(false)]
1011         public override Decoder GetDecoder()
1012         {
1013             return new DecoderNLS(this);
1014         }
1015
1016
1017         [System.Runtime.InteropServices.ComVisible(false)]
1018         public override Encoder GetEncoder()
1019         {
1020             return new EncoderNLS(this);
1021         }
1022     }
1023 }