(* -*- 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);