Parse UCD files as UTF8, and parse Blocks.txt for Unicode block information.
This commit is contained in:
@@ -12,7 +12,7 @@ namespace UnicodeCharacterInspector
|
||||
{
|
||||
private string character;
|
||||
private int codePoint;
|
||||
private UnicodeCharInfo characterInfo = UnicodeInfo.Default.Get(0);
|
||||
private UnicodeCharInfo characterInfo = UnicodeInfo.Default.GetCharInfo(0);
|
||||
|
||||
public CharacterInfoViewModel()
|
||||
{
|
||||
@@ -40,12 +40,12 @@ namespace UnicodeCharacterInspector
|
||||
if ((character = value) != null)
|
||||
{
|
||||
codePoint = char.ConvertToUtf32(character, 0);
|
||||
characterInfo = UnicodeInfo.Default.Get(codePoint);
|
||||
characterInfo = UnicodeInfo.Default.GetCharInfo(codePoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
codePoint = 0;
|
||||
characterInfo = UnicodeInfo.Default.Get(0);
|
||||
characterInfo = UnicodeInfo.Default.GetCharInfo(0);
|
||||
}
|
||||
|
||||
NotifyPropertyChanged();
|
||||
@@ -53,6 +53,7 @@ namespace UnicodeCharacterInspector
|
||||
NotifyPropertyChanged("Name");
|
||||
NotifyPropertyChanged("OldName");
|
||||
NotifyPropertyChanged("Category");
|
||||
NotifyPropertyChanged("Block");
|
||||
NotifyPropertyChanged("CanonicalCombiningClass");
|
||||
NotifyPropertyChanged("BidirectionalClass");
|
||||
NotifyPropertyChanged("DecompositionType");
|
||||
@@ -84,6 +85,11 @@ namespace UnicodeCharacterInspector
|
||||
get { return character != null ? characterInfo.Category : null as UnicodeCategory?; }
|
||||
}
|
||||
|
||||
public string Block
|
||||
{
|
||||
get { return character != null ? characterInfo.Block : null; }
|
||||
}
|
||||
|
||||
public CanonicalCombiningClass? CanonicalCombiningClass
|
||||
{
|
||||
get { return character != null ? characterInfo.CanonicalCombiningClass : null as CanonicalCombiningClass?; }
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.CodePoint, Converter={StaticResource NullToVisibilityConverter}}" Content="Code Point" />
|
||||
@@ -79,20 +80,22 @@
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.OldName, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.OldName}" />
|
||||
<Label Grid.Row="3" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.Category, Converter={StaticResource NullToVisibilityConverter}}" Content="Category" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.Category, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.Category}" />
|
||||
<Label Grid.Row="4" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.CanonicalCombiningClass, Converter={StaticResource NullToVisibilityConverter}}" Content="Canonical Combining Class" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.CanonicalCombiningClass, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.CanonicalCombiningClass}" />
|
||||
<Label Grid.Row="5" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.BidirectionalClass, Converter={StaticResource NullToVisibilityConverter}}" Content="Bidirectional Class" />
|
||||
<TextBlock Grid.Row="5" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.BidirectionalClass, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.BidirectionalClass}" />
|
||||
<Label Grid.Row="6" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.DecompositionType, Converter={StaticResource NullToVisibilityConverter}}" Content="Decomposition Type" />
|
||||
<TextBlock Grid.Row="6" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.DecompositionType, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.DecompositionType}" />
|
||||
<Label Grid.Row="7" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.DecompositionMapping, Converter={StaticResource NullToVisibilityConverter}}" Content="Decomposition Mapping" />
|
||||
<TextBlock Grid.Row="7" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.DecompositionMapping, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.DecompositionMapping}" />
|
||||
<Label Grid.Row="8" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.NumericType, Converter={StaticResource NullToVisibilityConverter}}" Content="Numeric Type" />
|
||||
<TextBlock Grid.Row="8" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.NumericType, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.NumericType}" />
|
||||
<Label Grid.Row="9" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.NumericValue, Converter={StaticResource NullToVisibilityConverter}}" Content="Numeric Value" />
|
||||
<TextBlock Grid.Row="9" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.NumericValue, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.NumericValue}" />
|
||||
<Label Grid.Row="10" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource NullToVisibilityConverter}}" Content="Contributory Properties" />
|
||||
<TextBlock Grid.Row="10" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.ContributoryProperties}" />
|
||||
<Label Grid.Row="4" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.Block, Converter={StaticResource NullToVisibilityConverter}}" Content="Block" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.Block, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.Block}" />
|
||||
<Label Grid.Row="5" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.CanonicalCombiningClass, Converter={StaticResource NullToVisibilityConverter}}" Content="Canonical Combining Class" />
|
||||
<TextBlock Grid.Row="5" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.CanonicalCombiningClass, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.CanonicalCombiningClass}" />
|
||||
<Label Grid.Row="6" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.BidirectionalClass, Converter={StaticResource NullToVisibilityConverter}}" Content="Bidirectional Class" />
|
||||
<TextBlock Grid.Row="6" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.BidirectionalClass, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.BidirectionalClass}" />
|
||||
<Label Grid.Row="7" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.DecompositionType, Converter={StaticResource NullToVisibilityConverter}}" Content="Decomposition Type" />
|
||||
<TextBlock Grid.Row="7" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.DecompositionType, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.DecompositionType}" />
|
||||
<Label Grid.Row="8" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.DecompositionMapping, Converter={StaticResource NullToVisibilityConverter}}" Content="Decomposition Mapping" />
|
||||
<TextBlock Grid.Row="8" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.DecompositionMapping, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.DecompositionMapping}" />
|
||||
<Label Grid.Row="9" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.NumericType, Converter={StaticResource NullToVisibilityConverter}}" Content="Numeric Type" />
|
||||
<TextBlock Grid.Row="9" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.NumericType, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.NumericType}" />
|
||||
<Label Grid.Row="10" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.NumericValue, Converter={StaticResource NullToVisibilityConverter}}" Content="Numeric Value" />
|
||||
<TextBlock Grid.Row="10" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.NumericValue, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.NumericValue}" />
|
||||
<Label Grid.Row="11" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource NullToVisibilityConverter}}" Content="Contributory Properties" />
|
||||
<TextBlock Grid.Row="11" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.ContributoryProperties}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace System.Unicode.Builder
|
||||
{
|
||||
"UnicodeData.txt",
|
||||
"PropList.txt",
|
||||
"Blocks.txt",
|
||||
"Jamo.txt"
|
||||
};
|
||||
|
||||
@@ -113,7 +114,7 @@ namespace System.Unicode.Builder
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
UnicodeDataBuilder data;
|
||||
UnicodeInfoBuilder data;
|
||||
|
||||
using (var ucdSource = GetUcdSource(null, null, null))
|
||||
{
|
||||
|
||||
@@ -9,12 +9,12 @@ namespace System.Unicode.Builder
|
||||
{
|
||||
public class UnicodeDataFileReader : IDisposable
|
||||
{
|
||||
private struct AsciiCharBuffer
|
||||
private struct Utf8Buffer
|
||||
{
|
||||
private readonly UnicodeDataFileReader reader;
|
||||
private int length;
|
||||
|
||||
public AsciiCharBuffer(UnicodeDataFileReader reader)
|
||||
public Utf8Buffer(UnicodeDataFileReader reader)
|
||||
{
|
||||
this.reader = reader;
|
||||
this.length = 0;
|
||||
@@ -25,8 +25,8 @@ namespace System.Unicode.Builder
|
||||
private void EnsureExtraCapacity(int count)
|
||||
{
|
||||
if (count < 0) throw new ArgumentOutOfRangeException("requiredExtraCapacity");
|
||||
if (reader.charBuffer.Length < checked(length + count))
|
||||
Array.Resize(ref reader.charBuffer, Math.Max(length + count, reader.charBuffer.Length << 1));
|
||||
if (reader.utf8StringBuffer.Length < checked(length + count))
|
||||
Array.Resize(ref reader.utf8StringBuffer, Math.Max(length + count, reader.utf8StringBuffer.Length << 1));
|
||||
}
|
||||
|
||||
public void Append(byte[] value, int startIndex, int count)
|
||||
@@ -37,27 +37,23 @@ namespace System.Unicode.Builder
|
||||
|
||||
EnsureExtraCapacity(value.Length);
|
||||
|
||||
var buffer = reader.charBuffer;
|
||||
var buffer = reader.utf8StringBuffer;
|
||||
|
||||
for (int i = startIndex; i < count; ++i)
|
||||
{
|
||||
byte b = value[i];
|
||||
|
||||
if (b > 127) throw new InvalidDataException(string.Format("Unexpected character value: {0}.", b));
|
||||
|
||||
buffer[length++] = (char)b;
|
||||
buffer[length++] = value[i];
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return length > 0 ? new string(reader.charBuffer, 0, length) : string.Empty;
|
||||
return length > 0 ? Encoding.UTF8.GetString(reader.utf8StringBuffer, 0, length) : string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Stream stream;
|
||||
private readonly byte[] byteBuffer;
|
||||
private char[] charBuffer;
|
||||
private byte[] utf8StringBuffer;
|
||||
private int index;
|
||||
private int length;
|
||||
private bool hasField = false;
|
||||
@@ -72,7 +68,7 @@ namespace System.Unicode.Builder
|
||||
{
|
||||
this.stream = stream;
|
||||
this.byteBuffer = new byte[8192];
|
||||
this.charBuffer = new char[100];
|
||||
this.utf8StringBuffer = new byte[100];
|
||||
this.leaveOpen = leaveOpen;
|
||||
}
|
||||
|
||||
@@ -156,7 +152,7 @@ namespace System.Unicode.Builder
|
||||
}
|
||||
}
|
||||
|
||||
var buffer = new AsciiCharBuffer(this);
|
||||
var buffer = new Utf8Buffer(this);
|
||||
int startOffset;
|
||||
int endOffset;
|
||||
|
||||
|
||||
@@ -8,10 +8,11 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace System.Unicode.Builder
|
||||
{
|
||||
public class UnicodeDataProcessor
|
||||
internal class UnicodeDataProcessor
|
||||
{
|
||||
public const string UnicodeDataFileName = "UnicodeData.txt";
|
||||
public const string PropListFileName = "PropList.txt";
|
||||
public const string BlocksFileName = "Blocks.txt";
|
||||
|
||||
private static string ParseSimpleCaseMapping(string mapping)
|
||||
{
|
||||
@@ -23,12 +24,21 @@ namespace System.Unicode.Builder
|
||||
private static string NullIfEmpty(string s)
|
||||
{
|
||||
return string.IsNullOrEmpty(s) ? null : s;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<UnicodeDataBuilder> BuildDataAsync(IUcdSource ucdSource)
|
||||
public static async Task<UnicodeInfoBuilder> BuildDataAsync(IUcdSource ucdSource)
|
||||
{
|
||||
var builder = new UnicodeDataBuilder(new Version(7, 0));
|
||||
var builder = new UnicodeInfoBuilder(new Version(7, 0));
|
||||
|
||||
await ProcessUnicodeDataFile(ucdSource, builder).ConfigureAwait(false);
|
||||
await ProcessPropListFile(ucdSource, builder).ConfigureAwait(false);
|
||||
await ProcessBlocksFile(ucdSource, builder).ConfigureAwait(false);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static async Task ProcessUnicodeDataFile(IUcdSource ucdSource, UnicodeInfoBuilder builder)
|
||||
{
|
||||
using (var reader = new UnicodeDataFileReader(await ucdSource.OpenDataFileAsync(UnicodeDataFileName).ConfigureAwait(false)))
|
||||
{
|
||||
int rangeStartCodePoint = -1;
|
||||
@@ -55,11 +65,11 @@ namespace System.Unicode.Builder
|
||||
|
||||
codePoint = new UnicodeCharacterRange(rangeStartCodePoint, codePoint.LastCodePoint);
|
||||
|
||||
name = name.Substring(1, name.Length - 8).ToUpperInvariant(); // Upper-case the name in order to respect unicode naming scheme. (Spec says all names are uppercase ASCII)
|
||||
name = name.Substring(1, name.Length - 8).ToUpperInvariant(); // Upper-case the name in order to respect unicode naming scheme. (Spec says all names are uppercase ASCII)
|
||||
|
||||
rangeStartCodePoint = -1;
|
||||
}
|
||||
else if (name == "<control>") // Ignore the name of the property for these code points, as it should really be empty by the spec.
|
||||
else if (name == "<control>") // Ignore the name of the property for these code points, as it should really be empty by the spec.
|
||||
{
|
||||
// For control characters, we can derive a character label in of the form <control-NNNN>, which is not the character name.
|
||||
name = null;
|
||||
@@ -70,7 +80,7 @@ namespace System.Unicode.Builder
|
||||
}
|
||||
}
|
||||
else if (rangeStartCodePoint >= 0)
|
||||
{
|
||||
{
|
||||
throw new InvalidDataException("Invalid range data in UnicodeData.txt.");
|
||||
}
|
||||
|
||||
@@ -142,7 +152,10 @@ namespace System.Unicode.Builder
|
||||
builder.Insert(characterData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static async Task ProcessPropListFile(IUcdSource ucdSource, UnicodeInfoBuilder builder)
|
||||
{
|
||||
using (var reader = new UnicodeDataFileReader(await ucdSource.OpenDataFileAsync(PropListFileName).ConfigureAwait(false)))
|
||||
{
|
||||
while (reader.MoveToNextLine())
|
||||
@@ -156,8 +169,17 @@ namespace System.Unicode.Builder
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder;
|
||||
private static async Task ProcessBlocksFile(IUcdSource ucdSource, UnicodeInfoBuilder builder)
|
||||
{
|
||||
using (var reader = new UnicodeDataFileReader(await ucdSource.OpenDataFileAsync(BlocksFileName).ConfigureAwait(false)))
|
||||
{
|
||||
while (reader.MoveToNextLine())
|
||||
{
|
||||
builder.AddBlockEntry(new UnicodeBlock(UnicodeCharacterRange.Parse(reader.ReadField()), reader.ReadField().Trim()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-3
@@ -7,13 +7,14 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace System.Unicode.Builder
|
||||
{
|
||||
public class UnicodeDataBuilder
|
||||
internal class UnicodeInfoBuilder
|
||||
{
|
||||
private readonly Version unicodeVersion;
|
||||
private UnicodeCharacterDataBuilder[] entries = new UnicodeCharacterDataBuilder[10000];
|
||||
private int entryCount;
|
||||
private List<UnicodeBlock> blockEntries = new List<UnicodeBlock>(100);
|
||||
|
||||
public UnicodeDataBuilder(Version unicodeVersion)
|
||||
public UnicodeInfoBuilder(Version unicodeVersion)
|
||||
{
|
||||
this.unicodeVersion = unicodeVersion;
|
||||
}
|
||||
@@ -121,6 +122,11 @@ namespace System.Unicode.Builder
|
||||
}
|
||||
}
|
||||
|
||||
public void AddBlockEntry(UnicodeBlock block)
|
||||
{
|
||||
blockEntries.Add(block);
|
||||
}
|
||||
|
||||
public UnicodeInfo ToUnicodeData()
|
||||
{
|
||||
var finalData = new UnicodeCharacterData[entryCount];
|
||||
@@ -128,7 +134,14 @@ namespace System.Unicode.Builder
|
||||
for (int i = 0; i < finalData.Length; ++i)
|
||||
finalData[i] = entries[i].ToCharacterData();
|
||||
|
||||
return new UnicodeInfo(unicodeVersion, finalData);
|
||||
return new UnicodeInfo(unicodeVersion, finalData, blockEntries.ToArray());
|
||||
}
|
||||
|
||||
private void WriteUnicodeBlockToFile(BinaryWriter writer, UnicodeBlock block)
|
||||
{
|
||||
writer.WriteCodePoint(block.CodePointRange.FirstCodePoint);
|
||||
writer.WriteCodePoint(block.CodePointRange.LastCodePoint);
|
||||
writer.Write(block.Name);
|
||||
}
|
||||
|
||||
public void WriteToStream(Stream stream)
|
||||
@@ -143,6 +156,10 @@ namespace System.Unicode.Builder
|
||||
{
|
||||
entries[i].WriteToFile(writer);
|
||||
}
|
||||
if (blockEntries.Count > 255) throw new InvalidOperationException("There are too many block entries. The file format needs to be upgraded.");
|
||||
writer.Write((byte)blockEntries.Count);
|
||||
for (int i = 0; i < blockEntries.Count; ++i)
|
||||
WriteUnicodeBlockToFile(writer, blockEntries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UnicodeCharacterDataBuilder.cs" />
|
||||
<Compile Include="UnicodeDataBuilder.cs" />
|
||||
<Compile Include="UnicodeInfoBuilder.cs" />
|
||||
<Compile Include="UnicodeDataFileReader.cs" />
|
||||
<Compile Include="UnicodeDataProcessor.cs" />
|
||||
<Compile Include="ZipUcdSource.cs" />
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace System.Unicode.Tests
|
||||
|
||||
var data = (await UnicodeDataProcessor.BuildDataAsync(source)).ToUnicodeData();
|
||||
|
||||
Assert.AreEqual((int)'\t', data.Get('\t').CodePoint);
|
||||
Assert.AreEqual((int)'\t', data.GetCharInfo('\t').CodePoint);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Unicode
|
||||
{
|
||||
public struct UnicodeBlock
|
||||
{
|
||||
public readonly UnicodeCharacterRange CodePointRange;
|
||||
public readonly string Name;
|
||||
|
||||
internal UnicodeBlock(UnicodeCharacterRange codePointRange, string name)
|
||||
{
|
||||
this.CodePointRange = codePointRange;
|
||||
this.Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ namespace System.Unicode
|
||||
{
|
||||
private readonly int codePoint;
|
||||
private readonly UnicodeCharacterData characterData;
|
||||
private readonly string block;
|
||||
|
||||
public int CodePoint { get { return codePoint; } }
|
||||
|
||||
@@ -25,6 +26,7 @@ namespace System.Unicode
|
||||
}
|
||||
|
||||
public UnicodeCategory Category { get { return characterData.Category; } }
|
||||
public string Block { get { return block; } }
|
||||
public CanonicalCombiningClass CanonicalCombiningClass { get { return characterData.CanonicalCombiningClass; } }
|
||||
public BidirectionalClass BidirectionalClass { get { return characterData.BidirectionalClass; } }
|
||||
public CompatibilityFormattingTag DecompositionType { get { return characterData.DecompositionType; } }
|
||||
@@ -38,10 +40,11 @@ namespace System.Unicode
|
||||
public string SimpleTitleCaseMapping { get { return characterData.SimpleTitleCaseMapping; } }
|
||||
public ContributoryProperties ContributoryProperties { get { return characterData.ContributoryProperties; } }
|
||||
|
||||
internal UnicodeCharInfo(int codePoint, UnicodeCharacterData characterData)
|
||||
internal UnicodeCharInfo(int codePoint, UnicodeCharacterData characterData, string block)
|
||||
{
|
||||
this.codePoint = codePoint;
|
||||
this.characterData = characterData;
|
||||
this.block = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace System.Unicode
|
||||
|
||||
private static UnicodeInfo ReadEmbeddedUnicodeData()
|
||||
{
|
||||
using (var stream = new DeflateStream(typeof(UnicodeInfo).GetTypeInfo().Assembly.GetManifestResourceStream("System.Unicode.ucd.dat"), CompressionMode.Decompress, false))
|
||||
using (var stream = new DeflateStream(typeof(UnicodeInfo).GetTypeInfo().Assembly.GetManifestResourceStream("ucd.dat"), CompressionMode.Decompress, false))
|
||||
{
|
||||
return FromStream(stream);
|
||||
}
|
||||
@@ -25,6 +25,7 @@ namespace System.Unicode
|
||||
|
||||
private readonly Version unicodeVersion;
|
||||
private readonly UnicodeCharacterData[] characterData;
|
||||
private readonly UnicodeBlock[] blockEntries;
|
||||
|
||||
public static UnicodeInfo FromStream(Stream stream)
|
||||
{
|
||||
@@ -43,18 +44,25 @@ namespace System.Unicode
|
||||
|
||||
var unicodeVersion = new Version(reader.ReadUInt16(), reader.ReadByte());
|
||||
|
||||
var entries = new UnicodeCharacterData[ReadCodePoint(reader)];
|
||||
var characterDataEntries = new UnicodeCharacterData[ReadCodePoint(reader)];
|
||||
|
||||
for (int i = 0; i < entries.Length; ++i)
|
||||
for (int i = 0; i < characterDataEntries.Length; ++i)
|
||||
{
|
||||
entries[i] = ReadEntry(reader);
|
||||
characterDataEntries[i] = ReadCharacterDataEntry(reader);
|
||||
}
|
||||
|
||||
return new UnicodeInfo(unicodeVersion, entries);
|
||||
var blockEntries = new UnicodeBlock[reader.ReadByte()];
|
||||
|
||||
for (int i = 0; i < blockEntries.Length; ++i)
|
||||
{
|
||||
blockEntries[i] = ReadBlockEntry(reader);
|
||||
}
|
||||
|
||||
return new UnicodeInfo(unicodeVersion, characterDataEntries, blockEntries);
|
||||
}
|
||||
}
|
||||
|
||||
private static UnicodeCharacterData ReadEntry(BinaryReader reader)
|
||||
private static UnicodeCharacterData ReadCharacterDataEntry(BinaryReader reader)
|
||||
{
|
||||
var fields = (UcdFields)reader.ReadUInt16();
|
||||
|
||||
@@ -97,6 +105,11 @@ namespace System.Unicode
|
||||
);
|
||||
}
|
||||
|
||||
private static UnicodeBlock ReadBlockEntry(BinaryReader reader)
|
||||
{
|
||||
return new UnicodeBlock(new UnicodeCharacterRange(ReadCodePoint(reader), ReadCodePoint(reader)), reader.ReadString());
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
internal static int ReadCodePoint(BinaryReader reader)
|
||||
#else
|
||||
@@ -120,10 +133,11 @@ namespace System.Unicode
|
||||
}
|
||||
}
|
||||
|
||||
internal UnicodeInfo(Version unicodeVersion, UnicodeCharacterData[] characterData)
|
||||
internal UnicodeInfo(Version unicodeVersion, UnicodeCharacterData[] characterData, UnicodeBlock[] blockEntries)
|
||||
{
|
||||
this.unicodeVersion = unicodeVersion;
|
||||
this.characterData = characterData;
|
||||
this.blockEntries = blockEntries;
|
||||
}
|
||||
|
||||
public Version UnicodeVersion { get { return unicodeVersion; } }
|
||||
@@ -147,9 +161,40 @@ namespace System.Unicode
|
||||
return null;
|
||||
}
|
||||
|
||||
public UnicodeCharInfo Get(int codePoint)
|
||||
private int FindBlockIndex(int codePoint)
|
||||
{
|
||||
return new UnicodeCharInfo(codePoint, FindCodePoint(codePoint));
|
||||
int minIndex = 0;
|
||||
int maxIndex = blockEntries.Length - 1;
|
||||
|
||||
do
|
||||
{
|
||||
int index = (minIndex + maxIndex) >> 1;
|
||||
|
||||
int Δ = blockEntries[index].CodePointRange.CompareCodePoint(codePoint);
|
||||
|
||||
if (Δ == 0) return index;
|
||||
else if (Δ < 0) maxIndex = index - 1;
|
||||
else minIndex = index + 1;
|
||||
} while (minIndex <= maxIndex);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private string GetBlockName(int codePoint)
|
||||
{
|
||||
int i = FindBlockIndex(codePoint);
|
||||
|
||||
return i >= 0 ? blockEntries[i].Name : null;
|
||||
}
|
||||
|
||||
public UnicodeCharInfo GetCharInfo(int codePoint)
|
||||
{
|
||||
return new UnicodeCharInfo(codePoint, FindCodePoint(codePoint), GetBlockName(codePoint));
|
||||
}
|
||||
|
||||
public UnicodeBlock[] GetBlocks()
|
||||
{
|
||||
return (UnicodeBlock[])blockEntries.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,9 @@
|
||||
<Link>System.Unicode.snk</Link>
|
||||
</None>
|
||||
<None Include="app.config" />
|
||||
<EmbeddedResource Include="ucd.dat" />
|
||||
<EmbeddedResource Include="ucd.dat">
|
||||
<LogicalName>ucd.dat</LogicalName>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BidirectionalClass.cs" />
|
||||
@@ -66,6 +68,7 @@
|
||||
<Compile Include="EnumHelper.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StringExtensions.cs" />
|
||||
<Compile Include="UnicodeBlock.cs" />
|
||||
<Compile Include="UnicodeCategoryExtensions.cs" />
|
||||
<Compile Include="UnicodeCategoryInfo.cs" />
|
||||
<Compile Include="UnicodeCharacterData.cs" />
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user