From 533c9e6d1bbd42ab4f828916a53e0a6030f07b7a Mon Sep 17 00:00:00 2001 From: GoldenCrystal Date: Sat, 15 Nov 2014 00:58:03 +0100 Subject: [PATCH] Preparing to integrate parts of Unihan. --- UnicodeCharacterInspector/App.config | 6 +- UnicodeCharacterInspector/App.manifest | 33 +++++++++++ .../UnicodeCharacterInspector.csproj | 5 ++ .../{FileUcdSource.cs => FileDataSource.cs} | 4 +- .../{HttpUcdSource.cs => HttpDataSource.cs} | 6 +- .../{IUcdSource.cs => IDataSource.cs} | 2 +- UnicodeInformation.Builder/Program.cs | 58 +++++++++++-------- .../UnicodeDataProcessor.cs | 10 ++-- .../UnicodeInformation.Builder.csproj | 8 +-- .../{ZipUcdSource.cs => ZipDataSource.cs} | 4 +- .../UnicodeDataManagerTests.cs | 23 +++++--- UnicodeInformation/UnicodeInformation.csproj | 3 + UnicodeInformation/UnihanCharacterData.cs | 55 ++++++++++++++++++ UnicodeInformation/UnihanFields.cs | 29 ++++++++++ UnicodeInformation/UnihanNumericType.cs | 20 +++++++ 15 files changed, 213 insertions(+), 53 deletions(-) create mode 100644 UnicodeCharacterInspector/App.manifest rename UnicodeInformation.Builder/{FileUcdSource.cs => FileDataSource.cs} (83%) rename UnicodeInformation.Builder/{HttpUcdSource.cs => HttpDataSource.cs} (87%) rename UnicodeInformation.Builder/{IUcdSource.cs => IDataSource.cs} (84%) rename UnicodeInformation.Builder/{ZipUcdSource.cs => ZipDataSource.cs} (87%) create mode 100644 UnicodeInformation/UnihanCharacterData.cs create mode 100644 UnicodeInformation/UnihanFields.cs create mode 100644 UnicodeInformation/UnihanNumericType.cs diff --git a/UnicodeCharacterInspector/App.config b/UnicodeCharacterInspector/App.config index 8e15646..d1428ad 100644 --- a/UnicodeCharacterInspector/App.config +++ b/UnicodeCharacterInspector/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/UnicodeCharacterInspector/App.manifest b/UnicodeCharacterInspector/App.manifest new file mode 100644 index 0000000..e74ab2a --- /dev/null +++ b/UnicodeCharacterInspector/App.manifest @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UnicodeCharacterInspector/UnicodeCharacterInspector.csproj b/UnicodeCharacterInspector/UnicodeCharacterInspector.csproj index 426225d..b767a37 100644 --- a/UnicodeCharacterInspector/UnicodeCharacterInspector.csproj +++ b/UnicodeCharacterInspector/UnicodeCharacterInspector.csproj @@ -14,6 +14,7 @@ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 f1bfc594 + AnyCPU @@ -34,6 +35,9 @@ prompt 4 + + App.manifest + @@ -80,6 +84,7 @@ + diff --git a/UnicodeInformation.Builder/FileUcdSource.cs b/UnicodeInformation.Builder/FileDataSource.cs similarity index 83% rename from UnicodeInformation.Builder/FileUcdSource.cs rename to UnicodeInformation.Builder/FileDataSource.cs index d452172..f3ba7b1 100644 --- a/UnicodeInformation.Builder/FileUcdSource.cs +++ b/UnicodeInformation.Builder/FileDataSource.cs @@ -8,11 +8,11 @@ using System.Unicode; namespace System.Unicode.Builder { - public sealed class FileUcdSource : IUcdSource + public sealed class FileDataSource : IDataSource { private readonly string baseDirectory; - public FileUcdSource(string baseDirectory) + public FileDataSource(string baseDirectory) { this.baseDirectory = Path.GetFullPath(baseDirectory); } diff --git a/UnicodeInformation.Builder/HttpUcdSource.cs b/UnicodeInformation.Builder/HttpDataSource.cs similarity index 87% rename from UnicodeInformation.Builder/HttpUcdSource.cs rename to UnicodeInformation.Builder/HttpDataSource.cs index 0133ce7..129dbd9 100644 --- a/UnicodeInformation.Builder/HttpUcdSource.cs +++ b/UnicodeInformation.Builder/HttpDataSource.cs @@ -8,19 +8,19 @@ using System.Threading.Tasks; namespace System.Unicode.Builder { - public class HttpUcdSource : IUcdSource + public class HttpDataSource : IDataSource { public static readonly Uri UnicodeCharacterDataUri = new Uri("http://www.unicode.org/Public/UCD/latest/ucd/", UriKind.Absolute); private readonly HttpClient httpClient; private readonly Uri baseUri; - public HttpUcdSource() + public HttpDataSource() : this(UnicodeCharacterDataUri) { } - public HttpUcdSource(Uri baseUri) + public HttpDataSource(Uri baseUri) { this.httpClient = new HttpClient(); this.baseUri = baseUri; diff --git a/UnicodeInformation.Builder/IUcdSource.cs b/UnicodeInformation.Builder/IDataSource.cs similarity index 84% rename from UnicodeInformation.Builder/IUcdSource.cs rename to UnicodeInformation.Builder/IDataSource.cs index 2c51a4b..3e807b8 100644 --- a/UnicodeInformation.Builder/IUcdSource.cs +++ b/UnicodeInformation.Builder/IDataSource.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace System.Unicode.Builder { - public interface IUcdSource : IDisposable + public interface IDataSource : IDisposable { Task OpenDataFileAsync(string fileName); } diff --git a/UnicodeInformation.Builder/Program.cs b/UnicodeInformation.Builder/Program.cs index f836a3e..d52d240 100644 --- a/UnicodeInformation.Builder/Program.cs +++ b/UnicodeInformation.Builder/Program.cs @@ -13,7 +13,7 @@ namespace System.Unicode.Builder { public const string UnihanDirectoryName = "Unihan"; public const string UnihanArchiveName = "Unihan.zip"; - public const string UcdDirectoryName = "UCD"; + public const string directoryName = "UCD"; public const string UcdArchiveName = "UCD.zip"; public static readonly string[] ucdRequiredFiles = new[] @@ -22,32 +22,39 @@ namespace System.Unicode.Builder "PropList.txt", "DerivedCoreProperties.txt", "Blocks.txt", - "Jamo.txt" + "Jamo.txt", }; - private static byte[] DownloadUcdArchive() + public static readonly string[] unihanRequiredFiles = new[] + { + "Unihan_NumericValues.txt", + "Unihan_Readings.txt", + "Unihan_Variants.txt", + }; + + private static byte[] DownloadDataArchive(string archiveName) { using (var httpClient = new HttpClient()) { - return httpClient.GetByteArrayAsync(HttpUcdSource.UnicodeCharacterDataUri + UcdArchiveName).Result; + return httpClient.GetByteArrayAsync(HttpDataSource.UnicodeCharacterDataUri + archiveName).Result; } } - internal static IUcdSource GetUcdSource(bool? shouldDownload, bool? shouldSaveArchive, bool? shouldExtract) + internal static IDataSource GetDataSource(string archiveName, string directoryName, string[] requiredFiles, bool? shouldDownload, bool? shouldSaveArchive, bool? shouldExtract) { string baseDirectory = Environment.CurrentDirectory; - string ucdDirectory = Path.Combine(baseDirectory, UcdDirectoryName); - string ucdArchiveFileName = Path.Combine(baseDirectory, UcdArchiveName); + string dataDirectory = Path.Combine(baseDirectory, Program.directoryName); + string dataArchiveFileName = Path.Combine(baseDirectory, archiveName); if (shouldDownload != true) { - bool hasValidDirectory = Directory.Exists(ucdDirectory); + bool hasValidDirectory = Directory.Exists(dataDirectory); if (hasValidDirectory) { - foreach (string ucdRequiredFile in ucdRequiredFiles) + foreach (string requiredFile in requiredFiles) { - if (!File.Exists(Path.Combine(ucdDirectory, ucdRequiredFile))) + if (!File.Exists(Path.Combine(dataDirectory, requiredFile))) { hasValidDirectory = false; break; @@ -57,47 +64,47 @@ namespace System.Unicode.Builder if (hasValidDirectory) { - return new FileUcdSource(ucdDirectory); + return new FileDataSource(dataDirectory); } - if (File.Exists(ucdArchiveFileName)) + if (File.Exists(dataArchiveFileName)) { if (shouldExtract == true) { - ZipFile.ExtractToDirectory(ucdArchiveFileName, ucdDirectory); - return new FileUcdSource(ucdDirectory); + ZipFile.ExtractToDirectory(dataArchiveFileName, dataDirectory); + return new FileDataSource(dataDirectory); } else { - return new ZipUcdSource(File.OpenRead(ucdArchiveFileName)); + return new ZipDataSource(File.OpenRead(dataArchiveFileName)); } } } if (shouldDownload != false) { - var ucdArchiveData = DownloadUcdArchive(); + var dataArchiveData = DownloadDataArchive(archiveName); if (shouldSaveArchive == true) { - var stream = File.Open(ucdArchiveFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); + var stream = File.Open(dataArchiveFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); try { - stream.Write(ucdArchiveData, 0, ucdArchiveData.Length); - ucdArchiveData = null; // Release the reference now, since we won't need it anymore. + stream.Write(dataArchiveData, 0, dataArchiveData.Length); + dataArchiveData = null; // Release the reference now, since we won't need it anymore. if (shouldExtract == true) { using (var archive = new ZipArchive(stream, ZipArchiveMode.Read, false)) { - archive.ExtractToDirectory(ucdDirectory); + archive.ExtractToDirectory(dataDirectory); - return new FileUcdSource(ucdDirectory); + return new FileDataSource(dataDirectory); } } else { - return new ZipUcdSource(stream); + return new ZipDataSource(stream); } } catch @@ -108,7 +115,7 @@ namespace System.Unicode.Builder } else { - return new ZipUcdSource(new MemoryStream(ucdArchiveData)); + return new ZipDataSource(new MemoryStream(dataArchiveData)); } } @@ -119,9 +126,10 @@ namespace System.Unicode.Builder { UnicodeInfoBuilder data; - using (var ucdSource = GetUcdSource(null, null, null)) + using (var ucdSource = GetDataSource(UcdArchiveName, directoryName, ucdRequiredFiles, null, null, null)) + using (var unihanSource = GetDataSource(UnihanArchiveName, UnihanDirectoryName, unihanRequiredFiles, null, null, null)) { - data = UnicodeDataProcessor.BuildDataAsync(ucdSource).Result; + data = UnicodeDataProcessor.BuildDataAsync(ucdSource, unihanSource).Result; } using (var stream = new DeflateStream(File.Create("ucd.dat"), CompressionLevel.Optimal, false)) diff --git a/UnicodeInformation.Builder/UnicodeDataProcessor.cs b/UnicodeInformation.Builder/UnicodeDataProcessor.cs index 29858d2..93a90a9 100644 --- a/UnicodeInformation.Builder/UnicodeDataProcessor.cs +++ b/UnicodeInformation.Builder/UnicodeDataProcessor.cs @@ -27,7 +27,7 @@ namespace System.Unicode.Builder return string.IsNullOrEmpty(s) ? null : s; } - public static async Task BuildDataAsync(IUcdSource ucdSource) + public static async Task BuildDataAsync(IDataSource ucdSource, IDataSource unihanSource) { var builder = new UnicodeInfoBuilder(new Version(7, 0)); @@ -39,7 +39,7 @@ namespace System.Unicode.Builder return builder; } - private static async Task ProcessUnicodeDataFile(IUcdSource ucdSource, UnicodeInfoBuilder builder) + private static async Task ProcessUnicodeDataFile(IDataSource ucdSource, UnicodeInfoBuilder builder) { using (var reader = new UnicodeDataFileReader(await ucdSource.OpenDataFileAsync(UnicodeDataFileName).ConfigureAwait(false))) { @@ -156,7 +156,7 @@ namespace System.Unicode.Builder } } - private static async Task ProcessPropListFile(IUcdSource ucdSource, UnicodeInfoBuilder builder) + private static async Task ProcessPropListFile(IDataSource ucdSource, UnicodeInfoBuilder builder) { using (var reader = new UnicodeDataFileReader(await ucdSource.OpenDataFileAsync(PropListFileName).ConfigureAwait(false))) { @@ -173,7 +173,7 @@ namespace System.Unicode.Builder } } - private static async Task ProcessDerivedCorePropertiesFile(IUcdSource ucdSource, UnicodeInfoBuilder builder) + private static async Task ProcessDerivedCorePropertiesFile(IDataSource ucdSource, UnicodeInfoBuilder builder) { using (var reader = new UnicodeDataFileReader(await ucdSource.OpenDataFileAsync(DerivedCorePropertiesFileName).ConfigureAwait(false))) { @@ -190,7 +190,7 @@ namespace System.Unicode.Builder } } - private static async Task ProcessBlocksFile(IUcdSource ucdSource, UnicodeInfoBuilder builder) + private static async Task ProcessBlocksFile(IDataSource ucdSource, UnicodeInfoBuilder builder) { using (var reader = new UnicodeDataFileReader(await ucdSource.OpenDataFileAsync(BlocksFileName).ConfigureAwait(false))) { diff --git a/UnicodeInformation.Builder/UnicodeInformation.Builder.csproj b/UnicodeInformation.Builder/UnicodeInformation.Builder.csproj index f8b431d..1294119 100644 --- a/UnicodeInformation.Builder/UnicodeInformation.Builder.csproj +++ b/UnicodeInformation.Builder/UnicodeInformation.Builder.csproj @@ -54,16 +54,16 @@ - - - + + + - + diff --git a/UnicodeInformation.Builder/ZipUcdSource.cs b/UnicodeInformation.Builder/ZipDataSource.cs similarity index 87% rename from UnicodeInformation.Builder/ZipUcdSource.cs rename to UnicodeInformation.Builder/ZipDataSource.cs index f5faf08..3b0e0a7 100644 --- a/UnicodeInformation.Builder/ZipUcdSource.cs +++ b/UnicodeInformation.Builder/ZipDataSource.cs @@ -8,11 +8,11 @@ using System.Threading.Tasks; namespace System.Unicode.Builder { - public sealed class ZipUcdSource : IUcdSource + public sealed class ZipDataSource : IDataSource { private readonly ZipArchive archive; - public ZipUcdSource(Stream stream) + public ZipDataSource(Stream stream) { archive = new ZipArchive(stream, ZipArchiveMode.Read, false); } diff --git a/UnicodeInformation.Tests/UnicodeDataManagerTests.cs b/UnicodeInformation.Tests/UnicodeDataManagerTests.cs index 1c25bf4..42ffd99 100644 --- a/UnicodeInformation.Tests/UnicodeDataManagerTests.cs +++ b/UnicodeInformation.Tests/UnicodeDataManagerTests.cs @@ -23,12 +23,19 @@ namespace System.Unicode.Tests { Directory.CreateDirectory(directoryName); - var fileName = Path.Combine(directoryName, "UCD.zip"); + string ucdFileName = Path.Combine(directoryName, "UCD.zip"); + string unihanFileName = Path.Combine(directoryName, "Unihan.zip"); - if (!File.Exists(fileName)) + if (!File.Exists(ucdFileName)) { - new WebClient().DownloadFile("http://www.unicode.org/Public/UCD/latest/ucd/UCD.zip", fileName); - ZipFile.ExtractToDirectory(fileName, directoryName); + new WebClient().DownloadFile("http://www.unicode.org/Public/UCD/latest/ucd/UCD.zip", ucdFileName); + ZipFile.ExtractToDirectory(ucdFileName, directoryName); + } + + if (!File.Exists(unihanFileName)) + { + new WebClient().DownloadFile("http://www.unicode.org/Public/UCD/latest/ucd/Unihan.zip", unihanFileName); + ZipFile.ExtractToDirectory(unihanFileName, directoryName); } } } @@ -36,9 +43,9 @@ namespace System.Unicode.Tests [TestMethod] public async Task BuildDataAsync() { - var source = new FileUcdSource(UcdDirectoryName); + var source = new FileDataSource(UcdDirectoryName); - var data = (await UnicodeDataProcessor.BuildDataAsync(source)).ToUnicodeData(); + var data = (await UnicodeDataProcessor.BuildDataAsync(source, source)).ToUnicodeData(); Assert.AreEqual((int)'\t', data.GetCharInfo('\t').CodePoint); } @@ -46,9 +53,9 @@ namespace System.Unicode.Tests [TestMethod] public async Task BuildAndWriteDataAsync() { - var source = new FileUcdSource(UcdDirectoryName); + var source = new FileDataSource(UcdDirectoryName); - var data = await UnicodeDataProcessor.BuildDataAsync(source); + var data = await UnicodeDataProcessor.BuildDataAsync(source, source); using (var stream = new DeflateStream(File.Create("ucd.dat"), CompressionLevel.Optimal, false)) { diff --git a/UnicodeInformation/UnicodeInformation.csproj b/UnicodeInformation/UnicodeInformation.csproj index e089625..34c6758 100644 --- a/UnicodeInformation/UnicodeInformation.csproj +++ b/UnicodeInformation/UnicodeInformation.csproj @@ -76,7 +76,10 @@ + + + diff --git a/UnicodeInformation/UnihanCharacterData.cs b/UnicodeInformation/UnihanCharacterData.cs new file mode 100644 index 0000000..6a09986 --- /dev/null +++ b/UnicodeInformation/UnihanCharacterData.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Unicode +{ + internal sealed class UnihanCharacterData + { + public readonly int CodePoint; + public readonly UnihanNumericType NumericType; + public readonly ulong NumericValue; + public readonly string Definition; + public readonly string MandarinReading; + public readonly string CantoneseReading; + public readonly string JapaneseKunReading; + public readonly string JapaneseOnReading; + public readonly string KoreanReading; + public readonly string HangulReading; + public readonly string VietnameseReading; + public readonly string SimplifiedVariant; + public readonly string TraditionalVariant; + + internal static int PackCodePoint(int codePoint) + { + if (codePoint >= 0x3400) + { + if (codePoint < 0x4E00) return codePoint + 0x1E00; + else if (codePoint < 0xA000) return codePoint - 0x4E00; + else if (codePoint >= 0xF900 && codePoint < 0xFB00) return codePoint + 0xFD00; + else if (codePoint >= 0x20000) + { + if (codePoint < 0x2F800) return codePoint - 0x19400; + else if (codePoint < 0x30000) return codePoint - 0x10000; + } + } + + throw new ArgumentOutOfRangeException("codePoint"); + } + + internal static int UnpackCodePoint(int packedCodePoint) + { + if (packedCodePoint >= 0) + { + if (packedCodePoint < 0x05200) return packedCodePoint + 0x4E00; + else if (packedCodePoint < 0x06C00) return packedCodePoint - 0x1E00; + else if (packedCodePoint < 0x1F600) return packedCodePoint + 0x19400; + else if (packedCodePoint < 0x1F800) return packedCodePoint - 0xFD00; + else if (packedCodePoint < 0x20000) return packedCodePoint + 0x10000; + } + throw new ArgumentOutOfRangeException("packedCodePoint"); + } + } +} diff --git a/UnicodeInformation/UnihanFields.cs b/UnicodeInformation/UnihanFields.cs new file mode 100644 index 0000000..2d52757 --- /dev/null +++ b/UnicodeInformation/UnihanFields.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Unicode +{ + [Flags] + internal enum UnihanFields : ushort + { + // NumericType / NumericValue : Not exactly a bit mask here… + AccountingNumeric = 1, + OtherNumeric = 2, + PrimaryNumeric = 3, + + Definition = 4, + MandarinReading = 8, + CantoneseReading = 16, + JapaneseKunReading = 32, + JapaneseOnReading = 64, + KoreanReading = 128, + HangulReading = 256, + VietnameseReading = 512, + + SimplifiedVariant = 1024, + TraditionalVariant = 2048, + } +} diff --git a/UnicodeInformation/UnihanNumericType.cs b/UnicodeInformation/UnihanNumericType.cs new file mode 100644 index 0000000..01db806 --- /dev/null +++ b/UnicodeInformation/UnihanNumericType.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Unicode +{ + /// Represents the different numeric types from the Unihan database. + public enum UnihanNumericType : byte + { + None = 0, + [ValueName("kAccountingNumeric")] + Accounting = 1, + [ValueName("kOtherNumeric")] + Other = 2, + [ValueName("kPrimaryNumeric")] + Primary = 3 + } +}