]> git.donarmstrong.com Git - bamtools.git/blobdiff - src/api/internal/BamHeader_p.cpp
Merge with earlier IODevice work
[bamtools.git] / src / api / internal / BamHeader_p.cpp
index 45dc379f52327c6cc9a77d232e1b53a9b83bd56e..7ec1181703a07c8e7ad48bd4c2cf5b3c1f12d6f6 100644 (file)
@@ -2,24 +2,37 @@
 // BamHeader_p.cpp (c) 2010 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 21 March 2011 (DB)
+// Last modified: 7 October 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides the basic functionality for handling BAM headers.
 // ***************************************************************************
 
 #include <api/BamAux.h>
 #include <api/BamConstants.h>
+#include <api/internal/BamException_p.h>
 #include <api/internal/BamHeader_p.h>
 #include <api/internal/BgzfStream_p.h>
 using namespace BamTools;
 using namespace BamTools::Internal;
 
-#include <cstdio>
 #include <cstdlib>
 #include <cstring>
-#include <iostream>
 using namespace std;
 
+// ------------------------
+// static utility methods
+// ------------------------
+
+static inline
+bool isValidMagicNumber(const char* buffer) {
+    return ( strncmp(buffer, Constants::BAM_HEADER_MAGIC,
+                     Constants::BAM_HEADER_MAGIC_LENGTH) == 0 );
+}
+
+// --------------------------
+// BamHeader implementation
+// --------------------------
+
 // ctor
 BamHeader::BamHeader(void) { }
 
@@ -27,23 +40,17 @@ BamHeader::BamHeader(void) { }
 BamHeader::~BamHeader(void) { }
 
 // reads magic number from BGZF stream, returns true if valid
-bool BamHeader::CheckMagicNumber(BgzfStream* stream) {
+void BamHeader::CheckMagicNumber(BgzfStream* stream) {
 
     // try to read magic number
     char buffer[Constants::BAM_HEADER_MAGIC_LENGTH];
-    if ( stream->Read(buffer, Constants::BAM_HEADER_MAGIC_LENGTH) != Constants::BAM_HEADER_MAGIC_LENGTH ) {
-        fprintf(stderr, "BamHeader ERROR: could not read magic number\n");
-        return false;
-    }
+    const size_t numBytesRead = stream->Read(buffer, Constants::BAM_HEADER_MAGIC_LENGTH);
+    if ( numBytesRead != (int)Constants::BAM_HEADER_MAGIC_LENGTH )
+        throw BamException("BamHeader::CheckMagicNumber", "could not read magic number");
 
     // validate magic number
-    if ( strncmp(buffer, Constants::BAM_HEADER_MAGIC, Constants::BAM_HEADER_MAGIC_LENGTH) != 0 ) {
-        fprintf(stderr, "BamHeader ERROR: invalid magic number\n");
-        return false;
-    }
-
-    // all checks out
-    return true;
+    if ( !isValidMagicNumber(buffer) )
+        throw BamException("BamHeader::CheckMagicNumber", "invalid magic number");
 }
 
 // clear SamHeader data
@@ -57,68 +64,49 @@ bool BamHeader::IsValid(void) const {
 }
 
 // load BAM header ('magic number' and SAM header text) from BGZF stream
-// returns true if all OK
-bool BamHeader::Load(BgzfStream* stream) {
+void BamHeader::Load(BgzfStream* stream) {
 
-    // cannot load if invalid stream
-    if ( stream == 0 )
-        return false;
+    // read & check magic number
+    CheckMagicNumber(stream);
 
-    // cannot load if magic number is invalid
-    if ( !CheckMagicNumber(stream) )
-        return false;
-
-    // cannot load header if cannot read header length
+    // read header (length, then actual text)
     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;
+    ReadHeaderLength(stream, length);
+    ReadHeaderText(stream, length);
 }
 
 // reads SAM header text length from BGZF stream, stores it in @length
-// returns read success/fail status
-bool BamHeader::ReadHeaderLength(BgzfStream* stream, uint32_t& length) {
+void BamHeader::ReadHeaderLength(BgzfStream* stream, uint32_t& length) {
 
-    // attempt to read BAM header text length
+    // read BAM header text length
     char buffer[sizeof(uint32_t)];
-    if ( stream->Read(buffer, sizeof(uint32_t)) != sizeof(uint32_t) ) {
-        fprintf(stderr, "BamHeader ERROR: could not read header length\n");
-        return false;
-    }
+    const size_t numBytesRead = stream->Read(buffer, sizeof(uint32_t));
+    if ( numBytesRead != sizeof(uint32_t) )
+        throw BamException("BamHeader::ReadHeaderLength", "could not read header length");
 
-    // convert char buffer to length, return success
+    // convert char buffer to length
     length = BamTools::UnpackUnsignedInt(buffer);
     if ( BamTools::SystemIsBigEndian() )
         BamTools::SwapEndian_32(length);
-    return true;
 }
 
 // reads SAM header text from BGZF stream, stores in SamHeader object
-// returns read success/fail status
-bool BamHeader::ReadHeaderText(BgzfStream* stream, const uint32_t& length) {
+void BamHeader::ReadHeaderText(BgzfStream* stream, const uint32_t& length) {
 
-    // set up destination buffer
+    // read header text
     char* headerText = (char*)calloc(length + 1, 1);
+    const size_t bytesRead = stream->Read(headerText, length);
 
-    // attempt to read header text
-    const unsigned bytesRead = stream->Read(headerText, length);
-    const bool readOk = ( bytesRead == length );
-    if ( readOk )
-        m_header.SetHeaderText( (string)((const char*)headerText) );
-    else
-        fprintf(stderr, "BamHeader ERROR: could not read header text\n");
+    // if error reading, clean up buffer & throw
+    if ( bytesRead != length ) {
+        free(headerText);
+        throw BamException("BamHeader::ReadHeaderText", "could not read header text");
+    }
 
-    // clean up calloc-ed temp variable (on success or fail)
+    // otherwise, text was read OK
+    // store & cleanup
+    m_header.SetHeaderText( (string)((const char*)headerText) );
     free(headerText);
-
-    // return read success
-    return readOk;
 }
 
 // returns *copy* of SamHeader data object