]> git.donarmstrong.com Git - bamtools.git/blob - BamAux.h
Added concept of a fully specified region of interest to the BamReader API. Added...
[bamtools.git] / BamAux.h
1 // ***************************************************************************\r
2 // BamAux.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: 16 June 2010 (DB)\r
7 // ---------------------------------------------------------------------------\r
8 // Provides the basic constants, data structures, etc. for using BAM files\r
9 // ***************************************************************************\r
10 \r
11 #ifndef BAMAUX_H\r
12 #define BAMAUX_H\r
13 \r
14 // C inclues\r
15 #include <cstdio>\r
16 #include <cstdlib>\r
17 #include <cstring>\r
18 \r
19 // C++ includes\r
20 #include <exception>\r
21 #include <map>\r
22 #include <string>\r
23 #include <utility>\r
24 #include <vector>\r
25 \r
26 // Platform-specific type definitions\r
27 #ifndef BAMTOOLS_TYPES\r
28 #define BAMTOOLS_TYPES\r
29     #ifdef _MSC_VER\r
30         typedef char                 int8_t;\r
31         typedef unsigned char       uint8_t;\r
32         typedef short               int16_t;\r
33         typedef unsigned short     uint16_t;\r
34         typedef int                 int32_t;\r
35         typedef unsigned int       uint32_t;\r
36         typedef long long           int64_t;\r
37         typedef unsigned long long uint64_t;\r
38     #else\r
39         #include <stdint.h>\r
40     #endif\r
41 #endif // BAMTOOLS_TYPES\r
42 \r
43 namespace BamTools {\r
44 \r
45 // BAM constants\r
46 const int BAM_CORE_SIZE   = 32;\r
47 const int BAM_CMATCH      = 0;\r
48 const int BAM_CINS        = 1;\r
49 const int BAM_CDEL        = 2;\r
50 const int BAM_CREF_SKIP   = 3;\r
51 const int BAM_CSOFT_CLIP  = 4;\r
52 const int BAM_CHARD_CLIP  = 5;\r
53 const int BAM_CPAD        = 6;\r
54 const int BAM_CIGAR_SHIFT = 4;\r
55 const int BAM_CIGAR_MASK  = ((1 << BAM_CIGAR_SHIFT) - 1);\r
56 \r
57 // BAM index constants\r
58 const int MAX_BIN           = 37450;    // =(8^6-1)/7+1\r
59 const int BAM_MIN_CHUNK_GAP = 32768;\r
60 const int BAM_LIDX_SHIFT    = 14;\r
61 \r
62 // Explicit variable sizes\r
63 const int BT_SIZEOF_INT = 4;\r
64 \r
65 struct CigarOp;\r
66 \r
67 struct BamAlignment {\r
68 \r
69     // constructors & destructor\r
70     public:\r
71         BamAlignment(void);\r
72         BamAlignment(const BamAlignment& other);\r
73         ~BamAlignment(void);\r
74 \r
75     // Queries against alignment flags\r
76     public:        \r
77         bool IsDuplicate(void) const;           // Returns true if this read is a PCR duplicate       \r
78         bool IsFailedQC(void) const;            // Returns true if this read failed quality control      \r
79         bool IsFirstMate(void) const;           // Returns true if alignment is first mate on read        \r
80         bool IsMapped(void) const;              // Returns true if alignment is mapped        \r
81         bool IsMateMapped(void) const;          // Returns true if alignment's mate is mapped        \r
82         bool IsMateReverseStrand(void) const;   // Returns true if alignment's mate mapped to reverse strand        \r
83         bool IsPaired(void) const;              // Returns true if alignment part of paired-end read        \r
84         bool IsPrimaryAlignment(void) const;    // Returns true if reported position is primary alignment       \r
85         bool IsProperPair(void) const;          // Returns true if alignment is part of read that satisfied paired-end resolution     \r
86         bool IsReverseStrand(void) const;       // Returns true if alignment mapped to reverse strand\r
87         bool IsSecondMate(void) const;          // Returns true if alignment is second mate on read\r
88 \r
89     // Manipulate alignment flags\r
90     public:        \r
91         void SetIsDuplicate(bool ok);           // Sets "PCR duplicate" flag        \r
92         void SetIsFailedQC(bool ok);            // Sets "failed quality control" flag        \r
93         void SetIsFirstMate(bool ok);           // Sets "alignment is first mate" flag        \r
94         void SetIsMateUnmapped(bool ok);        // Sets "alignment's mate is mapped" flag        \r
95         void SetIsMateReverseStrand(bool ok);   // Sets "alignment's mate mapped to reverse strand" flag        \r
96         void SetIsPaired(bool ok);              // Sets "alignment part of paired-end read" flag        \r
97         void SetIsProperPair(bool ok);          // Sets "alignment is part of read that satisfied paired-end resolution" flag        \r
98         void SetIsReverseStrand(bool ok);       // Sets "alignment mapped to reverse strand" flag        \r
99         void SetIsSecondaryAlignment(bool ok);  // Sets "position is primary alignment" flag        \r
100         void SetIsSecondMate(bool ok);          // Sets "alignment is second mate on read" flag        \r
101         void SetIsUnmapped(bool ok);            // Sets "alignment is mapped" flag\r
102 \r
103     // Tag data access methods\r
104     public:\r
105         bool GetEditDistance(uint8_t& editDistance) const;      // get "NM" tag data - contributed by Aaron Quinlan\r
106         bool GetReadGroup(std::string& readGroup) const;        // get "RG" tag data\r
107         \r
108         bool GetTag(const std::string& tag, std::string& destination);\r
109         template<typename T> bool GetTag(const std::string& tag, T& destination);\r
110 \r
111     // Additional data access methods\r
112     public:\r
113         int GetEndPosition(bool usePadded = false) const;       // calculates alignment end position, based on starting position and CIGAR operations\r
114 \r
115     // 'internal' utility methods \r
116     private:\r
117         static void SkipToNextTag(const char storageType, char* &pTagData, unsigned int& numBytesParsed);\r
118 \r
119     // Data members\r
120     public:\r
121         std::string  Name;              // Read name\r
122         int32_t      Length;            // Query length\r
123         std::string  QueryBases;        // 'Original' sequence (as reported from sequencing machine)\r
124         std::string  AlignedBases;      // 'Aligned' sequence (includes any indels, padding, clipping)\r
125         std::string  Qualities;         // FASTQ qualities (ASCII characters, not numeric values)\r
126         std::string  TagData;           // Tag data (accessor methods will pull the requested information out)\r
127         int32_t      RefID;             // ID number for reference sequence\r
128         int32_t      Position;          // Position (0-based) where alignment starts\r
129         uint16_t     Bin;               // Bin in BAM file where this alignment resides\r
130         uint16_t     MapQuality;        // Mapping quality score\r
131         uint32_t     AlignmentFlag;     // Alignment bit-flag - see Is<something>() methods to query this value, SetIs<something>() methods to manipulate \r
132         std::vector<CigarOp> CigarData; // CIGAR operations for this alignment\r
133         int32_t      MateRefID;         // ID number for reference sequence where alignment's mate was aligned\r
134         int32_t      MatePosition;      // Position (0-based) where alignment's mate starts\r
135         int32_t      InsertSize;        // Mate-pair insert size\r
136         \r
137         struct BamAlignmentSupportData {\r
138       \r
139             // data members\r
140             std::string AllCharData;\r
141             uint32_t    BlockLength;\r
142             uint32_t    NumCigarOperations;\r
143             uint32_t    QueryNameLength;\r
144             uint32_t    QuerySequenceLength;\r
145             bool        IsParsed;\r
146             \r
147             // constructor\r
148             BamAlignmentSupportData(void)\r
149                 : BlockLength(0)\r
150                 , NumCigarOperations(0)\r
151                 , QueryNameLength(0)\r
152                 , QuerySequenceLength(0)\r
153                 , IsParsed(false)\r
154             { }\r
155         };\r
156         \r
157         BamAlignmentSupportData SupportData;  // Contains raw character data & lengths \r
158 \r
159     // Alignment flag query constants\r
160     // Use the get/set methods above instead\r
161     private:\r
162         enum { PAIRED        = 1\r
163              , PROPER_PAIR   = 2\r
164              , UNMAPPED      = 4\r
165              , MATE_UNMAPPED = 8\r
166              , REVERSE       = 16\r
167              , MATE_REVERSE  = 32\r
168              , READ_1        = 64\r
169              , READ_2        = 128\r
170              , SECONDARY     = 256\r
171              , QC_FAILED     = 512\r
172              , DUPLICATE     = 1024 \r
173              };\r
174 };\r
175 \r
176 // ----------------------------------------------------------------\r
177 // Auxiliary data structs & typedefs\r
178 \r
179 struct CigarOp {\r
180   \r
181     // data members\r
182     char     Type;   // Operation type (MIDNSHP)\r
183     uint32_t Length; // Operation length (number of bases)\r
184     \r
185     // constructor\r
186     CigarOp(const char type = '\0', \r
187             const uint32_t length = 0) \r
188         : Type(type)\r
189         , Length(length) \r
190     { }\r
191 };\r
192 \r
193 struct RefData {\r
194    \r
195     // data members\r
196     std::string RefName;          // Name of reference sequence\r
197     int32_t     RefLength;        // Length of reference sequence\r
198     bool        RefHasAlignments; // True if BAM file contains alignments mapped to reference sequence\r
199     \r
200     // constructor\r
201     RefData(const int32_t& length = 0, \r
202             bool ok = false)\r
203         : RefLength(length)\r
204         , RefHasAlignments(ok)\r
205     { }\r
206 };\r
207 \r
208 typedef std::vector<RefData>      RefVector;\r
209 typedef std::vector<BamAlignment> BamAlignmentVector;\r
210 \r
211 struct BamRegion {\r
212   \r
213     // data members\r
214     int LeftRefID;\r
215     int LeftPosition;\r
216     int RightRefID;\r
217     int RightPosition;\r
218     \r
219     // constructor\r
220     BamRegion(const int& leftID   = -1, \r
221               const int& leftPos  = -1,\r
222               const int& rightID  = -1,\r
223               const int& rightPos = -1)\r
224         : LeftRefID(leftID)\r
225         , LeftPosition(leftPos)\r
226         , RightRefID(rightID)\r
227         , RightPosition(rightPos)\r
228     { }\r
229 };\r
230 \r
231 // ----------------------------------------------------------------\r
232 // Indexing structs & typedefs\r
233 \r
234 struct Chunk {\r
235 \r
236     // data members\r
237     uint64_t Start;\r
238     uint64_t Stop;\r
239 \r
240     // constructor\r
241     Chunk(const uint64_t& start = 0, \r
242           const uint64_t& stop = 0)\r
243         : Start(start)\r
244         , Stop(stop)\r
245     { }\r
246 };\r
247 \r
248 inline\r
249 bool ChunkLessThan(const Chunk& lhs, const Chunk& rhs) {\r
250     return lhs.Start < rhs.Start;\r
251 }\r
252 \r
253 typedef std::vector<Chunk> ChunkVector;\r
254 typedef std::map<uint32_t, ChunkVector> BamBinMap;\r
255 typedef std::vector<uint64_t> LinearOffsetVector;\r
256 \r
257 struct ReferenceIndex {\r
258     // data members\r
259     BamBinMap Bins;\r
260     LinearOffsetVector Offsets;\r
261     // constructor\r
262     ReferenceIndex(const BamBinMap& binMap = BamBinMap(),\r
263                    const LinearOffsetVector& offsets = LinearOffsetVector())\r
264         : Bins(binMap)\r
265         , Offsets(offsets)\r
266     { }\r
267 };\r
268 \r
269 typedef std::vector<ReferenceIndex> BamIndex;\r
270 \r
271 // ----------------------------------------------------------------\r
272 // BamAlignment member methods\r
273 \r
274 // constructors & destructor\r
275 inline \r
276 BamAlignment::BamAlignment(void) { }\r
277 \r
278 inline \r
279 BamAlignment::BamAlignment(const BamAlignment& other)\r
280     : Name(other.Name)\r
281     , Length(other.Length)\r
282     , QueryBases(other.QueryBases)\r
283     , AlignedBases(other.AlignedBases)\r
284     , Qualities(other.Qualities)\r
285     , TagData(other.TagData)\r
286     , RefID(other.RefID)\r
287     , Position(other.Position)\r
288     , Bin(other.Bin)\r
289     , MapQuality(other.MapQuality)\r
290     , AlignmentFlag(other.AlignmentFlag)\r
291     , CigarData(other.CigarData)\r
292     , MateRefID(other.MateRefID)\r
293     , MatePosition(other.MatePosition)\r
294     , InsertSize(other.InsertSize)\r
295     , SupportData(other.SupportData)\r
296 { }\r
297 \r
298 inline \r
299 BamAlignment::~BamAlignment(void) { }\r
300 \r
301 // Queries against alignment flags\r
302 inline bool BamAlignment::IsDuplicate(void) const         { return ( (AlignmentFlag & DUPLICATE)     != 0 ); }\r
303 inline bool BamAlignment::IsFailedQC(void) const          { return ( (AlignmentFlag & QC_FAILED)     != 0 ); }\r
304 inline bool BamAlignment::IsFirstMate(void) const         { return ( (AlignmentFlag & READ_1)        != 0 ); }\r
305 inline bool BamAlignment::IsMapped(void) const            { return ( (AlignmentFlag & UNMAPPED)      == 0 ); }\r
306 inline bool BamAlignment::IsMateMapped(void) const        { return ( (AlignmentFlag & MATE_UNMAPPED) == 0 ); }\r
307 inline bool BamAlignment::IsMateReverseStrand(void) const { return ( (AlignmentFlag & MATE_REVERSE)  != 0 ); }\r
308 inline bool BamAlignment::IsPaired(void) const            { return ( (AlignmentFlag & PAIRED)        != 0 ); }\r
309 inline bool BamAlignment::IsPrimaryAlignment(void) const  { return ( (AlignmentFlag & SECONDARY)     == 0 ); }\r
310 inline bool BamAlignment::IsProperPair(void) const        { return ( (AlignmentFlag & PROPER_PAIR)   != 0 ); }\r
311 inline bool BamAlignment::IsReverseStrand(void) const     { return ( (AlignmentFlag & REVERSE)       != 0 ); }\r
312 inline bool BamAlignment::IsSecondMate(void) const        { return ( (AlignmentFlag & READ_2)        != 0 ); }\r
313 \r
314 // Manipulate alignment flags \r
315 inline void BamAlignment::SetIsDuplicate(bool ok)          { if (ok) AlignmentFlag |= DUPLICATE;     else AlignmentFlag &= ~DUPLICATE; }\r
316 inline void BamAlignment::SetIsFailedQC(bool ok)           { if (ok) AlignmentFlag |= QC_FAILED;     else AlignmentFlag &= ~QC_FAILED; }\r
317 inline void BamAlignment::SetIsFirstMate(bool ok)          { if (ok) AlignmentFlag |= READ_1;        else AlignmentFlag &= ~READ_1; }\r
318 inline void BamAlignment::SetIsMateUnmapped(bool ok)       { if (ok) AlignmentFlag |= MATE_UNMAPPED; else AlignmentFlag &= ~MATE_UNMAPPED; }\r
319 inline void BamAlignment::SetIsMateReverseStrand(bool ok)  { if (ok) AlignmentFlag |= MATE_REVERSE;  else AlignmentFlag &= ~MATE_REVERSE; }\r
320 inline void BamAlignment::SetIsPaired(bool ok)             { if (ok) AlignmentFlag |= PAIRED;        else AlignmentFlag &= ~PAIRED; }\r
321 inline void BamAlignment::SetIsProperPair(bool ok)         { if (ok) AlignmentFlag |= PROPER_PAIR;   else AlignmentFlag &= ~PROPER_PAIR; }\r
322 inline void BamAlignment::SetIsReverseStrand(bool ok)      { if (ok) AlignmentFlag |= REVERSE;       else AlignmentFlag &= ~REVERSE; }\r
323 inline void BamAlignment::SetIsSecondaryAlignment(bool ok) { if (ok) AlignmentFlag |= SECONDARY;     else AlignmentFlag &= ~SECONDARY; }\r
324 inline void BamAlignment::SetIsSecondMate(bool ok)         { if (ok) AlignmentFlag |= READ_2;        else AlignmentFlag &= ~READ_2; }\r
325 inline void BamAlignment::SetIsUnmapped(bool ok)           { if (ok) AlignmentFlag |= UNMAPPED;      else AlignmentFlag &= ~UNMAPPED; }\r
326 \r
327 // calculates alignment end position, based on starting position and CIGAR operations\r
328 inline \r
329 int BamAlignment::GetEndPosition(bool usePadded) const {\r
330 \r
331     // initialize alignment end to starting position\r
332     int alignEnd = Position;\r
333 \r
334     // iterate over cigar operations\r
335     std::vector<CigarOp>::const_iterator cigarIter = CigarData.begin();\r
336     std::vector<CigarOp>::const_iterator cigarEnd  = CigarData.end();\r
337     for ( ; cigarIter != cigarEnd; ++cigarIter) {\r
338         const char cigarType = (*cigarIter).Type;\r
339         if ( cigarType == 'M' || cigarType == 'D' || cigarType == 'N' ) {\r
340             alignEnd += (*cigarIter).Length;\r
341         } \r
342         else if ( usePadded && cigarType == 'I' ) {\r
343             alignEnd += (*cigarIter).Length;\r
344         }\r
345     }\r
346     return alignEnd;\r
347 }\r
348 \r
349 // get "NM" tag data - contributed by Aaron Quinlan\r
350 // stores data in 'editDistance', returns success/fail\r
351 inline \r
352 bool BamAlignment::GetEditDistance(uint8_t& editDistance) const {\r
353 \r
354     if ( TagData.empty() ) { return false; }\r
355 \r
356     // localize the tag data\r
357     char* pTagData = (char*)TagData.data();\r
358     const unsigned int tagDataLen = TagData.size();\r
359     unsigned int numBytesParsed = 0;\r
360 \r
361     bool foundEditDistanceTag = false;\r
362     while( numBytesParsed < tagDataLen ) {\r
363 \r
364         const char* pTagType = pTagData;\r
365         const char* pTagStorageType = pTagData + 2;\r
366         pTagData       += 3;\r
367         numBytesParsed += 3;\r
368 \r
369         // check the current tag\r
370         if ( strncmp(pTagType, "NM", 2) == 0 ) {\r
371             foundEditDistanceTag = true;\r
372             break;\r
373         }\r
374 \r
375         // get the storage class and find the next tag\r
376         if (*pTagStorageType == '\0') { return false; }\r
377         SkipToNextTag( *pTagStorageType, pTagData, numBytesParsed );\r
378         if (*pTagData == '\0') { return false; }\r
379     }\r
380     // return if the edit distance tag was not present\r
381     if ( !foundEditDistanceTag ) { return false; }\r
382 \r
383     // assign the editDistance value\r
384     std::memcpy(&editDistance, pTagData, 1);\r
385     return true;\r
386 }\r
387 \r
388 // get "RG" tag data\r
389 // stores data in 'readGroup', returns success/fail\r
390 inline \r
391 bool BamAlignment::GetReadGroup(std::string& readGroup) const {\r
392 \r
393     if ( TagData.empty() ) { return false; }\r
394 \r
395     // localize the tag data\r
396     char* pTagData = (char*)TagData.data();\r
397     const unsigned int tagDataLen = TagData.size();\r
398     unsigned int numBytesParsed = 0;\r
399 \r
400     bool foundReadGroupTag = false;\r
401     while( numBytesParsed < tagDataLen ) {\r
402 \r
403         const char* pTagType = pTagData;\r
404         const char* pTagStorageType = pTagData + 2;\r
405         pTagData       += 3;\r
406         numBytesParsed += 3;\r
407 \r
408         // check the current tag\r
409         if ( std::strncmp(pTagType, "RG", 2) == 0 ) {\r
410             foundReadGroupTag = true;\r
411             break;\r
412         }\r
413 \r
414         // get the storage class and find the next tag\r
415         if (*pTagStorageType == '\0') { return false; }\r
416         SkipToNextTag( *pTagStorageType, pTagData, numBytesParsed );\r
417         if (*pTagData == '\0') { return false; }\r
418     }\r
419 \r
420     // return if the read group tag was not present\r
421     if ( !foundReadGroupTag ) { return false; }\r
422 \r
423     // assign the read group\r
424     const unsigned int readGroupLen = std::strlen(pTagData);\r
425     readGroup.resize(readGroupLen);\r
426     std::memcpy( (char*)readGroup.data(), pTagData, readGroupLen );\r
427     return true;\r
428 }\r
429 \r
430 inline\r
431 bool BamAlignment::GetTag(const std::string& tag, std::string& destination) {\r
432   \r
433     if ( TagData.empty() ) { return false; }\r
434 \r
435     // localize the tag data\r
436     char* pTagData = (char*)TagData.data();\r
437     const unsigned int tagDataLen = TagData.size();\r
438     unsigned int numBytesParsed = 0;\r
439 \r
440     bool foundReadGroupTag = false;\r
441     while( numBytesParsed < tagDataLen ) {\r
442 \r
443         const char* pTagType = pTagData;\r
444         const char* pTagStorageType = pTagData + 2;\r
445         pTagData       += 3;\r
446         numBytesParsed += 3;\r
447 \r
448         // check the current tag\r
449         if ( std::strncmp(pTagType, tag.c_str(), 2) == 0 ) {\r
450             foundReadGroupTag = true;\r
451             break;\r
452         }\r
453 \r
454         // get the storage class and find the next tag\r
455         if (*pTagStorageType == '\0') { return false; }\r
456         SkipToNextTag( *pTagStorageType, pTagData, numBytesParsed );\r
457         if (*pTagData == '\0') { return false; }\r
458     }\r
459 \r
460     // return if the read group tag was not present\r
461     if ( !foundReadGroupTag ) { return false; }\r
462 \r
463     // assign the read group\r
464     const unsigned int dataLen = std::strlen(pTagData);\r
465     destination.resize(dataLen);\r
466     std::memcpy( (char*)destination.data(), pTagData, dataLen );\r
467     return true;\r
468 }\r
469 \r
470 template<typename T> \r
471 bool BamAlignment::GetTag(const std::string& tag, T& destination) {\r
472   \r
473     if ( TagData.empty() ) { return false; }\r
474 \r
475     // localize the tag data\r
476     char* pTagData = (char*)TagData.data();\r
477     const unsigned int tagDataLen = TagData.size();\r
478     unsigned int numBytesParsed = 0;\r
479 \r
480     bool foundDesiredTag = false;\r
481     while( numBytesParsed < tagDataLen ) {\r
482 \r
483         const char* pTagType = pTagData;\r
484         const char* pTagStorageType = pTagData + 2;\r
485         pTagData       += 3;\r
486         numBytesParsed += 3;\r
487 \r
488         // check the current tag\r
489         if ( strncmp(pTagType, tag.c_str(), 2) == 0 ) {\r
490             foundDesiredTag = true;\r
491             break;\r
492         }\r
493 \r
494         // get the storage class and find the next tag\r
495         if (*pTagStorageType == '\0') { return false; }\r
496         SkipToNextTag( *pTagStorageType, pTagData, numBytesParsed );\r
497         if (*pTagData == '\0') { return false; }\r
498     }\r
499     // return if the edit distance tag was not present\r
500     if ( !foundDesiredTag ) { return false; }\r
501 \r
502     // assign the editDistance value\r
503     std::memcpy(&destination, pTagData, sizeof(T));\r
504     return true;\r
505 }\r
506 \r
507 inline\r
508 void BamAlignment::SkipToNextTag(const char storageType, char* &pTagData, unsigned int& numBytesParsed) {\r
509     \r
510     switch(storageType) {\r
511 \r
512         case 'A':\r
513         case 'c':\r
514         case 'C':\r
515             ++numBytesParsed;\r
516             ++pTagData;\r
517             break;\r
518 \r
519         case 's':\r
520         case 'S':\r
521             numBytesParsed += 2;\r
522             pTagData       += 2;\r
523             break;\r
524 \r
525         case 'f':\r
526         case 'i':\r
527         case 'I':\r
528             numBytesParsed += 4;\r
529             pTagData       += 4;\r
530             break;\r
531 \r
532         case 'Z':\r
533         case 'H':\r
534             while(*pTagData) {\r
535                 ++numBytesParsed;\r
536                 ++pTagData;\r
537             }\r
538         // ---------------------------\r
539         // Added: 3-25-2010 DWB\r
540         // Contributed: ARQ\r
541         // Fixed: error parsing variable length tag data\r
542             ++pTagData;\r
543         // ---------------------------\r
544             break;\r
545 \r
546         default:\r
547             printf("ERROR: Unknown tag storage class encountered: [%c]\n", *pTagData);\r
548             exit(1);\r
549     }\r
550 }\r
551 \r
552 // ----------------------------------------------------------------\r
553 // Added: 3-35-2010 DWB\r
554 // Fixed: Routines to provide endian-correctness\r
555 // ----------------------------------------------------------------\r
556 \r
557 // returns true if system is big endian\r
558 inline bool SystemIsBigEndian(void) {\r
559    const uint16_t one = 0x0001;\r
560    return ((*(char*) &one) == 0 );\r
561 }\r
562 \r
563 // swaps endianness of 16-bit value 'in place'\r
564 inline void SwapEndian_16(int16_t& x) {\r
565     x = ((x >> 8) | (x << 8));\r
566 }\r
567 \r
568 inline void SwapEndian_16(uint16_t& x) {\r
569     x = ((x >> 8) | (x << 8));\r
570 }\r
571 \r
572 // swaps endianness of 32-bit value 'in-place'\r
573 inline void SwapEndian_32(int32_t& x) {\r
574     x = ( (x >> 24) | \r
575          ((x << 8) & 0x00FF0000) | \r
576          ((x >> 8) & 0x0000FF00) | \r
577           (x << 24)\r
578         );\r
579 }\r
580 \r
581 inline void SwapEndian_32(uint32_t& x) {\r
582     x = ( (x >> 24) | \r
583          ((x << 8) & 0x00FF0000) | \r
584          ((x >> 8) & 0x0000FF00) | \r
585           (x << 24)\r
586         );\r
587 }\r
588 \r
589 // swaps endianness of 64-bit value 'in-place'\r
590 inline void SwapEndian_64(int64_t& x) {\r
591     x = ( (x >> 56) | \r
592          ((x << 40) & 0x00FF000000000000ll) |\r
593          ((x << 24) & 0x0000FF0000000000ll) |\r
594          ((x << 8)  & 0x000000FF00000000ll) |\r
595          ((x >> 8)  & 0x00000000FF000000ll) |\r
596          ((x >> 24) & 0x0000000000FF0000ll) |\r
597          ((x >> 40) & 0x000000000000FF00ll) |\r
598           (x << 56)\r
599         );\r
600 }\r
601 \r
602 inline void SwapEndian_64(uint64_t& x) {\r
603     x = ( (x >> 56) | \r
604          ((x << 40) & 0x00FF000000000000ll) |\r
605          ((x << 24) & 0x0000FF0000000000ll) |\r
606          ((x << 8)  & 0x000000FF00000000ll) |\r
607          ((x >> 8)  & 0x00000000FF000000ll) |\r
608          ((x >> 24) & 0x0000000000FF0000ll) |\r
609          ((x >> 40) & 0x000000000000FF00ll) |\r
610           (x << 56)\r
611         );\r
612 }\r
613 \r
614 // swaps endianness of 'next 2 bytes' in a char buffer (in-place)\r
615 inline void SwapEndian_16p(char* data) {\r
616     uint16_t& value = (uint16_t&)*data; \r
617     SwapEndian_16(value);\r
618 }\r
619 \r
620 // swaps endianness of 'next 4 bytes' in a char buffer (in-place)\r
621 inline void SwapEndian_32p(char* data) {\r
622     uint32_t& value = (uint32_t&)*data; \r
623     SwapEndian_32(value);\r
624 }\r
625 \r
626 // swaps endianness of 'next 8 bytes' in a char buffer (in-place)\r
627 inline void SwapEndian_64p(char* data) {\r
628     uint64_t& value = (uint64_t&)*data; \r
629     SwapEndian_64(value);\r
630 }\r
631 \r
632 } // namespace BamTools\r
633 \r
634 #endif // BAMAUX_H\r