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