3 // Copyright (c) Microsoft Corporation. All rights reserved.
9 using System.Runtime.Serialization;
10 using System.Security.Permissions;
11 using System.Diagnostics.Contracts;
15 // Note that ASCIIEncoding is optomized with no best fit and ? for fallback.
16 // It doesn't come in other flavors.
18 // Note: ASCIIEncoding is the only encoding that doesn't do best fit (windows has best fit).
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.
25 [System.Runtime.InteropServices.ComVisible(true)]
26 public class ASCIIEncoding : Encoding
29 public ASCIIEncoding() : base(Encoding.CodePageASCII)
33 internal override void SetDefaultFallbacks()
35 // For ASCIIEncoding we just use default replacement fallback
36 this.encoderFallback = EncoderFallback.ReplacementFallback;
37 this.decoderFallback = DecoderFallback.ReplacementFallback;
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.
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
51 // Returns the number of bytes required to encode a range of characters in
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
59 [System.Security.SecuritySafeCritical] // auto-generated
60 public override unsafe int GetByteCount(char[] chars, int index, int count)
62 // Validate input parameters
64 throw new ArgumentNullException("chars",
65 Environment.GetResourceString("ArgumentNull_Array"));
67 if (index < 0 || count < 0)
68 throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"),
69 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
71 if (chars.Length - index < count)
72 throw new ArgumentOutOfRangeException("chars",
73 Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
74 Contract.EndContractBlock();
76 // If no input, return 0, avoid fixed empty array problem
77 if (chars.Length == 0)
80 // Just call the pointer version
81 fixed (char* pChars = chars)
82 return GetByteCount(pChars + index, count, null);
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
90 [System.Security.SecuritySafeCritical] // auto-generated
91 public override unsafe int GetByteCount(String chars)
95 throw new ArgumentNullException("chars");
96 Contract.EndContractBlock();
98 fixed (char* pChars = chars)
99 return GetByteCount(pChars, chars.Length, null);
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
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)
111 // Validate Parameters
113 throw new ArgumentNullException("chars",
114 Environment.GetResourceString("ArgumentNull_Array"));
117 throw new ArgumentOutOfRangeException("count",
118 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
119 Contract.EndContractBlock();
121 // Call it with empty encoder
122 return GetByteCount(chars, count, null);
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
130 [System.Security.SecuritySafeCritical] // auto-generated
131 public override unsafe int GetBytes(String chars, int charIndex, int charCount,
132 byte[] bytes, int byteIndex)
134 if (chars == null || bytes == null)
135 throw new ArgumentNullException((chars == null ? "chars" : "bytes"),
136 Environment.GetResourceString("ArgumentNull_Array"));
138 if (charIndex < 0 || charCount < 0)
139 throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"),
140 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
142 if (chars.Length - charIndex < charCount)
143 throw new ArgumentOutOfRangeException("chars",
144 Environment.GetResourceString("ArgumentOutOfRange_IndexCount"));
146 if (byteIndex < 0 || byteIndex > bytes.Length)
147 throw new ArgumentOutOfRangeException("byteIndex",
148 Environment.GetResourceString("ArgumentOutOfRange_Index"));
149 Contract.EndContractBlock();
151 int byteCount = bytes.Length - byteIndex;
153 // Fixed doesn't like empty byte arrays
154 if (bytes.Length == 0)
157 fixed (char* pChars = chars)
158 fixed ( byte* pBytes = bytes)
159 return GetBytes(pChars + charIndex, charCount,
160 pBytes + byteIndex, byteCount, null);
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.
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
177 [System.Security.SecuritySafeCritical] // auto-generated
178 public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
179 byte[] bytes, int byteIndex)
181 // Validate parameters
182 if (chars == null || bytes == null)
183 throw new ArgumentNullException((chars == null ? "chars" : "bytes"),
184 Environment.GetResourceString("ArgumentNull_Array"));
186 if (charIndex < 0 || charCount < 0)
187 throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"),
188 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
190 if (chars.Length - charIndex < charCount)
191 throw new ArgumentOutOfRangeException("chars",
192 Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
194 if (byteIndex < 0 || byteIndex > bytes.Length)
195 throw new ArgumentOutOfRangeException("byteIndex",
196 Environment.GetResourceString("ArgumentOutOfRange_Index"));
197 Contract.EndContractBlock();
199 // If nothing to encode return 0, avoid fixed problem
200 if (chars.Length == 0)
203 // Just call pointer version
204 int byteCount = bytes.Length - byteIndex;
206 // Fixed doesn't like empty byte arrays
207 if (bytes.Length == 0)
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);
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
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)
226 // Validate Parameters
227 if (bytes == null || chars == null)
228 throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
229 Environment.GetResourceString("ArgumentNull_Array"));
231 if (charCount < 0 || byteCount < 0)
232 throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"),
233 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
234 Contract.EndContractBlock();
236 return GetBytes(chars, charCount, bytes, byteCount, null);
239 // Returns the number of characters produced by decoding a range of bytes
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
247 [System.Security.SecuritySafeCritical] // auto-generated
248 public override unsafe int GetCharCount(byte[] bytes, int index, int count)
250 // Validate Parameters
252 throw new ArgumentNullException("bytes",
253 Environment.GetResourceString("ArgumentNull_Array"));
255 if (index < 0 || count < 0)
256 throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"),
257 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
259 if (bytes.Length - index < count)
260 throw new ArgumentOutOfRangeException("bytes",
261 Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
262 Contract.EndContractBlock();
264 // If no input just return 0, fixed doesn't like 0 length arrays
265 if (bytes.Length == 0)
268 // Just call pointer version
269 fixed (byte* pBytes = bytes)
270 return GetCharCount(pBytes + index, count, null);
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
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)
282 // Validate Parameters
284 throw new ArgumentNullException("bytes",
285 Environment.GetResourceString("ArgumentNull_Array"));
288 throw new ArgumentOutOfRangeException("count",
289 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
290 Contract.EndContractBlock();
292 return GetCharCount(bytes, count, null);
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
300 [System.Security.SecuritySafeCritical] // auto-generated
301 public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
302 char[] chars, int charIndex)
304 // Validate Parameters
305 if (bytes == null || chars == null)
306 throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
307 Environment.GetResourceString("ArgumentNull_Array"));
309 if (byteIndex < 0 || byteCount < 0)
310 throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"),
311 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
313 if ( bytes.Length - byteIndex < byteCount)
314 throw new ArgumentOutOfRangeException("bytes",
315 Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
317 if (charIndex < 0 || charIndex > chars.Length)
318 throw new ArgumentOutOfRangeException("charIndex",
319 Environment.GetResourceString("ArgumentOutOfRange_Index"));
320 Contract.EndContractBlock();
322 // If no input, return 0 & avoid fixed problem
323 if (bytes.Length == 0)
326 // Just call pointer version
327 int charCount = chars.Length - charIndex;
329 // Fixed doesn't like empty char arrays
330 if (chars.Length == 0)
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);
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
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)
349 // Validate Parameters
350 if (bytes == null || chars == null)
351 throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
352 Environment.GetResourceString("ArgumentNull_Array"));
354 if (charCount < 0 || byteCount < 0)
355 throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"),
356 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
357 Contract.EndContractBlock();
359 return GetChars(bytes, byteCount, chars, charCount, null);
362 // Returns a string containing the decoded representation of a range of
363 // bytes in a byte array.
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
370 [System.Security.SecuritySafeCritical] // auto-generated
371 public override unsafe String GetString(byte[] bytes, int byteIndex, int byteCount)
373 // Validate Parameters
375 throw new ArgumentNullException("bytes",
376 Environment.GetResourceString("ArgumentNull_Array"));
378 if (byteIndex < 0 || byteCount < 0)
379 throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"),
380 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
383 if (bytes.Length - byteIndex < byteCount)
384 throw new ArgumentOutOfRangeException("bytes",
385 Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
386 Contract.EndContractBlock();
388 // Avoid problems with empty input buffer
389 if (bytes.Length == 0) return String.Empty;
391 fixed (byte* pBytes = bytes)
392 return String.CreateStringFromEncoding(
393 pBytes + byteIndex, byteCount, this);
397 // End of standard methods copied from EncodingNLS.cs
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)
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");
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");
413 char charLeftOver = (char)0;
414 EncoderReplacementFallback fallback = null;
416 // Start by assuming default count, then +/- for fallback characters
417 char* charEnd = chars + charCount;
419 // For fallback we may need a fallback buffer, we know we aren't default fallback.
420 EncoderFallbackBuffer fallbackBuffer = null;
424 charLeftOver = encoder.charLeftOver;
425 Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
426 "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
428 fallback = encoder.Fallback as EncoderReplacementFallback;
430 // We mustn't have left over fallback data when counting
431 if (encoder.InternalHasFallbackBuffer)
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()));
439 // Set our internal fallback interesting things.
440 fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
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()));
453 fallback = this.EncoderFallback as EncoderReplacementFallback;
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)
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.
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.
467 // Do we have an extra char left over from last time?
468 if (charLeftOver > 0)
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
478 // We may have a left over character from last time, try and process it.
479 if (charLeftOver > 0)
481 Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
482 Contract.Assert(encoder != null, "[ASCIIEncoding.GetByteCount]Expected encoder");
484 // Since left over char was a surrogate, it'll have to be fallen back.
486 fallbackBuffer = encoder.FallbackBuffer;
487 fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
489 // This will fallback a pair if *chars is a low surrogate
490 fallbackBuffer.InternalFallback(charLeftOver, ref chars);
493 // Now we may have fallback char[] already from the encoder
495 // Go ahead and do it, including the fallback.
497 while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
501 // First unwind any fallback
504 // No fallback, just get next char
509 // Check for fallback, this'll catch surrogate pairs too.
510 // no chars >= 0x80 are allowed.
513 if (fallbackBuffer == null)
515 // Initialize the buffer
517 fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
519 fallbackBuffer = encoder.FallbackBuffer;
520 fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, false);
524 fallbackBuffer.InternalFallback(ch, ref chars);
528 // We'll use this one
532 Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
533 "[ASCIIEncoding.GetByteCount]Expected Empty fallback buffer");
538 [System.Security.SecurityCritical] // auto-generated
539 internal override unsafe int GetBytes(char* chars, int charCount,
540 byte* bytes, int byteCount, EncoderNLS encoder)
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");
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");
551 // Get any left over characters
552 char charLeftOver = (char)0;
553 EncoderReplacementFallback fallback = null;
555 // For fallback we may need a fallback buffer, we know we aren't default fallback.
556 EncoderFallbackBuffer fallbackBuffer = null;
559 char* charEnd = chars + charCount;
560 byte* byteStart = bytes;
561 char* charStart = chars;
565 charLeftOver = encoder.charLeftOver;
566 fallback = encoder.Fallback as EncoderReplacementFallback;
568 // We mustn't have left over fallback data when counting
569 if (encoder.InternalHasFallbackBuffer)
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()));
577 // Set our internal fallback interesting things.
578 fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
581 Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
582 "[ASCIIEncoding.GetBytes]leftover character should be high surrogate");
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()));
595 fallback = this.EncoderFallback as EncoderReplacementFallback;
599 // See if we do the fast default or slightly slower fallback
600 if (fallback != null && fallback.MaxCharCount == 1)
603 char cReplacement = fallback.DefaultString[0];
605 // Check for replacements in range, otherwise fall back to slow version.
606 if (cReplacement <= (char)0x7f)
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)
616 // Throw even if doing no throw version because this is just 1 char,
617 // so buffer will never be big enough
619 ThrowBytesOverflow(encoder, true);
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.
626 // This keeps us from overrunning our output buffer
627 if (byteCount < charCount)
629 // Throw or make buffer smaller?
630 ThrowBytesOverflow(encoder, byteCount < 1);
632 // Just use what we can
633 charEnd = chars + byteCount;
636 // We just do a quick copy
637 while (chars < charEnd)
639 char ch2 = *(chars++);
640 if (ch2 >= 0x0080) *(bytes++) = (byte)cReplacement;
641 else *(bytes++) = unchecked((byte)(ch2));
647 encoder.charLeftOver = (char)0;
648 encoder.m_charsUsed = (int)(chars-charStart);
651 return (int)(bytes - byteStart);
655 // Slower version, have to do real fallback.
658 byte* byteEnd = bytes + byteCount;
660 // We may have a left over character from last time, try and process it.
661 if (charLeftOver > 0)
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);
669 // Since left over char was a surrogate, it'll have to be fallen back.
671 // This will fallback a pair if *chars is a low surrogate
672 fallbackBuffer.InternalFallback(charLeftOver, ref chars);
675 // Now we may have fallback char[] already from the encoder
677 // Go ahead and do it, including the fallback.
679 while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
682 // First unwind any fallback
685 // No fallback, just get next char
690 // Check for fallback, this'll catch surrogate pairs too.
691 // All characters >= 0x80 must fall back.
694 // Initialize the buffer
695 if (fallbackBuffer == null)
698 fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
700 fallbackBuffer = encoder.FallbackBuffer;
701 fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
705 fallbackBuffer.InternalFallback(ch, ref chars);
707 // Go ahead & continue (& do the fallback)
711 // We'll use this one
713 if (bytes >= byteEnd)
715 // didn't use this char, we'll throw or use buffer
716 if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false)
718 Contract.Assert(chars > charStart || bytes == byteStart,
719 "[ASCIIEncoding.GetBytes]Expected chars to have advanced already.");
720 chars--; // don't use last char
723 fallbackBuffer.MovePrevious();
725 // Are we throwing or using buffer?
726 ThrowBytesOverflow(encoder, bytes == byteStart); // throw?
727 break; // don't throw, stop
730 // Go ahead and add it
731 *bytes = unchecked((byte)ch);
735 // Need to do encoder stuff
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;
743 // Set our chars used count
744 encoder.m_charsUsed = (int)(chars - charStart);
747 Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 ||
748 (encoder != null && !encoder.m_throwOnOverflow ),
749 "[ASCIIEncoding.GetBytes]Expected Empty fallback buffer at end");
751 return (int)(bytes - byteStart);
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)
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");
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;
766 fallback = this.DecoderFallback as DecoderReplacementFallback;
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");
775 if (fallback != null && fallback.MaxCharCount == 1)
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.
783 // Only need decoder fallback buffer if not using default replacement fallback, no best fit for ASCII
784 DecoderFallbackBuffer fallbackBuffer = null;
786 // Have to do it the hard way.
787 // Assume charCount will be == count
788 int charCount = count;
789 byte[] byteBuffer = new byte[1];
791 // Do it our fast way
792 byte* byteEnd = bytes + count;
795 while (bytes < byteEnd)
797 // Faster if don't use *bytes++;
801 // If unknown we have to do fallback count
804 if (fallbackBuffer == null)
807 fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
809 fallbackBuffer = decoder.FallbackBuffer;
810 fallbackBuffer.InternalInitialize(byteEnd - count, null);
813 // Use fallback buffer
815 charCount--; // Have to unreserve the one we already allocated for b
816 charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
820 // Fallback buffer must be empty
821 Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
822 "[ASCIIEncoding.GetCharCount]Expected Empty fallback buffer");
824 // Converted sequence is same length as input
828 [System.Security.SecurityCritical] // auto-generated
829 internal override unsafe int GetChars(byte* bytes, int byteCount,
830 char* chars, int charCount, DecoderNLS decoder)
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");
838 // Do it fast way if using ? replacement fallback
839 byte* byteEnd = bytes + byteCount;
840 byte* byteStart = bytes;
841 char* charStart = chars;
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;
849 fallback = this.DecoderFallback as DecoderReplacementFallback;
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");
858 if (fallback != null && fallback.MaxCharCount == 1)
860 // Try it the fast way
861 char replacementChar = fallback.DefaultString[0];
863 // Need byteCount chars, otherwise too small buffer
864 if (charCount < byteCount)
866 // Need at least 1 output byte, throw if must throw
867 ThrowCharsOverflow(decoder, charCount < 1);
869 // Not throwing, use what we can
870 byteEnd = bytes + charCount;
873 // Quick loop, just do '?' replacement because we don't have fallbacks for decodings.
874 while (bytes < byteEnd)
878 // This is an invalid byte in the ASCII encoding.
879 *(chars++) = replacementChar;
881 *(chars++) = unchecked((char)b);
884 // bytes & chars used are the same
886 decoder.m_bytesUsed = (int)(bytes - byteStart);
887 return (int)(chars - charStart);
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;
895 // Not quite so fast loop
896 while (bytes < byteEnd)
898 // Faster if don't use *bytes++;
904 // This is an invalid byte in the ASCII encoding.
905 if (fallbackBuffer == null)
908 fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
910 fallbackBuffer = decoder.FallbackBuffer;
911 fallbackBuffer.InternalInitialize(byteEnd - byteCount, charEnd);
914 // Use fallback buffer
917 // Note that chars won't get updated unless this succeeds
918 if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
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
931 // Make sure we have buffer space
932 if (chars >= charEnd)
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
941 *(chars) = unchecked((char)b);
946 // Might have had decoder fallback stuff.
948 decoder.m_bytesUsed = (int)(bytes - byteStart);
950 // Expect Empty fallback buffer for GetChars
951 Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
952 "[ASCIIEncoding.GetChars]Expected Empty fallback buffer");
954 return (int)(chars - charStart);
958 public override int GetMaxByteCount(int charCount)
961 throw new ArgumentOutOfRangeException("charCount",
962 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
963 Contract.EndContractBlock();
965 // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
966 long byteCount = (long)charCount + 1;
968 if (EncoderFallback.MaxCharCount > 1)
969 byteCount *= EncoderFallback.MaxCharCount;
971 // 1 to 1 for most characters. Only surrogates with fallbacks have less.
973 if (byteCount > 0x7fffffff)
974 throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
975 return (int)byteCount;
979 public override int GetMaxCharCount(int byteCount)
982 throw new ArgumentOutOfRangeException("byteCount",
983 Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
984 Contract.EndContractBlock();
986 // Just return length, SBCS stay the same length because they don't map to surrogate
987 long charCount = (long)byteCount;
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;
993 if (charCount > 0x7fffffff)
994 throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
996 return (int)charCount;
999 // True if and only if the encoding only uses single byte code points. (Ie, ASCII, 1252, etc)
1001 [System.Runtime.InteropServices.ComVisible(false)]
1002 public override bool IsSingleByte
1010 [System.Runtime.InteropServices.ComVisible(false)]
1011 public override Decoder GetDecoder()
1013 return new DecoderNLS(this);
1017 [System.Runtime.InteropServices.ComVisible(false)]
1018 public override Encoder GetEncoder()
1020 return new EncoderNLS(this);