summaryrefslogtreecommitdiffstats
path: root/buffer.sml
blob: 054f29cd2c9f5c2b2a547689242ab2fe8546a664 (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
structure Buffer =
struct
  fun append (a : Word8ArraySlice.slice) (b : Word8ArraySlice.slice) : Word8ArraySlice.slice =
    let
      val bLen = Word8ArraySlice.length b
      val (base, i, aLen) = Word8ArraySlice.base a
      val baseLen = Word8Array.length base
    in
      if i + aLen + bLen <= baseLen
      then
        (Word8ArraySlice.copy { 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.copy { 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.WR
            { name = "buffer"
            , chunkSize = 1
            , writeVec = NONE
            , writeArr =
                SOME
                  (fn a =>
                    (buffer := append (!buffer) a ;
                     Word8ArraySlice.length a))
            , writeVecNB = NONE
            , writeArrNB = NONE
            , block = NONE
            , canOutput = NONE
            , getPos = NONE
            , setPos = NONE
            , endPos = NONE
            , verifyPos = NONE
            , close = fn () => ()
            , ioDesc = NONE
            },
           IO.NO_BUF)),
       buffer)
    end
end