/* * Copyright (C) 2013 FooProject * * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ //#define TEST_ASYNC using System; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; namespace FooEditEngine { /// /// Documentの拡張クラス /// public static class DocumentExtend { static Progress _Progress = new Progress(); /// /// 進捗処理を表す /// public static event EventHandler Progress { add { _Progress.ProgressChanged += value; } remove { _Progress.ProgressChanged -= value; } } #if !METRO /// /// ファイルからドキュメントを構築します /// /// Documentオブジェクト /// 読み取り先のファイル /// エンコーディング /// /// 非同期操作中はこのメソッドを実行することはできません。 /// public static void Load(this Document doc, string filepath, Encoding enc) { if (doc.State != AsyncState.None) throw new InvalidOperationException(); using (StreamReader sr = new StreamReader(filepath, enc)) { Load(doc,sr); } } /// /// ファイルからドキュメントを非同期的に構築します /// /// Documentオブジェクト /// 読み取り先のファイル /// エンコーディング /// キャンセル用のトークン /// /// 読み取り操作は別スレッドで行われます。 /// また、非同期操作中にこのメソッドを読みだすことはできません /// public static async Task LoadAsync(this Document doc, string filepath, Encoding enc, CancellationTokenSource token) { if (doc.State != AsyncState.None) throw new InvalidOperationException(); using (StreamReader sr = new StreamReader(filepath, enc)) { await LoadAsync(doc,sr, token); } } #endif /// /// ストリームからドキュメントを構築します /// /// Documentオブジェクト /// 読み取り先のストリーム /// /// 非同期操作中はこのメソッドを実行することはできません /// public static void Load(this Document doc, TextReader sr) { Task t = LoadAsync(doc,sr, null); t.Wait(); } /// /// ストリームからドキュメントを非同期的に構築します /// /// Documentオブジェクト /// 読み取り先のストリーム /// キャンセルトークン /// Taskオブジェクト /// /// 読み取り操作は別スレッドで行われます。 /// また、非同期操作中はこのメソッドを実行することはできません。 /// public static async Task LoadAsync(this Document doc, TextReader sr, CancellationTokenSource tokenSource = null) { if (doc.State != AsyncState.None) throw new InvalidOperationException(); if (sr.Peek() == -1) { return; } IProgress progress = _Progress; try { progress.Report(new ProgressEventArgs(ProgressState.Start)); doc.StringBuffer.Clear(); doc.State = AsyncState.Loading; doc.FireUpdateEvent = false; doc.UndoManager.BeginLock(); string str; for (int i = 0; (str = await sr.ReadLineAsync().ConfigureAwait(false)) != null; i++) { int index = doc.StringBuffer.Length; if (index < 0) index = 0; doc.StringBuffer.Replace(index, 0, Util.GetEnumrator(str + Document.NewLine),str.Length + 1); if (tokenSource != null) tokenSource.Token.ThrowIfCancellationRequested(); #if TEST_ASYNC System.Threading.Thread.Sleep(10); #endif } } finally { doc.FireUpdateEvent = true; doc.UndoManager.EndLock(); doc.State = AsyncState.None; progress.Report(new ProgressEventArgs(ProgressState.Complete)); } } #if !METRO /// /// ドキュメントをファイルに保存します /// /// Documentオブジェクト /// 保存先のファイル /// 保存したいエンコード /// 改行を表す文字列 /// 非同期操作中はこのメソッドを実行することはできません public static void Save(this Document doc, string filepath, Encoding enc, string newline) { if (doc.State != AsyncState.None) throw new InvalidOperationException(); using (StreamWriter sw = new StreamWriter(filepath, false, enc)) { sw.NewLine = newline; Save(doc,sw); } } /// /// ドキュメントをファイルに保存します /// /// Documentオブジェクト /// 保存先のファイル /// 保存したいエンコード /// 改行を表す文字列 /// CancellationTokenSourceオブジェクト /// 非同期操作中はこのメソッドを実行することはできません public static async Task SaveAsync(this Document doc, string filepath, Encoding enc, string newline,CancellationTokenSource token) { if (doc.State != AsyncState.None) throw new InvalidOperationException(); using (StreamWriter sw = new StreamWriter(filepath, false, enc)) { sw.NewLine = newline; await SaveAsync(doc,sw, token); } } #endif /// /// ストリームに保存します /// /// Documentオブジェクト /// 保存先のストリーム /// Taskオブジェクト /// 非同期操作中はこのメソッドを実行することはできません public static void Save(this Document doc, StreamWriter sw) { Task t = SaveAsync(doc,sw, null); t.Wait(); } /// /// ストリームに非同期モードで保存します /// /// Documentオブジェクト /// 保存先のストリーム /// キャンセルトークン /// Taskオブジェクト /// 非同期操作中はこのメソッドを実行することはできません public static async Task SaveAsync(this Document doc,StreamWriter sw, CancellationTokenSource tokenSource = null) { if (doc.State != AsyncState.None) throw new InvalidOperationException(); IProgress progress = _Progress; try { progress.Report(new ProgressEventArgs(ProgressState.Start)); doc.State = AsyncState.Saving; StringBuilder line = new StringBuilder(); for (int i = 0; i < doc.Length; i++) { char c = doc[i]; line.Append(c); if (c == Document.NewLine || i == doc.Length - 1) { string str = line.ToString(); str = str.Replace(Document.NewLine.ToString(), sw.NewLine); await sw.WriteAsync(str).ConfigureAwait(false); line.Clear(); if (tokenSource != null) tokenSource.Token.ThrowIfCancellationRequested(); #if TEST_ASYNC System.Threading.Thread.Sleep(10); #endif } } } finally { doc.State = AsyncState.None; progress.Report(new ProgressEventArgs(ProgressState.Complete)); } } } }