using System.Collections; using System.Collections.Generic; using System.Globalization; namespace System.Unicode { /// Represents a range of Unicode code points. public struct UnicodeCodePointRange : IEnumerable { /// Represents an enumerator which enumerated through all the code points in the . public struct Enumerator : IEnumerator { private readonly int start; private readonly int end; private int index; /// Initializes a new instance of the struct. /// The start of the range. /// The end of the range. internal Enumerator(int start, int end) { this.start = start; this.end = end; this.index = start - 1; } /// Does nothing. public void Dispose() { } /// Gets the element in the collection at the current position of the enumerator.. /// The element in the collection at the current position of the enumerator. public int Current { get { return index; } } object IEnumerator.Current { get { return index; } } /// Advances the enumerator to the next element of the collection. /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. public bool MoveNext() { return index < end && ++index == index; } void IEnumerator.Reset() { index = start - 1; } } /// The first code point in the range. public readonly int FirstCodePoint; /// The last code point in the range. public readonly int LastCodePoint; /// Gets a value indicating whether this value represents a single code point. /// if this value represents a single code point; otherwise, . public bool IsSingleCodePoint { get { return FirstCodePoint == LastCodePoint; } } /// Initializes a new instance of the struct for a single code point. /// The code point. /// public UnicodeCodePointRange(int codePoint) { if (codePoint < 0 || codePoint > 0x10FFFF) throw new ArgumentOutOfRangeException(nameof(codePoint)); FirstCodePoint = codePoint; LastCodePoint = codePoint; } /// Initializes a new instance of the struct with specified bounds. /// The first code point in the range. /// The last code point in the range. /// /// is less than 0 or greated than 0x10FFFF, /// or is less than or greated than 0x10FFFF. /// public UnicodeCodePointRange(int firstCodePoint, int lastCodePoint) { if (firstCodePoint < 0 || firstCodePoint > 0x10FFFF) throw new ArgumentOutOfRangeException(nameof(firstCodePoint)); if (lastCodePoint < firstCodePoint || lastCodePoint > 0x10FFFF) throw new ArgumentOutOfRangeException(nameof(lastCodePoint)); FirstCodePoint = firstCodePoint; LastCodePoint = lastCodePoint; } /// Determines whether the range contains the specific code point. /// This method does not validate its inputs, but will always return for any invalid code point. /// The integer to check against the range. /// if the range contains the specified code point; otherwise, . public bool Contains(int i) { // Since the first and last code points have been checked or are at their default value of zero, the method will always exlcude invalid code points. return i >= FirstCodePoint & i <= LastCodePoint; } internal int CompareCodePoint(int codePoint) { return FirstCodePoint <= codePoint ? LastCodePoint < codePoint ? 1 : 0 : -1; } /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() { return FirstCodePoint == LastCodePoint ? FirstCodePoint.ToString("X4") : FirstCodePoint.ToString("X4") + ".." + LastCodePoint.ToString("X4"); } /// Parses the specified into a . /// Code point ranges are encoded as one unprefixed hexadecimal number for single code points, or a pair of unprefixed hexadecimal numbers separated by the characters "..". /// The text to parse. /// The parsed value. /// The parameter was not in an allowed format. public static UnicodeCodePointRange Parse(string s) { int start, end; var rangeSeparatorOffset = s.IndexOf(".."); if (rangeSeparatorOffset == 0) throw new FormatException(); else if (rangeSeparatorOffset < 0) { start = end = int.Parse(s, NumberStyles.HexNumber); } else { start = int.Parse(s.Substring(0, rangeSeparatorOffset), NumberStyles.HexNumber); end = int.Parse(s.Substring(rangeSeparatorOffset + 2), NumberStyles.HexNumber); } return new UnicodeCodePointRange(start, end); } /// Returns an enumerator that iterates through the collection. /// A that can be used to iterate through the collection. public Enumerator GetEnumerator() { return new Enumerator(FirstCodePoint, LastCodePoint); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }