-
Notifications
You must be signed in to change notification settings - Fork 0
/
word8ringbuffer.sml
58 lines (51 loc) · 1.75 KB
/
word8ringbuffer.sml
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
52
53
54
55
56
57
58
structure Word8RingBuffer :> sig
type t
val create : int -> t
val put : t * Word8Array.array -> unit
val putVec : t * Word8Vector.vector -> unit
val putElem : t * Word8.word -> unit
val getElem : t * int -> Word8.word
(* prev (t, sz): returns last sz bytes of the buffer *)
val prev : t * int -> Word8Array.array
end = struct
type t = { buffer : Word8Array.array, p : int ref }
fun create size = { buffer = Word8Array.array (size, 0w0), p = ref 0 }
fun put' app ({buffer, p}, arr) =
let
val bufferLen = Word8Array.length buffer
fun putByte byte = (
Word8Array.update (buffer, !p, byte);
p := (!p + 1) mod bufferLen)
in
app putByte arr
end
val put = put' Word8Array.app;
val putVec = put' Word8Vector.app;
val putElem = put' (fn f => fn x => f x)
fun getElem ({buffer, p = ref p}, distance) =
let
val bufferLen = Word8Array.length buffer
val pos = (p - distance) mod bufferLen
in
Word8Array.sub (buffer, pos)
end
fun prev ({buffer, p = ref p}, size) =
let
val dest = Word8Array.array (size, 0w00)
fun copy (_, 0) = ()
| copy (bufferPos, destPos) =
let
val nextBufferPos =
if bufferPos = 0 then Word8Array.length buffer - 1
else bufferPos - 1
val nextDestPos = destPos - 1
val byte = Word8Array.sub (buffer, nextBufferPos)
in
Word8Array.update (dest, nextDestPos, byte);
copy (nextBufferPos, nextDestPos)
end
in
copy (p, Word8Array.length dest);
dest
end
end