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

  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. namespace System.Text
  16. {
  17.     using System.Runtime.Serialization;
  18.     using System.Security.Permissions;
  19.     using System.Text;
  20.     using System;
  21.     // An Encoder is used to encode a sequence of blocks of characters into
  22.     // a sequence of blocks of bytes. Following instantiation of an encoder,
  23.     // sequential blocks of characters are converted into blocks of bytes through
  24.     // calls to the GetBytes method. The encoder maintains state between the
  25.     // conversions, allowing it to correctly encode character sequences that span
  26.     // adjacent blocks.
  27.     //
  28.     // Instances of specific implementations of the Encoder abstract base
  29.     // class are typically obtained through calls to the GetEncoder method
  30.     // of Encoding objects.
  31.     //
  32.    
  33.     [Serializable()]
  34.     internal class EncoderNLS : Encoder, ISerializable
  35.     {
  36.         // Need a place for the last left over character, most of our encodings use this
  37.         internal char charLeftOver;
  38.        
  39.         protected Encoding m_encoding;
  40.        
  41.         [NonSerialized()]
  42.         protected bool m_mustFlush;
  43.         [NonSerialized()]
  44.         internal bool m_throwOnOverflow;
  45.         [NonSerialized()]
  46.         internal int m_charsUsed;
  47.        
  48.         #region Serialization
  49.        
  50.         // Constructor called by serialization. called during deserialization.
  51.         internal EncoderNLS(SerializationInfo info, StreamingContext context)
  52.         {
  53.             throw new NotSupportedException(String.Format(System.Globalization.CultureInfo.CurrentCulture, Environment.GetResourceString("NotSupported_TypeCannotDeserialized"), this.GetType()));
  54.         }
  55.        
  56.         // ISerializable implementation. called during serialization.
  57.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  58.         void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
  59.         {
  60.             SerializeEncoder(info);
  61.             info.AddValue("encoding", this.m_encoding);
  62.             info.AddValue("charLeftOver", this.charLeftOver);
  63.             info.SetType(typeof(Encoding.DefaultEncoder));
  64.         }
  65.        
  66.         #endregion Serialization
  67.        
  68.         internal EncoderNLS(Encoding encoding)
  69.         {
  70.             this.m_encoding = encoding;
  71.             this.m_fallback = this.m_encoding.EncoderFallback;
  72.             this.Reset();
  73.         }
  74.        
  75.         // This one is used when deserializing (like UTF7Encoding.Encoder)
  76.         internal EncoderNLS()
  77.         {
  78.             this.m_encoding = null;
  79.             this.Reset();
  80.         }
  81.        
  82.         public override void Reset()
  83.         {
  84.             this.charLeftOver = (char)0;
  85.             if (m_fallbackBuffer != null)
  86.                 m_fallbackBuffer.Reset();
  87.         }
  88.        
  89.         unsafe public override int GetByteCount(char[] chars, int index, int count, bool flush)
  90.         {
  91.             // Validate input parameters
  92.             if (chars == null)
  93.                 throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
  94.            
  95.             if (index < 0 || count < 0)
  96.                 throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  97.            
  98.             if (chars.Length - index < count)
  99.                 throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  100.            
  101.             // Avoid empty input problem
  102.             if (chars.Length == 0)
  103.                 chars = new char[1];
  104.            
  105.             // Just call the pointer version
  106.             int result = -1;
  107.             fixed (char* pChars = chars) {
  108.                 result = GetByteCount(pChars + index, count, flush);
  109.             }
  110.             return result;
  111.         }
  112.        
  113.         unsafe public override int GetByteCount(char* chars, int count, bool flush)
  114.         {
  115.             // Validate input parameters
  116.             if (chars == null)
  117.                 throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
  118.            
  119.             if (count < 0)
  120.                 throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  121.            
  122.             this.m_mustFlush = flush;
  123.             this.m_throwOnOverflow = true;
  124.             return m_encoding.GetByteCount(chars, count, this);
  125.         }
  126.        
  127.         unsafe public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, bool flush)
  128.         {
  129.             // Validate parameters
  130.             if (chars == null || bytes == null)
  131.                 throw new ArgumentNullException((chars == null ? "chars" : "bytes"), Environment.GetResourceString("ArgumentNull_Array"));
  132.            
  133.             if (charIndex < 0 || charCount < 0)
  134.                 throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  135.            
  136.             if (chars.Length - charIndex < charCount)
  137.                 throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  138.            
  139.             if (byteIndex < 0 || byteIndex > bytes.Length)
  140.                 throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  141.            
  142.             if (chars.Length == 0)
  143.                 chars = new char[1];
  144.            
  145.             int byteCount = bytes.Length - byteIndex;
  146.             if (bytes.Length == 0)
  147.                 bytes = new byte[1];
  148.            
  149.             // Just call pointer version
  150.             fixed (char* pChars = chars)
  151.                 fixed (byte* pBytes = bytes)
  152.                
  153.                 // Remember that charCount is # to decode, not size of array.
  154.                     return GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, flush);
  155.         }
  156.        
  157.         unsafe public override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, bool flush)
  158.         {
  159.             // Validate parameters
  160.             if (chars == null || bytes == null)
  161.                 throw new ArgumentNullException((chars == null ? "chars" : "bytes"), Environment.GetResourceString("ArgumentNull_Array"));
  162.            
  163.             if (byteCount < 0 || charCount < 0)
  164.                 throw new ArgumentOutOfRangeException((byteCount < 0 ? "byteCount" : "charCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  165.            
  166.             this.m_mustFlush = flush;
  167.             this.m_throwOnOverflow = true;
  168.             return m_encoding.GetBytes(chars, charCount, bytes, byteCount, this);
  169.         }
  170.        
  171.         // This method is used when your output buffer might not be large enough for the entire result.
  172.         // Just call the pointer version. (This gets bytes)
  173.         unsafe public override void Convert(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, int byteCount, bool flush, out int charsUsed, out int bytesUsed, out bool completed
  174.         )
  175.         {
  176.             // Validate parameters
  177.             if (chars == null || bytes == null)
  178.                 throw new ArgumentNullException((chars == null ? "chars" : "bytes"), Environment.GetResourceString("ArgumentNull_Array"));
  179.            
  180.             if (charIndex < 0 || charCount < 0)
  181.                 throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  182.            
  183.             if (byteIndex < 0 || byteCount < 0)
  184.                 throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  185.            
  186.             if (chars.Length - charIndex < charCount)
  187.                 throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  188.            
  189.             if (bytes.Length - byteIndex < byteCount)
  190.                 throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
  191.            
  192.            
  193.             // Avoid empty input problem
  194.             if (chars.Length == 0)
  195.                 chars = new char[1];
  196.             if (bytes.Length == 0)
  197.                 bytes = new byte[1];
  198.            
  199.             // Just call the pointer version (can't do this for non-msft encoders)
  200.             fixed (char* pChars = chars) {
  201.                 fixed (byte* pBytes = bytes) {
  202.                     Convert(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, flush, out charsUsed, out bytesUsed, out completed);
  203.                 }
  204.             }
  205.         }
  206.        
  207.         // This is the version that uses pointers. We call the base encoding worker function
  208.         // after setting our appropriate internal variables. This is getting bytes
  209.         unsafe public override void Convert(char* chars, int charCount, byte* bytes, int byteCount, bool flush, out int charsUsed, out int bytesUsed, out bool completed)
  210.         {
  211.             // Validate input parameters
  212.             if (bytes == null || chars == null)
  213.                 throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
  214.             if (charCount < 0 || byteCount < 0)
  215.                 throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  216.            
  217.             // We don't want to throw
  218.             this.m_mustFlush = flush;
  219.             this.m_throwOnOverflow = false;
  220.             this.m_charsUsed = 0;
  221.            
  222.             // Do conversion
  223.             bytesUsed = this.m_encoding.GetBytes(chars, charCount, bytes, byteCount, this);
  224.             charsUsed = this.m_charsUsed;
  225.            
  226.             // Its completed if they've used what they wanted AND if they didn't want flush or if we are flushed
  227.             completed = (charsUsed == charCount) && (!flush || !this.HasState) && (m_fallbackBuffer == null || m_fallbackBuffer.Remaining == 0);
  228.            
  229.             // Our data thingys are now full, we can return
  230.         }
  231.        
  232.         public Encoding Encoding {
  233.             get { return m_encoding; }
  234.         }
  235.        
  236.         public bool MustFlush {
  237.             get { return m_mustFlush; }
  238.         }
  239.        
  240.        
  241.         // Anything left in our encoder?
  242.         internal virtual bool HasState {
  243.             get { return (this.charLeftOver != (char)0); }
  244.         }
  245.        
  246.         // Allow encoding to clear our must flush instead of throwing (in ThrowBytesOverflow)
  247.         internal void ClearMustFlush()
  248.         {
  249.             m_mustFlush = false;
  250.         }
  251.        
  252.     }
  253. }

Developer Fusion