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: 22 July 2010 (DB)
\r
7 // ---------------------------------------------------------------------------
\r
8 // Provides the basic constants, data structures, etc. for using BAM files
\r
9 // ***************************************************************************
\r
21 #include <exception>
\r
30 // Platform-specific type definitions
\r
31 #ifndef BAMTOOLS_TYPES
\r
32 #define BAMTOOLS_TYPES
\r
34 typedef char int8_t;
\r
35 typedef unsigned char uint8_t;
\r
36 typedef short int16_t;
\r
37 typedef unsigned short uint16_t;
\r
38 typedef int int32_t;
\r
39 typedef unsigned int uint32_t;
\r
40 typedef long long int64_t;
\r
41 typedef unsigned long long uint64_t;
\r
45 #endif // BAMTOOLS_TYPES
\r
47 namespace BamTools {
\r
50 const int BAM_CORE_SIZE = 32;
\r
51 const int BAM_CMATCH = 0;
\r
52 const int BAM_CINS = 1;
\r
53 const int BAM_CDEL = 2;
\r
54 const int BAM_CREF_SKIP = 3;
\r
55 const int BAM_CSOFT_CLIP = 4;
\r
56 const int BAM_CHARD_CLIP = 5;
\r
57 const int BAM_CPAD = 6;
\r
58 const int BAM_CIGAR_SHIFT = 4;
\r
59 const int BAM_CIGAR_MASK = ((1 << BAM_CIGAR_SHIFT) - 1);
\r
61 // BAM index constants
\r
62 const int MAX_BIN = 37450; // =(8^6-1)/7+1
\r
63 const int BAM_MIN_CHUNK_GAP = 32768;
\r
64 const int BAM_LIDX_SHIFT = 14;
\r
66 // Explicit variable sizes
\r
67 const int BT_SIZEOF_INT = 4;
\r
71 struct BamAlignment {
\r
73 // constructors & destructor
\r
76 BamAlignment(const BamAlignment& other);
\r
77 ~BamAlignment(void);
\r
79 // Queries against alignment flags
\r
81 bool IsDuplicate(void) const; // Returns true if this read is a PCR duplicate
\r
82 bool IsFailedQC(void) const; // Returns true if this read failed quality control
\r
83 bool IsFirstMate(void) const; // Returns true if alignment is first mate on read
\r
84 bool IsMapped(void) const; // Returns true if alignment is mapped
\r
85 bool IsMateMapped(void) const; // Returns true if alignment's mate is mapped
\r
86 bool IsMateReverseStrand(void) const; // Returns true if alignment's mate mapped to reverse strand
\r
87 bool IsPaired(void) const; // Returns true if alignment part of paired-end read
\r
88 bool IsPrimaryAlignment(void) const; // Returns true if reported position is primary alignment
\r
89 bool IsProperPair(void) const; // Returns true if alignment is part of read that satisfied paired-end resolution
\r
90 bool IsReverseStrand(void) const; // Returns true if alignment mapped to reverse strand
\r
91 bool IsSecondMate(void) const; // Returns true if alignment is second mate on read
\r
93 // Manipulate alignment flags
\r
95 void SetIsDuplicate(bool ok); // Sets "PCR duplicate" flag
\r
96 void SetIsFailedQC(bool ok); // Sets "failed quality control" flag
\r
97 void SetIsFirstMate(bool ok); // Sets "alignment is first mate" flag
\r
98 void SetIsMateUnmapped(bool ok); // Sets "alignment's mate is mapped" flag
\r
99 void SetIsMateReverseStrand(bool ok); // Sets "alignment's mate mapped to reverse strand" flag
\r
100 void SetIsPaired(bool ok); // Sets "alignment part of paired-end read" flag
\r
101 void SetIsProperPair(bool ok); // Sets "alignment is part of read that satisfied paired-end resolution" flag
\r
102 void SetIsReverseStrand(bool ok); // Sets "alignment mapped to reverse strand" flag
\r
103 void SetIsSecondaryAlignment(bool ok); // Sets "position is primary alignment" flag
\r
104 void SetIsSecondMate(bool ok); // Sets "alignment is second mate on read" flag
\r
105 void SetIsUnmapped(bool ok); // Sets "alignment is mapped" flag
\r
107 // Tag data access methods
\r
109 // generic tag data access methods
\r
110 bool GetTag(const std::string& tag, std::string& destination) const; // access variable-length char or hex strings
\r
111 bool GetTag(const std::string& tag, uint32_t& destination) const; // access unsigned integer data
\r
112 bool GetTag(const std::string& tag, int32_t& destination) const; // access signed integer data
\r
113 bool GetTag(const std::string& tag, float& destination) const; // access floating point data
\r
115 // specific tag data access methods - only remain here for legacy support
\r
116 bool GetEditDistance(uint8_t& editDistance) const; // get "NM" tag data - contributed by Aaron Quinlan
\r
117 bool GetReadGroup(std::string& readGroup) const; // get "RG" tag data
\r
120 // Additional data access methods
\r
122 int GetEndPosition(bool usePadded = false) const; // calculates alignment end position, based on starting position and CIGAR operations
\r
124 // 'internal' utility methods
\r
126 static bool SkipToNextTag(const char storageType, char* &pTagData, unsigned int& numBytesParsed);
\r
130 std::string Name; // Read name
\r
131 int32_t Length; // Query length
\r
132 std::string QueryBases; // 'Original' sequence (as reported from sequencing machine)
\r
133 std::string AlignedBases; // 'Aligned' sequence (includes any indels, padding, clipping)
\r
134 std::string Qualities; // FASTQ qualities (ASCII characters, not numeric values)
\r
135 std::string TagData; // Tag data (accessor methods will pull the requested information out)
\r
136 int32_t RefID; // ID number for reference sequence
\r
137 int32_t Position; // Position (0-based) where alignment starts
\r
138 uint16_t Bin; // Bin in BAM file where this alignment resides
\r
139 uint16_t MapQuality; // Mapping quality score
\r
140 uint32_t AlignmentFlag; // Alignment bit-flag - see Is<something>() methods to query this value, SetIs<something>() methods to manipulate
\r
141 std::vector<CigarOp> CigarData; // CIGAR operations for this alignment
\r
142 int32_t MateRefID; // ID number for reference sequence where alignment's mate was aligned
\r
143 int32_t MatePosition; // Position (0-based) where alignment's mate starts
\r
144 int32_t InsertSize; // Mate-pair insert size
\r
147 struct BamAlignmentSupportData {
\r
150 std::string AllCharData;
\r
151 uint32_t BlockLength;
\r
152 uint32_t NumCigarOperations;
\r
153 uint32_t QueryNameLength;
\r
154 uint32_t QuerySequenceLength;
\r
158 BamAlignmentSupportData(void)
\r
160 , NumCigarOperations(0)
\r
161 , QueryNameLength(0)
\r
162 , QuerySequenceLength(0)
\r
163 , HasCoreOnly(false)
\r
167 BamAlignmentSupportData SupportData; // Contains raw character data & lengths
\r
169 // Alignment flag query constants
\r
170 // Use the get/set methods above instead
\r
175 , MATE_UNMAPPED = 8
\r
177 , MATE_REVERSE = 32
\r
182 , DUPLICATE = 1024
\r
186 // ----------------------------------------------------------------
\r
187 // Auxiliary data structs & typedefs
\r
192 char Type; // Operation type (MIDNSHP)
\r
193 uint32_t Length; // Operation length (number of bases)
\r
196 CigarOp(const char type = '\0',
\r
197 const uint32_t length = 0)
\r
206 std::string RefName; // Name of reference sequence
\r
207 int32_t RefLength; // Length of reference sequence
\r
208 bool RefHasAlignments; // True if BAM file contains alignments mapped to reference sequence
\r
211 RefData(const int32_t& length = 0,
\r
213 : RefLength(length)
\r
214 , RefHasAlignments(ok)
\r
218 typedef std::vector<RefData> RefVector;
\r
219 typedef std::vector<BamAlignment> BamAlignmentVector;
\r
230 BamRegion(const int& leftID = -1,
\r
231 const int& leftPos = -1,
\r
232 const int& rightID = -1,
\r
233 const int& rightPos = -1)
\r
234 : LeftRefID(leftID)
\r
235 , LeftPosition(leftPos)
\r
236 , RightRefID(rightID)
\r
237 , RightPosition(rightPos)
\r
241 // ----------------------------------------------------------------
\r
242 // BamAlignment member methods
\r
244 // constructors & destructor
\r
246 BamAlignment::BamAlignment(void) { }
\r
249 BamAlignment::BamAlignment(const BamAlignment& other)
\r
251 , Length(other.Length)
\r
252 , QueryBases(other.QueryBases)
\r
253 , AlignedBases(other.AlignedBases)
\r
254 , Qualities(other.Qualities)
\r
255 , TagData(other.TagData)
\r
256 , RefID(other.RefID)
\r
257 , Position(other.Position)
\r
259 , MapQuality(other.MapQuality)
\r
260 , AlignmentFlag(other.AlignmentFlag)
\r
261 , CigarData(other.CigarData)
\r
262 , MateRefID(other.MateRefID)
\r
263 , MatePosition(other.MatePosition)
\r
264 , InsertSize(other.InsertSize)
\r
265 , SupportData(other.SupportData)
\r
269 BamAlignment::~BamAlignment(void) { }
\r
271 // Queries against alignment flags
\r
272 inline bool BamAlignment::IsDuplicate(void) const { return ( (AlignmentFlag & DUPLICATE) != 0 ); }
\r
273 inline bool BamAlignment::IsFailedQC(void) const { return ( (AlignmentFlag & QC_FAILED) != 0 ); }
\r
274 inline bool BamAlignment::IsFirstMate(void) const { return ( (AlignmentFlag & READ_1) != 0 ); }
\r
275 inline bool BamAlignment::IsMapped(void) const { return ( (AlignmentFlag & UNMAPPED) == 0 ); }
\r
276 inline bool BamAlignment::IsMateMapped(void) const { return ( (AlignmentFlag & MATE_UNMAPPED) == 0 ); }
\r
277 inline bool BamAlignment::IsMateReverseStrand(void) const { return ( (AlignmentFlag & MATE_REVERSE) != 0 ); }
\r
278 inline bool BamAlignment::IsPaired(void) const { return ( (AlignmentFlag & PAIRED) != 0 ); }
\r
279 inline bool BamAlignment::IsPrimaryAlignment(void) const { return ( (AlignmentFlag & SECONDARY) == 0 ); }
\r
280 inline bool BamAlignment::IsProperPair(void) const { return ( (AlignmentFlag & PROPER_PAIR) != 0 ); }
\r
281 inline bool BamAlignment::IsReverseStrand(void) const { return ( (AlignmentFlag & REVERSE) != 0 ); }
\r
282 inline bool BamAlignment::IsSecondMate(void) const { return ( (AlignmentFlag & READ_2) != 0 ); }
\r
284 // Manipulate alignment flags
\r
285 inline void BamAlignment::SetIsDuplicate(bool ok) { if (ok) AlignmentFlag |= DUPLICATE; else AlignmentFlag &= ~DUPLICATE; }
\r
286 inline void BamAlignment::SetIsFailedQC(bool ok) { if (ok) AlignmentFlag |= QC_FAILED; else AlignmentFlag &= ~QC_FAILED; }
\r
287 inline void BamAlignment::SetIsFirstMate(bool ok) { if (ok) AlignmentFlag |= READ_1; else AlignmentFlag &= ~READ_1; }
\r
288 inline void BamAlignment::SetIsMateUnmapped(bool ok) { if (ok) AlignmentFlag |= MATE_UNMAPPED; else AlignmentFlag &= ~MATE_UNMAPPED; }
\r
289 inline void BamAlignment::SetIsMateReverseStrand(bool ok) { if (ok) AlignmentFlag |= MATE_REVERSE; else AlignmentFlag &= ~MATE_REVERSE; }
\r
290 inline void BamAlignment::SetIsPaired(bool ok) { if (ok) AlignmentFlag |= PAIRED; else AlignmentFlag &= ~PAIRED; }
\r
291 inline void BamAlignment::SetIsProperPair(bool ok) { if (ok) AlignmentFlag |= PROPER_PAIR; else AlignmentFlag &= ~PROPER_PAIR; }
\r
292 inline void BamAlignment::SetIsReverseStrand(bool ok) { if (ok) AlignmentFlag |= REVERSE; else AlignmentFlag &= ~REVERSE; }
\r
293 inline void BamAlignment::SetIsSecondaryAlignment(bool ok) { if (ok) AlignmentFlag |= SECONDARY; else AlignmentFlag &= ~SECONDARY; }
\r
294 inline void BamAlignment::SetIsSecondMate(bool ok) { if (ok) AlignmentFlag |= READ_2; else AlignmentFlag &= ~READ_2; }
\r
295 inline void BamAlignment::SetIsUnmapped(bool ok) { if (ok) AlignmentFlag |= UNMAPPED; else AlignmentFlag &= ~UNMAPPED; }
\r
297 // calculates alignment end position, based on starting position and CIGAR operations
\r
299 int BamAlignment::GetEndPosition(bool usePadded) const {
\r
301 // initialize alignment end to starting position
\r
302 int alignEnd = Position;
\r
304 // iterate over cigar operations
\r
305 std::vector<CigarOp>::const_iterator cigarIter = CigarData.begin();
\r
306 std::vector<CigarOp>::const_iterator cigarEnd = CigarData.end();
\r
307 for ( ; cigarIter != cigarEnd; ++cigarIter) {
\r
308 const char cigarType = (*cigarIter).Type;
\r
309 if ( cigarType == 'M' || cigarType == 'D' || cigarType == 'N' ) {
\r
310 alignEnd += (*cigarIter).Length;
\r
312 else if ( usePadded && cigarType == 'I' ) {
\r
313 alignEnd += (*cigarIter).Length;
\r
319 // get "NM" tag data - contributed by Aaron Quinlan
\r
320 // stores data in 'editDistance', returns success/fail
\r
322 bool BamAlignment::GetEditDistance(uint8_t& editDistance) const {
\r
324 // make sure tag data exists
\r
325 if ( TagData.empty() ) return false;
\r
327 // localize the tag data
\r
328 char* pTagData = (char*)TagData.data();
\r
329 const unsigned int tagDataLen = TagData.size();
\r
330 unsigned int numBytesParsed = 0;
\r
332 bool foundEditDistanceTag = false;
\r
333 while ( numBytesParsed < tagDataLen ) {
\r
335 const char* pTagType = pTagData;
\r
336 const char* pTagStorageType = pTagData + 2;
\r
338 numBytesParsed += 3;
\r
340 // check the current tag
\r
341 if ( strncmp(pTagType, "NM", 2) == 0 ) {
\r
342 foundEditDistanceTag = true;
\r
346 // get the storage class and find the next tag
\r
347 if ( *pTagStorageType == '\0' ) return false;
\r
348 if ( !SkipToNextTag(*pTagStorageType, pTagData, numBytesParsed) ) return false;
\r
349 if ( *pTagData == '\0' ) return false;
\r
351 // return if the edit distance tag was not present
\r
352 if ( !foundEditDistanceTag ) return false;
\r
354 // assign the editDistance value
\r
355 std::memcpy(&editDistance, pTagData, 1);
\r
359 // get "RG" tag data
\r
360 // stores data in 'readGroup', returns success/fail
\r
362 bool BamAlignment::GetReadGroup(std::string& readGroup) const {
\r
364 // make sure tag data exists
\r
365 if ( TagData.empty() ) return false;
\r
367 // localize the tag data
\r
368 char* pTagData = (char*)TagData.data();
\r
369 const unsigned int tagDataLen = TagData.size();
\r
370 unsigned int numBytesParsed = 0;
\r
372 bool foundReadGroupTag = false;
\r
373 while( numBytesParsed < tagDataLen ) {
\r
375 const char* pTagType = pTagData;
\r
376 const char* pTagStorageType = pTagData + 2;
\r
378 numBytesParsed += 3;
\r
380 // check the current tag
\r
381 if ( std::strncmp(pTagType, "RG", 2) == 0 ) {
\r
382 foundReadGroupTag = true;
\r
386 // get the storage class and find the next tag
\r
387 if ( *pTagStorageType == '\0' ) return false;
\r
388 if ( !SkipToNextTag(*pTagStorageType, pTagData, numBytesParsed) ) return false;
\r
389 if ( *pTagData == '\0' ) return false;
\r
392 // return if the read group tag was not present
\r
393 if ( !foundReadGroupTag ) return false;
\r
395 // assign the read group
\r
396 const unsigned int readGroupLen = std::strlen(pTagData);
\r
397 readGroup.resize(readGroupLen);
\r
398 std::memcpy( (char*)readGroup.data(), pTagData, readGroupLen );
\r
403 bool BamAlignment::GetTag(const std::string& tag, std::string& destination) const {
\r
405 // make sure tag data exists
\r
406 if ( TagData.empty() ) return false;
\r
408 // localize the tag data
\r
409 char* pTagData = (char*)TagData.data();
\r
410 const unsigned int tagDataLen = TagData.size();
\r
411 unsigned int numBytesParsed = 0;
\r
413 bool foundReadGroupTag = false;
\r
414 while ( numBytesParsed < tagDataLen ) {
\r
416 const char* pTagType = pTagData;
\r
417 const char* pTagStorageType = pTagData + 2;
\r
419 numBytesParsed += 3;
\r
421 // check the current tag
\r
422 if ( std::strncmp(pTagType, tag.c_str(), 2) == 0 ) {
\r
423 foundReadGroupTag = true;
\r
427 // get the storage class and find the next tag
\r
428 if ( *pTagStorageType == '\0' ) return false;
\r
429 if ( !SkipToNextTag(*pTagStorageType, pTagData, numBytesParsed) ) return false;
\r
430 if ( *pTagData == '\0' ) return false;
\r
433 // return if the read group tag was not present
\r
434 if ( !foundReadGroupTag ) return false;
\r
436 // assign the read group
\r
437 const unsigned int dataLen = std::strlen(pTagData);
\r
438 destination.resize(dataLen);
\r
439 std::memcpy( (char*)destination.data(), pTagData, dataLen );
\r
444 bool BamAlignment::GetTag(const std::string& tag, uint32_t& destination) const {
\r
446 // make sure data exists
\r
447 if ( TagData.empty() ) return false;
\r
449 // clear out destination
\r
452 // localize the tag data
\r
453 char* pTagData = (char*)TagData.data();
\r
454 const unsigned int tagDataLen = TagData.size();
\r
455 unsigned int numBytesParsed = 0;
\r
457 int destinationLength = 0;
\r
458 bool foundDesiredTag = false;
\r
459 while ( numBytesParsed < tagDataLen ) {
\r
461 const char* pTagType = pTagData;
\r
462 const char* pTagStorageType = pTagData + 2;
\r
464 numBytesParsed += 3;
\r
466 // check the current tag
\r
467 if ( strncmp(pTagType, tag.c_str(), 2) == 0 ) {
\r
469 // determine actual length of data depending on tag type
\r
470 // this is necessary because some tags may be of variable byte-lengths (i.e. char or short)
\r
471 const char type = *pTagStorageType;
\r
478 destinationLength = 1;
\r
484 destinationLength = 2;
\r
490 destinationLength = 4;
\r
493 // unsupported type for integer destination (float & var-length strings)
\r
497 printf("ERROR: Cannot store tag of type %c in integer destination\n", type);
\r
500 // unknown tag type
\r
502 printf("ERROR: Unknown tag storage class encountered: [%c]\n", *pTagData);
\r
506 foundDesiredTag = true;
\r
510 // get the storage class and find the next tag
\r
511 if ( *pTagStorageType == '\0' ) return false;
\r
512 if ( !SkipToNextTag(*pTagStorageType, pTagData, numBytesParsed) ) return false;
\r
513 if ( *pTagData == '\0' ) return false;
\r
515 // return if the edit distance tag was not present
\r
516 if ( !foundDesiredTag ) return false;
\r
518 // assign the editDistance value
\r
519 std::memcpy(&destination, pTagData, destinationLength);
\r
524 bool BamAlignment::GetTag(const std::string& tag, int32_t& destination) const {
\r
525 return GetTag(tag, (uint32_t&)destination);
\r
529 bool BamAlignment::GetTag(const std::string& tag, float& destination) const {
\r
531 // make sure data exists
\r
532 if ( TagData.empty() ) return false;
\r
534 // clear out destination
\r
537 // localize the tag data
\r
538 char* pTagData = (char*)TagData.data();
\r
539 const unsigned int tagDataLen = TagData.size();
\r
540 unsigned int numBytesParsed = 0;
\r
542 int destinationLength = 0;
\r
543 bool foundDesiredTag = false;
\r
544 while( numBytesParsed < tagDataLen ) {
\r
546 const char* pTagType = pTagData;
\r
547 const char* pTagStorageType = pTagData + 2;
\r
549 numBytesParsed += 3;
\r
551 // check the current tag
\r
552 if ( strncmp(pTagType, tag.c_str(), 2) == 0 ) {
\r
554 // determine actual length of data depending on tag type
\r
555 // this is necessary because some tags may be of variable byte-lengths (i.e. char or short)
\r
556 const char type = *pTagStorageType;
\r
563 destinationLength = 1;
\r
569 destinationLength = 2;
\r
576 destinationLength = 4;
\r
579 // unsupported type (var-length strings)
\r
582 printf("ERROR: Cannot store tag of type %c in integer destination\n", type);
\r
585 // unknown tag type
\r
587 printf("ERROR: Unknown tag storage class encountered: [%c]\n", *pTagData);
\r
591 foundDesiredTag = true;
\r
595 // get the storage class and find the next tag
\r
596 if ( *pTagStorageType == '\0' ) return false;
\r
597 if ( !SkipToNextTag(*pTagStorageType, pTagData, numBytesParsed) ) return false;
\r
598 if ( *pTagData == '\0' ) return false;
\r
600 // return if the edit distance tag was not present
\r
601 if ( !foundDesiredTag ) return false;
\r
603 // assign the editDistance value
\r
604 std::memcpy(&destination, pTagData, destinationLength);
\r
609 bool BamAlignment::SkipToNextTag(const char storageType, char* &pTagData, unsigned int& numBytesParsed) {
\r
611 switch(storageType) {
\r
622 numBytesParsed += 2;
\r
629 numBytesParsed += 4;
\r
639 // ---------------------------
\r
640 // Added: 3-25-2010 DWB
\r
641 // Contributed: ARQ
\r
642 // Fixed: error parsing variable length tag data
\r
644 // ---------------------------
\r
649 printf("ERROR: Unknown tag storage class encountered: [%c]\n", *pTagData);
\r
657 // ----------------------------------------------------------------
\r
658 // Added: 3-35-2010 DWB
\r
659 // Fixed: Routines to provide endian-correctness
\r
660 // ----------------------------------------------------------------
\r
662 // returns true if system is big endian
\r
663 inline bool SystemIsBigEndian(void) {
\r
664 const uint16_t one = 0x0001;
\r
665 return ((*(char*) &one) == 0 );
\r
668 // swaps endianness of 16-bit value 'in place'
\r
669 inline void SwapEndian_16(int16_t& x) {
\r
670 x = ((x >> 8) | (x << 8));
\r
673 inline void SwapEndian_16(uint16_t& x) {
\r
674 x = ((x >> 8) | (x << 8));
\r
677 // swaps endianness of 32-bit value 'in-place'
\r
678 inline void SwapEndian_32(int32_t& x) {
\r
680 ((x << 8) & 0x00FF0000) |
\r
681 ((x >> 8) & 0x0000FF00) |
\r
686 inline void SwapEndian_32(uint32_t& x) {
\r
688 ((x << 8) & 0x00FF0000) |
\r
689 ((x >> 8) & 0x0000FF00) |
\r
694 // swaps endianness of 64-bit value 'in-place'
\r
695 inline void SwapEndian_64(int64_t& x) {
\r
697 ((x << 40) & 0x00FF000000000000ll) |
\r
698 ((x << 24) & 0x0000FF0000000000ll) |
\r
699 ((x << 8) & 0x000000FF00000000ll) |
\r
700 ((x >> 8) & 0x00000000FF000000ll) |
\r
701 ((x >> 24) & 0x0000000000FF0000ll) |
\r
702 ((x >> 40) & 0x000000000000FF00ll) |
\r
707 inline void SwapEndian_64(uint64_t& x) {
\r
709 ((x << 40) & 0x00FF000000000000ll) |
\r
710 ((x << 24) & 0x0000FF0000000000ll) |
\r
711 ((x << 8) & 0x000000FF00000000ll) |
\r
712 ((x >> 8) & 0x00000000FF000000ll) |
\r
713 ((x >> 24) & 0x0000000000FF0000ll) |
\r
714 ((x >> 40) & 0x000000000000FF00ll) |
\r
719 // swaps endianness of 'next 2 bytes' in a char buffer (in-place)
\r
720 inline void SwapEndian_16p(char* data) {
\r
721 uint16_t& value = (uint16_t&)*data;
\r
722 SwapEndian_16(value);
\r
725 // swaps endianness of 'next 4 bytes' in a char buffer (in-place)
\r
726 inline void SwapEndian_32p(char* data) {
\r
727 uint32_t& value = (uint32_t&)*data;
\r
728 SwapEndian_32(value);
\r
731 // swaps endianness of 'next 8 bytes' in a char buffer (in-place)
\r
732 inline void SwapEndian_64p(char* data) {
\r
733 uint64_t& value = (uint64_t&)*data;
\r
734 SwapEndian_64(value);
\r
737 } // namespace BamTools
\r