summaryrefslogtreecommitdiff
path: root/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs
blob: f547e3e813a300d2d24a042d558582c9b9ee0b6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

// 

// 

////////////////////////////////////////////////////////////////////////////
//
//  Class:    TextElementEnumerator
//
//  Purpose:  
//
//  Date:     March 31, 1999
//
////////////////////////////////////////////////////////////////////////////

using System.Collections;
using System.Diagnostics.Contracts;

namespace System.Globalization
{
    //
    // This is public because GetTextElement() is public.
    //

    [System.Runtime.InteropServices.ComVisible(true)]
    public class TextElementEnumerator : IEnumerator
    {
        private String str;
        private int index;
        private int startIndex;

        private int strLen;                // This is the length of the total string, counting from the beginning of string.

        private int currTextElementLen; // The current text element lenght after MoveNext() is called.

        private UnicodeCategory uc;

        private int charLen;            // 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.

        internal TextElementEnumerator(String str, int startIndex, int strLen)
        {
            Contract.Assert(str != null, "TextElementEnumerator(): str != null");
            Contract.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0");
            Contract.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex");
            this.str = str;
            this.startIndex = startIndex;
            this.strLen = strLen;
            Reset();
        }

        public bool MoveNext()
        {
            if (index >= strLen)
            {
                // Make the index to be greater than strLen so that we can throw exception if GetTextElement() is called.
                index = strLen + 1;
                return (false);
            }
            currTextElementLen = StringInfo.GetCurrentTextElementLen(str, index, strLen, ref uc, ref charLen);
            index += currTextElementLen;
            return (true);
        }

        //
        // Get the current text element.
        //

        public Object Current
        {
            get
            {
                return (GetTextElement());
            }
        }

        //
        // Get the current text element.
        //

        public String GetTextElement()
        {
            if (index == startIndex)
            {
                throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
            }
            if (index > strLen)
            {
                throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
            }

            return (str.Substring(index - currTextElementLen, currTextElementLen));
        }

        //
        // Get the starting index of the current text element.
        //

        public int ElementIndex
        {
            get
            {
                if (index == startIndex)
                {
                    throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
                }
                return (index - currTextElementLen);
            }
        }


        public void Reset()
        {
            index = startIndex;
            if (index < strLen)
            {
                // If we have more than 1 character, get the category of the current char.
                uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen);
            }
        }
    }
}