summaryrefslogtreecommitdiffstats
path: root/buffer.sml
blob: 03292bb0e00411a7ee2807167c2532480a1bfb80 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
structure Buffer =
struct
  fun append (a : Word8ArraySlice.slice) (b : Word8VectorSlice.slice) : Word8ArraySlice.slice =
    let
      val bLen = Word8VectorSlice.length b
      val (base, i, aLen) = Word8ArraySlice.base a
      val baseLen = Word8Array.length base
    in
      if i + aLen + bLen <= baseLen
      then
        (Word8ArraySlice.copyVec { src = b, dst = base, di = i + aLen } ;
         Word8ArraySlice.slice (base, i, SOME (aLen + bLen)))
      else
        let val newBuf = Word8Array.array (baseLen * 2 + bLen, Word8.fromInt 0)
        in
          Word8ArraySlice.copy { src = a, dst = newBuf, di = 0 } ;
          Word8ArraySlice.copyVec { src = b, dst = newBuf, di = aLen } ;
          Word8ArraySlice.slice (newBuf, 0, SOME (aLen + bLen))
        end
    end

  fun buf () : BinIO.outstream * Word8ArraySlice.slice ref =
    let val buffer = ref (Word8ArraySlice.full (Word8Array.array (0, Word8.fromInt 0)))
    in
      (BinIO.mkOutstream
        (BinIO.StreamIO.mkOutstream
          (BinPrimIO.augmentWriter
            (BinPrimIO.WR
              { name = "buffer"
              , chunkSize = 1
              , writeVec =
                  SOME
                    (fn a =>
                      (buffer := append (!buffer) a ;
                       Word8VectorSlice.length a))
              , writeArr = NONE
              , writeVecNB = NONE
              , writeArrNB = NONE
              , block = SOME (fn () => ())
              , canOutput = SOME (fn () => true)
              , getPos = NONE
              , setPos = NONE
              , endPos = NONE
              , verifyPos = NONE
              , close = fn () => ()
              , ioDesc = NONE
              }),
           IO.NO_BUF)),
       buffer)
    end
end