(* -*- mode: sml -*-
* $Id: reversefile.smlnj,v 1.4 2001/07/09 00:25:28 doug Exp $
* http://www.bagley.org/~doug/shootout/
* from Tom 7
*)
structure Test : sig
val main : (string * string list) -> OS.Process.status
end = struct
val bufsize = 4096
val rdbufsize = 4096
val stdout = Posix.FileSys.wordToFD 0w1
val stdin = Posix.FileSys.wordToFD 0w0
datatype block = END
| MORE of int ref * Word8Array.array * block
val buff = Unsafe.Word8Array.create rdbufsize
fun out END = ()
| out (MORE (ir as ref i, a, next)) =
let in
Posix.IO.writeArr (stdout, {buf=a, i=i, sz=NONE});
out next
end
fun rd (start, len, count, b) =
if (start + len) >= count then
(* done with this block.
Copy from start to the end of the array into
buff, then return the starting index into buff. *)
let in
Word8Array.copy {di=0,
dst=buff,
src=buff,
len=SOME len,
si=start};
(b, len)
end
else
if Unsafe.Word8Array.sub(buff, start + len) = 0w10 then
case b of MORE(ir as ref i, a, _) =>
if i > len then
let in
Word8Array.copy {di=i-len - 1,
dst=a,
len=SOME(len + 1),
si=start,
src=buff};
ir := i - (len + 1);
rd(start + len + 1, 0, count, b)
end
else
let
val na = Unsafe.Word8Array.create bufsize
val l = (len + 1) - i
in
Word8Array.copy {di=0,
dst=a,
len=SOME i,
si=(start + len + 1) - i,
src=buff};
Word8Array.copy {di=bufsize - l,
dst=na,
len=SOME l,
si=start,
src=buff};
ir := 0;
rd(start + len + 1, 0, count, MORE(ref (bufsize - l), na, b))
end
else rd (start, len + 1, count, b)
fun loop (b, s) =
let
val count = Posix.IO.readArr (stdin,
{buf=buff, i=s, sz=SOME (rdbufsize-s)})
val (bb, bs) = rd (0, s, count + s, b)
in
case count of
0 => out bb
| _ => loop (bb, bs)
end
fun main(name, args) =
( loop (MORE(ref bufsize, Unsafe.Word8Array.create bufsize, END), 0);
OS.Process.success);
end
val _ = SMLofNJ.exportFn("reversefile", Test.main);