]> git.donarmstrong.com Git - bamtools.git/blob - src/api/internal/BamHeader_p.cpp
Major update to BamTools version 1.0
[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: 21 March 2011 (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/internal/BamHeader_p.h>
14 #include <api/internal/BgzfStream_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 // ctor
25 BamHeader::BamHeader(void) { }
26
27 // dtor
28 BamHeader::~BamHeader(void) { }
29
30 // reads magic number from BGZF stream, returns true if valid
31 bool BamHeader::CheckMagicNumber(BgzfStream* stream) {
32
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");
37         return false;
38     }
39
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");
43         return false;
44     }
45
46     // all checks out
47     return true;
48 }
49
50 // clear SamHeader data
51 void BamHeader::Clear(void) {
52     m_header.Clear();
53 }
54
55 // return true if SamHeader data is valid
56 bool BamHeader::IsValid(void) const {
57     return m_header.IsValid();
58 }
59
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) {
63
64     // cannot load if invalid stream
65     if ( stream == 0 )
66         return false;
67
68     // cannot load if magic number is invalid
69     if ( !CheckMagicNumber(stream) )
70         return false;
71
72     // cannot load header if cannot read header length
73     uint32_t length(0);
74     if ( !ReadHeaderLength(stream, length) )
75         return false;
76
77     // cannot load header if cannot read header text
78     if ( !ReadHeaderText(stream, length) )
79         return false;
80
81     // otherwise, everything OK
82     return true;
83 }
84
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) {
88
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");
93         return false;
94     }
95
96     // convert char buffer to length, return success
97     length = BamTools::UnpackUnsignedInt(buffer);
98     if ( BamTools::SystemIsBigEndian() )
99         BamTools::SwapEndian_32(length);
100     return true;
101 }
102
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) {
106
107     // set up destination buffer
108     char* headerText = (char*)calloc(length + 1, 1);
109
110     // attempt to read header text
111     const unsigned bytesRead = stream->Read(headerText, length);
112     const bool readOk = ( bytesRead == length );
113     if ( readOk )
114         m_header.SetHeaderText( (string)((const char*)headerText) );
115     else
116         fprintf(stderr, "BamHeader ERROR: could not read header text\n");
117
118     // clean up calloc-ed temp variable (on success or fail)
119     free(headerText);
120
121     // return read success
122     return readOk;
123 }
124
125 // returns *copy* of SamHeader data object
126 SamHeader BamHeader::ToSamHeader(void) const {
127     return m_header;
128 }
129
130 // returns SAM-formatted string of header data
131 string BamHeader::ToString(void) const {
132     return m_header.ToString();
133 }