The Labs \ Source Viewer \ SSCLI \ System.Text \ DecoderReplacementFallback

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. // DecoderReplacementFallback.cs
  16. //
  17. namespace System.Text
  18. {
  19.     using System;
  20.    
  21.     [Serializable()]
  22.     public sealed class DecoderReplacementFallback : DecoderFallback
  23.     {
  24.         // Our variables
  25.         private string strDefault;
  26.        
  27.         // Construction. Default replacement fallback uses no best fit and ? replacement string
  28.         public DecoderReplacementFallback() : this("?")
  29.         {
  30.         }
  31.        
  32.         public DecoderReplacementFallback(string replacement)
  33.         {
  34.             if (replacement == null)
  35.                 throw new ArgumentNullException("replacement");
  36.            
  37.             // Make sure it doesn't have bad surrogate pairs
  38.             bool bFoundHigh = false;
  39.             for (int i = 0; i < replacement.Length; i++) {
  40.                 // Found a surrogate?
  41.                 if (Char.IsSurrogate(replacement, i)) {
  42.                     // High or Low?
  43.                     if (Char.IsHighSurrogate(replacement, i)) {
  44.                         // if already had a high one, stop
  45.                         if (bFoundHigh)
  46.                             break;
  47.                         // break & throw at the bFoundHIgh below
  48.                         bFoundHigh = true;
  49.                     }
  50.                     else {
  51.                         // Low, did we have a high?
  52.                         if (!bFoundHigh) {
  53.                             // Didn't have one, make if fail when we stop
  54.                             bFoundHigh = true;
  55.                             break;
  56.                         }
  57.                        
  58.                         // Clear flag
  59.                         bFoundHigh = false;
  60.                     }
  61.                 }
  62.                 else if (bFoundHigh)
  63.                     // If last was high we're in trouble (not surrogate so not low surrogate, so break)
  64.                     break;
  65.             }
  66.             if (bFoundHigh)
  67.                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex", "replacement"));
  68.            
  69.             strDefault = replacement;
  70.         }
  71.        
  72.         public string DefaultString {
  73.             get { return strDefault; }
  74.         }
  75.        
  76.         public override DecoderFallbackBuffer CreateFallbackBuffer()
  77.         {
  78.             return new DecoderReplacementFallbackBuffer(this);
  79.         }
  80.        
  81.         // Maximum number of characters that this instance of this fallback could return
  82.         public override int MaxCharCount {
  83.             get { return strDefault.Length; }
  84.         }
  85.        
  86.         public override bool Equals(object value)
  87.         {
  88.             DecoderReplacementFallback that = value as DecoderReplacementFallback;
  89.             if (that != null) {
  90.                 return (this.strDefault == that.strDefault);
  91.             }
  92.             return (false);
  93.         }
  94.        
  95.         public override int GetHashCode()
  96.         {
  97.             return strDefault.GetHashCode();
  98.         }
  99.     }
  100.    
  101.    
  102.    
  103.     public sealed class DecoderReplacementFallbackBuffer : DecoderFallbackBuffer
  104.     {
  105.         // Store our default string
  106.         private string strDefault;
  107.         int fallbackCount = -1;
  108.         int fallbackIndex = -1;
  109.        
  110.         // Construction
  111.         public DecoderReplacementFallbackBuffer(DecoderReplacementFallback fallback)
  112.         {
  113.             this.strDefault = fallback.DefaultString;
  114.         }
  115.        
  116.         // Fallback Methods
  117.         public override bool Fallback(byte[] bytesUnknown, int index)
  118.         {
  119.             // We expect no previous fallback in our buffer
  120.             BCLDebug.Assert(fallbackCount < 1, "[DecoderReplacementFallbackBuffer.Fallback] Calling fallback without a previously empty buffer");
  121.            
  122.             // We can't call recursively but others might (note, we don't test on last char!!!)
  123.             if (fallbackCount >= 1) {
  124.                 ThrowLastBytesRecursive(bytesUnknown);
  125.             }
  126.            
  127.             // Go ahead and get our fallback
  128.             if (strDefault.Length == 0)
  129.                 return false;
  130.            
  131.             fallbackCount = strDefault.Length;
  132.             fallbackIndex = -1;
  133.            
  134.             return true;
  135.         }
  136.        
  137.         public override char GetNextChar()
  138.         {
  139.             // We want it to get < 0 because == 0 means that the current/last character is a fallback
  140.             // and we need to detect recursion. We could have a flag but we already have this counter.
  141.             fallbackCount--;
  142.             fallbackIndex++;
  143.            
  144.             // Do we have anything left? 0 is now last fallback char, negative is nothing left
  145.             if (fallbackCount < 0)
  146.                 return (char)0;
  147.            
  148.             // Need to get it out of the buffer.
  149.             BCLDebug.Assert(fallbackIndex < strDefault.Length && fallbackIndex >= 0, "Index exceeds buffer range");
  150.             return strDefault[fallbackIndex];
  151.         }
  152.        
  153.         public override bool MovePrevious()
  154.         {
  155.             // Back up one, only if we just processed the last character (or earlier)
  156.             if (fallbackCount >= -1 && fallbackIndex >= 0) {
  157.                 fallbackIndex--;
  158.                 fallbackCount++;
  159.                 return true;
  160.             }
  161.            
  162.             // Return false 'cause we couldn't do it.
  163.             return false;
  164.         }
  165.        
  166.         // How many characters left to output?
  167.         public override int Remaining {
  168. // Our count is 0 for 1 character left.
  169.             get { return (fallbackCount < 0) ? 0 : fallbackCount; }
  170.         }
  171.        
  172.         // Clear the buffer
  173.         unsafe public override void Reset()
  174.         {
  175.             fallbackCount = -1;
  176.             fallbackIndex = -1;
  177.             byteStart = null;
  178.         }
  179.        
  180.         // This version just counts the fallback and doesn't actually copy anything.
  181.         unsafe internal override int InternalFallback(byte[] bytes, byte* pBytes)
  182.         {
  183.             // return our replacement string Length
  184.             return strDefault.Length;
  185.         }
  186.     }
  187. }

Developer Fusion