using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace System.Unicode.Builder { internal class Program { public const string UnihanDirectoryName = "Unihan"; public const string UnihanArchiveName = "Unihan.zip"; public const string UcdDirectoryName = "UCD"; public const string UcdArchiveName = "UCD.zip"; public static readonly string[] ucdRequiredFiles = new[] { "UnicodeData.txt", "PropList.txt", "DerivedCoreProperties.txt", "CJKRadicals.txt", //"Jamo.txt", // Not used right now, as the hangul syllable algorithm implementation takes care of this. "NameAliases.txt", "NamesList.txt", "Blocks.txt", }; public static readonly string[] unihanRequiredFiles = new[] { "Unihan_NumericValues.txt", "Unihan_Readings.txt", "Unihan_Variants.txt", "Unihan_IRGSources.txt", }; private static HttpClient httpClient; // The only purpose of this is for tests… internal static void SetHttpMessageHandler(HttpMessageHandler handler) { httpClient = new HttpClient(handler ?? new HttpClientHandler()); } private static HttpClient HttpClient { get { return httpClient ?? (httpClient = new HttpClient()); } } private static byte[] DownloadDataArchive(string archiveName) { return HttpClient.GetByteArrayAsync(HttpDataSource.UnicodeCharacterDataUri + archiveName).Result; } internal static IDataSource GetDataSource(string archiveName, string directoryName, string[] requiredFiles, bool? shouldDownload, bool? shouldSaveArchive, bool? shouldExtract) { string baseDirectory = Environment.CurrentDirectory; string dataDirectory = Path.Combine(baseDirectory, UcdDirectoryName); string dataArchiveFileName = Path.Combine(baseDirectory, archiveName); if (shouldDownload != true) { bool hasValidDirectory = Directory.Exists(dataDirectory); if (hasValidDirectory) { foreach (string requiredFile in requiredFiles) { if (!File.Exists(Path.Combine(dataDirectory, requiredFile))) { hasValidDirectory = false; break; } } } if (hasValidDirectory) { return new FileDataSource(dataDirectory); } if (File.Exists(dataArchiveFileName)) { if (shouldExtract == true) { ZipFile.ExtractToDirectory(dataArchiveFileName, dataDirectory); return new FileDataSource(dataDirectory); } else { return new ZipDataSource(File.OpenRead(dataArchiveFileName)); } } } if (shouldDownload != false) { var dataArchiveData = DownloadDataArchive(archiveName); if (shouldSaveArchive == true) { var stream = File.Open(dataArchiveFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); try { 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(dataDirectory); return new FileDataSource(dataDirectory); } } else { return new ZipDataSource(stream); } } catch { stream.Dispose(); throw; } } else { return new ZipDataSource(new MemoryStream(dataArchiveData)); } } throw new InvalidOperationException(); } private static void Main(string[] args) { UnicodeInfoBuilder data; using (var ucdSource = GetDataSource(UcdArchiveName, UcdDirectoryName, ucdRequiredFiles, null, null, null)) using (var unihanSource = GetDataSource(UnihanArchiveName, UnihanDirectoryName, unihanRequiredFiles, null, null, null)) { data = UnicodeDataProcessor.BuildDataAsync(ucdSource, unihanSource).Result; } using (var stream = new DeflateStream(File.Create("ucd.dat"), CompressionLevel.Optimal, false)) data.WriteToStream(stream); } } }