src/Pure/General/buffer.ML
changeset 70998 7926d2fc3c4c
parent 70601 79831e40e2be
child 74231 b3c65c984210
equal deleted inserted replaced
70997:325247f32da9 70998:7926d2fc3c4c
     7 signature BUFFER =
     7 signature BUFFER =
     8 sig
     8 sig
     9   type T
     9   type T
    10   val empty: T
    10   val empty: T
    11   val is_empty: T -> bool
    11   val is_empty: T -> bool
    12   val chunks: T -> string list
       
    13   val content: T -> string
    12   val content: T -> string
    14   val add: string -> T -> T
    13   val add: string -> T -> T
       
    14   val output: T -> (string -> unit) -> unit
    15   val markup: Markup.T -> (T -> T) -> T -> T
    15   val markup: Markup.T -> (T -> T) -> T -> T
    16   val output: T -> BinIO.outstream -> unit
       
    17 end;
    16 end;
    18 
    17 
    19 structure Buffer: BUFFER =
    18 structure Buffer: BUFFER =
    20 struct
    19 struct
    21 
    20 
    22 abstype T = Buffer of {chunk_size: int, chunk: string list, buffer: string list}
    21 abstype T = Buffer of string list
    23 with
    22 with
    24 
    23 
    25 val empty = Buffer {chunk_size = 0, chunk = [], buffer = []};
    24 val empty = Buffer [];
    26 
    25 
    27 fun is_empty (Buffer {chunk, buffer, ...}) = null chunk andalso null buffer;
    26 fun is_empty (Buffer xs) = null xs;
    28 
    27 
    29 local
    28 fun add "" buf = buf
    30   val chunk_limit = 4096;
    29   | add x (Buffer xs) = Buffer (x :: xs);
    31 
    30 
    32   fun add_chunk [] buffer = buffer
    31 fun content (Buffer xs) = implode (rev xs);
    33     | add_chunk chunk buffer = implode (rev chunk) :: buffer;
       
    34 in
       
    35 
    32 
    36 fun chunks (Buffer {chunk, buffer, ...}) = rev (add_chunk chunk buffer);
    33 fun output (Buffer xs) out = List.app out (rev xs);
    37 
       
    38 val content = implode o chunks;
       
    39 
       
    40 fun add x (buf as Buffer {chunk_size, chunk, buffer}) =
       
    41   let val n = size x in
       
    42     if n = 0 then buf
       
    43     else if n + chunk_size < chunk_limit then
       
    44       Buffer {chunk_size = n + chunk_size, chunk = x :: chunk, buffer = buffer}
       
    45     else
       
    46       Buffer {chunk_size = 0, chunk = [],
       
    47         buffer =
       
    48           if n < chunk_limit
       
    49           then add_chunk (x :: chunk) buffer
       
    50           else x :: add_chunk chunk buffer}
       
    51   end;
       
    52 
       
    53 end;
       
    54 
    34 
    55 end;
    35 end;
    56 
    36 
    57 fun markup m body =
    37 fun markup m body =
    58   let val (bg, en) = Markup.output m
    38   let val (bg, en) = Markup.output m
    59   in add bg #> body #> add en end;
    39   in add bg #> body #> add en end;
    60 
    40 
    61 fun output buf stream =
       
    62   List.app (fn s => BinIO.output (stream, Byte.stringToBytes s)) (chunks buf);
       
    63 
       
    64 end;
    41 end;