優れたテキスト エディターは、プログラマーが行う可能性のあるあらゆる種類の作業に役立つはずです。これには、サイズが数ギガバイトになる場合があるファイルを開くことも含まれます。したがって、すべてを RAM にバッファリングするという考え方はお勧めしません。
ファイルを表すスライスの検索ツリーを設定することをお勧めします。ここで、単一のスライスは次のようになります。
- ディスク上の実際のファイルのバイト範囲への参照、または
- 編集された「ページ」への参照。
ファイルを開くときは、単一の項目をツリーに挿入することから始めます。これは、ファイル全体を表す単純な範囲です (たとえば、10 MiB ファイルの場合)。
std::map<size_t, slice_info> slices;
slices[0].size = 10*1024*1024;
ユーザーがファイルを編集するとき、編集ポイントの周りに適切なサイズ (たとえば 4 KiB) の「ページ」を作成します。木はその時点で接合されます。この例では、編集ポイントは 5 MiB にあります。
size_t const PAGE_SIZE = 4*1024;
slices[0].size = 5*1024*1024;
slices[5*1024*1024].size = PAGE_SIZE;
slices[5*1024*1024].buffer = create_buffer(file, 5*1024*1024, PAGE_SIZE);
slices[5*1024*1024 + PAGE_SIZE].size = 5*1024*1024 - PAGE_SIZE
メモリ マップト ファイルは、読み取り専用バッファ (ソース ファイル) とコピーされた編集可能バッファ (後者は一時ディレクトリに配置されます) の両方に使用できます。これにより、エディターがクラッシュした場合の回復も可能になります。
固定サイズのページを使用すると、すべてのブロックが同じサイズになるため、メモリ ヒープの断片化が大幅に減少し、テキストを挿入するために 4 KiB を超えるデータを事前に移動する必要はありません。
これは、多くの細かい詳細に入ることなく、一般的なアイデアを提供するための簡略化された説明です。実際の実装では、おそらくより洗練されたものにする必要があります。たとえば、オーバーフローするページに対処するためにページ内の可変量のデータを許可し、大きなファイル全体で正規表現置換を実行しても作成されないように、多くの小さなスライスをマージします。多くの小さなバッファ。ツリーに同時に保持する必要があるスライスの数にはおそらく制限が必要ですが、重要な点は、どこかに挿入を開始するときは、大きすぎないスライスで作業していることを確認する必要があるということです。
正規表現の場合、実行中にエディター全体がハングしない限り、パフォーマンスはそれほど問題ではないと思います。Boost.Regexを試してみてください。おそらくニーズに十分に対応できる速度であり、必要なバッファリング戦略をプラグインするのに十分な汎用性もあります。
構文の強調表示にも同じことが当てはまります。バックグラウンドで実行すると、ユーザーが入力しているときにそれほど邪魔になりません。ここでは、スライス アプローチを使用して利益を得ることができます。
- 各スライスは、編集操作中にロックできるミューテックスを持つことができ、構文の強調表示または「インテリセンス」型分析をバックグラウンド スレッドで実行できます。
- 構文強調表示エンジンの状態を保存して、スライスで編集を行うたびに、ファイルの先頭からではなく、そのスライスの先頭から構文強調表示を再開できるようにすることができます。
フリースタンディングの構文強調表示エンジンについては知りませんが、通常は正規表現置換に基づいています (たとえば、vim の構文強調表示ファイルを参照してください)。