]> git.donarmstrong.com Git - bamtools.git/blobdiff - src/api/internal/BamHeader_p.cpp
Update to BamTools API 0.9.2 with exposure of SamHeader object from BamReader and...
[bamtools.git] / src / api / internal / BamHeader_p.cpp
diff --git a/src/api/internal/BamHeader_p.cpp b/src/api/internal/BamHeader_p.cpp
new file mode 100644 (file)
index 0000000..c613b12
--- /dev/null
@@ -0,0 +1,155 @@
+// ***************************************************************************
+// BamHeader_p.cpp (c) 2010 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// All rights reserved.
+// ---------------------------------------------------------------------------
+// Last modified: 25 December 2010 (DB)
+// ---------------------------------------------------------------------------
+// Provides the basic functionality for handling BAM headers.
+// ***************************************************************************
+
+#include <api/BamAux.h>
+#include <api/BamConstants.h>
+#include <api/BGZF.h>
+#include <api/internal/BamHeader_p.h>
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+using namespace std;
+
+// ---------------------------------
+// BamHeaderPrivate implementation
+
+struct BamHeader::BamHeaderPrivate {
+
+    // data members
+    SamHeader* m_samHeader;
+
+    // ctor
+    BamHeaderPrivate(void)
+        : m_samHeader(0)
+    { }
+
+    // 'public' interface
+    bool Load(BgzfData* stream);
+
+    // internal methods
+    bool CheckMagicNumber(BgzfData* stream);
+    bool ReadHeaderLength(BgzfData* stream, uint32_t& length);
+    bool ReadHeaderText(BgzfData* stream, const uint32_t& length);
+};
+
+bool BamHeader::BamHeaderPrivate::Load(BgzfData* stream) {
+
+    // cannot load if invalid stream
+    if ( stream == 0 )
+        return false;
+
+    // cannot load if magic number is invalid
+    if ( !CheckMagicNumber(stream) )
+        return false;
+
+    // cannot load header if cannot read header length
+    uint32_t length(0);
+    if ( !ReadHeaderLength(stream, length) )
+        return false;
+
+    // cannot load header if cannot read header text
+    if ( !ReadHeaderText(stream, length) )
+        return false;
+
+    // otherwise, everything OK
+    return true;
+}
+
+bool BamHeader::BamHeaderPrivate::CheckMagicNumber(BgzfData* stream) {
+
+    // try to read magic number
+    char buffer[Constants::BAM_HEADER_MAGIC_SIZE];
+    if ( stream->Read(buffer, Constants::BAM_HEADER_MAGIC_SIZE) != (int)Constants::BAM_HEADER_MAGIC_SIZE ) {
+        fprintf(stderr, "BAM header error - could not read magic number\n");
+        return false;
+    }
+
+    // validate magic number
+    if ( strncmp(buffer, Constants::BAM_HEADER_MAGIC, Constants::BAM_HEADER_MAGIC_SIZE) != 0 ) {
+        fprintf(stderr, "BAM header error - invalid magic number\n");
+        return false;
+    }
+
+    // all checks out
+    return true;
+}
+
+bool BamHeader::BamHeaderPrivate::ReadHeaderLength(BgzfData* stream, uint32_t& length) {
+
+    // attempt to read BAM header text length
+    char buffer[sizeof(uint32_t)];
+    if ( stream->Read(buffer, sizeof(uint32_t)) != sizeof(uint32_t) ) {
+        fprintf(stderr, "BAM header error - could not read header length\n");
+        return false;
+    }
+
+    // convert char buffer to length, return success
+    length = BgzfData::UnpackUnsignedInt(buffer);
+    if ( BamTools::SystemIsBigEndian() )
+        SwapEndian_32(length);
+    return true;
+}
+
+bool BamHeader::BamHeaderPrivate::ReadHeaderText(BgzfData* stream, const uint32_t& length) {
+
+    // set up destination buffer
+    char* headerText = (char*)calloc(length + 1, 1);
+
+    // attempt to read header text
+    const unsigned bytesRead = stream->Read(headerText, length);
+    const bool readOk = ( bytesRead == length );
+    if ( readOk )
+        m_samHeader = new SamHeader( (string)((const char*)headerText) );
+    else
+        fprintf(stderr, "BAM header error - could not read header text\n");
+
+    // clean up calloc-ed temp variable (on success or fail)
+    free(headerText);
+
+    // return read success
+    return readOk;
+}
+
+// --------------------------
+// BamHeader implementation
+
+BamHeader::BamHeader(void)
+    : d(new BamHeaderPrivate)
+{ }
+
+BamHeader::~BamHeader(void) {
+    delete d;
+    d = 0;
+}
+
+void BamHeader::Clear(void) {
+    delete d->m_samHeader;
+    d->m_samHeader = new SamHeader("");
+}
+
+bool BamHeader::IsValid(void) const {
+    return d->m_samHeader->IsValid();
+}
+
+bool BamHeader::Load(BgzfData* stream) {
+    return d->Load(stream);
+}
+
+SamHeader BamHeader::ToSamHeader(void) const {
+    return *(d->m_samHeader);
+}
+
+string BamHeader::ToString(void) const {
+    return d->m_samHeader->ToString();
+}