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
let packets (s : string) : string list =
let n = String.length s in
let out = ref [] and partial = Buffer.create 4096 in
let rec page (at : int) : unit =
if at + 27 <= n && String.sub s at 4 = "OggS" then (
let segments = Char.code s.[at + 26] in
if at + 27 + segments <= n then (
let data = ref (at + 27 + segments) in
for i = 0 to segments - 1 do
let size = Char.code s.[at + 27 + i] in
if !data + size <= n then Buffer.add_substring partial s !data size;
data := !data + size;
if size < 255 then (
out := Buffer.contents partial :: !out;
Buffer.clear partial)
done;
page !data))
in
page 0;
List.rev !out
let length (s : string) : int option =
let n = String.length s in
let rec page (at : int) (last : int option) : int option =
if at + 27 <= n && String.sub s at 4 = "OggS" then (
let segments = Char.code s.[at + 26] in
let size = ref 0 in
for i = 0 to min segments (n - at - 27) - 1 do size := !size + Char.code s.[at + 27 + i] done;
let granule = ref 0 in
for i = 7 downto 0 do granule := (!granule lsl 8) lor Char.code s.[at + 6 + i] done;
page (at + 27 + segments + !size) (if !granule < 0 || Char.code s.[at + 13] = 0xff then last else Some !granule))
else last
in
page 0 None