The Labs \ Source Viewer \ SSCLI \ System.Globalization \ TextElementEnumerator

  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. ////////////////////////////////////////////////////////////////////////////
  16. //
  17. // Class: TextElementEnumerator
  18. //
  19. // Purpose:
  20. //
  21. // Date: March 31, 1999
  22. //
  23. ////////////////////////////////////////////////////////////////////////////
  24. using System.Runtime.Serialization;
  25. namespace System.Globalization
  26. {
  27.     using System.Collections;
  28.    
  29.     //
  30.     // This is public because GetTextElement() is public.
  31.     //
  32.    
  33.     [Serializable()]
  34.     [System.Runtime.InteropServices.ComVisible(true)]
  35.     public class TextElementEnumerator : IEnumerator
  36.     {
  37.         private string str;
  38.         private int index;
  39.         private int startIndex;
  40.        
  41.         [NonSerialized()]
  42.         private int strLen;
  43.         // This is the length of the total string, counting from the beginning of string.
  44.         [NonSerialized()]
  45.         private int currTextElementLen;
  46.         // The current text element lenght after MoveNext() is called.
  47.         [OptionalField(VersionAdded = 2)]
  48.         private UnicodeCategory uc;
  49.        
  50.         [OptionalField(VersionAdded = 2)]
  51.         private int charLen;
  52.         // The next abstract char to look at after MoveNext() is called. It could be 1 or 2, depending on if it is a surrogate or not.
  53.         internal TextElementEnumerator(string str, int startIndex, int strLen)
  54.         {
  55.             BCLDebug.Assert(str != null, "TextElementEnumerator(): str != null");
  56.             BCLDebug.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0");
  57.             BCLDebug.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex");
  58.             this.str = str;
  59.             this.startIndex = startIndex;
  60.             this.strLen = strLen;
  61.             Reset();
  62.         }
  63.        
  64.         #region Serialization
  65.         private int endIndex;
  66.         private int nextTextElementLen;
  67.        
  68.         [OnDeserializing()]
  69.         private void OnDeserializing(StreamingContext ctx)
  70.         {
  71.             charLen = -1;
  72.         }
  73.        
  74.         [OnDeserialized()]
  75.         private void OnDeserialized(StreamingContext ctx)
  76.         {
  77.             strLen = endIndex + 1;
  78.             currTextElementLen = nextTextElementLen;
  79.            
  80.             if (charLen == -1) {
  81.                 uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen);
  82.             }
  83.         }
  84.        
  85.         [OnSerializing()]
  86.         private void OnSerializing(StreamingContext ctx)
  87.         {
  88.             endIndex = strLen - 1;
  89.             nextTextElementLen = currTextElementLen;
  90.         }
  91.        
  92.         #endregion Serialization
  93.        
  94.        
  95.        
  96.         public bool MoveNext()
  97.         {
  98.             if (index >= strLen) {
  99.                 // Make the index to be greater than strLen so that we can throw exception if GetTextElement() is called.
  100.                 index = strLen + 1;
  101.                 return (false);
  102.             }
  103.             currTextElementLen = StringInfo.GetCurrentTextElementLen(str, index, strLen, ref uc, ref charLen);
  104.             index += currTextElementLen;
  105.             return (true);
  106.         }
  107.        
  108.         //
  109.         // Get the current text element.
  110.         //
  111.        
  112.         public object Current {
  113.             get { return (GetTextElement()); }
  114.         }
  115.        
  116.         //
  117.         // Get the current text element.
  118.         //
  119.        
  120.         public string GetTextElement()
  121.         {
  122.             if (index == startIndex) {
  123.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
  124.             }
  125.             if (index > strLen) {
  126.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumEnded"));
  127.             }
  128.            
  129.             return (str.Substring(index - currTextElementLen, currTextElementLen));
  130.         }
  131.        
  132.         //
  133.         // Get the starting index of the current text element.
  134.         //
  135.        
  136.         public int ElementIndex {
  137.             get {
  138.                 if (index == startIndex) {
  139.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
  140.                 }
  141.                 return (index - currTextElementLen);
  142.             }
  143.         }
  144.        
  145.        
  146.         public void Reset()
  147.         {
  148.             index = startIndex;
  149.             if (index < strLen) {
  150.                 // If we have more than 1 character, get the category of the current char.
  151.                 uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen);
  152.             }
  153.         }
  154.     }
  155. }

Developer Fusion