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)
34 : m_samHeader(new SamHeader(""))
38 ~BamHeaderPrivate(void) {
44 bool Load(BgzfData* stream);
47 bool CheckMagicNumber(BgzfData* stream);
48 bool ReadHeaderLength(BgzfData* stream, uint32_t& length);
49 bool ReadHeaderText(BgzfData* stream, const uint32_t& length);
52 bool BamHeader::BamHeaderPrivate::Load(BgzfData* stream) {
54 // cannot load if invalid stream
58 // cannot load if magic number is invalid
59 if ( !CheckMagicNumber(stream) )
62 // cannot load header if cannot read header length
64 if ( !ReadHeaderLength(stream, length) )
67 // cannot load header if cannot read header text
68 if ( !ReadHeaderText(stream, length) )
71 // otherwise, everything OK
75 bool BamHeader::BamHeaderPrivate::CheckMagicNumber(BgzfData* stream) {
77 // try to read magic number
78 char buffer[Constants::BAM_HEADER_MAGIC_SIZE];
79 if ( stream->Read(buffer, Constants::BAM_HEADER_MAGIC_SIZE) != (int)Constants::BAM_HEADER_MAGIC_SIZE ) {
80 fprintf(stderr, "BAM header error - could not read magic number\n");
84 // validate magic number
85 if ( strncmp(buffer, Constants::BAM_HEADER_MAGIC, Constants::BAM_HEADER_MAGIC_SIZE) != 0 ) {
86 fprintf(stderr, "BAM header error - invalid magic number\n");
94 bool BamHeader::BamHeaderPrivate::ReadHeaderLength(BgzfData* stream, uint32_t& length) {
96 // attempt to read BAM header text length
97 char buffer[sizeof(uint32_t)];
98 if ( stream->Read(buffer, sizeof(uint32_t)) != sizeof(uint32_t) ) {
99 fprintf(stderr, "BAM header error - could not read header length\n");
103 // convert char buffer to length, return success
104 length = BgzfData::UnpackUnsignedInt(buffer);
105 if ( BamTools::SystemIsBigEndian() )
106 SwapEndian_32(length);
110 bool BamHeader::BamHeaderPrivate::ReadHeaderText(BgzfData* stream, const uint32_t& length) {
112 // set up destination buffer
113 char* headerText = (char*)calloc(length + 1, 1);
115 // attempt to read header text
116 const unsigned bytesRead = stream->Read(headerText, length);
117 const bool readOk = ( bytesRead == length );
119 m_samHeader->SetHeaderText( (string)((const char*)headerText) );
121 fprintf(stderr, "BAM header error - could not read header text\n");
123 // clean up calloc-ed temp variable (on success or fail)
126 // return read success
130 // --------------------------
131 // BamHeader implementation
133 BamHeader::BamHeader(void)
134 : d(new BamHeaderPrivate)
137 BamHeader::~BamHeader(void) {
142 void BamHeader::Clear(void) {
143 d->m_samHeader->Clear();
146 bool BamHeader::IsValid(void) const {
147 return d->m_samHeader->IsValid();
150 bool BamHeader::Load(BgzfData* stream) {
151 return d->Load(stream);
154 SamHeader BamHeader::ToSamHeader(void) const {
155 return *(d->m_samHeader);
158 string BamHeader::ToString(void) const {
159 return d->m_samHeader->ToString();