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: 25 December 2010 (DB)
7 // ---------------------------------------------------------------------------
8 // Provides the basic functionality for handling BAM headers.
9 // ***************************************************************************
11 #include <api/BamAux.h>
12 #include <api/BamConstants.h>
14 #include <api/internal/BamHeader_p.h>
15 using namespace BamTools;
16 using namespace BamTools::Internal;
24 // ---------------------------------
25 // BamHeaderPrivate implementation
27 struct BamHeader::BamHeaderPrivate {
30 SamHeader* m_samHeader;
33 BamHeaderPrivate(void)
38 bool Load(BgzfData* stream);
41 bool CheckMagicNumber(BgzfData* stream);
42 bool ReadHeaderLength(BgzfData* stream, uint32_t& length);
43 bool ReadHeaderText(BgzfData* stream, const uint32_t& length);
46 bool BamHeader::BamHeaderPrivate::Load(BgzfData* stream) {
48 // cannot load if invalid stream
52 // cannot load if magic number is invalid
53 if ( !CheckMagicNumber(stream) )
56 // cannot load header if cannot read header length
58 if ( !ReadHeaderLength(stream, length) )
61 // cannot load header if cannot read header text
62 if ( !ReadHeaderText(stream, length) )
65 // otherwise, everything OK
69 bool BamHeader::BamHeaderPrivate::CheckMagicNumber(BgzfData* stream) {
71 // try to read magic number
72 char buffer[Constants::BAM_HEADER_MAGIC_SIZE];
73 if ( stream->Read(buffer, Constants::BAM_HEADER_MAGIC_SIZE) != (int)Constants::BAM_HEADER_MAGIC_SIZE ) {
74 fprintf(stderr, "BAM header error - could not read magic number\n");
78 // validate magic number
79 if ( strncmp(buffer, Constants::BAM_HEADER_MAGIC, Constants::BAM_HEADER_MAGIC_SIZE) != 0 ) {
80 fprintf(stderr, "BAM header error - invalid magic number\n");
88 bool BamHeader::BamHeaderPrivate::ReadHeaderLength(BgzfData* stream, uint32_t& length) {
90 // attempt to read BAM header text length
91 char buffer[sizeof(uint32_t)];
92 if ( stream->Read(buffer, sizeof(uint32_t)) != sizeof(uint32_t) ) {
93 fprintf(stderr, "BAM header error - could not read header length\n");
97 // convert char buffer to length, return success
98 length = BgzfData::UnpackUnsignedInt(buffer);
99 if ( BamTools::SystemIsBigEndian() )
100 SwapEndian_32(length);
104 bool BamHeader::BamHeaderPrivate::ReadHeaderText(BgzfData* stream, const uint32_t& length) {
106 // set up destination buffer
107 char* headerText = (char*)calloc(length + 1, 1);
109 // attempt to read header text
110 const unsigned bytesRead = stream->Read(headerText, length);
111 const bool readOk = ( bytesRead == length );
113 m_samHeader = new SamHeader( (string)((const char*)headerText) );
115 fprintf(stderr, "BAM header error - could not read header text\n");
117 // clean up calloc-ed temp variable (on success or fail)
120 // return read success
124 // --------------------------
125 // BamHeader implementation
127 BamHeader::BamHeader(void)
128 : d(new BamHeaderPrivate)
131 BamHeader::~BamHeader(void) {
136 void BamHeader::Clear(void) {
137 delete d->m_samHeader;
138 d->m_samHeader = new SamHeader("");
141 bool BamHeader::IsValid(void) const {
142 return d->m_samHeader->IsValid();
145 bool BamHeader::Load(BgzfData* stream) {
146 return d->Load(stream);
149 SamHeader BamHeader::ToSamHeader(void) const {
150 return *(d->m_samHeader);
153 string BamHeader::ToString(void) const {
154 return d->m_samHeader->ToString();