Added a permissive code point enumerator, which doesn't choke on lone surrogates.
This commit is contained in:
@@ -13,6 +13,8 @@ namespace System.Unicode
|
||||
|
||||
public CodePointEnumerable(string text)
|
||||
{
|
||||
if (text == null) throw new ArgumentNullException(nameof(text));
|
||||
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Unicode
|
||||
{
|
||||
public struct PermissiveCodePointEnumerable : IEnumerable<int>
|
||||
{
|
||||
private readonly string text;
|
||||
|
||||
public PermissiveCodePointEnumerable(string text)
|
||||
{
|
||||
if (text == null) throw new ArgumentNullException(nameof(text));
|
||||
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public string Text { get { return text; } }
|
||||
|
||||
public PermissiveCodePointEnumerator GetEnumerator()
|
||||
{
|
||||
return new PermissiveCodePointEnumerator(text);
|
||||
}
|
||||
|
||||
IEnumerator<int> IEnumerable<int>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Unicode
|
||||
{
|
||||
public struct PermissiveCodePointEnumerator : IEnumerator<int>
|
||||
{
|
||||
private readonly string text;
|
||||
private int current;
|
||||
private int index;
|
||||
|
||||
public PermissiveCodePointEnumerator(string text)
|
||||
{
|
||||
if (text == null) throw new ArgumentNullException(nameof(text));
|
||||
|
||||
this.text = text;
|
||||
this.current = 0;
|
||||
this.index = -1;
|
||||
}
|
||||
|
||||
public int Current { get { return current; } }
|
||||
|
||||
object IEnumerator.Current { get { return current; } }
|
||||
|
||||
void IDisposable.Dispose() { }
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (index < text.Length && (index += current > 0xFFFF ? 2 : 1) < text.Length)
|
||||
{
|
||||
current = GetUtf32(text, index);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
current = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
current = 0;
|
||||
index = -1;
|
||||
}
|
||||
|
||||
private static int GetUtf32(string s, int index)
|
||||
{
|
||||
char c1 = s[index];
|
||||
|
||||
if (char.IsHighSurrogate(c1) && ++index < s.Length)
|
||||
{
|
||||
char c2 = s[index];
|
||||
|
||||
if (char.IsLowSurrogate(c2)) return char.ConvertToUtf32(c1, c2);
|
||||
}
|
||||
|
||||
return c1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,5 +12,10 @@ namespace System.Unicode
|
||||
{
|
||||
return new CodePointEnumerable(s);
|
||||
}
|
||||
|
||||
public static PermissiveCodePointEnumerable AsPermissiveCodePointEnumerable(this string s)
|
||||
{
|
||||
return new PermissiveCodePointEnumerable(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
<Compile Include="BidirectionalClass.cs" />
|
||||
<Compile Include="CjkRadicalData.cs" />
|
||||
<Compile Include="CjkRadicalInfo.cs" />
|
||||
<Compile Include="PermissiveCodePointEnumerable.cs" />
|
||||
<Compile Include="PermissiveCodePointEnumerator.cs" />
|
||||
<Compile Include="CompatibilityFormattingTag.cs" />
|
||||
<Compile Include="ContributoryProperties.cs" />
|
||||
<Compile Include="CanonicalCombiningClass.cs" />
|
||||
|
||||
Reference in New Issue
Block a user