bin-io-fn.sml

来自「这是我们参加06年全国开源软件的竞赛作品」· SML 代码 · 共 714 行 · 第 1/2 页

SML
714
字号
	fun getReader (ISTRM(buf, pos)) = let	      val IBUF{data, info as INFO{reader, ...}, more, ...} = buf	      fun getData more = (case SV.mGet more		     of (MORE(IBUF{data, more=more', ...})) => data :: getData more'		      | _ => []		    (* end case *))	      in		terminate info;		if (pos < V.length data)		  then (		      reader,		      V.concat(vecExtract(data, pos, NONE) :: getData more)		    )		  else (reader, V.concat(getData more))	      end      (** Position operations on instreams **)	datatype in_pos = INP of {	    base : pos,	    offset : int,	    info : info	  }	fun getPosIn (ISTRM(buf, pos)) = (case buf	       of IBUF{basePos=NONE, info, ...} =>		    inputExn (info, "getPosIn", IO.RandomAccessNotSupported)		| IBUF{basePos=SOME p, info, ...} => INP{		      base = p, offset = pos, info = info		    }	      (* end case *))	fun filePosIn (INP{base, offset, ...}) =	      Position.+(base, Position.fromInt offset)	fun setPosIn (pos as INP{info as INFO{reader, ...}, ...}) = let	      val fpos = filePosIn pos	      val (PIO.RD rd) = reader	      in		terminate info;		valOf (#setPos rd) fpos;		mkInstream (PIO.RD rd, NONE)	      end      (*** Output streams ***)      (* an output stream is implemented as a monitor using an mvar to       * hold its data.       *)	datatype ostrm_info = OSTRM of {	    buf : A.array,	    pos : int ref,	    closed : bool ref,	    bufferMode : IO.buffer_mode ref,	    writer : writer,	    writeArr : {buf : A.array, i : int, sz : int option} -> unit,	    writeVec : {buf : V.vector, i : int, sz : int option} -> unit,	    cleanTag : CleanIO.tag	  }	type outstream = ostrm_info SV.mvar	fun outputExn (OSTRM{writer=PIO.WR{name, ...}, ...}, mlOp, exn) =	      raise IO.Io{function=mlOp, name=name, cause=exn}      (* lock access to the stream and make sure that it is not closed. *)	fun lockAndChkClosedOut (strmMV, mlOp) = (case SV.mTake strmMV	       of (strm as OSTRM({closed=ref true, ...})) => (		    SV.mPut (strmMV, strm);		    outputExn (strm, mlOp, IO.ClosedStream))		| strm => strm	      (* end case *))	fun flushBuffer (strmMV, strm as OSTRM{buf, pos, writeArr, ...}, mlOp) = (	      case !pos	       of 0 => ()		| n => ((		    writeArr {buf=buf, i=0, sz=SOME n}; pos := 0)		      handle ex => (			SV.mPut(strmMV, strm); outputExn (strm, mlOp, ex)))	      (* end case *))	fun output (strmMV, v) = let	      val (strm as OSTRM os) = lockAndChkClosedOut (strmMV, "output")	      fun release () = SV.mPut (strmMV, strm)	      val {buf, pos, bufferMode, ...} = os	      fun flush () = flushBuffer (strmMV, strm, "output")	      fun flushAll () = (#writeArr os {buf=buf, i=0, sz=NONE}		    handle ex => (release(); outputExn (strm, "output", ex)))	      fun writeDirect () = (		    case !pos		     of 0 => ()		      | n => (#writeArr os {buf=buf, i=0, sz=SOME n}; pos := 0)		    (* end case *);		    #writeVec os {buf=v, i=0, sz=NONE})		      handle ex => (release(); outputExn (strm, "output", ex))	      fun insert copyVec = let		    val bufLen = A.length buf		    val dataLen = V.length v		    in		      if (dataLen >= bufLen)			then writeDirect()			else let			  val i = !pos			  val avail = bufLen - i			  in			    if (avail < dataLen)			      then (				copyVec(v, 0, avail, buf, i);				flushAll();				copyVec(v, avail, dataLen-avail, buf, 0);			  	pos := dataLen-avail)			    else (			      copyVec(v, 0, dataLen, buf, i);			      pos := i + dataLen;			      if (avail = dataLen) then flush() else ())			  end		    end	      in		case !bufferMode		 of IO.NO_BUF => writeDirect ()		  | _ => let		      fun copyVec (src, srcI, srcLen, dst, dstI) = A.copyVec {			      src = src, si = srcI, len = SOME srcLen,			      dst = dst, di = dstI			    }		      in			insert copyVec		      end		(* end case *);		release()	      end	fun output1 (strmMV, elem) = let	      val (strm as OSTRM{buf, pos, bufferMode, writeArr, ...}) =		    lockAndChkClosedOut (strmMV, "output1")	      fun release () = SV.mPut (strmMV, strm)	      in		case !bufferMode		 of IO.NO_BUF => (		      arrUpdate (buf, 0, elem);		      writeArr {buf=buf, i=0, sz=SOME 1}			handle ex => (release(); outputExn (strm, "output1", ex)))		  | _ => let val i = !pos val i' = i+1		      in			arrUpdate (buf, i, elem); pos := i';			if (i' = A.length buf)			  then flushBuffer (strmMV, strm, "output1")			  else ()		      end		(* end case *);		release()	      end	fun flushOut strmMV = let	      val strm = lockAndChkClosedOut (strmMV, "flushOut")	      in		flushBuffer (strmMV, strm, "flushOut");		SV.mPut (strmMV, strm)	      end	fun closeOut strmMV = let	      val (strm as OSTRM{writer=PIO.WR{close, ...}, closed, cleanTag, ...}) =		    SV.mTake strmMV	      in		if !closed		  then ()		  else (		    flushBuffer (strmMV, strm, "closeOut");		    closed := true;		    CleanIO.removeCleaner cleanTag;		    close());		SV.mPut (strmMV, strm)	      end	fun mkOutstream (wr as PIO.WR{chunkSize, writeArr, writeVec, ...}, mode) =	      let	      fun iterate f (buf, i, sz) = let		    fun lp (_, 0) = ()		      | lp (i, n) = let val n' = f{buf=buf, i=i, sz=SOME n}			  in lp (i+n', n-n') end		    in		      lp (i, sz)		    end	      fun writeArr' {buf, i, sz} = let		    val len = (case sz			   of NONE => A.length buf - i			    | (SOME n) => n			  (* end case *))		    in		      iterate writeArr (buf, i, len)		    end	      fun writeVec' {buf, i, sz} = let		    val len = (case sz			   of NONE => V.length buf - i			    | (SOME n) => n			  (* end case *))		    in		      iterate writeVec (buf, i, len)		    end	    (* install a dummy cleaner *)	      val tag = CleanIO.addCleaner dummyCleaner	      val strm = SV.mVarInit (OSTRM{		      buf = A.array(chunkSize, someElem),		      pos = ref 0,		      closed = ref false,		      bufferMode = ref mode,		      writer = wr,		      writeArr = writeArr',		      writeVec = writeVec',		      cleanTag = tag		    })	      in		CleanIO.rebindCleaner (tag, fn () => closeOut strm);		strm	      end	fun getWriter strmMV = let	      val (strm as OSTRM{writer, bufferMode, ...}) =		    lockAndChkClosedOut (strmMV, "getWriter")	      in		(writer, !bufferMode) before SV.mPut(strmMV, strm)	      end      (** Position operations on outstreams **)	datatype out_pos = OUTP of {	    pos : PIO.pos,	    strm : outstream	  }	fun getPosOut strmMV = let	      val (strm as OSTRM{writer, ...}) =		    lockAndChkClosedOut (strmMV, "getWriter")	      fun release () = SV.mPut(strmMV, strm)	      in		flushBuffer (strmMV, strm, "getPosOut");		case writer	 	 of PIO.WR{getPos=SOME f, ...} => (		      OUTP{pos = f(), strm = strmMV}		        handle ex => (release(); outputExn(strm, "getPosOut", ex)))		  | _ => (		      release();		      outputExn(strm, "getPosOut", IO.RandomAccessNotSupported))		(* end case *)		before release()	      end	fun filePosOut (OUTP{pos, strm=strmMV}) = (	      SV.mPut (strmMV, lockAndChkClosedOut (strmMV, "filePosOut"));	      pos)	fun setPosOut (OUTP{pos, strm=strmMV}) = let	      val (strm as OSTRM{writer, ...}) =		    lockAndChkClosedOut (strmMV, "setPosOut")	      fun release () = SV.mPut(strmMV, strm)	      in		case writer		 of PIO.WR{setPos=SOME f, ...} => (		      (f pos)			handle ex => (release(); outputExn(strm, "setPosOut", ex)))		  | _ => (		      release();		      outputExn(strm, "getPosOut", IO.RandomAccessNotSupported))		(* end case *);		release()	      end	fun setBufferMode (strmMV, mode) = let	      val (strm as OSTRM{bufferMode, ...}) =		    lockAndChkClosedOut (strmMV, "setBufferMode")	      in		if (mode = IO.NO_BUF)		  then flushBuffer (strmMV, strm, "setBufferMode")		  else ();		bufferMode := mode;		SV.mPut (strmMV, strm)	      end	fun getBufferMode strmMV = let(** should we be checking for closed streams here??? **)	      val (strm as OSTRM{bufferMode, ...}) =		    lockAndChkClosedOut (strmMV, "getBufferMode")	      in		!bufferMode before SV.mPut (strmMV, strm)	      end      end (* StreamIO *)    type vector = V.vector    type elem = V.elem    type instream = StreamIO.instream SV.mvar    type outstream = StreamIO.outstream SV.mvar  (** Input operations **)    fun input strm = let val (v, strm') = StreamIO.input(SV.mTake strm)	  in	    SV.mPut (strm, strm'); v	  end    fun input1 strm = (case StreamIO.input1(SV.mTake strm)	   of NONE => NONE	    | (SOME(elem, strm')) => (SV.mPut (strm, strm'); SOME elem)	  (* end case *))    fun inputN (strm, n) = let val (v, strm') = StreamIO.inputN (SV.mTake strm, n)	  in	    SV.mPut (strm, strm'); v	  end    fun inputAll (strm : instream) = let	  val (v, strm') = StreamIO.inputAll(SV.mTake strm)	  in	    SV.mPut (strm, strm'); v	  end    fun input1Evt _ = raise Fail "input1Evt unimplemented"    fun inputEvt _ = raise Fail "inputEvt unimplemented"    fun inputNEvt _ = raise Fail "inputNEvt unimplemented"    fun inputAllEvt _ = raise Fail "inputAllEvt unimplemented"    fun canInput (strm, n) = StreamIO.canInput (SV.mGet strm, n)    fun lookahead (strm : instream) = (case StreamIO.input1(SV.mGet strm)	   of NONE => NONE	    | (SOME(elem, _)) => SOME elem	  (* end case *))    fun closeIn strm = let	  val (s as StreamIO.ISTRM(buf as StreamIO.IBUF{data, ...}, _)) =		SV.mTake strm	  in	    StreamIO.closeIn s;	    SV.mPut(strm, StreamIO.findEOS buf)	  end    fun endOfStream strm = StreamIO.endOfStream(SV.mGet strm)    fun getPosIn strm = StreamIO.getPosIn(SV.mGet strm)    fun setPosIn (strm, p) = mUpdate(strm, StreamIO.setPosIn p)  (** Output operations **)    fun output (strm, v) = StreamIO.output(SV.mGet strm, v)    fun output1 (strm, c) = StreamIO.output1(SV.mGet strm, c)    fun flushOut strm = StreamIO.flushOut(SV.mGet strm)    fun closeOut strm = StreamIO.closeOut(SV.mGet strm)    fun getPosOut strm = StreamIO.getPosOut(SV.mGet strm)    fun setPosOut (strm, p as StreamIO.OUTP{strm=strm', ...}) = (	  mUpdate(strm, strm'); StreamIO.setPosOut p)    fun mkInstream (strm : StreamIO.instream) = SV.mVarInit strm    fun getInstream (strm : instream) = SV.mGet strm    fun setInstream (strm : instream, strm') = mUpdate(strm, strm')    fun mkOutstream (strm : StreamIO.outstream) = SV.mVarInit strm    fun getOutstream (strm : outstream) = SV.mGet strm    fun setOutstream (strm : outstream, strm') = mUpdate(strm, strm')  (** Open files **)    fun openIn fname =	  mkInstream(StreamIO.mkInstream(OSPrimIO.openRd fname, NONE))	    handle ex => raise IO.Io{function="openIn", name=fname, cause=ex}    fun openOut fname =	  mkOutstream(StreamIO.mkOutstream(OSPrimIO.openWr fname, IO.BLOCK_BUF))	    handle ex => raise IO.Io{function="openOut", name=fname, cause=ex}    fun openAppend fname =	  mkOutstream(StreamIO.mkOutstream(OSPrimIO.openApp fname, IO.NO_BUF))	    handle ex => raise IO.Io{function="openAppend", name=fname, cause=ex}  end (* BinIOFn *)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?