1 // ***************************************************************************
2 // BamHeader_p.cpp (c) 2010 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 10 October 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides the basic functionality for handling BAM headers.
8 // ***************************************************************************
10 #include "api/BamAux.h"
11 #include "api/BamConstants.h"
12 #include "api/internal/BamException_p.h"
13 #include "api/internal/BamHeader_p.h"
14 #include "api/internal/BgzfStream_p.h"
15 using namespace BamTools;
16 using namespace BamTools::Internal;
22 // ------------------------
23 // static utility methods
24 // ------------------------
27 bool isValidMagicNumber(const char* buffer) {
28 return ( strncmp(buffer, Constants::BAM_HEADER_MAGIC,
29 Constants::BAM_HEADER_MAGIC_LENGTH) == 0 );
32 // --------------------------
33 // BamHeader implementation
34 // --------------------------
37 BamHeader::BamHeader(void) { }
40 BamHeader::~BamHeader(void) { }
42 // reads magic number from BGZF stream, returns true if valid
43 void BamHeader::CheckMagicNumber(BgzfStream* stream) {
45 // try to read magic number
46 char buffer[Constants::BAM_HEADER_MAGIC_LENGTH];
47 const size_t numBytesRead = stream->Read(buffer, Constants::BAM_HEADER_MAGIC_LENGTH);
48 if ( numBytesRead != (int)Constants::BAM_HEADER_MAGIC_LENGTH )
49 throw BamException("BamHeader::CheckMagicNumber", "could not read magic number");
51 // validate magic number
52 if ( !isValidMagicNumber(buffer) )
53 throw BamException("BamHeader::CheckMagicNumber", "invalid magic number");
56 // clear SamHeader data
57 void BamHeader::Clear(void) {
61 // return true if SamHeader data is valid
62 bool BamHeader::IsValid(void) const {
63 return m_header.IsValid();
66 // load BAM header ('magic number' and SAM header text) from BGZF stream
67 void BamHeader::Load(BgzfStream* stream) {
69 // read & check magic number
70 CheckMagicNumber(stream);
72 // read header (length, then actual text)
74 ReadHeaderLength(stream, length);
75 ReadHeaderText(stream, length);
78 // reads SAM header text length from BGZF stream, stores it in @length
79 void BamHeader::ReadHeaderLength(BgzfStream* stream, uint32_t& length) {
81 // read BAM header text length
82 char buffer[sizeof(uint32_t)];
83 const size_t numBytesRead = stream->Read(buffer, sizeof(uint32_t));
84 if ( numBytesRead != sizeof(uint32_t) )
85 throw BamException("BamHeader::ReadHeaderLength", "could not read header length");
87 // convert char buffer to length
88 length = BamTools::UnpackUnsignedInt(buffer);
89 if ( BamTools::SystemIsBigEndian() )
90 BamTools::SwapEndian_32(length);
93 // reads SAM header text from BGZF stream, stores in SamHeader object
94 void BamHeader::ReadHeaderText(BgzfStream* stream, const uint32_t& length) {
97 char* headerText = (char*)calloc(length + 1, 1);
98 const size_t bytesRead = stream->Read(headerText, length);
100 // if error reading, clean up buffer & throw
101 if ( bytesRead != length ) {
103 throw BamException("BamHeader::ReadHeaderText", "could not read header text");
106 // otherwise, text was read OK
108 m_header.SetHeaderText( (string)((const char*)headerText) );
112 // returns *copy* of SamHeader data object
113 SamHeader BamHeader::ToSamHeader(void) const {
117 // returns SAM-formatted string of header data
118 string BamHeader::ToString(void) const {
119 return m_header.ToString();