]> git.donarmstrong.com Git - bamtools.git/blob - src/api/internal/BamHeader_p.cpp
7ec1181703a07c8e7ad48bd4c2cf5b3c1f12d6f6
[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: 7 October 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/BamException_p.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 <cstdlib>
19 #include <cstring>
20 using namespace std;
21
22 // ------------------------
23 // static utility methods
24 // ------------------------
25
26 static inline
27 bool isValidMagicNumber(const char* buffer) {
28     return ( strncmp(buffer, Constants::BAM_HEADER_MAGIC,
29                      Constants::BAM_HEADER_MAGIC_LENGTH) == 0 );
30 }
31
32 // --------------------------
33 // BamHeader implementation
34 // --------------------------
35
36 // ctor
37 BamHeader::BamHeader(void) { }
38
39 // dtor
40 BamHeader::~BamHeader(void) { }
41
42 // reads magic number from BGZF stream, returns true if valid
43 void BamHeader::CheckMagicNumber(BgzfStream* stream) {
44
45     // try to read magic number
46     char buffer[Constants::BAM_HEADER_MAGIC_LENGTH];
47     const size_t numBytesRead = stream->Read(buffer, Constants::BAM_HEADER_MAGIC_LENGTH);
48     if ( numBytesRead != (int)Constants::BAM_HEADER_MAGIC_LENGTH )
49         throw BamException("BamHeader::CheckMagicNumber", "could not read magic number");
50
51     // validate magic number
52     if ( !isValidMagicNumber(buffer) )
53         throw BamException("BamHeader::CheckMagicNumber", "invalid magic number");
54 }
55
56 // clear SamHeader data
57 void BamHeader::Clear(void) {
58     m_header.Clear();
59 }
60
61 // return true if SamHeader data is valid
62 bool BamHeader::IsValid(void) const {
63     return m_header.IsValid();
64 }
65
66 // load BAM header ('magic number' and SAM header text) from BGZF stream
67 void BamHeader::Load(BgzfStream* stream) {
68
69     // read & check magic number
70     CheckMagicNumber(stream);
71
72     // read header (length, then actual text)
73     uint32_t length(0);
74     ReadHeaderLength(stream, length);
75     ReadHeaderText(stream, length);
76 }
77
78 // reads SAM header text length from BGZF stream, stores it in @length
79 void BamHeader::ReadHeaderLength(BgzfStream* stream, uint32_t& length) {
80
81     // read BAM header text length
82     char buffer[sizeof(uint32_t)];
83     const size_t numBytesRead = stream->Read(buffer, sizeof(uint32_t));
84     if ( numBytesRead != sizeof(uint32_t) )
85         throw BamException("BamHeader::ReadHeaderLength", "could not read header length");
86
87     // convert char buffer to length
88     length = BamTools::UnpackUnsignedInt(buffer);
89     if ( BamTools::SystemIsBigEndian() )
90         BamTools::SwapEndian_32(length);
91 }
92
93 // reads SAM header text from BGZF stream, stores in SamHeader object
94 void BamHeader::ReadHeaderText(BgzfStream* stream, const uint32_t& length) {
95
96     // read header text
97     char* headerText = (char*)calloc(length + 1, 1);
98     const size_t bytesRead = stream->Read(headerText, length);
99
100     // if error reading, clean up buffer & throw
101     if ( bytesRead != length ) {
102         free(headerText);
103         throw BamException("BamHeader::ReadHeaderText", "could not read header text");
104     }
105
106     // otherwise, text was read OK
107     // store & cleanup
108     m_header.SetHeaderText( (string)((const char*)headerText) );
109     free(headerText);
110 }
111
112 // returns *copy* of SamHeader data object
113 SamHeader BamHeader::ToSamHeader(void) const {
114     return m_header;
115 }
116
117 // returns SAM-formatted string of header data
118 string BamHeader::ToString(void) const {
119     return m_header.ToString();
120 }