]> git.donarmstrong.com Git - bamtools.git/blob - src/api/BGZF.h
Implemented index cache mode for both BAI & BTI formats
[bamtools.git] / src / api / BGZF.h
1 // ***************************************************************************\r
2 // BGZF.h (c) 2009 Derek Barnett, Michael Str�mberg\r
3 // Marth Lab, Department of Biology, Boston College\r
4 // All rights reserved.\r
5 // ---------------------------------------------------------------------------\r
6 // Last modified: 20 October 2010 (DB)\r
7 // ---------------------------------------------------------------------------\r
8 // BGZF routines were adapted from the bgzf.c code developed at the Broad\r
9 // Institute.\r
10 // ---------------------------------------------------------------------------\r
11 // Provides the basic functionality for reading & writing BGZF files\r
12 // ***************************************************************************\r
13 \r
14 #ifndef BGZF_H\r
15 #define BGZF_H\r
16 \r
17 #include <cstdio>\r
18 #include <cstdlib>\r
19 #include <cstring>\r
20 #include <string>\r
21 #include "zlib.h"\r
22 \r
23 // Platform-specific large-file support\r
24 #ifndef BAMTOOLS_LFS\r
25 #define BAMTOOLS_LFS\r
26     #ifdef WIN32\r
27         #define ftell64(a)     _ftelli64(a)\r
28         #define fseek64(a,b,c) _fseeki64(a,b,c)\r
29     #else\r
30         #define ftell64(a)     ftello(a)\r
31         #define fseek64(a,b,c) fseeko(a,b,c) \r
32     #endif\r
33 #endif // BAMTOOLS_LFS\r
34 \r
35 // Platform-specific type definitions\r
36 #ifndef BAMTOOLS_TYPES\r
37 #define BAMTOOLS_TYPES\r
38     #ifdef _MSC_VER\r
39         typedef char                 int8_t;\r
40         typedef unsigned char       uint8_t;\r
41         typedef short               int16_t;\r
42         typedef unsigned short     uint16_t;\r
43         typedef int                 int32_t;\r
44         typedef unsigned int       uint32_t;\r
45         typedef long long           int64_t;\r
46         typedef unsigned long long uint64_t;\r
47     #else    \r
48         #include <stdint.h>\r
49     #endif\r
50 #endif // BAMTOOLS_TYPES\r
51 \r
52 namespace BamTools {\r
53 \r
54 // zlib constants\r
55 const int GZIP_ID1   = 31;\r
56 const int GZIP_ID2   = 139;\r
57 const int CM_DEFLATE = 8;\r
58 const int FLG_FEXTRA = 4;\r
59 const int OS_UNKNOWN = 255;\r
60 const int BGZF_XLEN  = 6;\r
61 const int BGZF_ID1   = 66;\r
62 const int BGZF_ID2   = 67;\r
63 const int BGZF_LEN   = 2;\r
64 const int GZIP_WINDOW_BITS    = -15;\r
65 const int Z_DEFAULT_MEM_LEVEL = 8;\r
66 \r
67 // BZGF constants\r
68 const int BLOCK_HEADER_LENGTH = 18;\r
69 const int BLOCK_FOOTER_LENGTH = 8;\r
70 const int MAX_BLOCK_SIZE      = 65536;\r
71 const int DEFAULT_BLOCK_SIZE  = 65536;\r
72 \r
73 struct BgzfData {\r
74 \r
75     // data members\r
76     public:\r
77         unsigned int UncompressedBlockSize;\r
78         unsigned int CompressedBlockSize;\r
79         unsigned int BlockLength;\r
80         unsigned int BlockOffset;\r
81         uint64_t BlockAddress;\r
82         bool     IsOpen;\r
83         bool     IsWriteOnly;\r
84         bool     IsWriteUncompressed;\r
85         FILE*    Stream;\r
86         char*    UncompressedBlock;\r
87         char*    CompressedBlock;\r
88 \r
89     // constructor & destructor\r
90     public:\r
91         BgzfData(void);\r
92         ~BgzfData(void);\r
93 \r
94     // main interface methods\r
95     public:       \r
96         // closes BGZF file\r
97         void Close(void);\r
98         // opens the BGZF file (mode is either "rb" for reading, or "wb" for writing)\r
99         bool Open(const std::string& filename, const char* mode, bool isWriteUncompressed = false);\r
100         // reads BGZF data into a byte buffer\r
101         int Read(char* data, const unsigned int dataLength);\r
102         // seek to position in BGZF file\r
103         bool Seek(int64_t position);\r
104         // get file position in BGZF file\r
105         int64_t Tell(void);\r
106         // writes the supplied data into the BGZF buffer\r
107         unsigned int Write(const char* data, const unsigned int dataLen);\r
108 \r
109     // internal methods\r
110     private:\r
111         // compresses the current block\r
112         int DeflateBlock(void);\r
113         // flushes the data in the BGZF block\r
114         void FlushBlock(void);\r
115         // de-compresses the current block\r
116         int InflateBlock(const int& blockLength);\r
117         // reads a BGZF block\r
118         bool ReadBlock(void);\r
119     \r
120     // static 'utility' methods\r
121     public:\r
122         // checks BGZF block header\r
123         static inline bool CheckBlockHeader(char* header);\r
124         // packs an unsigned integer into the specified buffer\r
125         static inline void PackUnsignedInt(char* buffer, unsigned int value);\r
126         // packs an unsigned short into the specified buffer\r
127         static inline void PackUnsignedShort(char* buffer, unsigned short value);\r
128         // unpacks a buffer into a double\r
129         static inline double UnpackDouble(char* buffer);\r
130         static inline double UnpackDouble(const char* buffer);\r
131         // unpacks a buffer into a float\r
132         static inline float UnpackFloat(char* buffer);\r
133         static inline float UnpackFloat(const char* buffer);\r
134         // unpacks a buffer into a signed int\r
135         static inline signed int UnpackSignedInt(char* buffer);\r
136         static inline signed int UnpackSignedInt(const char* buffer);\r
137         // unpacks a buffer into a signed short\r
138         static inline signed short UnpackSignedShort(char* buffer);\r
139         static inline signed short UnpackSignedShort(const char* buffer);\r
140         // unpacks a buffer into an unsigned int\r
141         static inline unsigned int UnpackUnsignedInt(char* buffer);\r
142         static inline unsigned int UnpackUnsignedInt(const char* buffer);\r
143         // unpacks a buffer into an unsigned short\r
144         static inline unsigned short UnpackUnsignedShort(char* buffer);\r
145         static inline unsigned short UnpackUnsignedShort(const char* buffer);\r
146 };\r
147 \r
148 // -------------------------------------------------------------\r
149 // static 'utility' method implementations\r
150 \r
151 // checks BGZF block header\r
152 inline\r
153 bool BgzfData::CheckBlockHeader(char* header) {\r
154     return (header[0] == GZIP_ID1 &&\r
155             header[1] == (char)GZIP_ID2 &&\r
156             header[2] == Z_DEFLATED &&\r
157             (header[3] & FLG_FEXTRA) != 0 &&\r
158             BgzfData::UnpackUnsignedShort(&header[10]) == BGZF_XLEN &&\r
159             header[12] == BGZF_ID1 &&\r
160             header[13] == BGZF_ID2 &&\r
161             BgzfData::UnpackUnsignedShort(&header[14]) == BGZF_LEN );\r
162 }\r
163 \r
164 // 'packs' an unsigned integer into the specified buffer\r
165 inline\r
166 void BgzfData::PackUnsignedInt(char* buffer, unsigned int value) {\r
167     buffer[0] = (char)value;\r
168     buffer[1] = (char)(value >> 8);\r
169     buffer[2] = (char)(value >> 16);\r
170     buffer[3] = (char)(value >> 24);\r
171 }\r
172 \r
173 // 'packs' an unsigned short into the specified buffer\r
174 inline\r
175 void BgzfData::PackUnsignedShort(char* buffer, unsigned short value) {\r
176     buffer[0] = (char)value;\r
177     buffer[1] = (char)(value >> 8);\r
178 }\r
179 \r
180 // 'unpacks' a buffer into a double (includes both non-const & const char* flavors)\r
181 inline\r
182 double BgzfData::UnpackDouble(char* buffer) {\r
183     union { double value; unsigned char valueBuffer[sizeof(double)]; } un;\r
184     un.value = 0;\r
185     un.valueBuffer[0] = buffer[0];\r
186     un.valueBuffer[1] = buffer[1];\r
187     un.valueBuffer[2] = buffer[2];\r
188     un.valueBuffer[3] = buffer[3];\r
189     un.valueBuffer[4] = buffer[4];\r
190     un.valueBuffer[5] = buffer[5];\r
191     un.valueBuffer[6] = buffer[6];\r
192     un.valueBuffer[7] = buffer[7];\r
193     return un.value;\r
194 }\r
195 \r
196 inline\r
197 double BgzfData::UnpackDouble(const char* buffer) {\r
198     union { double value; unsigned char valueBuffer[sizeof(double)]; } un;\r
199     un.value = 0;\r
200     un.valueBuffer[0] = buffer[0];\r
201     un.valueBuffer[1] = buffer[1];\r
202     un.valueBuffer[2] = buffer[2];\r
203     un.valueBuffer[3] = buffer[3];\r
204     un.valueBuffer[4] = buffer[4];\r
205     un.valueBuffer[5] = buffer[5];\r
206     un.valueBuffer[6] = buffer[6];\r
207     un.valueBuffer[7] = buffer[7];\r
208     return un.value;\r
209 }\r
210 \r
211 // 'unpacks' a buffer into a float (includes both non-const & const char* flavors)\r
212 inline\r
213 float BgzfData::UnpackFloat(char* buffer) {\r
214     union { float value; unsigned char valueBuffer[sizeof(float)]; } un;\r
215     un.value = 0;\r
216     un.valueBuffer[0] = buffer[0];\r
217     un.valueBuffer[1] = buffer[1];\r
218     un.valueBuffer[2] = buffer[2];\r
219     un.valueBuffer[3] = buffer[3];\r
220     return un.value;\r
221 }\r
222 \r
223 inline\r
224 float BgzfData::UnpackFloat(const char* buffer) {\r
225     union { float value; unsigned char valueBuffer[sizeof(float)]; } un;\r
226     un.value = 0;\r
227     un.valueBuffer[0] = buffer[0];\r
228     un.valueBuffer[1] = buffer[1];\r
229     un.valueBuffer[2] = buffer[2];\r
230     un.valueBuffer[3] = buffer[3];\r
231     return un.value;\r
232 }\r
233 \r
234 // 'unpacks' a buffer into a signed int (includes both non-const & const char* flavors)\r
235 inline\r
236 signed int BgzfData::UnpackSignedInt(char* buffer) {\r
237     union { signed int value; unsigned char valueBuffer[sizeof(signed int)]; } un;\r
238     un.value = 0;\r
239     un.valueBuffer[0] = buffer[0];\r
240     un.valueBuffer[1] = buffer[1];\r
241     un.valueBuffer[2] = buffer[2];\r
242     un.valueBuffer[3] = buffer[3];\r
243     return un.value;\r
244 }\r
245 \r
246 inline\r
247 signed int BgzfData::UnpackSignedInt(const char* buffer) {\r
248     union { signed int value; unsigned char valueBuffer[sizeof(signed int)]; } un;\r
249     un.value = 0;\r
250     un.valueBuffer[0] = buffer[0];\r
251     un.valueBuffer[1] = buffer[1];\r
252     un.valueBuffer[2] = buffer[2];\r
253     un.valueBuffer[3] = buffer[3];\r
254     return un.value;\r
255 }\r
256 \r
257 // 'unpacks' a buffer into a signed short (includes both non-const & const char* flavors)\r
258 inline\r
259 signed short BgzfData::UnpackSignedShort(char* buffer) {\r
260     union { signed short value; unsigned char valueBuffer[sizeof(signed short)]; } un;\r
261     un.value = 0;\r
262     un.valueBuffer[0] = buffer[0];\r
263     un.valueBuffer[1] = buffer[1];\r
264     return un.value;\r
265 }\r
266 \r
267 inline\r
268 signed short BgzfData::UnpackSignedShort(const char* buffer) {\r
269     union { signed short value; unsigned char valueBuffer[sizeof(signed short)]; } un;\r
270     un.value = 0;\r
271     un.valueBuffer[0] = buffer[0];\r
272     un.valueBuffer[1] = buffer[1];\r
273     return un.value;\r
274 }\r
275 \r
276 // 'unpacks' a buffer into an unsigned int (includes both non-const & const char* flavors)\r
277 inline\r
278 unsigned int BgzfData::UnpackUnsignedInt(char* buffer) {\r
279     union { unsigned int value; unsigned char valueBuffer[sizeof(unsigned int)]; } un;\r
280     un.value = 0;\r
281     un.valueBuffer[0] = buffer[0];\r
282     un.valueBuffer[1] = buffer[1];\r
283     un.valueBuffer[2] = buffer[2];\r
284     un.valueBuffer[3] = buffer[3];\r
285     return un.value;\r
286 }\r
287 \r
288 inline\r
289 unsigned int BgzfData::UnpackUnsignedInt(const char* buffer) {\r
290     union { unsigned int value; unsigned char valueBuffer[sizeof(unsigned int)]; } un;\r
291     un.value = 0;\r
292     un.valueBuffer[0] = buffer[0];\r
293     un.valueBuffer[1] = buffer[1];\r
294     un.valueBuffer[2] = buffer[2];\r
295     un.valueBuffer[3] = buffer[3];\r
296     return un.value;\r
297 }\r
298 \r
299 // 'unpacks' a buffer into an unsigned short (includes both non-const & const char* flavors)\r
300 inline\r
301 unsigned short BgzfData::UnpackUnsignedShort(char* buffer) {\r
302     union { unsigned short value; unsigned char valueBuffer[sizeof(unsigned short)]; } un;\r
303     un.value = 0;\r
304     un.valueBuffer[0] = buffer[0];\r
305     un.valueBuffer[1] = buffer[1];\r
306     return un.value;\r
307 }\r
308 \r
309 inline\r
310 unsigned short BgzfData::UnpackUnsignedShort(const char* buffer) {\r
311     union { unsigned short value; unsigned char valueBuffer[sizeof(unsigned short)]; } un;\r
312     un.value = 0;\r
313     un.valueBuffer[0] = buffer[0];\r
314     un.valueBuffer[1] = buffer[1];\r
315     return un.value;\r
316 }\r
317 \r
318 } // namespace BamTools\r
319 \r
320 #endif // BGZF_H\r