⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 text-io-fn.sml

📁 这是我们参加06年全国开源软件的竞赛作品
💻 SML
📖 第 1 页 / 共 3 页
字号:
(* text-io-fn.sml * * COPYRIGHT (c) 1995 AT&T Bell Laboratories. * * This is the CML version of the TextIO functor. *)functor TextIOFn (    structure OSPrimIO : sig        include OS_PRIM_IO	val stdIn   : unit -> PrimIO.reader	val stdOut  : unit -> PrimIO.writer	val stdErr  : unit -> PrimIO.writer	val strReader : string -> PrimIO.reader      end	where type PrimIO.array = TextPrimIO.array	where type PrimIO.vector = TextPrimIO.vector	where type PrimIO.elem = TextPrimIO.elem	where type PrimIO.pos = TextPrimIO.pos	where type PrimIO.reader = TextPrimIO.reader	where type PrimIO.writer = TextPrimIO.writer  ) : CML_TEXT_IO = struct    structure PIO = OSPrimIO.PrimIO    structure A = CharArray    structure V = CharVector    structure SV = SyncVar  (* assign to an MVar *)    fun mUpdate (mv, x) = ignore(SV.mSwap(mv, x))  (* an element for initializing buffers *)    val someElem = #"\000"    val vecExtract = V.extract    val vecSub = V.sub    val arrUpdate = A.update    val substringBase = Substring.base    val empty = ""    fun dummyCleaner () = ()    structure StreamIO =      struct	type vector = V.vector	type elem = V.elem	type reader = PIO.reader	type writer = PIO.writer	type pos = PIO.pos      (*** Functional input streams ***)	datatype instream = ISTRM of (in_buffer * int)	and in_buffer = IBUF of {	    basePos : pos option,	    more : more SV.mvar,	(* when this cell is empty, it means that *)					(* there is an outstanding request to the *)					(* server to extend the stream. *)	    data : vector,	    info : info	  }	and more	  = MORE of in_buffer	(* forward link to additional data *)	  | NOMORE		(* placeholder for forward link *)	  | TERMINATED		(* termination of the stream *)	and info = INFO of {	    reader : reader,	    readVec : int -> vector,	    readVecEvt : int -> vector CML.event,	    closed : bool ref,	    getPos : unit -> pos option,	    tail : more SV.mvar SV.mvar,		(* points to the more cell of the last buffer *)	    cleanTag : CleanIO.tag	  }	fun infoOfIBuf (IBUF{info, ...}) = info	fun chunkSzOfIBuf buf = let	      val INFO{reader=PIO.RD{chunkSize, ...}, ...} = infoOfIBuf buf	      in		chunkSize	      end	fun readVec (IBUF{info=INFO{readVec=f, ...}, ...}) = f	fun inputExn (INFO{reader=PIO.RD{name, ...}, ...}, mlOp, exn) =	      raise IO.Io{function=mlOp, name=name, cause=exn}	datatype more_data = EOF | DATA of in_buffer      (* extend the stream by a chunk.       * Invariant: the more m-variable is empty on entry and full on exit.       *)	fun extendStream (readFn, mlOp, buf as IBUF{more, info, ...}) = (let	      val INFO{getPos, tail, ...} = info	      val basePos = getPos()	      val chunk = readFn (chunkSzOfIBuf buf)	      in		if (V.length chunk = 0)		  then (SV.mPut (more, NOMORE); EOF)		  else let		    val newMore = SV.mVar()		    val buf' = IBUF{			    basePos = basePos, data = chunk,			    more = newMore, info = info			  }		    in		    (* note that we do not fill the more cell until		     * after the tail has been updated.  This ensures		     * that someone attempting to access the tail will		     * not acquire the lock until after we are done.		     *)		      mUpdate (tail, newMore);		      SV.mPut (more, MORE buf');  (* releases lock!! *)		      SV.mPut (newMore, NOMORE);		      DATA buf'		    end	      end		handle ex => (		  SV.mPut (more, NOMORE);		  inputExn(info, mlOp, ex)))      (* get the next buffer in the stream, extending it if necessary.  If       * the stream must be extended, we lock it by taking the value from the       * more cell; the extendStream function is responsible for filling in       * the cell.       *)	fun getBuffer (readFn, mlOp) (buf as IBUF{more, info, ...}) = let	      fun get TERMINATED = EOF		| get (MORE buf') = DATA buf'		| get NOMORE = (case SV.mTake more		     of NOMORE => extendStream (readFn, mlOp, buf)		      | next => (SV.mPut(more, next); get next)		    (* end case *))	      in		get (SV.mGet more)	      end      (* read a chunk that is at least the specified size *)	fun readChunk buf = let	      val INFO{readVec, reader=PIO.RD{chunkSize, ...}, ...} =		     infoOfIBuf buf	      in		case (chunkSize - 1)		 of 0 => (fn n => readVec n)		  | k => (* round up to next multiple of chunkSize *)		      (fn n => readVec(Int.quot(n+k, chunkSize) * chunkSize))		(* end case *)	      end	fun generalizedInput getBuf = let	      fun get (ISTRM(buf as IBUF{data, ...}, pos)) = let		    val len = V.length data		    in		      if (pos < len)			then (vecExtract(data, pos, NONE), ISTRM(buf, len))			else (case (getBuf buf)			   of EOF => (empty, ISTRM(buf, len))			    | (DATA rest) => get (ISTRM(rest, 0))			  (* end case *))		    end	      in		get	      end      (* terminate an input stream *)	fun terminate (info as INFO{tail, cleanTag, ...}) = let	      val m = SV.mGet tail	      in		case SV.mTake m		 of (m' as MORE _) => (SV.mPut(m, m'); terminate info)		  | TERMINATED => SV.mPut(m, TERMINATED)		  | _ => (		      CleanIO.removeCleaner cleanTag;		      SV.mPut(m, TERMINATED))	        (* end case *)	      end      (* find the end of the stream *)	fun findEOS (buf as IBUF{more, data, ...}) = (case (SV.mGet more)	       of (MORE buf) => findEOS buf		| _ => ISTRM(buf, V.length data)	      (* end case *))	fun input (strm as ISTRM(buf, _)) =	      generalizedInput (getBuffer (readVec buf, "input")) strm	fun input1 (ISTRM(buf, pos)) = let	      val IBUF{data, more, ...} = buf	      in		if (pos < V.length data)		  then SOME(vecSub(data, pos), ISTRM(buf, pos+1))		  else let		    fun get (MORE buf) = input1 (ISTRM(buf, 0))		      | get TERMINATED = NONE		      | get NOMORE = (case SV.mTake more			   of NOMORE => (				case extendStream (readVec buf, "input1", buf)				 of EOF => NONE				  | (DATA rest) => input1 (ISTRM(rest, 0))				(* end case *))			    | next => (SV.mPut(more, next); get next)			  (* end case *))		    in		      get (SV.mGet more)		    end	      end	fun inputN (ISTRM(buf, pos), n) = let	      fun join (item, (list, strm)) = (item::list, strm)	      fun inputList (buf as IBUF{data, ...}, i, n) = let		    val len = V.length data		    val remain = len-i		    in		      if (remain >= n)			then ([vecExtract(data, i, SOME n)], ISTRM(buf, i+n))		      else join (			vecExtract(data, i, NONE),			nextBuf(buf, n-remain))		    end	      and nextBuf (buf as IBUF{more, data, ...}, n) = let		    fun get (MORE buf) = inputList (buf, 0, n)		      | get TERMINATED = ([], ISTRM(buf, V.length data))		      | get NOMORE = (case (SV.mTake more)			   of NOMORE => (case extendStream (readVec buf, "inputN", buf)				 of EOF => ([], ISTRM(buf, V.length data))				  | (DATA rest) => inputList (rest, 0, n)				(* end case *))			    | next => (SV.mPut(more, next); get next)			  (* end case *))		    in		      get (SV.mGet more)		    end	      val (data, strm) = inputList (buf, pos, n)	      in		(V.concat data, strm)	      end	fun inputAll (strm as ISTRM(buf, _)) = let	      val INFO{reader=PIO.RD{avail, ...}, ...} = infoOfIBuf buf 	    (* read a chunk that is as large as the available input.  Note	     * that for systems that use CR-LF for #"\n", the size will be	     * too large, but this should be okay.	     *)	      fun bigChunk _ = let		    val delta = (case avail()			   of NONE => chunkSzOfIBuf buf			    | (SOME n) => n			  (* end case *))		    in		      readChunk buf delta		    end	      val bigInput =		    generalizedInput (getBuffer (bigChunk, "inputAll"))	      fun loop (v, strm) =		    if (V.length v = 0) then [] else v :: loop(bigInput strm)	      val data = V.concat (loop (bigInput strm))	      in		(data, findEOS buf)	      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 inputLineEvt _ = raise Fail "inputLineEvt unimplemented"      (* Return SOME k, if k <= amount characters can be read without blocking. *)	fun canInput (strm as ISTRM(buf, pos), amount) = let(******	      val readVecNB = (case buf		   of (IBUF{info as INFO{readVecNB=NONE, ...}, ...}) =>			inputExn(info, "canInput", IO.NonblockingNotSupported)		    | (IBUF{info=INFO{readVecNB=SOME f, ...}, ...}) => f		  (* end case *))******)	      fun tryInput (buf as IBUF{data, ...}, i, n) = let		    val len = V.length data		    val remain = len - i		    in		      if (remain >= n)			then SOME n			else nextBuf (buf, n - remain)		    end	      and nextBuf (IBUF{more, ...}, n) = let		    fun get (MORE buf) = tryInput (buf, 0, n)		      | get TERMINATED = SOME(amount - n)(******		      | get NOMORE = (case SV.mTake more			   of NOMORE => ((				case extendStream (readVecNB, "canInput", buf)				 of EOF => SOME(amount - n)				  | (DATA b) => tryInput (b, 0, n)				(* end case *))				  handle IO.Io{cause=WouldBlock, ...} => SOME(amount - n))			    | next => (SV.mPut(more, next); get next)			  (* end case *))******)		      | get NOMORE = SOME(amount - n)		    in		      get (SV.mGet more)		    end	      in		if (amount < 0)		  then raise Size		  else tryInput (buf, pos, amount)	      end(*** We need some kind of lock on the input stream to do this safely!!! ***)	fun closeIn (ISTRM(buf, _)) = (case (infoOfIBuf buf)	       of INFO{closed=ref true, ...} => ()		| (info as INFO{closed, reader=PIO.RD{close, ...}, ...}) => (		    terminate info;		    closed := true;		    close() handle ex => inputExn(info, "closeIn", ex))	      (* end case *))	fun endOfStream (ISTRM(buf as IBUF{more, ...}, pos)) = (	      case SV.mTake more	       of (next as MORE _) => (SV.mPut(more, next); false)		| next => let		    val IBUF{data, info=INFO{closed, ...}, ...} = buf		    in		      if (pos = V.length data)			then (case (next, !closed)			    of (NOMORE, false) => (			        case extendStream (readVec buf, "endOfStream", buf)			         of EOF => true				  | _ => false				(* end case *))			     | _ => (SV.mPut(more, next); true)			  (* end case *))			else (SV.mPut(more, next); false)		    end	      (* end case *))	fun mkInstream' (reader, optData) = let	      val PIO.RD{readVec, readVecEvt, getPos, setPos, ...} = reader

⌨️ 快捷键说明

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