]> git.donarmstrong.com Git - bamtools.git/blob - src/api/internal/BamHeader_p.cpp
Minor update to API version 0.9.3 - addition of SamHeader::SetHeaderText().
[bamtools.git] / src / api / internal / BamHeader_p.cpp
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 // ***************************************************************************
10
11 #include <api/BamAux.h>
12 #include <api/BamConstants.h>
13 #include <api/BGZF.h>
14 #include <api/internal/BamHeader_p.h>
15 using namespace BamTools;
16 using namespace BamTools::Internal;
17
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <iostream>
22 using namespace std;
23
24 // ---------------------------------
25 // BamHeaderPrivate implementation
26
27 struct BamHeader::BamHeaderPrivate {
28
29     // data members
30     SamHeader* m_samHeader;
31
32     // ctor
33     BamHeaderPrivate(void)
34         : m_samHeader(new SamHeader(""))
35     { }
36
37     // dtor
38     ~BamHeaderPrivate(void) {
39         delete m_samHeader;
40         m_samHeader = 0;
41     }
42
43     // 'public' interface
44     bool Load(BgzfData* stream);
45
46     // internal methods
47     bool CheckMagicNumber(BgzfData* stream);
48     bool ReadHeaderLength(BgzfData* stream, uint32_t& length);
49     bool ReadHeaderText(BgzfData* stream, const uint32_t& length);
50 };
51
52 bool BamHeader::BamHeaderPrivate::Load(BgzfData* stream) {
53
54     // cannot load if invalid stream
55     if ( stream == 0 )
56         return false;
57
58     // cannot load if magic number is invalid
59     if ( !CheckMagicNumber(stream) )
60         return false;
61
62     // cannot load header if cannot read header length
63     uint32_t length(0);
64     if ( !ReadHeaderLength(stream, length) )
65         return false;
66
67     // cannot load header if cannot read header text
68     if ( !ReadHeaderText(stream, length) )
69         return false;
70
71     // otherwise, everything OK
72     return true;
73 }
74
75 bool BamHeader::BamHeaderPrivate::CheckMagicNumber(BgzfData* stream) {
76
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");
81         return false;
82     }
83
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");
87         return false;
88     }
89
90     // all checks out
91     return true;
92 }
93
94 bool BamHeader::BamHeaderPrivate::ReadHeaderLength(BgzfData* stream, uint32_t& length) {
95
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");
100         return false;
101     }
102
103     // convert char buffer to length, return success
104     length = BgzfData::UnpackUnsignedInt(buffer);
105     if ( BamTools::SystemIsBigEndian() )
106         SwapEndian_32(length);
107     return true;
108 }
109
110 bool BamHeader::BamHeaderPrivate::ReadHeaderText(BgzfData* stream, const uint32_t& length) {
111
112     // set up destination buffer
113     char* headerText = (char*)calloc(length + 1, 1);
114
115     // attempt to read header text
116     const unsigned bytesRead = stream->Read(headerText, length);
117     const bool readOk = ( bytesRead == length );
118     if ( readOk )
119         m_samHeader->SetHeaderText( (string)((const char*)headerText) );
120     else
121         fprintf(stderr, "BAM header error - could not read header text\n");
122
123     // clean up calloc-ed temp variable (on success or fail)
124     free(headerText);
125
126     // return read success
127     return readOk;
128 }
129
130 // --------------------------
131 // BamHeader implementation
132
133 BamHeader::BamHeader(void)
134     : d(new BamHeaderPrivate)
135 { }
136
137 BamHeader::~BamHeader(void) {
138     delete d;
139     d = 0;
140 }
141
142 void BamHeader::Clear(void) {
143     d->m_samHeader->Clear();
144 }
145
146 bool BamHeader::IsValid(void) const {
147     return d->m_samHeader->IsValid();
148 }
149
150 bool BamHeader::Load(BgzfData* stream) {
151     return d->Load(stream);
152 }
153
154 SamHeader BamHeader::ToSamHeader(void) const {
155     return *(d->m_samHeader);
156 }
157
158 string BamHeader::ToString(void) const {
159     return d->m_samHeader->ToString();
160 }