/*
* 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));
}
}
}
}