OSDN Git Service

Document.Stateプロパティを廃止した
[fooeditengine/FooEditEngine.git] / Common / Document.cs
1 /*\r
2  * Copyright (C) 2013 FooProject\r
3  * * 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\r
4  * the Free Software Foundation; either version 3 of the License, or (at your option) any later version.\r
5 \r
6  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of \r
7  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
8 \r
9 You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.\r
10  */\r
11 \r
12 using System;\r
13 using System.IO;\r
14 using System.Collections.Generic;\r
15 using System.Text;\r
16 using System.Text.RegularExpressions;\r
17 using System.Threading;\r
18 using System.Threading.Tasks;\r
19 using System.Linq;\r
20 \r
21 namespace FooEditEngine\r
22 {\r
23     /// <summary>\r
24     /// 進行状況を表す列挙体\r
25     /// </summary>\r
26     public enum ProgressState\r
27     {\r
28         /// <summary>\r
29         /// 操作が開始したことを表す\r
30         /// </summary>\r
31         Start,\r
32         /// <summary>\r
33         /// 操作が終了したことを表す\r
34         /// </summary>\r
35         Complete,\r
36     }\r
37     /// <summary>\r
38     /// 進行状況を表すためのイベントデータ\r
39     /// </summary>\r
40     public sealed class ProgressEventArgs : EventArgs\r
41     {\r
42         /// <summary>\r
43         /// 進行状況\r
44         /// </summary>\r
45         public ProgressState state;\r
46         /// <summary>\r
47         /// コンストラクター\r
48         /// </summary>\r
49         /// <param name="state">ProgressStateオブジェクト</param>\r
50         public ProgressEventArgs(ProgressState state)\r
51         {\r
52             this.state = state;\r
53         }\r
54     }\r
55 \r
56     /// <summary>\r
57     /// 進行状況を通知するためのデリゲート\r
58     /// </summary>\r
59     /// <param name="sender">送信元クラス</param>\r
60     /// <param name="e">イベントデータ</param>\r
61     public delegate void ProgressEventHandler(object sender, ProgressEventArgs e);\r
62 \r
63     /// <summary>\r
64     /// 更新タイプを表す列挙体\r
65     /// </summary>\r
66     public enum UpdateType\r
67     {\r
68         /// <summary>\r
69         /// ドキュメントが置き換えられたことを表す\r
70         /// </summary>\r
71         Replace,\r
72         /// <summary>\r
73         /// ドキュメント全体が削除されたことを表す\r
74         /// </summary>\r
75         Clear,\r
76     }\r
77 \r
78     /// <summary>\r
79     /// 更新タイプを通知するためのイベントデータ\r
80     /// </summary>\r
81     public sealed class DocumentUpdateEventArgs : EventArgs\r
82     {\r
83         /// <summary>\r
84         /// 更新タイプ\r
85         /// </summary>\r
86         public UpdateType type;\r
87         /// <summary>\r
88         /// 開始位置\r
89         /// </summary>\r
90         public int startIndex;\r
91         /// <summary>\r
92         /// 削除された長さ\r
93         /// </summary>\r
94         public int removeLength;\r
95         /// <summary>\r
96         /// 追加された長さ\r
97         /// </summary>\r
98         public int insertLength;\r
99         /// <summary>\r
100         /// コンストラクター\r
101         /// </summary>\r
102         /// <param name="type">更新タイプ</param>\r
103         /// <param name="startIndex">開始インデックス</param>\r
104         /// <param name="removeLength">削除された長さ</param>\r
105         /// <param name="insertLength">追加された長さ</param>\r
106         public DocumentUpdateEventArgs(UpdateType type, int startIndex, int removeLength, int insertLength)\r
107         {\r
108             this.type = type;\r
109             this.startIndex = startIndex;\r
110             this.removeLength = removeLength;\r
111             this.insertLength = insertLength;\r
112         }\r
113     }\r
114 \r
115     /// <summary>\r
116     /// ドキュメントに更新があったことを伝えるためのデリゲート\r
117     /// </summary>\r
118     /// <param name="sender">送信元クラス</param>\r
119     /// <param name="e">イベントデータ</param>\r
120     public delegate void DocumentUpdateEventHandler(object sender, DocumentUpdateEventArgs e);\r
121 \r
122     /// <summary>\r
123     /// ドキュメントの管理を行う\r
124     /// </summary>\r
125     /// <remarks>この型のすべてのメソッド・プロパティはスレッドセーフです</remarks>\r
126     public sealed class Document : IEnumerable<char>, IRandomEnumrator<char>\r
127     {\r
128         const int ProgressNotifyCount = 100;\r
129         Regex regex;\r
130         Match match;\r
131         StringBuffer buffer;\r
132         bool _EnableFireUpdateEvent = true;\r
133 \r
134         /// <summary>\r
135         /// コンストラクター\r
136         /// </summary>\r
137         public Document()\r
138             : this(null)\r
139         {\r
140         }\r
141 \r
142         internal Document(Document doc)\r
143         {\r
144             if (doc == null)\r
145                 this.buffer = new StringBuffer();\r
146             else\r
147                 this.buffer = new StringBuffer(doc.buffer);\r
148             this.buffer.Update += new DocumentUpdateEventHandler(buffer_Update);\r
149             this.UpdateCalledAlways += (s, e) => { };\r
150             this.Update += new DocumentUpdateEventHandler((s, e) => { });\r
151             this.ChangeFireUpdateEvent += new EventHandler((s, e) => { });\r
152             this.Markers = new MarkerCollection(this);\r
153             this.UndoManager = new UndoManager();\r
154         }\r
155 \r
156         /// <summary>\r
157         /// ドキュメントが更新された時に呼ばれるイベント\r
158         /// </summary>\r
159         public event DocumentUpdateEventHandler Update;\r
160 \r
161         /// <summary>\r
162         /// ドキュメントが更新された時に呼びされるイベント\r
163         /// </summary>\r
164         /// <remarks>\r
165         /// FireUpdateEventの値に関わらず常に呼びされます\r
166         /// </remarks>\r
167         internal event DocumentUpdateEventHandler UpdateCalledAlways;\r
168 \r
169         /// <summary>\r
170         /// FireUpdateEventの値が変わったときに呼び出されるイベント\r
171         /// </summary>\r
172         public event EventHandler ChangeFireUpdateEvent;\r
173 \r
174         /// <summary>\r
175         /// 改行コードの内部表現\r
176         /// </summary>\r
177         public const char NewLine = '\n';\r
178 \r
179         /// <summary>\r
180         /// EOFの内部表現\r
181         /// </summary>\r
182         public const char EndOfFile = '\u001a';\r
183 \r
184         /// <summary>\r
185         /// アンドゥ管理クラスを表す\r
186         /// </summary>\r
187         public UndoManager UndoManager\r
188         {\r
189             get;\r
190             private set;\r
191         }\r
192 \r
193         /// <summary>\r
194         /// 文字列の長さ\r
195         /// </summary>\r
196         public int Length\r
197         {\r
198             get\r
199             {\r
200                 return this.buffer.Length;\r
201             }\r
202         }\r
203 \r
204         /// <summary>\r
205         /// 変更のたびにUpdateイベントを発生させるかどうか\r
206         /// </summary>\r
207         public bool FireUpdateEvent\r
208         {\r
209             get\r
210             {\r
211                 return this._EnableFireUpdateEvent;\r
212             }\r
213             set\r
214             {\r
215                 this._EnableFireUpdateEvent = value;\r
216                 this.ChangeFireUpdateEvent(this, null);\r
217             }\r
218         }\r
219 \r
220         /// <summary>\r
221         /// インデクサー\r
222         /// </summary>\r
223         /// <param name="i">インデックス(自然数でなければならない)</param>\r
224         /// <returns>Char型</returns>\r
225         public char this[int i]\r
226         {\r
227             get\r
228             {\r
229                 return this.buffer[i];\r
230             }\r
231         }\r
232 \r
233         /// <summary>\r
234         /// マーカーコレクション\r
235         /// </summary>\r
236         public MarkerCollection Markers\r
237         {\r
238             get;\r
239             private set;\r
240         }\r
241 \r
242         internal StringBuffer StringBuffer\r
243         {\r
244             get\r
245             {\r
246                 return this.buffer;\r
247             }\r
248         }\r
249 \r
250         /// <summary>\r
251         /// DocumentReaderを作成します\r
252         /// </summary>\r
253         /// <returns>DocumentReaderオブジェクト</returns>\r
254         public DocumentReader CreateReader()\r
255         {\r
256             return new DocumentReader(this.buffer);\r
257         }\r
258 \r
259         /// <summary>\r
260         /// マーカーを設定する\r
261         /// </summary>\r
262         /// <param name="id">マーカーID</param>\r
263         /// <param name="m">設定したいマーカー</param>\r
264         public void SetMarker(int id,Marker m)\r
265         {\r
266             if (m.start < 0 || m.start + m.length > this.Length)\r
267                 throw new ArgumentOutOfRangeException("startもしくはendが指定できる範囲を超えています");\r
268 \r
269             this.Markers.Add(id,m);\r
270         }\r
271 \r
272         /// <summary>\r
273         /// マーカーを削除する\r
274         /// </summary>\r
275         /// <param name="id">マーカーID</param>\r
276         /// <param name="start">開始インデックス</param>\r
277         /// <param name="length">削除する長さ</param>\r
278         public void RemoveMarker(int id,int start, int length)\r
279         {\r
280             if (start < 0 || start + length > this.Length)\r
281                 throw new ArgumentOutOfRangeException("startもしくはendが指定できる範囲を超えています");\r
282 \r
283             this.Markers.RemoveAll(id,start, length);\r
284         }\r
285 \r
286         /// <summary>\r
287         /// マーカーを削除する\r
288         /// </summary>\r
289         /// <param name="id">マーカーID</param>\r
290         /// <param name="type">削除したいマーカーのタイプ</param>\r
291         public void RemoveMarker(int id, HilightType type)\r
292         {\r
293             this.Markers.RemoveAll(id,type);\r
294         }\r
295 \r
296         /// <summary>\r
297         /// インデックスに対応するマーカーを得る\r
298         /// </summary>\r
299         /// <param name="id">マーカーID</param>\r
300         /// <param name="index">インデックス</param>\r
301         /// <returns>Marker構造体の列挙子</returns>\r
302         public IEnumerable<Marker> GetMarkers(int id, int index)\r
303         {\r
304             if (index < 0 || index > this.Length)\r
305                 throw new ArgumentOutOfRangeException("indexが範囲を超えています");\r
306             return this.Markers.Get(id,index);\r
307         }\r
308 \r
309         /// <summary>\r
310         /// 部分文字列を取得する\r
311         /// </summary>\r
312         /// <param name="index">開始インデックス</param>\r
313         /// <param name="length">長さ</param>\r
314         /// <returns>Stringオブジェクト</returns>\r
315         public string ToString(int index, int length)\r
316         {\r
317             return this.buffer.ToString(index, length);\r
318         }\r
319 \r
320         /// <summary>\r
321         /// インデックスを開始位置とする文字列を返す\r
322         /// </summary>\r
323         /// <param name="index">開始インデックス</param>\r
324         /// <returns>Stringオブジェクト</returns>\r
325         public string ToString(int index)\r
326         {\r
327             return this.ToString(index, this.buffer.Length - index);\r
328         }\r
329 \r
330         /// <summary>\r
331         /// 行を取得する\r
332         /// </summary>\r
333         /// <param name="startIndex">開始インデックス</param>\r
334         /// <param name="endIndex">終了インデックス</param>\r
335         /// <param name="maxCharCount">最大長</param>\r
336         /// <returns>行イテレーターが返される</returns>\r
337         public IEnumerable<string> GetLines(int startIndex, int endIndex, int maxCharCount = -1)\r
338         {\r
339             return this.buffer.GetLines(startIndex, endIndex, maxCharCount);\r
340         }\r
341 \r
342         internal IEnumerable<Tuple<int, int>> ForEachLines(int startIndex, int endIndex, int maxCharCount = -1)\r
343         {\r
344             return this.buffer.ForEachLines(startIndex, endIndex, maxCharCount);\r
345         }\r
346 \r
347 \r
348         /// <summary>\r
349         /// 文字列を追加する\r
350         /// </summary>\r
351         /// <param name="s">追加したい文字列</param>\r
352         /// <remarks>非同期操作中はこのメソッドを実行することはできません</remarks>\r
353         public void Append(string s)\r
354         {\r
355             this.Replace(this.buffer.Length, 0, s);\r
356         }\r
357 \r
358         /// <summary>\r
359         /// 文字列を挿入する\r
360         /// </summary>\r
361         /// <param name="index">開始インデックス</param>\r
362         /// <param name="s">追加したい文字列</param>\r
363         /// <remarks>読み出し操作中はこのメソッドを実行することはできません</remarks>\r
364         public void Insert(int index, string s)\r
365         {\r
366             this.Replace(index, 0, s);\r
367         }\r
368 \r
369         /// <summary>\r
370         /// 文字列を削除する\r
371         /// </summary>\r
372         /// <param name="index">開始インデックス</param>\r
373         /// <param name="length">長さ</param>\r
374         /// <remarks>読み出し操作中はこのメソッドを実行することはできません</remarks>\r
375         public void Remove(int index, int length)\r
376         {\r
377             this.Replace(index, length, "");\r
378         }\r
379 \r
380         /// <summary>\r
381         /// ドキュメントを置き換える\r
382         /// </summary>\r
383         /// <param name="index">開始インデックス</param>\r
384         /// <param name="length">長さ</param>\r
385         /// <param name="s">文字列</param>\r
386         /// <remarks>読み出し操作中はこのメソッドを実行することはできません</remarks>\r
387         public void Replace(int index, int length, string s)\r
388         {\r
389             if (index < 0 || index > this.buffer.Length || index + length > this.buffer.Length || length < 0)\r
390                 throw new ArgumentOutOfRangeException();\r
391             if (length == 0 && (s == string.Empty || s == null))\r
392                 return;\r
393 \r
394             foreach(int id in this.Markers.IDs)\r
395                 this.RemoveMarker(id,index, length);\r
396 \r
397             ReplaceCommand cmd = new ReplaceCommand(this.buffer, index, length, s);\r
398             this.UndoManager.push(cmd);\r
399             cmd.redo();\r
400         }\r
401 \r
402         /// <summary>\r
403         /// 物理行をすべて削除する\r
404         /// </summary>\r
405         /// <remarks>Dirtyフラグも同時にクリアーされます</remarks>\r
406         /// <remarks>非同期操作中はこのメソッドを実行することはできません</remarks>\r
407         public void Clear()\r
408         {\r
409             this.buffer.Clear();\r
410         }\r
411 \r
412         /// <summary>\r
413         /// Find()およびReplaceAll()で使用するパラメーターをセットします\r
414         /// </summary>\r
415         /// <param name="pattern">検索したい文字列</param>\r
416         /// <param name="UseRegex">正規表現を使用するなら真</param>\r
417         /// <param name="opt">RegexOptions列挙体</param>\r
418         public void SetFindParam(string pattern, bool UseRegex, RegexOptions opt)\r
419         {\r
420             this.match = null;\r
421             if (UseRegex)\r
422                 this.regex = new Regex(pattern, opt);\r
423             else\r
424                 this.regex = new Regex(Regex.Escape(pattern), opt);\r
425         }\r
426 \r
427         /// <summary>\r
428         /// 現在の検索パラメーターでWatchDogを生成する\r
429         /// </summary>\r
430         /// <param name="type">ハイライトタイプ</param>\r
431         /// <param name="color">色</param>\r
432         /// <returns>WatchDogオブジェクト</returns>\r
433         public RegexMarkerPattern CreateWatchDogByFindParam(HilightType type,Color color)\r
434         {\r
435             if (this.regex == null)\r
436                 throw new InvalidOperationException("SetFindParam()を呼び出してください");\r
437             return new RegexMarkerPattern(this.regex,type,color);\r
438         }\r
439 \r
440         /// <summary>\r
441         /// 指定した文字列を検索します\r
442         /// </summary>\r
443         /// <returns>見つかった場合はSearchResult列挙子を返却します</returns>\r
444         /// <remarks>見つかったパターン以外を置き換えた場合、正常に動作しないことがあります</remarks>\r
445         public IEnumerator<SearchResult> Find()\r
446         {\r
447             return this.Find(0, this.Length);\r
448         }\r
449 \r
450         /// <summary>\r
451         /// 指定した文字列を検索します\r
452         /// </summary>\r
453         /// <returns>見つかった場合はSearchResult列挙子を返却します</returns>\r
454         /// <param name="start">開始インデックス</param>\r
455         /// <param name="length">検索する長さ</param>\r
456         /// <remarks>見つかったパターン以外を置き換えた場合、正常に動作しないことがあります</remarks>\r
457         public IEnumerator<SearchResult> Find(int start, int length)\r
458         {\r
459             if (this.regex == null)\r
460                 throw new InvalidOperationException();\r
461             if (start < 0 || start >= this.Length)\r
462                 throw new ArgumentOutOfRangeException();\r
463 \r
464             int end = start + length - 1;\r
465 \r
466             if(end > this.Length - 1)\r
467                 throw new ArgumentOutOfRangeException();\r
468 \r
469             StringBuilder line = new StringBuilder();\r
470             int oldLength = this.Length;\r
471             for (int i = start; i <= end; i++)\r
472             {\r
473                 char c = this[i];\r
474                 line.Append(c);\r
475                 if (c == Document.NewLine || i == end)\r
476                 {\r
477                     this.match = this.regex.Match(line.ToString());\r
478                     while (this.match.Success)\r
479                     {\r
480                         int startIndex = i - line.Length + 1 + this.match.Index;\r
481                         int endIndex = startIndex + this.match.Length - 1;\r
482 \r
483                         yield return new SearchResult(this.match, startIndex, endIndex);\r
484 \r
485                         if (this.Length != oldLength)   //長さが変わった場合は置き換え後のパターンの終点+1まで戻る\r
486                         {\r
487                             int delta = this.Length - oldLength;\r
488                             i = endIndex + delta;\r
489                             end = end + delta;\r
490                             oldLength = this.Length;\r
491                             break;\r
492                         }\r
493 \r
494                         this.match = this.match.NextMatch();\r
495                     }\r
496                     line.Clear();\r
497                 }\r
498             }\r
499         }\r
500 \r
501         /// <summary>\r
502         /// 任意のパターンですべて置き換えます\r
503         /// </summary>\r
504         /// <param name="replacePattern">置き換え後のパターン</param>\r
505         /// <param name="groupReplace">グループ置き換えを行うなら真。そうでないなら偽</param>\r
506         public void ReplaceAll(string replacePattern,bool groupReplace)\r
507         {\r
508             if (this.regex == null)\r
509                 throw new InvalidOperationException();\r
510             ReplaceAllCommand cmd = new ReplaceAllCommand(this.buffer, this.regex, replacePattern, groupReplace);\r
511             this.UndoManager.push(cmd);\r
512             cmd.redo();\r
513         }\r
514 \r
515         /// <summary>\r
516         /// 任意のパターンで置き換える\r
517         /// </summary>\r
518         /// <param name="target">対象となる文字列</param>\r
519         /// <param name="pattern">置き換え後の文字列</param>\r
520         /// <param name="ci">大文字も文字を区別しないなら真。そうでないなら偽</param>\r
521         /// <remarks>\r
522         /// 検索時に大文字小文字を区別します。また、このメソッドでは正規表現を使用することはできません\r
523         /// </remarks>\r
524         public void ReplaceAll2(string target, string pattern,bool ci = false)\r
525         {\r
526             FastReplaceAllCommand cmd = new FastReplaceAllCommand(this.buffer, target, pattern,ci);\r
527             this.UndoManager.push(cmd);\r
528             cmd.redo();\r
529         }\r
530 \r
531         #region IEnumerable<char> メンバー\r
532 \r
533         /// <summary>\r
534         /// 列挙子を返します\r
535         /// </summary>\r
536         /// <returns>IEnumeratorオブジェクトを返す</returns>\r
537         public IEnumerator<char> GetEnumerator()\r
538         {\r
539             return this.buffer.GetEnumerator();\r
540         }\r
541 \r
542         #endregion\r
543 \r
544         #region IEnumerable メンバー\r
545 \r
546         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
547         {\r
548             throw new NotImplementedException();\r
549         }\r
550 \r
551         #endregion\r
552 \r
553         void buffer_Update(object sender, DocumentUpdateEventArgs e)\r
554         {\r
555             this.UpdateCalledAlways(this, e);\r
556             if(this.FireUpdateEvent)\r
557                 this.Update(this, e);\r
558         }\r
559     }\r
560 \r
561     /// <summary>\r
562     /// 検索結果を表す\r
563     /// </summary>\r
564     public class SearchResult\r
565     {\r
566         private Match Match;\r
567 \r
568         /// <summary>\r
569         /// 一致した場所の開始位置を表す\r
570         /// </summary>\r
571         public int Start;\r
572 \r
573         /// <summary>\r
574         /// 一致した場所の終了位置を表す\r
575         /// </summary>\r
576         public int End;\r
577 \r
578         /// <summary>\r
579         /// 見つかった文字列を返す\r
580         /// </summary>\r
581         public string Value\r
582         {\r
583             get { return this.Match.Value; }\r
584         }\r
585 \r
586         /// <summary>\r
587         /// 指定したパターンを置き換えて返す\r
588         /// </summary>\r
589         /// <param name="replacement">置き換える文字列</param>\r
590         /// <returns>置き換え後の文字列</returns>\r
591         public string Result(string replacement)\r
592         {\r
593             return this.Match.Result(replacement);\r
594         }\r
595 \r
596         /// <summary>\r
597         /// コンストラクター\r
598         /// </summary>\r
599         /// <param name="m">Matchオブジェクト</param>\r
600         /// <param name="start">開始インデックス</param>\r
601         /// <param name="end">終了インデックス</param>\r
602         public SearchResult(Match m, int start,int end)\r
603         {\r
604             this.Match = m;\r
605             this.Start = start;\r
606             this.End = end;\r
607         }\r
608     }\r
609 \r
610     /// <summary>\r
611     /// ドキュメントリーダー\r
612     /// </summary>\r
613     public class DocumentReader : TextReader\r
614     {\r
615         StringBuffer document;      \r
616         int currentIndex;\r
617 \r
618         /// <summary>\r
619         /// コンストラクター\r
620         /// </summary>\r
621         /// <param name="doc"></param>\r
622         internal DocumentReader(StringBuffer doc)\r
623         {\r
624             if (doc == null)\r
625                 throw new ArgumentNullException();\r
626             this.document = doc;\r
627         }\r
628 \r
629         /// <summary>\r
630         /// 文字を取得する\r
631         /// </summary>\r
632         /// <returns>文字。取得できない場合は-1</returns>\r
633         public override int Peek()\r
634         {\r
635             if (this.document == null)\r
636                 throw new InvalidOperationException();\r
637             if (this.currentIndex >= this.document.Length)\r
638                 return -1;\r
639             return this.document[this.currentIndex];\r
640         }\r
641 \r
642         /// <summary>\r
643         /// 文字を取得し、イテレーターを一つ進める\r
644         /// </summary>\r
645         /// <returns>文字。取得できない場合は-1</returns>\r
646         public override int Read()\r
647         {\r
648             int c = this.Peek();\r
649             if(c != -1)\r
650                 this.currentIndex++;\r
651             return c;\r
652         }\r
653 \r
654         /// <summary>\r
655         /// 文字列を読み取りバッファーに書き込む\r
656         /// </summary>\r
657         /// <param name="buffer">バッファー</param>\r
658         /// <param name="index">開始インデックス</param>\r
659         /// <param name="count">カウント</param>\r
660         /// <returns>読み取られた文字数</returns>\r
661         public override int Read(char[] buffer, int index, int count)\r
662         {\r
663             if (this.document == null)\r
664                 throw new InvalidOperationException();\r
665 \r
666             if (buffer == null)\r
667                 throw new ArgumentNullException();\r
668 \r
669             if (this.document.Length < count)\r
670                 throw new ArgumentException();\r
671 \r
672             if (index < 0 || count < 0)\r
673                 throw new ArgumentOutOfRangeException();\r
674 \r
675             if (this.document.Length == 0)\r
676                 return 0;\r
677 \r
678             int actualCount = count;\r
679             if (index + count - 1 > this.document.Length - 1)\r
680                 actualCount = this.document.Length - index;\r
681 \r
682             string str = this.document.ToString(index, actualCount);\r
683 \r
684             for (int i = 0; i < str.Length; i++)    //ToCharArray()だと戻った時に消えてしまう\r
685                 buffer[i] = str[i];\r
686 \r
687             this.currentIndex = index + actualCount;\r
688             \r
689             return actualCount;\r
690         }\r
691 \r
692         /// <summary>\r
693         /// オブジェクトを破棄する\r
694         /// </summary>\r
695         /// <param name="disposing">真ならアンマネージドリソースを解放する</param>\r
696         protected override void Dispose(bool disposing)\r
697         {\r
698             this.document = null;\r
699         }\r
700     }\r
701 }\r