-
Notifications
You must be signed in to change notification settings - Fork 12
/
reader.clj
123 lines (109 loc) · 3.28 KB
/
reader.clj
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
(ns cljam.io.bam-index.reader
(:require [clojure.java.io :as cio]
[cljam.io.util.lsb :as lsb]
[cljam.io.bam-index.common :refer [bai-magic]]
[cljam.io.bam-index.chunk :as chunk]
[cljam.util :as util])
(:import java.util.Arrays
[java.io FileInputStream Closeable IOException]
[cljam.io.bam_index.chunk Chunk]))
(deftype BAIReader [url reader]
Closeable
(close [this]
(.close ^Closeable (.reader this))))
(defn- skip-chunks!
[rdr]
(let [n-chunks (lsb/read-int rdr)]
(loop [i 0]
(when (< i n-chunks)
(lsb/skip rdr 16)
(recur (inc i))))))
(defn- skip-bin-index!
[rdr]
(let [n-bidx (lsb/read-int rdr)]
(loop [i 0]
(when (< i n-bidx)
(lsb/skip rdr 4)
(skip-chunks! rdr)
(recur (inc i))))))
(defn- skip-linear-index!
[rdr]
(let [n-lidx (lsb/read-int rdr)]
(loop [i 0]
(when (< i n-lidx)
(lsb/skip rdr 8)
(recur (inc i))))))
(defn- skip-index!
[rdr n]
(loop [i 0]
(when (< i n)
(skip-bin-index! rdr)
(skip-linear-index! rdr)
(recur (inc i)))))
(defn- read-chunks!
[rdr]
(let [n (lsb/read-int rdr)]
(loop [i 0, chunks []]
(if (< i n)
(recur (inc i) (conj chunks (Chunk. (lsb/read-long rdr) (lsb/read-long rdr))))
chunks))))
(defn- read-bin-index**!
[rdr]
(let [n (lsb/read-int rdr)]
(loop [i 0, bidx []]
(if (< i n)
(let [bin (lsb/read-int rdr)
chunks (read-chunks! rdr)]
(recur (inc i) (conj bidx {:bin bin, :chunks chunks})))
bidx))))
(defn- read-bin-index*!
[rdr ref-idx]
(let [n-ref (lsb/read-int rdr)]
(when (>= ref-idx n-ref)
(throw (IndexOutOfBoundsException. "The reference index number is invalid")))
(skip-index! rdr ref-idx)
(read-bin-index**! rdr)))
(defn- read-linear-index**!
[rdr]
(let [n (lsb/read-int rdr)]
(loop [i 0, lidx []]
(if (< i n)
(recur (inc i) (conj lidx (lsb/read-long rdr)))
lidx))))
(defn- read-linear-index*!
[rdr ref-idx]
(let [n-ref (lsb/read-int rdr)]
(when (>= ref-idx n-ref)
(throw (IndexOutOfBoundsException. "The reference index number is invalid")))
(skip-index! rdr ref-idx)
(skip-bin-index! rdr)
(read-linear-index**! rdr)))
(defn read-bin-index!
[^BAIReader rdr ref-idx]
(read-bin-index*! (.reader rdr) ref-idx))
(defn read-linear-index!
[^BAIReader rdr ref-idx]
(read-linear-index*! (.reader rdr) ref-idx))
(defn read-all-index!
[^BAIReader r]
(let [rdr (.reader r)
n-ref (lsb/read-int rdr)
refs (range n-ref)
all-idx (map (fn [_] [(read-bin-index**! rdr) (read-linear-index**! rdr)]) refs)
bidx-seq (map first all-idx)
bidx (zipmap
refs
(map (fn [bins]
(zipmap (map :bin bins) (map :chunks bins)))
bidx-seq))
lidx (zipmap refs (map second all-idx))]
{:bidx bidx
:lidx lidx}))
(defn reader [f]
(let [url (util/as-url f)
r (if (= (.getProtocol url) "file")
(FileInputStream. (cio/file url))
(.openStream url))]
(when-not (Arrays/equals ^bytes (lsb/read-bytes r 4) (.getBytes ^String bai-magic))
(throw (IOException. "Invalid BAI file")))
(->BAIReader url r)))