Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Diff of /sml/branches/SMLNJ/src/compiler/PervEnv/IO/text-io-fn.sml
ViewVC logotype

Diff of /sml/branches/SMLNJ/src/compiler/PervEnv/IO/text-io-fn.sml

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 166, Sat Nov 7 20:11:41 1998 UTC revision 167, Sat Nov 7 20:11:41 1998 UTC
# Line 67  Line 67 
67          type writer = PIO.writer          type writer = PIO.writer
68          type pos = PIO.pos          type pos = PIO.pos
69    
70        (*** Functional input streams ***)        (*** Functional input streams ***
71           ** We represent an instream by a pointer to a buffer and an offset
72           ** into the buffer.  The buffers are chained by the "more" field from
73           ** the beginning of the stream towards the end.  If the "more" field
74           ** is EOS, then it refers to an empty buffer (consuming the EOF marker
75           ** involves moving the stream from immeditaly in front of the EOS to
76           ** to the empty buffer).  A "more" field of TERMINATED marks a
77           ** terminated stream.  We also have the invariant that the "tail"
78           ** field of the "info" structure points to a more ref that is either
79           ** NOMORE or TERMINATED.
80           **)
81          datatype instream = ISTRM of (in_buffer * int)          datatype instream = ISTRM of (in_buffer * int)
82          and in_buffer = IBUF of {          and in_buffer = IBUF of {
83              basePos : pos option,              basePos : pos option,
# Line 77  Line 87 
87            }            }
88          and more          and more
89            = MORE of in_buffer   (* forward link to additional data *)            = MORE of in_buffer   (* forward link to additional data *)
90              | EOS of in_buffer    (* End of stream marker *)
91            | NOMORE              (* placeholder for forward link *)            | NOMORE              (* placeholder for forward link *)
92            | TERMINATED          (* termination of the stream *)            | TERMINATED          (* termination of the stream *)
93    
# Line 104  Line 115 
115        (* this exception is raised by readVecNB in the blocking case *)        (* this exception is raised by readVecNB in the blocking case *)
116          exception WouldBlock          exception WouldBlock
117    
         datatype more_data = EOF | DATA of in_buffer  
   
118          fun extendStream (readFn, mlOp, buf as IBUF{more, info, ...}) = (let          fun extendStream (readFn, mlOp, buf as IBUF{more, info, ...}) = (let
119                val INFO{getPos, tail, ...} = info                val INFO{getPos, tail, ...} = info
120                val basePos = getPos()                val basePos = getPos()
121                val chunk = readFn (chunkSzOfIBuf buf)                val chunk = readFn (chunkSzOfIBuf buf)
               in  
                 if (V.length chunk = 0)  
                   then EOF  
                   else let  
122                      val newMore = ref NOMORE                      val newMore = ref NOMORE
123                      val buf' = IBUF{                      val buf' = IBUF{
124                              basePos = basePos, data = chunk,                              basePos = basePos, data = chunk,
125                              more = newMore, info = info                              more = newMore, info = info
126                            }                            }
127                  val next = if (V.length chunk = 0) then EOS buf' else MORE buf'
128                      in                      in
129                        more := MORE buf';                  more := next;
130                        tail := newMore;                        tail := newMore;
131                        DATA buf'                  next
                     end  
132                end                end
133                  handle ex => inputExn(info, mlOp, ex))                  handle ex => inputExn(info, mlOp, ex))
134    
135          fun getBuffer (readFn, mlOp) (buf as IBUF{more, info, ...}) = (          fun getBuffer (readFn, mlOp) (buf as IBUF{more, info, ...}) = (
136                case !more                case !more
137                 of TERMINATED => EOF                 of TERMINATED => (EOS buf)
138                  | NOMORE => extendStream (readFn, mlOp, buf)                  | NOMORE => extendStream (readFn, mlOp, buf)
139                  | (MORE buf') => DATA buf'                  | more => more
140                (* end case *))                (* end case *))
141    
142        (* read a chunk that is at least the specified size *)        (* read a chunk that is at least the specified size *)
# Line 153  Line 158 
158                        if (pos < len)                        if (pos < len)
159                          then (vecExtract(data, pos, NONE), ISTRM(buf, len))                          then (vecExtract(data, pos, NONE), ISTRM(buf, len))
160                          else (case (getBuf buf)                          else (case (getBuf buf)
161                             of EOF => (empty, ISTRM(buf, len))                             of (EOS buf) => (empty, ISTRM(buf, 0))
162                              | (DATA rest) => get (ISTRM(rest, 0))                              | (MORE rest) => get (ISTRM(rest, 0))
163                                | _ => raise Fail "bogus getBuf"
164                            (* end case *))                            (* end case *))
165                      end                      end
166                in                in
# Line 170  Line 176 
176                  | (m as ref TERMINATED) => ()                  | (m as ref TERMINATED) => ()
177                (* end case *))                (* end case *))
178    
       (* find the end of the stream *)  
         fun findEOS (IBUF{more=ref(MORE buf), ...}) = findEOS buf  
           | findEOS (buf as IBUF{data, ...}) = ISTRM(buf, V.length data)  
   
179          fun input (strm as ISTRM(buf, _)) =          fun input (strm as ISTRM(buf, _)) =
180                generalizedInput (getBuffer (readVec buf, "input")) strm                generalizedInput (getBuffer (readVec buf, "input")) strm
181          fun input1 (ISTRM(buf, pos)) = let          fun input1 (ISTRM(buf, pos)) = let
# Line 183  Line 185 
185                    then SOME(vecSub(data, pos), ISTRM(buf, pos+1))                    then SOME(vecSub(data, pos), ISTRM(buf, pos+1))
186                    else (case !more                    else (case !more
187                       of (MORE buf) => input1 (ISTRM(buf, 0))                       of (MORE buf) => input1 (ISTRM(buf, 0))
188                          | (EOS _) => NONE
189                        | NOMORE => (                        | NOMORE => (
190                            case extendStream (readVec buf, "input1", buf)                            case extendStream (readVec buf, "input1", buf)
191                             of EOF => NONE                             of (MORE rest) => input1 (ISTRM(rest, 0))
192                              | (DATA rest) => input1 (ISTRM(rest, 0))                              | _ => NONE
193                            (* end case *))                            (* end case *))
194                        | TERMINATED => NONE                        | TERMINATED => NONE
195                      (* end case *))                      (* end case *))
# Line 205  Line 208 
208                      end                      end
209                and nextBuf (buf as IBUF{more, data, ...}, n) = (case !more                and nextBuf (buf as IBUF{more, data, ...}, n) = (case !more
210                       of (MORE buf) => inputList (buf, 0, n)                       of (MORE buf) => inputList (buf, 0, n)
211                          | (EOS buf) => ([], ISTRM(buf, 0))
212                        | NOMORE => (                        | NOMORE => (
213                            case extendStream (readVec buf, "inputN", buf)                            case extendStream (readVec buf, "inputN", buf)
214                             of EOF => ([], ISTRM(buf, V.length data))                             of (MORE rest) => inputList (rest, 0, n)
215                              | (DATA rest) => inputList (rest, 0, n)                              | _ => ([], ISTRM(buf, V.length data))
216                            (* end case *))                            (* end case *))
217                        | TERMINATED => ([], ISTRM(buf, V.length data))                        | TERMINATED => ([], ISTRM(buf, V.length data))
218                      (* end case *))                      (* end case *))
# Line 218  Line 222 
222                end                end
223          fun inputAll (strm as ISTRM(buf, _)) = let          fun inputAll (strm as ISTRM(buf, _)) = let
224                val INFO{reader=PIO.RD{avail, ...}, ...} = infoOfIBuf buf                val INFO{reader=PIO.RD{avail, ...}, ...} = infoOfIBuf buf
225              (* read a chunk that is as large as the available input.  Note              (* Read a chunk that is as large as the available input.  Note
226               * that for systems that use CR-LF for #"\n", the size will be               * that for systems that use CR-LF for #"\n", the size will be
227               * too large, but this should be okay.               * too large, but this should be okay.
228               *)               *)
# Line 232  Line 236 
236                      end                      end
237                val bigInput =                val bigInput =
238                      generalizedInput (getBuffer (bigChunk, "inputAll"))                      generalizedInput (getBuffer (bigChunk, "inputAll"))
239                fun loop (v, strm) =                fun loop (v, strm) = if (V.length v = 0)
240                      if (V.length v = 0) then [] else v :: loop(bigInput strm)                      then ([], strm)
241                val data = V.concat (loop (bigInput strm))                      else let val (l, strm') = loop(bigInput strm)
242                in data                        in
243                            (v :: l, strm')
244                          end
245                  val (data, strm') = loop (bigInput strm)
246                  in
247                    (V.concat data, strm')
248                end                end
249        (* Return SOME k, if k <= amount characters can be read without blocking. *)        (* Return SOME k, if k <= amount characters can be read without blocking. *)
250          fun canInput (strm as ISTRM(buf, pos), amount) = let          fun canInput (strm as ISTRM(buf, pos), amount) = let
# Line 254  Line 263 
263                      end                      end
264                and nextBuf (IBUF{more, ...}, n) = (case !more                and nextBuf (IBUF{more, ...}, n) = (case !more
265                       of (MORE buf) => tryInput (buf, 0, n)                       of (MORE buf) => tryInput (buf, 0, n)
266                          | (EOS _) => SOME(amount - n)
267                        | TERMINATED => SOME(amount - n)                        | TERMINATED => SOME(amount - n)
268                        | NOMORE => ((                        | NOMORE => ((
269                            case extendStream (readVecNB, "canInput", buf)                            case extendStream (readVecNB, "canInput", buf)
270                             of EOF => SOME(amount - n)                             of (MORE b) => tryInput (b, 0, n)
271                              | (DATA b) => tryInput (b, 0, n)                              | _ => SOME(amount - n)
272                            (* end case *))                            (* end case *))
273                              handle IO.Io{cause=WouldBlock, ...} => SOME(amount - n))                              handle IO.Io{cause=WouldBlock, ...} => SOME(amount - n))
274                      (* end case *))                      (* end case *))
# Line 276  Line 286 
286                (* end case *))                (* end case *))
287          fun endOfStream (ISTRM(buf, pos)) = (case buf          fun endOfStream (ISTRM(buf, pos)) = (case buf
288                 of (IBUF{more=ref(MORE _), ...}) => false                 of (IBUF{more=ref(MORE _), ...}) => false
289                    | (IBUF{more=ref(EOS _), ...}) => true
290                  | (IBUF{more, data, info=INFO{closed, ...}, ...}) =>                  | (IBUF{more, data, info=INFO{closed, ...}, ...}) =>
291                      if (pos = V.length data)                      if (pos = V.length data)
292                        then (case (!more, !closed)                        then (case (!more, !closed)
293                           of (NOMORE, false) => (                           of (NOMORE, false) => (
294                                case extendStream (readVec buf, "endOfStream", buf)                                case extendStream (readVec buf, "endOfStream", buf)
295                                 of EOF => true                                 of (EOS _) => true
296                                  | _ => false                                  | _ => false
297                              (* end case *))                              (* end case *))
298                            | _ => true                            | _ => true
# Line 317  Line 328 
328                        closed = closedFlg, getPos = getPos, tail = ref more,                        closed = closedFlg, getPos = getPos, tail = ref more,
329                        cleanTag = tag                        cleanTag = tag
330                      }                      }
331                val buf =  (** What should we do about the position when there is initial data?? **)
 (** What should we do about the position in this case ?? **)  
332  (** Suggestion: When building a stream with supplied initial data,  (** Suggestion: When building a stream with supplied initial data,
333   ** nothing can be said about the positions inside that initial   ** nothing can be said about the positions inside that initial
334   ** data (who knows where that data even came from!).   ** data (who knows where that data even came from!).
335   **)   **)
336                          IBUF{                val basePos = if (V.length data = 0)
337                              basePos = NONE, data=data,                      then getPos()
338                              info=info, more=more}                      else NONE
339                in                in
340                  ISTRM(buf, 0)                  ISTRM(
341                      IBUF{basePos = basePos, data = data, info = info, more = more},
342                      0)
343                end                end
344    
345          fun getReader (ISTRM(buf, pos)) = let          fun getReader (ISTRM(buf, pos)) = let
# Line 344  Line 356 
356                    else (reader, V.concat(getData(!more)))                    else (reader, V.concat(getData(!more)))
357                end                end
358    
359        (** Position operations on instreams **)        (* Get the underlying file position of a stream *)
360          datatype in_pos = INP of {          fun filePosIn (ISTRM(buf, pos)) = (case buf
             base : pos,  
             offset : int,  
             info : info  
           }  
   
         fun getPosIn (ISTRM(buf, pos)) = (case buf  
361                 of IBUF{basePos=NONE, info, ...} =>                 of IBUF{basePos=NONE, info, ...} =>
362                      inputExn (info, "getPosIn", IO.RandomAccessNotSupported)                      inputExn (info, "filePosIn", IO.RandomAccessNotSupported)
363                  | IBUF{basePos=SOME p, info, ...} => INP{                  | IBUF{basePos=SOME base, info, ...} => let
                       base = p, offset = pos, info = info  
                     }  
               (* end case *))  
         fun filePosIn (INP{base, offset=0, ...}) = base  
           | filePosIn (INP{base, offset, info}) = let  
364                val INFO{reader=PIO.RD rd, readVec, ...} = info                val INFO{reader=PIO.RD rd, readVec, ...} = info
365                in                in
366                  case (#getPos rd, #setPos rd)                  case (#getPos rd, #setPos rd)
# Line 373  Line 374 
374                              (* end case *))                              (* end case *))
375                        in                        in
376                          setPos base;                          setPos base;
377                          readN offset;                                readN pos;
378                          getPos () before setPos tmpPos                          getPos () before setPos tmpPos
379                        end                        end
380                    | _ => raise Fail "filePosIn: impossible"                    | _ => raise Fail "filePosIn: impossible"
381                  (* end case *)                  (* end case *)
382                end                end
383          fun setPosIn (pos as INP{info as INFO{reader, ...}, ...}) = let                (* end case *))
               val fpos = filePosIn pos  
               val (PIO.RD rd) = reader  
               in  
                 terminate info;  
                 Option.valOf (#setPos rd) fpos;  
                 mkInstream (PIO.RD rd, empty)  
               end  
384    
385        (** Text stream specific operations **)        (** Text stream specific operations **)
386          fun inputLine (ISTRM(buf as IBUF{data, ...}, pos)) = let          fun inputLine (ISTRM(buf as IBUF{data, more, ...}, pos)) = let
387                fun join (item, (list, strm)) = (item::list, strm)                fun join (item, (list, strm)) = (item::list, strm)
388                fun nextBuf (isEmpty, buf as IBUF{more, data, ...}) = let                fun nextBuf (buf as IBUF{more, data, ...}) = let
389                      fun last () =                      fun last () = (["\n"], ISTRM(buf, V.length data))
                           (if isEmpty then [] else ["\n"], ISTRM(buf, V.length data))  
390                      in                      in
391                        case !more                        case !more
392                         of (MORE buf) => scanData (buf, 0)                         of (MORE buf) => scanData (buf, 0)
393                            | (EOS buf) => last ()
394                          | NOMORE => (                          | NOMORE => (
395                              case extendStream (readVec buf, "inputLine", buf)                              case extendStream (readVec buf, "inputLine", buf)
396                               of EOF => last ()                               of (EOS _) => last ()
397                                | (DATA rest) => scanData (rest, 0)                                | (MORE rest) => scanData (rest, 0)
398                              (* end case *))                              (* end case *))
399                          | TERMINATED => last ()                          | TERMINATED => last ()
400                        (* end case *)                        (* end case *)
# Line 408  Line 402 
402                and scanData (buf as IBUF{data, more, ...}, i) = let                and scanData (buf as IBUF{data, more, ...}, i) = let
403                      val len = V.length data                      val len = V.length data
404                      fun scan j = if (j = len)                      fun scan j = if (j = len)
405                              then join(vecExtract(data, i, NONE), nextBuf(false, buf))                              then join(vecExtract(data, i, NONE), nextBuf buf)
406                            else if (vecSub(data, j) = #"\n")                            else if (vecSub(data, j) = #"\n")
407                              then ([vecExtract(data, i, SOME(j+1-i))], ISTRM(buf, j+1))                              then ([vecExtract(data, i, SOME(j+1-i))], ISTRM(buf, j+1))
408                              else scan (j+1)                              else scan (j+1)
# Line 416  Line 410 
410                        scan i                        scan i
411                      end                      end
412                val (data, strm) = if (V.length data = pos)                val (data, strm) = if (V.length data = pos)
413                      then nextBuf (true, buf)                      then (case getBuffer (readVec buf, "inputLine") buf
414                           of (EOS buf) => ([""], ISTRM(buf, 0))
415                            | _ => nextBuf buf
416                          (* end case *))
417                      else scanData (buf, pos)                      else scanData (buf, pos)
418                in                in
419                  (V.concat data, strm)                  (V.concat data, strm)
# Line 743  Line 740 
740              strm := strm'; v              strm := strm'; v
741            end            end
742      fun inputAll (strm : instream) = let      fun inputAll (strm : instream) = let
743            val (s as StreamIO.ISTRM(buf, _)) = !strm            val (v, s) = StreamIO.inputAll(!strm)
           val v = StreamIO.inputAll s  
744            in            in
745              strm := StreamIO.findEOS buf; v              strm := s; v
746            end            end
747      fun canInput (strm, n) = StreamIO.canInput (!strm, n)      fun canInput (strm, n) = StreamIO.canInput (!strm, n)
748      fun lookahead (strm : instream) = (case StreamIO.input1(!strm)      fun lookahead (strm : instream) = (case StreamIO.input1(!strm)
# Line 755  Line 751 
751            (* end case *))            (* end case *))
752      fun closeIn strm = let      fun closeIn strm = let
753            val (s as StreamIO.ISTRM(buf as StreamIO.IBUF{data, ...}, _)) = !strm            val (s as StreamIO.ISTRM(buf as StreamIO.IBUF{data, ...}, _)) = !strm
754            (* find the end of the stream *)
755              fun findEOS (StreamIO.IBUF{more=ref(StreamIO.MORE buf), ...}) =
756                    findEOS buf
757                | findEOS (StreamIO.IBUF{more=ref(StreamIO.EOS buf), ...}) =
758                    findEOS buf
759                | findEOS (buf as StreamIO.IBUF{data, ...}) =
760                    StreamIO.ISTRM(buf, V.length data)
761            in            in
762              StreamIO.closeIn s;              StreamIO.closeIn s;
763              strm := StreamIO.findEOS buf              strm := findEOS buf
764            end            end
765      fun endOfStream strm = StreamIO.endOfStream(! strm)      fun endOfStream strm = StreamIO.endOfStream(! strm)
     fun getPosIn strm = StreamIO.getPosIn(!strm)  
     fun setPosIn (strm, p) = (strm := StreamIO.setPosIn p)  
766    
767    (** Output operations **)    (** Output operations **)
768      fun output (strm, v) = StreamIO.output(!strm, v)      fun output (strm, v) = StreamIO.output(!strm, v)
# Line 879  Line 880 
880    end (* TextIOFn *)    end (* TextIOFn *)
881    
882  (*  (*
883   * $Log$   * $Log: text-io-fn.sml,v $
884     * Revision 1.4  1998/10/16 17:26:31  jhr
885     *   Implemented multiple EOF support; changes to basis I/O API
886     *
887     * Revision 1.3  1998/08/17 19:21:18  george
888     *   Changed the type of TextIO.StreamIO.mkInstream to eliminate the option.
889     *   [appel]
890     *
891   *)   *)

Legend:
Removed from v.166  
changed lines
  Added in v.167

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0