1 // ***************************************************************************
2 // BamHeader_p.cpp (c) 2010 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // All rights reserved.
5 // ---------------------------------------------------------------------------
6 // Last modified: 21 March 2011 (DB)
7 // ---------------------------------------------------------------------------
8 // Provides the basic functionality for handling BAM headers.
9 // ***************************************************************************
11 #include <api/BamAux.h>
12 #include <api/BamConstants.h>
13 #include <api/internal/BamHeader_p.h>
14 #include <api/internal/BgzfStream_p.h>
15 using namespace BamTools;
16 using namespace BamTools::Internal;
25 BamHeader::BamHeader(void) { }
28 BamHeader::~BamHeader(void) { }
30 // reads magic number from BGZF stream, returns true if valid
31 bool BamHeader::CheckMagicNumber(BgzfStream* stream) {
33 // try to read magic number
34 char buffer[Constants::BAM_HEADER_MAGIC_LENGTH];
35 if ( stream->Read(buffer, Constants::BAM_HEADER_MAGIC_LENGTH) != (int)Constants::BAM_HEADER_MAGIC_LENGTH ) {
36 fprintf(stderr, "BamHeader ERROR: could not read magic number\n");
40 // validate magic number
41 if ( strncmp(buffer, Constants::BAM_HEADER_MAGIC, Constants::BAM_HEADER_MAGIC_LENGTH) != 0 ) {
42 fprintf(stderr, "BamHeader ERROR: invalid magic number\n");
50 // clear SamHeader data
51 void BamHeader::Clear(void) {
55 // return true if SamHeader data is valid
56 bool BamHeader::IsValid(void) const {
57 return m_header.IsValid();
60 // load BAM header ('magic number' and SAM header text) from BGZF stream
61 // returns true if all OK
62 bool BamHeader::Load(BgzfStream* stream) {
64 // cannot load if invalid stream
68 // cannot load if magic number is invalid
69 if ( !CheckMagicNumber(stream) )
72 // cannot load header if cannot read header length
74 if ( !ReadHeaderLength(stream, length) )
77 // cannot load header if cannot read header text
78 if ( !ReadHeaderText(stream, length) )
81 // otherwise, everything OK
85 // reads SAM header text length from BGZF stream, stores it in @length
86 // returns read success/fail status
87 bool BamHeader::ReadHeaderLength(BgzfStream* stream, uint32_t& length) {
89 // attempt to read BAM header text length
90 char buffer[sizeof(uint32_t)];
91 if ( stream->Read(buffer, sizeof(uint32_t)) != sizeof(uint32_t) ) {
92 fprintf(stderr, "BamHeader ERROR: could not read header length\n");
96 // convert char buffer to length, return success
97 length = BamTools::UnpackUnsignedInt(buffer);
98 if ( BamTools::SystemIsBigEndian() )
99 BamTools::SwapEndian_32(length);
103 // reads SAM header text from BGZF stream, stores in SamHeader object
104 // returns read success/fail status
105 bool BamHeader::ReadHeaderText(BgzfStream* stream, const uint32_t& length) {
107 // set up destination buffer
108 char* headerText = (char*)calloc(length + 1, 1);
110 // attempt to read header text
111 const unsigned bytesRead = stream->Read(headerText, length);
112 const bool readOk = ( bytesRead == length );
114 m_header.SetHeaderText( (string)((const char*)headerText) );
116 fprintf(stderr, "BamHeader ERROR: could not read header text\n");
118 // clean up calloc-ed temp variable (on success or fail)
121 // return read success
125 // returns *copy* of SamHeader data object
126 SamHeader BamHeader::ToSamHeader(void) const {
130 // returns SAM-formatted string of header data
131 string BamHeader::ToString(void) const {
132 return m_header.ToString();