|
6316
|
1 |
(* Title: Pure/General/buffer.ML
|
|
|
2 |
ID: $Id$
|
|
|
3 |
Author: Markus Wenzel, TU Muenchen
|
|
|
4 |
|
|
26502
|
5 |
Efficient text buffers.
|
|
6316
|
6 |
*)
|
|
|
7 |
|
|
|
8 |
signature BUFFER =
|
|
|
9 |
sig
|
|
|
10 |
type T
|
|
|
11 |
val empty: T
|
|
|
12 |
val add: string -> T -> T
|
|
26502
|
13 |
val add_substring: substring -> T -> T
|
|
23785
|
14 |
val markup: Markup.T -> (T -> T) -> T -> T
|
|
6316
|
15 |
val content: T -> string
|
|
26502
|
16 |
val output: TextIO.outstream -> T -> unit
|
|
6316
|
17 |
val write: Path.T -> T -> unit
|
|
|
18 |
end;
|
|
|
19 |
|
|
|
20 |
structure Buffer: BUFFER =
|
|
|
21 |
struct
|
|
|
22 |
|
|
26502
|
23 |
(* datatype *)
|
|
|
24 |
|
|
|
25 |
datatype T =
|
|
|
26 |
EmptyBuffer
|
|
|
27 |
| String of string * T
|
|
|
28 |
| Substring of substring * T;
|
|
6316
|
29 |
|
|
26502
|
30 |
val empty = EmptyBuffer;
|
|
|
31 |
|
|
17062
|
32 |
|
|
26502
|
33 |
(* add content *)
|
|
|
34 |
|
|
|
35 |
fun add s buf = if s = "" then buf else String (s, buf);
|
|
|
36 |
fun add_substring s buf = if Substring.isEmpty s then buf else Substring (s, buf);
|
|
17062
|
37 |
|
|
23785
|
38 |
fun markup m body =
|
|
|
39 |
let val (bg, en) = Markup.output m
|
|
|
40 |
in add bg #> body #> add en end;
|
|
|
41 |
|
|
26502
|
42 |
|
|
|
43 |
(* cumulative content *)
|
|
|
44 |
|
|
|
45 |
fun rev_content EmptyBuffer acc = acc
|
|
|
46 |
| rev_content (String (s, buf)) acc = rev_content buf (s :: acc)
|
|
|
47 |
| rev_content (Substring (s, buf)) acc = rev_content buf (Substring.string s :: acc);
|
|
|
48 |
|
|
|
49 |
fun content buf = implode (rev_content buf []);
|
|
|
50 |
|
|
|
51 |
|
|
|
52 |
(* file output *)
|
|
17062
|
53 |
|
|
26502
|
54 |
fun rev_buffer EmptyBuffer acc = acc
|
|
|
55 |
| rev_buffer (String (s, buf)) acc = rev_buffer buf (String (s, acc))
|
|
|
56 |
| rev_buffer (Substring (s, buf)) acc = rev_buffer buf (Substring (s, acc));
|
|
6316
|
57 |
|
|
26502
|
58 |
fun output stream buffer =
|
|
|
59 |
let
|
|
|
60 |
fun rev_output EmptyBuffer = ()
|
|
|
61 |
| rev_output (String (s, buf)) = (TextIO.output (stream, s); rev_output buf)
|
|
|
62 |
| rev_output (Substring (s, buf)) = (TextIO.outputSubstr (stream, s); rev_output buf);
|
|
|
63 |
in rev_output (rev_buffer buffer empty) end;
|
|
|
64 |
|
|
|
65 |
fun write path buf = File.open_output (fn stream => output stream buf) path;
|
|
21630
|
66 |
|
|
6316
|
67 |
end;
|