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(); }
}
}