]> git.donarmstrong.com Git - bamtools.git/blob - src/api/internal/BamHeader_p.cpp
48b8c0908d7f16707b8eb832e98e601a97ddfca5
[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 // ---------------------------------------------------------------------------
5 // Last modified: 21 March 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides the basic functionality for handling BAM headers.
8 // ***************************************************************************
9
10 #include <api/BamAux.h>
11 #include <api/BamConstants.h>
12 #include <api/internal/BamHeader_p.h>
13 #include <api/internal/BgzfStream_p.h>
14 using namespace BamTools;
15 using namespace BamTools::Internal;
16
17 #include <cstdio>
18 #include <cstdlib>
19 #include <cstring>
20 #include <iostream>
21 using namespace std;
22
23 // ctor
24 BamHeader::BamHeader(void) { }
25
26 // dtor
27 BamHeader::~BamHeader(void) { }
28
29 // reads magic number from BGZF stream, returns true if valid
30 bool BamHeader::CheckMagicNumber(BgzfStream* stream) {
31
32     // try to read magic number
33     char buffer[Constants::BAM_HEADER_MAGIC_LENGTH];
34     if ( stream->Read(buffer, Constants::BAM_HEADER_MAGIC_LENGTH) != (int)Constants::BAM_HEADER_MAGIC_LENGTH ) {
35         fprintf(stderr, "BamHeader ERROR: could not read magic number\n");
36         return false;
37     }
38
39     // validate magic number
40     if ( strncmp(buffer, Constants::BAM_HEADER_MAGIC, Constants::BAM_HEADER_MAGIC_LENGTH) != 0 ) {
41         fprintf(stderr, "BamHeader ERROR: invalid magic number\n");
42         return false;
43     }
44
45     // all checks out
46     return true;
47 }
48
49 // clear SamHeader data
50 void BamHeader::Clear(void) {
51     m_header.Clear();
52 }
53
54 // return true if SamHeader data is valid
55 bool BamHeader::IsValid(void) const {
56     return m_header.IsValid();
57 }
58
59 // load BAM header ('magic number' and SAM header text) from BGZF stream
60 // returns true if all OK
61 bool BamHeader::Load(BgzfStream* stream) {
62
63     // cannot load if invalid stream
64     if ( stream == 0 )
65         return false;
66
67     // cannot load if magic number is invalid
68     if ( !CheckMagicNumber(stream) )
69         return false;
70
71     // cannot load header if cannot read header length
72     uint32_t length(0);
73     if ( !ReadHeaderLength(stream, length) )
74         return false;
75
76     // cannot load header if cannot read header text
77     if ( !ReadHeaderText(stream, length) )
78         return false;
79
80     // otherwise, everything OK
81     return true;
82 }
83
84 // reads SAM header text length from BGZF stream, stores it in @length
85 // returns read success/fail status
86 bool BamHeader::ReadHeaderLength(BgzfStream* stream, uint32_t& length) {
87
88     // attempt to read BAM header text length
89     char buffer[sizeof(uint32_t)];
90     if ( stream->Read(buffer, sizeof(uint32_t)) != sizeof(uint32_t) ) {
91         fprintf(stderr, "BamHeader ERROR: could not read header length\n");
92         return false;
93     }
94
95     // convert char buffer to length, return success
96     length = BamTools::UnpackUnsignedInt(buffer);
97     if ( BamTools::SystemIsBigEndian() )
98         BamTools::SwapEndian_32(length);
99     return true;
100 }
101
102 // reads SAM header text from BGZF stream, stores in SamHeader object
103 // returns read success/fail status
104 bool BamHeader::ReadHeaderText(BgzfStream* stream, const uint32_t& length) {
105
106     // set up destination buffer
107     char* headerText = (char*)calloc(length + 1, 1);
108
109     // attempt to read header text
110     const unsigned bytesRead = stream->Read(headerText, length);
111     const bool readOk = ( bytesRead == length );
112     if ( readOk )
113         m_header.SetHeaderText( (string)((const char*)headerText) );
114     else
115         fprintf(stderr, "BamHeader ERROR: could not read header text\n");
116
117     // clean up calloc-ed temp variable (on success or fail)
118     free(headerText);
119
120     // return read success
121     return readOk;
122 }
123
124 // returns *copy* of SamHeader data object
125 SamHeader BamHeader::ToSamHeader(void) const {
126     return m_header;
127 }
128
129 // returns SAM-formatted string of header data
130 string BamHeader::ToString(void) const {
131     return m_header.ToString();
132 }