]> git.donarmstrong.com Git - bamtools.git/commitdiff
Merge branches 'master' and 'iodevice' into iodevice
authorderek <derekwbarnett@gmail.com>
Fri, 9 Sep 2011 16:07:31 +0000 (12:07 -0400)
committerderek <derekwbarnett@gmail.com>
Fri, 9 Sep 2011 16:07:31 +0000 (12:07 -0400)
21 files changed:
src/api/BamConstants.h
src/api/CMakeLists.txt
src/api/IBamIODevice.h [new file with mode: 0644]
src/api/internal/BamDeviceFactory_p.cpp [new file with mode: 0644]
src/api/internal/BamDeviceFactory_p.h [new file with mode: 0644]
src/api/internal/BamFile_p.cpp [new file with mode: 0644]
src/api/internal/BamFile_p.h [new file with mode: 0644]
src/api/internal/BamFtp_p.cpp [new file with mode: 0644]
src/api/internal/BamFtp_p.h [new file with mode: 0644]
src/api/internal/BamHeader_p.cpp
src/api/internal/BamHttp_p.cpp [new file with mode: 0644]
src/api/internal/BamHttp_p.h [new file with mode: 0644]
src/api/internal/BamPipe_p.cpp [new file with mode: 0644]
src/api/internal/BamPipe_p.h [new file with mode: 0644]
src/api/internal/BamRandomAccessController_p.cpp
src/api/internal/BamReader_p.cpp
src/api/internal/BamWriter_p.cpp
src/api/internal/BgzfStream_p.cpp
src/api/internal/BgzfStream_p.h
src/shared/bamtools_global.h
src/utils/bamtools_utilities.h

index e433c8e79df37d318a6f4a9c7b94b060494b9a92..ac672a667a4350b970692c67fe8fc07c6f2a48b3 100644 (file)
@@ -1,9 +1,8 @@
 // ***************************************************************************
 // BamConstants.h (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
-// All rights reserved.
 // ---------------------------------------------------------------------------
-// Last modified: 19 April 2011 (DB)
+// Last modified: 9 September 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides basic constants for handling BAM files.
 // ***************************************************************************
@@ -27,8 +26,8 @@ const char* const  BAM_HEADER_MAGIC = "BAM\1";
 const unsigned int BAM_HEADER_MAGIC_LENGTH = 4;
 
 // BAM alignment core size
-const int BAM_CORE_SIZE = 32;
-const int BAM_CORE_BUFFER_SIZE = 8;
+const unsigned int BAM_CORE_SIZE = 32;
+const unsigned int BAM_CORE_BUFFER_SIZE = 8;
 
 // BAM alignment flags
 const int BAM_ALIGNMENT_PAIRED              = 0x0001;
@@ -119,8 +118,8 @@ const int Z_DEFAULT_MEM_LEVEL = 8;
 // BZGF constants
 const int BGZF_BLOCK_HEADER_LENGTH = 18;
 const int BGZF_BLOCK_FOOTER_LENGTH = 8;
-const int BGZF_MAX_BLOCK_SIZE      = 65536;
-const int BGZF_DEFAULT_BLOCK_SIZE  = 65536;
+const unsigned int BGZF_MAX_BLOCK_SIZE      = 65536;
+const unsigned int BGZF_DEFAULT_BLOCK_SIZE  = 65536;
 
 } // namespace Constants
 } // namespace BamTools
index 10c46d6bd36da18d8644ee8dbe64d1aa4e795af1..e9c3b65785969721e4b591752d7485f7ff239f9f 100644 (file)
@@ -25,9 +25,14 @@ set( BamToolsAPISources
         SamReadGroupDictionary.cpp
         SamSequence.cpp
         SamSequenceDictionary.cpp
+        internal/BamDeviceFactory_p.cpp
+        internal/BamFile_p.cpp
+        internal/BamFtp_p.cpp
         internal/BamHeader_p.cpp
+        internal/BamHttp_p.cpp
         internal/BamIndexFactory_p.cpp
         internal/BamMultiReader_p.cpp
+        internal/BamPipe_p.cpp
         internal/BamRandomAccessController_p.cpp
         internal/BamReader_p.cpp
         internal/BamStandardIndex_p.cpp
@@ -68,6 +73,7 @@ ExportHeader(APIHeaders BamIndex.h               ${ApiIncludeDir})
 ExportHeader(APIHeaders BamMultiReader.h         ${ApiIncludeDir})
 ExportHeader(APIHeaders BamReader.h              ${ApiIncludeDir})
 ExportHeader(APIHeaders BamWriter.h              ${ApiIncludeDir})
+ExportHeader(APIHeaders IBamIODevice.h           ${ApiIncludeDir})
 ExportHeader(APIHeaders SamConstants.h           ${ApiIncludeDir})
 ExportHeader(APIHeaders SamHeader.h              ${ApiIncludeDir})
 ExportHeader(APIHeaders SamProgram.h             ${ApiIncludeDir})
diff --git a/src/api/IBamIODevice.h b/src/api/IBamIODevice.h
new file mode 100644 (file)
index 0000000..c59bb4a
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef IBAMIODEVICE_H
+#define IBAMIODEVICE_H
+
+#include <api/api_global.h>
+#include <string>
+
+namespace BamTools {
+
+class API_EXPORT IBamIODevice {
+
+    // enums
+    public: enum OpenMode { NotOpen = 0
+                          , ReadOnly
+                          , WriteOnly
+                          };
+
+    // ctor & dtor
+    public:
+        IBamIODevice(void);
+        virtual ~IBamIODevice(void);
+
+    // IBamIODevice interface
+    public:
+        virtual void Close(void) =0;
+        virtual bool IsRandomAccess(void) const =0;
+        virtual bool Open(const OpenMode mode) =0;
+        virtual size_t Read(char* data, const unsigned int numBytes) =0;
+        virtual bool Seek(const int64_t& position) =0;
+        virtual int64_t Tell(void) const =0;
+        virtual size_t Write(const char* data, const unsigned int numBytes) =0;
+    public:
+        virtual std::string ErrorString(void);
+        virtual bool IsOpen(void) const;
+        virtual OpenMode Mode(void) const;
+
+    // internal methods
+    protected:
+        void SetErrorString(const std::string& errorString);
+
+    // data members
+    protected:
+        OpenMode    m_mode;
+        std::string m_errorString;
+};
+
+inline
+IBamIODevice::IBamIODevice(void)
+    : m_mode(IBamIODevice::NotOpen)
+{ }
+
+inline
+IBamIODevice::~IBamIODevice(void) { }
+
+inline
+std::string IBamIODevice::ErrorString(void) {
+    std::string e = m_errorString;
+    m_errorString.clear();
+    return e;
+}
+
+inline
+bool IBamIODevice::IsOpen(void) const {
+    return ( m_mode != IBamIODevice::NotOpen );
+}
+
+inline
+IBamIODevice::OpenMode IBamIODevice::Mode(void) const {
+    return m_mode;
+}
+
+inline
+void IBamIODevice::SetErrorString(const std::string& errorString) {
+    m_errorString = errorString;
+}
+
+} // namespace BamTools
+
+#endif // IBAMIODEVICE_H
diff --git a/src/api/internal/BamDeviceFactory_p.cpp b/src/api/internal/BamDeviceFactory_p.cpp
new file mode 100644 (file)
index 0000000..da0daad
--- /dev/null
@@ -0,0 +1,37 @@
+// ***************************************************************************
+// BamDeviceFactory_p.cpp (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Creates built-in concrete implementations of IBamIODevices
+// ***************************************************************************
+
+#include <api/internal/BamDeviceFactory_p.h>
+#include <api/internal/BamFile_p.h>
+#include <api/internal/BamFtp_p.h>
+#include <api/internal/BamHttp_p.h>
+#include <api/internal/BamPipe_p.h>
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+#include <iostream>
+using namespace std;
+
+IBamIODevice* BamDeviceFactory::CreateDevice(const string& source) {
+
+    // check for requested pipe
+    if ( source == "-" || source == "stdin" || source == "stdout" )
+        return new BamPipe;
+
+    // check for HTTP prefix
+    if ( source.find("http://") == 0 )
+        return new BamHttp(source);
+
+    // check for FTP prefix
+    if ( source.find("ftp://") == 0 )
+        return new BamFtp(source);
+
+    // otherwise assume a "normal" file
+    return new BamFile(source);
+}
diff --git a/src/api/internal/BamDeviceFactory_p.h b/src/api/internal/BamDeviceFactory_p.h
new file mode 100644 (file)
index 0000000..f126831
--- /dev/null
@@ -0,0 +1,37 @@
+// ***************************************************************************
+// BamDeviceFactory_p.h (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Creates built-in concrete implementations of IBamIODevices
+// ***************************************************************************
+
+#ifndef BAMDEVICEFACTORY_P_H
+#define BAMDEVICEFACTORY_P_H
+
+//  -------------
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the BamTools API.  It exists purely as an
+// implementation detail. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+
+#include <api/IBamIODevice.h>
+#include <string>
+
+namespace BamTools {
+namespace Internal {
+
+class BamDeviceFactory {
+    public:
+        static IBamIODevice* CreateDevice(const std::string& source);
+};
+
+} // namespace Internal
+} // namespace BamTools
+
+#endif // BAMDEVICEFACTORY_P_H
diff --git a/src/api/internal/BamFile_p.cpp b/src/api/internal/BamFile_p.cpp
new file mode 100644 (file)
index 0000000..d9c8673
--- /dev/null
@@ -0,0 +1,95 @@
+// ***************************************************************************
+// BamFile_p.cpp (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides reading of local BAM files
+// ***************************************************************************
+
+#include <api/internal/BamFile_p.h>
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+#include <cstdio>
+using namespace std;
+
+BamFile::BamFile(const string& filename)
+    : IBamIODevice()
+    , m_stream(0)
+    , m_filename(filename)
+{ }
+
+BamFile::~BamFile(void) {
+    Close();
+}
+
+void BamFile::Close(void) {
+
+    // skip if not open
+    if ( !IsOpen() )
+        return;
+
+    // flush & close FILE*
+    fflush(m_stream);
+    fclose(m_stream);
+
+    // reset internals
+    m_mode = IBamIODevice::NotOpen;
+    m_stream = 0;
+    m_filename.clear();
+}
+
+bool BamFile::IsRandomAccess(void) const {
+    return true;
+}
+
+bool BamFile::Open(const IBamIODevice::OpenMode mode) {
+
+    // make sure we're starting with a fresh file stream
+    Close();
+
+    // attempt to open FILE* depending on requested openmode
+    if ( mode == IBamIODevice::ReadOnly )
+        m_stream = fopen(m_filename.c_str(), "rb");
+    else if ( mode == IBamIODevice::WriteOnly )
+        m_stream = fopen(m_filename.c_str(), "wb");
+    else {
+        SetErrorString("BamFile ERROR - unknown device open mode");
+        return false;
+    }
+
+    // check that we obtained a valid FILE*
+    if ( m_stream == 0 ) {
+        string error = "BamFile ERROR - could not open handle on ";
+        error += ( (m_filename.empty()) ? "empty filename" : m_filename );
+        SetErrorString(error);
+        return false;
+    }
+
+    // store current IO mode & return success
+    m_mode = mode;
+    return true;
+}
+
+size_t BamFile::Read(char* data, const unsigned int numBytes) {
+    BT_ASSERT_X( m_stream, "BamFile::Read() - null stream" );
+    BT_ASSERT_X( (m_mode == IBamIODevice::ReadOnly), "BamFile::Read() - device not in read-only mode");
+    return fread(data, sizeof(char), numBytes, m_stream);
+}
+
+bool BamFile::Seek(const int64_t& position) {
+    BT_ASSERT_X( m_stream, "BamFile::Seek() - null stream" );
+    return ( fseek64(m_stream, position, SEEK_SET) == 0);
+}
+
+int64_t BamFile::Tell(void) const {
+    BT_ASSERT_X( m_stream, "BamFile::Tell() - null stream" );
+    return ftell64(m_stream);
+}
+
+size_t BamFile::Write(const char* data, const unsigned int numBytes) {
+    BT_ASSERT_X( m_stream, "BamFile::Write() - null stream" );
+    BT_ASSERT_X( (m_mode == IBamIODevice::WriteOnly), "BamFile::Write() - device not in write-only mode" );
+    return fwrite(data, sizeof(char), numBytes, m_stream);
+}
diff --git a/src/api/internal/BamFile_p.h b/src/api/internal/BamFile_p.h
new file mode 100644 (file)
index 0000000..d0712ef
--- /dev/null
@@ -0,0 +1,58 @@
+// ***************************************************************************
+// BamFile_p.h (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides reading/writing of local BAM files
+// ***************************************************************************
+
+#ifndef BAMFILE_P_H
+#define BAMFILE_P_H
+
+//  -------------
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the BamTools API.  It exists purely as an
+// implementation detail. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+
+#include <api/IBamIODevice.h>
+#include <string>
+
+namespace BamTools {
+namespace Internal {
+
+class BamFile : public IBamIODevice {
+
+    // ctor & dtor
+    public:
+        BamFile(const std::string& filename);
+        ~BamFile(void);
+
+    // IBamIODevice implementation
+    public:
+        void Close(void);
+        bool IsRandomAccess(void) const;
+        bool Open(const IBamIODevice::OpenMode mode);
+        size_t Read(char* data, const unsigned int numBytes);
+        bool Seek(const int64_t& position);
+        int64_t Tell(void) const;
+        size_t Write(const char* data, const unsigned int numBytes);
+
+    // internal methods
+    private:
+
+    // data members
+    private:
+        FILE* m_stream;
+        std::string m_filename;
+};
+
+} // namespace Internal
+} // namespace BamTools
+
+#endif // BAMFILE_P_H
diff --git a/src/api/internal/BamFtp_p.cpp b/src/api/internal/BamFtp_p.cpp
new file mode 100644 (file)
index 0000000..f957197
--- /dev/null
@@ -0,0 +1,56 @@
+// ***************************************************************************
+// BamFtp_p.cpp (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 9 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides reading/writing of BAM files on FTP server
+// ***************************************************************************
+
+#include <api/internal/BamFtp_p.h>
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+using namespace std;
+
+BamFtp::BamFtp(const string& url)
+    : IBamIODevice()
+{
+    BT_ASSERT_X(false, "BamFtp not yet implemented");
+}
+
+BamFtp::~BamFtp(void) { }
+
+void BamFtp::Close(void) {
+    return ;
+}
+
+bool BamFtp::IsRandomAccess(void) const {
+    return true;
+}
+
+bool BamFtp::Open(const IBamIODevice::OpenMode mode) {
+    (void) mode;
+    return true;
+}
+
+size_t BamFtp::Read(char* data, const unsigned int numBytes) {
+    (void)data;
+    (void)numBytes;
+    return 0;
+}
+
+bool BamFtp::Seek(const int64_t& position) {
+    (void)position;
+    return true;
+}
+
+int64_t BamFtp::Tell(void) const {
+    return -1;
+}
+
+size_t BamFtp::Write(const char* data, const unsigned int numBytes) {
+    (void)data;
+    (void)numBytes;
+    return 0;
+}
diff --git a/src/api/internal/BamFtp_p.h b/src/api/internal/BamFtp_p.h
new file mode 100644 (file)
index 0000000..d410201
--- /dev/null
@@ -0,0 +1,56 @@
+// ***************************************************************************
+// BamFtp_p.h (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides reading/writing of BAM files on FTP server
+// ***************************************************************************
+
+#ifndef BAMFTP_P_H
+#define BAMFTP_P_H
+
+//  -------------
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the BamTools API.  It exists purely as an
+// implementation detail. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+
+#include <api/IBamIODevice.h>
+#include <string>
+
+namespace BamTools {
+namespace Internal {
+
+class BamFtp : public IBamIODevice {
+
+    // ctor & dtor
+    public:
+        BamFtp(const std::string& url);
+        ~BamFtp(void);
+
+    // IBamIODevice implementation
+    public:
+        void Close(void);
+        bool IsRandomAccess(void) const;
+        bool Open(const IBamIODevice::OpenMode mode);
+        size_t Read(char* data, const unsigned int numBytes);
+        bool Seek(const int64_t& position);
+        int64_t Tell(void) const;
+        size_t Write(const char* data, const unsigned int numBytes);
+
+    // internal methods
+    private:
+
+    // data members
+    private:
+};
+
+} // namespace Internal
+} // namespace BamTools
+
+#endif // BAMFTP_P_H
index 0eaf7bc0f6ed2a7d7b4a1c0431021734962c024f..2f4ef3480e20c5b93fc9e1c650a6dd0e21977af2 100644 (file)
@@ -32,7 +32,7 @@ bool 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) != (int)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;
     }
diff --git a/src/api/internal/BamHttp_p.cpp b/src/api/internal/BamHttp_p.cpp
new file mode 100644 (file)
index 0000000..532194b
--- /dev/null
@@ -0,0 +1,56 @@
+// ***************************************************************************
+// BamHttp_p.cpp (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 9 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides reading/writing of BAM files on HTTP server
+// ***************************************************************************
+
+#include <api/internal/BamHttp_p.h>
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+using namespace std;
+
+BamHttp::BamHttp(const string& url)
+    : IBamIODevice()
+{
+    BT_ASSERT_X(false, "BamHttp not yet implemented");
+}
+
+BamHttp::~BamHttp(void) { }
+
+void BamHttp::Close(void) {
+    return ;
+}
+
+bool BamHttp::IsRandomAccess(void) const {
+    return true;
+}
+
+bool BamHttp::Open(const IBamIODevice::OpenMode mode) {
+    (void) mode;
+    return true;
+}
+
+size_t BamHttp::Read(char* data, const unsigned int numBytes) {
+    (void)data;
+    (void)numBytes;
+    return 0;
+}
+
+bool BamHttp::Seek(const int64_t& position) {
+    (void)position;
+    return true;
+}
+
+int64_t BamHttp::Tell(void) const {
+    return -1;
+}
+
+size_t BamHttp::Write(const char* data, const unsigned int numBytes) {
+    (void)data;
+    (void)numBytes;
+    return 0;
+}
diff --git a/src/api/internal/BamHttp_p.h b/src/api/internal/BamHttp_p.h
new file mode 100644 (file)
index 0000000..e1d2403
--- /dev/null
@@ -0,0 +1,56 @@
+// ***************************************************************************
+// BamHttp_p.h (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides reading/writing of BAM files on HTTP server
+// ***************************************************************************
+
+#ifndef BAMHTTP_P_H
+#define BAMHTTP_P_H
+
+//  -------------
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the BamTools API.  It exists purely as an
+// implementation detail. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+
+#include <api/IBamIODevice.h>
+#include <string>
+
+namespace BamTools {
+namespace Internal {
+
+class BamHttp : public IBamIODevice {
+
+    // ctor & dtor
+    public:
+        BamHttp(const std::string& url);
+        ~BamHttp(void);
+
+    // IBamIODevice implementation
+    public:
+        void Close(void);
+        bool IsRandomAccess(void) const;
+        bool Open(const IBamIODevice::OpenMode mode);
+        size_t Read(char* data, const unsigned int numBytes);
+        bool Seek(const int64_t& position);
+        int64_t Tell(void) const;
+        size_t Write(const char* data, const unsigned int numBytes);
+
+    // internal methods
+    private:
+
+    // data members
+    private:
+};
+
+} // namespace Internal
+} // namespace BamTools
+
+#endif // BAMHTTP_P_H
diff --git a/src/api/internal/BamPipe_p.cpp b/src/api/internal/BamPipe_p.cpp
new file mode 100644 (file)
index 0000000..6bfbf6f
--- /dev/null
@@ -0,0 +1,92 @@
+// ***************************************************************************
+// BamPipe_p.cpp (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides reading/writing of piped BAM files (stdin/stdout)
+// ***************************************************************************
+
+#include <api/internal/BamPipe_p.h>
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+#include <cstdio>
+using namespace std;
+
+BamPipe::BamPipe(void)
+    : IBamIODevice()
+    , m_stream(0)
+{ }
+
+BamPipe::~BamPipe(void) {
+    Close();
+}
+
+void BamPipe::Close(void) {
+
+    // skip if not open
+    if ( !IsOpen() ) return;
+
+    // flush & close FILE*
+    fflush(m_stream);
+    fclose(m_stream);
+
+    // reset internals
+    m_mode = IBamIODevice::NotOpen;
+    m_stream = 0;
+}
+
+bool BamPipe::IsRandomAccess(void) const {
+    return false;
+}
+
+bool BamPipe::Open(const IBamIODevice::OpenMode mode) {
+
+    // make sure we're starting with a fresh pipe
+    Close();
+
+    // open stdin/stdout depending on requested openmode
+    if ( mode == IBamIODevice::ReadOnly )
+        m_stream = freopen(0, "rb", stdin);
+    else if ( mode == IBamIODevice::WriteOnly )
+        m_stream = freopen(0, "wb", stdout);
+    else {
+        SetErrorString("BamPipe ERROR - unsupported device mode");
+        return false;
+    }
+
+    // check that we obtained a valid FILE*
+    if ( m_stream == 0 ) {
+        string error = "BamPipe ERROR - could not open handle on ";
+        error += ( (mode == IBamIODevice::ReadOnly) ? "stdin" : "stdout" );
+        SetErrorString(error);
+        return false;
+    }
+
+    // store current IO mode & return success
+    m_mode = mode;
+    return true;
+}
+
+size_t BamPipe::Read(char* data, const unsigned int numBytes) {
+    BT_ASSERT_X( m_stream, "BamPipe::Read() - null stream" );
+    BT_ASSERT_X( (m_mode == IBamIODevice::ReadOnly), "BamPipe::Read() - device not in read-only mode");
+    return fread(data, sizeof(char), numBytes, m_stream);
+}
+
+bool BamPipe::Seek(const int64_t& position) {
+    (void)position; // suppress compiler warning about unused variable
+    return false;   // seeking not allowed in pipe
+}
+
+int64_t BamPipe::Tell(void) const {
+    BT_ASSERT_X( m_stream, "BamPipe::Tell() - null stream" );
+    return ftell64(m_stream);
+}
+
+size_t BamPipe::Write(const char* data, const unsigned int numBytes) {
+    BT_ASSERT_X( m_stream, "BamPipe::Write() - null stream" );
+    BT_ASSERT_X( (m_mode == IBamIODevice::WriteOnly), "BamPipe::Write() - device not in write-only mode" );
+    return fwrite(data, sizeof(char), numBytes, m_stream);
+}
diff --git a/src/api/internal/BamPipe_p.h b/src/api/internal/BamPipe_p.h
new file mode 100644 (file)
index 0000000..386ede0
--- /dev/null
@@ -0,0 +1,57 @@
+// ***************************************************************************
+// BamPipe_p.h (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides reading/writing of piped BAM files (stdin/stdout)
+// ***************************************************************************
+
+#ifndef BAMPIPE_P_H
+#define BAMPIPE_P_H
+
+//  -------------
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the BamTools API.  It exists purely as an
+// implementation detail. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+
+#include <api/IBamIODevice.h>
+#include <string>
+
+namespace BamTools {
+namespace Internal {
+
+class BamPipe : public IBamIODevice {
+
+    // ctor & dtor
+    public:
+        BamPipe(void);
+        ~BamPipe(void);
+
+    // IBamIODevice implementation
+    public:
+        void Close(void);
+        bool IsRandomAccess(void) const;
+        bool Open(const IBamIODevice::OpenMode mode);
+        size_t Read(char* data, const unsigned int numBytes);
+        bool Seek(const int64_t& position);
+        int64_t Tell(void) const;
+        size_t Write(const char* data, const unsigned int numBytes);
+
+    // internal methods
+    private:
+
+    // data members
+    private:
+        FILE* m_stream;
+};
+
+} // namespace Internal
+} // namespace BamTools
+
+#endif // BAMPIPE_P_H
index 89636bbf0ecf46a76b4ec5a63cff085e6b899a04..9187b3a0025a919ab8932b7c28d723f7ae5da3e9 100644 (file)
@@ -134,6 +134,8 @@ void BamRandomAccessController::Close(void) {
 }
 
 void BamRandomAccessController::ClearIndex(void) {
+    if ( m_index == 0 )
+        return;
     delete m_index;
     m_index = 0;
 }
index 5daa1bf2950c6c7da9af4cc6c5f9bd4b40ca41c3..87fe310499847103e4e6a213a5a7134b5378e4ed 100644 (file)
@@ -10,6 +10,8 @@
 
 #include <api/BamConstants.h>
 #include <api/BamReader.h>
+#include <api/IBamIODevice.h>
+#include <api/internal/BamDeviceFactory_p.h>
 #include <api/internal/BamHeader_p.h>
 #include <api/internal/BamRandomAccessController_p.h>
 #include <api/internal/BamReader_p.h>
@@ -97,6 +99,9 @@ bool BamReaderPrivate::GetNextAlignment(BamAlignment& alignment) {
 // useful for operations requiring ONLY positional or other alignment-related information
 bool BamReaderPrivate::GetNextAlignmentCore(BamAlignment& alignment) {
 
+    if ( !m_stream.IsOpen() )
+        return false;
+
     // skip if region is set but has no alignments
     if ( m_randomAccessController.HasRegion() &&
          !m_randomAccessController.RegionHasAlignments() )
@@ -165,7 +170,7 @@ bool BamReaderPrivate::HasIndex(void) const {
 }
 
 bool BamReaderPrivate::IsOpen(void) const {
-    return m_stream.IsOpen;
+    return m_stream.IsOpen();
 }
 
 // load BAM header data
@@ -190,7 +195,7 @@ bool BamReaderPrivate::LoadNextAlignment(BamAlignment& alignment) {
 
     // swap core endian-ness if necessary
     if ( m_isBigEndian ) {
-        for ( int i = 0; i < Constants::BAM_CORE_SIZE; i+=sizeof(uint32_t) )
+        for ( unsigned int i = 0; i < Constants::BAM_CORE_SIZE; i+=sizeof(uint32_t) )
             BamTools::SwapEndian_32p(&x[i]);
     }
 
@@ -220,7 +225,7 @@ bool BamReaderPrivate::LoadNextAlignment(BamAlignment& alignment) {
     const unsigned int dataLength = alignment.SupportData.BlockLength - Constants::BAM_CORE_SIZE;
     char* allCharData = (char*)calloc(sizeof(char), dataLength);
 
-    if ( m_stream.Read(allCharData, dataLength) == (signed int)dataLength ) {
+    if ( m_stream.Read(allCharData, dataLength) == dataLength ) {
 
         // store 'allCharData' in supportData structure
         alignment.SupportData.AllCharData.assign((const char*)allCharData, dataLength);
@@ -301,12 +306,11 @@ bool BamReaderPrivate::LocateIndex(const BamIndex::IndexType& preferredType) {
 // opens BAM file (and index)
 bool BamReaderPrivate::Open(const string& filename) {
 
-    // close current BAM file if open
-    if ( m_stream.IsOpen )
-        Close();
+    // make sure we're starting with a fresh slate
+    Close();
 
     // attempt to open BgzfStream for reading
-    if ( !m_stream.Open(filename, "rb") ) {
+    if ( !m_stream.Open(filename, IBamIODevice::ReadOnly) ) {
         cerr << "BamReader ERROR: Could not open BGZF stream for " << filename << endl;
         return false;
     }
@@ -340,6 +344,9 @@ bool BamReaderPrivate::OpenIndex(const std::string& indexFilename) {
 // returns BAM file pointer to beginning of alignment data
 bool BamReaderPrivate::Rewind(void) {
 
+    if ( !m_stream.IsOpen() )
+        return false;
+
     // attempt rewind to first alignment
     if ( !m_stream.Seek(m_alignmentsBeginOffset) )
         return false;
index 490820cbc7583014ee75f4d5bf0adc51bd5f286e..508b6da06ed08b461287558bee8f7fa7ed8ca1c1 100644 (file)
@@ -125,7 +125,7 @@ void BamWriterPrivate::EncodeQuerySequence(const string& query, string& encodedQ
 
 // returns whether BAM file is open for writing or not
 bool BamWriterPrivate::IsOpen(void) const {
-    return m_stream.IsOpen;
+    return m_stream.IsOpen();
 }
 
 // opens the alignment archive
index ae645fd35d6164ac9d43399f5463c9bf1a830c96..b79164decabcf7d49feba9c6455da4eed96fa979 100644 (file)
@@ -3,38 +3,41 @@
 // Marth Lab, Department of Biology, Boston College
 // All rights reserved.
 // ---------------------------------------------------------------------------
-// Last modified: 2 September 2011(DB)
+// Last modified: 9 September 2011(DB)
 // ---------------------------------------------------------------------------
 // Based on BGZF routines developed at the Broad Institute.
 // Provides the basic functionality for reading & writing BGZF files
 // Replaces the old BGZF.* files to avoid clashing with other toolkits
 // ***************************************************************************
 
+#include <api/internal/BamDeviceFactory_p.h>
 #include <api/internal/BgzfStream_p.h>
 using namespace BamTools;
 using namespace BamTools::Internal;
 
 #include <cstring>
 #include <algorithm>
+#include <iostream>
 using namespace std;
 
 // constructor
 BgzfStream::BgzfStream(void)
-    : UncompressedBlockSize(Constants::BGZF_DEFAULT_BLOCK_SIZE)
-    , CompressedBlockSize(Constants::BGZF_MAX_BLOCK_SIZE)
-    , BlockLength(0)
-    , BlockOffset(0)
-    , BlockAddress(0)
-    , IsOpen(false)
-    , IsWriteOnly(false)
-    , IsWriteCompressed(true)
-    , Stream(NULL)
-    , UncompressedBlock(NULL)
-    , CompressedBlock(NULL)
+    : m_uncompressedBlockSize(Constants::BGZF_DEFAULT_BLOCK_SIZE)
+    , m_compressedBlockSize(Constants::BGZF_MAX_BLOCK_SIZE)
+    , m_blockLength(0)
+    , m_blockOffset(0)
+    , m_blockAddress(0)
+    , m_uncompressedBlock(NULL)
+    , m_compressedBlock(NULL)
+    , m_isOpen(false)
+    , m_isWriteOnly(false)
+    , m_isWriteCompressed(true)
+    , m_device(0)
+    , m_stream(NULL)
 {
     try {
-        CompressedBlock   = new char[CompressedBlockSize];
-        UncompressedBlock = new char[UncompressedBlockSize];
+        m_compressedBlock   = new char[m_compressedBlockSize];
+        m_uncompressedBlock = new char[m_uncompressedBlockSize];
     } catch( std::bad_alloc& ba ) {
         fprintf(stderr, "BgzfStream ERROR: unable to allocate memory\n");
         exit(1);
@@ -43,38 +46,40 @@ BgzfStream::BgzfStream(void)
 
 // destructor
 BgzfStream::~BgzfStream(void) {
-    if( CompressedBlock   ) delete[] CompressedBlock;
-    if( UncompressedBlock ) delete[] UncompressedBlock;
+    if( m_compressedBlock   ) delete[] m_compressedBlock;
+    if( m_uncompressedBlock ) delete[] m_uncompressedBlock;
 }
 
 // closes BGZF file
 void BgzfStream::Close(void) {
 
-    // skip if file not open
-    if ( !IsOpen ) return;
+    // skip if no device open
+    if ( m_device == 0 )
+        return;
 
     // if writing to file, flush the current BGZF block,
     // then write an empty block (as EOF marker)
-    if ( IsWriteOnly ) {
+    if ( m_device->IsOpen() && (m_device->Mode() == IBamIODevice::WriteOnly) ) {
         FlushBlock();
         int blockLength = DeflateBlock();
-        fwrite(CompressedBlock, 1, blockLength, Stream);
+        m_device->Write(m_compressedBlock, blockLength);
     }
 
-    // flush and close stream
-    fflush(Stream);
-    fclose(Stream);
+    // close device
+    m_device->Close();
 
-    // reset flags
-    IsWriteCompressed = true;
-    IsOpen = false;
+    // clean up & reset flags
+    delete m_device;
+    m_device = 0;
+    m_isWriteCompressed = true;
+    m_isOpen = false;
 }
 
 // compresses the current block
-int BgzfStream::DeflateBlock(void) {
+unsigned int BgzfStream::DeflateBlock(void) {
 
     // initialize the gzip header
-    char* buffer = CompressedBlock;
+    char* buffer = m_compressedBlock;
     memset(buffer, 0, 18);
     buffer[0]  = Constants::GZIP_ID1;
     buffer[1]  = (char)Constants::GZIP_ID2;
@@ -87,12 +92,12 @@ int BgzfStream::DeflateBlock(void) {
     buffer[14] = Constants::BGZF_LEN;
 
     // set compression level
-    const int compressionLevel = ( IsWriteCompressed ? Z_DEFAULT_COMPRESSION : 0 );
+    const int compressionLevel = ( m_isWriteCompressed ? Z_DEFAULT_COMPRESSION : 0 );
 
     // loop to retry for blocks that do not compress enough
-    int inputLength = BlockOffset;
-    int compressedLength = 0;
-    unsigned int bufferSize = CompressedBlockSize;
+    int inputLength = m_blockOffset;
+    unsigned int compressedLength = 0;
+    unsigned int bufferSize = m_compressedBlockSize;
 
     while ( true ) {
 
@@ -100,7 +105,7 @@ int BgzfStream::DeflateBlock(void) {
         z_stream zs;
         zs.zalloc    = NULL;
         zs.zfree     = NULL;
-        zs.next_in   = (Bytef*)UncompressedBlock;
+        zs.next_in   = (Bytef*)m_uncompressedBlock;
         zs.avail_in  = inputLength;
         zs.next_out  = (Bytef*)&buffer[Constants::BGZF_BLOCK_HEADER_LENGTH];
         zs.avail_out = bufferSize - Constants::BGZF_BLOCK_HEADER_LENGTH - Constants::BGZF_BLOCK_FOOTER_LENGTH;
@@ -158,22 +163,22 @@ int BgzfStream::DeflateBlock(void) {
 
     // store the CRC32 checksum
     unsigned int crc = crc32(0, NULL, 0);
-    crc = crc32(crc, (Bytef*)UncompressedBlock, inputLength);
+    crc = crc32(crc, (Bytef*)m_uncompressedBlock, inputLength);
     BamTools::PackUnsignedInt(&buffer[compressedLength - 8], crc);
     BamTools::PackUnsignedInt(&buffer[compressedLength - 4], inputLength);
 
     // ensure that we have less than a block of data left
-    int remaining = BlockOffset - inputLength;
+    int remaining = m_blockOffset - inputLength;
     if ( remaining > 0 ) {
         if ( remaining > inputLength ) {
             fprintf(stderr, "BgzfStream ERROR: after deflate, remainder too large\n");
             exit(1);
         }
-        memcpy(UncompressedBlock, UncompressedBlock + inputLength, remaining);
+        memcpy(m_uncompressedBlock, m_uncompressedBlock + inputLength, remaining);
     }
 
     // update block data
-    BlockOffset = remaining;
+    m_blockOffset = remaining;
 
     // return result
     return compressedLength;
@@ -182,14 +187,16 @@ int BgzfStream::DeflateBlock(void) {
 // flushes the data in the BGZF block
 void BgzfStream::FlushBlock(void) {
 
+    BT_ASSERT_X( m_device, "BgzfStream::FlushBlock() - attempting to flush to null device" );
+
     // flush all of the remaining blocks
-    while ( BlockOffset > 0 ) {
+    while ( m_blockOffset > 0 ) {
 
         // compress the data block
-        int blockLength = DeflateBlock();
+        unsigned int blockLength = DeflateBlock();
 
         // flush the data to our output stream
-        int numBytesWritten = fwrite(CompressedBlock, 1, blockLength, Stream);
+        unsigned int numBytesWritten = m_device->Write(m_compressedBlock, blockLength);
         if ( numBytesWritten != blockLength ) {
             fprintf(stderr, "BgzfStream ERROR: expected to write %u bytes during flushing, but wrote %u bytes\n",
                     blockLength, numBytesWritten);
@@ -197,7 +204,7 @@ void BgzfStream::FlushBlock(void) {
         }
 
         // update block data
-        BlockAddress += blockLength;
+        m_blockAddress += blockLength;
     }
 }
 
@@ -208,10 +215,10 @@ int BgzfStream::InflateBlock(const int& blockLength) {
     z_stream zs;
     zs.zalloc    = NULL;
     zs.zfree     = NULL;
-    zs.next_in   = (Bytef*)CompressedBlock + 18;
+    zs.next_in   = (Bytef*)m_compressedBlock + 18;
     zs.avail_in  = blockLength - 16;
-    zs.next_out  = (Bytef*)UncompressedBlock;
-    zs.avail_out = UncompressedBlockSize;
+    zs.next_out  = (Bytef*)m_uncompressedBlock;
+    zs.avail_out = m_uncompressedBlockSize;
 
     int status = inflateInit2(&zs, Constants::GZIP_WINDOW_BITS);
     if ( status != Z_OK ) {
@@ -236,17 +243,51 @@ int BgzfStream::InflateBlock(const int& blockLength) {
     return zs.total_out;
 }
 
+bool BgzfStream::IsOpen(void) const {
+    if ( m_device == 0 )
+        return false;
+    return m_device->IsOpen();
+}
+
+bool BgzfStream::Open(const string& filename, const IBamIODevice::OpenMode mode) {
+
+    // close current device if necessary
+    Close();
+
+    // sanity check
+    BT_ASSERT_X( (m_device == 0), "BgzfStream::Open() - unable to properly close previous IO device" );
+
+    // retrieve new IO device depending on filename
+    m_device = BamDeviceFactory::CreateDevice(filename);
+
+    // sanity check
+    BT_ASSERT_X( m_device, "BgzfStream::Open() - unable to create IO device from filename" );
+
+    // if device fails to open
+    if ( !m_device->Open(mode) ) {
+        cerr << "BgzfStream::Open() - unable to open IO device:" << endl;
+        cerr << m_device->ErrorString();
+        return false;
+    }
+
+    // otherwise, set flag & return true
+    m_isOpen = true;
+    m_isWriteOnly = ( mode == IBamIODevice::WriteOnly );
+    return true;
+
+}
+
 // opens the BGZF file for reading (mode is either "rb" for reading, or "wb" for writing)
 bool BgzfStream::Open(const string& filename, const char* mode) {
 
     // close current stream, if necessary, before opening next
-    if ( IsOpen ) Close();
+    if ( m_isOpen ) Close();
 
     // determine open mode
     if ( strcmp(mode, "rb") == 0 )
-        IsWriteOnly = false;
+        m_isWriteOnly = false;
     else if ( strcmp(mode, "wb") == 0)
-        IsWriteOnly = true;
+        m_isWriteOnly = true;
     else {
         fprintf(stderr, "BgzfStream ERROR: unknown file mode: %s\n", mode);
         return false;
@@ -254,31 +295,35 @@ bool BgzfStream::Open(const string& filename, const char* mode) {
 
     // open BGZF stream on a file
     if ( (filename != "stdin") && (filename != "stdout") && (filename != "-"))
-        Stream = fopen(filename.c_str(), mode);
+        m_stream = fopen(filename.c_str(), mode);
 
     // open BGZF stream on stdin
     else if ( (filename == "stdin" || filename == "-") && (strcmp(mode, "rb") == 0 ) )
-        Stream = freopen(NULL, mode, stdin);
+        m_stream = freopen(NULL, mode, stdin);
 
     // open BGZF stream on stdout
     else if ( (filename == "stdout" || filename == "-") && (strcmp(mode, "wb") == 0) )
-        Stream = freopen(NULL, mode, stdout);
+        m_stream = freopen(NULL, mode, stdout);
 
-    if ( !Stream ) {
+    if ( !m_stream ) {
         fprintf(stderr, "BgzfStream ERROR: unable to open file %s\n", filename.c_str() );
         return false;
     }
 
     // set flag & return success
-    IsOpen = true;
+    m_isOpen = true;
     return true;
 }
 
 // reads BGZF data into a byte buffer
-int BgzfStream::Read(char* data, const unsigned int dataLength) {
+unsigned int BgzfStream::Read(char* data, const unsigned int dataLength) {
+
+    if ( dataLength == 0 )
+        return 0;
 
-    // if stream not open for reading (or empty request)
-    if ( !IsOpen || IsWriteOnly || dataLength == 0 )
+    // if stream not open for reading
+    BT_ASSERT_X( m_device, "BgzfStream::Read() - trying to read from null device");
+    if ( !m_device->IsOpen() || (m_device->Mode() != IBamIODevice::ReadOnly) )
         return 0;
 
     // read blocks as needed until desired data length is retrieved
@@ -287,31 +332,31 @@ int BgzfStream::Read(char* data, const unsigned int dataLength) {
     while ( numBytesRead < dataLength ) {
 
         // determine bytes available in current block
-        int bytesAvailable = BlockLength - BlockOffset;
+        int bytesAvailable = m_blockLength - m_blockOffset;
 
         // read (and decompress) next block if needed
         if ( bytesAvailable <= 0 ) {
             if ( !ReadBlock() ) return -1;
-            bytesAvailable = BlockLength - BlockOffset;
+            bytesAvailable = m_blockLength - m_blockOffset;
             if ( bytesAvailable <= 0 ) break;
         }
 
         // copy data from uncompressed source buffer into data destination buffer
-        char* buffer   = UncompressedBlock;
+        char* buffer   = m_uncompressedBlock;
         int copyLength = min( (int)(dataLength-numBytesRead), bytesAvailable );
-        memcpy(output, buffer + BlockOffset, copyLength);
+        memcpy(output, buffer + m_blockOffset, copyLength);
 
         // update counters
-        BlockOffset  += copyLength;
-        output       += copyLength;
-        numBytesRead += copyLength;
+        m_blockOffset += copyLength;
+        output        += copyLength;
+        numBytesRead  += copyLength;
     }
 
     // update block data
-    if ( BlockOffset == BlockLength ) {
-        BlockAddress = ftell64(Stream);
-        BlockOffset  = 0;
-        BlockLength  = 0;
+    if ( m_blockOffset == m_blockLength ) {
+        m_blockAddress = m_device->Tell();
+        m_blockOffset  = 0;
+        m_blockLength  = 0;
     }
 
     return numBytesRead;
@@ -320,20 +365,23 @@ int BgzfStream::Read(char* data, const unsigned int dataLength) {
 // reads a BGZF block
 bool BgzfStream::ReadBlock(void) {
 
-    char header[Constants::BGZF_BLOCK_HEADER_LENGTH];
-    int64_t blockAddress = ftell64(Stream);
+    BT_ASSERT_X( m_device, "BgzfStream::ReadBlock() - trying to read from null IO device");
+
+    // store block's starting address
+    int64_t blockAddress = m_device->Tell();
 
     // read block header from file
-    int count = fread(header, 1, sizeof(header), Stream);
+    char header[Constants::BGZF_BLOCK_HEADER_LENGTH];
+    int numBytesRead = m_device->Read(header, Constants::BGZF_BLOCK_HEADER_LENGTH);
 
     // if block header empty
-    if ( count == 0 ) {
-        BlockLength = 0;
+    if ( numBytesRead == 0 ) {
+        m_blockLength = 0;
         return true;
     }
 
     // if block header invalid size
-    if ( count != sizeof(header) ) {
+    if ( numBytesRead != Constants::BGZF_BLOCK_HEADER_LENGTH ) {
         fprintf(stderr, "BgzfStream ERROR: read block failed - could not read block header\n");
         return false;
     }
@@ -346,29 +394,29 @@ bool BgzfStream::ReadBlock(void) {
 
     // copy header contents to compressed buffer
     int blockLength = BamTools::UnpackUnsignedShort(&header[16]) + 1;
-    char* compressedBlock = CompressedBlock;
+    char* compressedBlock = m_compressedBlock;
     memcpy(compressedBlock, header, Constants::BGZF_BLOCK_HEADER_LENGTH);
     int remaining = blockLength - Constants::BGZF_BLOCK_HEADER_LENGTH;
 
     // read remainder of block
-    count = fread(&compressedBlock[Constants::BGZF_BLOCK_HEADER_LENGTH], 1, remaining, Stream);
-    if ( count != remaining ) {
+    numBytesRead = m_device->Read(&compressedBlock[Constants::BGZF_BLOCK_HEADER_LENGTH], remaining);
+    if ( numBytesRead != remaining ) {
         fprintf(stderr, "BgzfStream ERROR: read block failed - could not read data from block\n");
         return false;
     }
 
     // decompress block data
-    count = InflateBlock(blockLength);
-    if ( count < 0 ) {
+    numBytesRead = InflateBlock(blockLength);
+    if ( numBytesRead < 0 ) {
         fprintf(stderr, "BgzfStream ERROR: read block failed - could not decompress block data\n");
         return false;
     }
 
     // update block data
-    if ( BlockLength != 0 )
-        BlockOffset = 0;
-    BlockAddress = blockAddress;
-    BlockLength  = count;
+    if ( m_blockLength != 0 )
+        m_blockOffset = 0;
+    m_blockAddress = blockAddress;
+    m_blockLength  = numBytesRead;
 
     // return success
     return true;
@@ -377,61 +425,65 @@ bool BgzfStream::ReadBlock(void) {
 // seek to position in BGZF file
 bool BgzfStream::Seek(const int64_t& position) {
 
-    // skip if not open
-    if ( !IsOpen ) return false;
+    BT_ASSERT_X( m_device, "BgzfStream::Seek() - trying to seek on null IO device");
+
+    // skip if not open or not seek-able
+    if ( !IsOpen() || !m_device->IsRandomAccess() )
+        return false;
 
     // determine adjusted offset & address
     int     blockOffset  = (position & 0xFFFF);
     int64_t blockAddress = (position >> 16) & 0xFFFFFFFFFFFFLL;
 
     // attempt seek in file
-    if ( fseek64(Stream, blockAddress, SEEK_SET) != 0 ) {
+    if ( !m_device->Seek(blockAddress) ) {
         fprintf(stderr, "BgzfStream ERROR: unable to seek in file\n");
         return false;
     }
 
     // update block data & return success
-    BlockLength  = 0;
-    BlockAddress = blockAddress;
-    BlockOffset  = blockOffset;
+    m_blockLength  = 0;
+    m_blockAddress = blockAddress;
+    m_blockOffset  = blockOffset;
     return true;
 }
 
 void BgzfStream::SetWriteCompressed(bool ok) {
-    IsWriteCompressed = ok;
+    m_isWriteCompressed = ok;
 }
 
 // get file position in BGZF file
 int64_t BgzfStream::Tell(void) const {
-    if ( !IsOpen )
-        return 0;
-    return ( (BlockAddress << 16) | (BlockOffset & 0xFFFF) );
+    if ( !m_isOpen ) return 0;
+    return ( (m_blockAddress << 16) | (m_blockOffset & 0xFFFF) );
 }
 
 // writes the supplied data into the BGZF buffer
-unsigned int BgzfStream::Write(const char* data, const unsigned int dataLen) {
+unsigned int BgzfStream::Write(const char* data, const unsigned int dataLength) {
 
-    // skip if file not open for writing
-    if ( !IsOpen || !IsWriteOnly ) return false;
+    BT_ASSERT_X( m_device, "BgzfStream::Write() - trying to write to null IO device");
+    BT_ASSERT_X( (m_device->Mode() == IBamIODevice::WriteOnly),
+                 "BgzfStream::Write() - trying to write to non-writable IO device");
 
     // write blocks as needed til all data is written
     unsigned int numBytesWritten = 0;
     const char* input = data;
-    unsigned int blockLength = UncompressedBlockSize;
-    while ( numBytesWritten < dataLen ) {
+    unsigned int blockLength = m_uncompressedBlockSize;
+    while ( numBytesWritten < dataLength ) {
 
         // copy data contents to uncompressed output buffer
-        unsigned int copyLength = min(blockLength - BlockOffset, dataLen - numBytesWritten);
-        char* buffer = UncompressedBlock;
-        memcpy(buffer + BlockOffset, input, copyLength);
+        unsigned int copyLength = min(blockLength - m_blockOffset, dataLength - numBytesWritten);
+        char* buffer = m_uncompressedBlock;
+        memcpy(buffer + m_blockOffset, input, copyLength);
 
         // update counter
-        BlockOffset     += copyLength;
+        m_blockOffset   += copyLength;
         input           += copyLength;
         numBytesWritten += copyLength;
 
         // flush (& compress) output buffer when full
-        if ( BlockOffset == blockLength ) FlushBlock();
+        if ( m_blockOffset == blockLength )
+            FlushBlock();
     }
 
     // return result
index c5e5d4872c0886509be74ca4e3d299f76a678025..04b6c34b88c0d122e3bc43f966b1cbafc4d39108 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <api/BamAux.h>
 #include <api/BamConstants.h>
+#include <api/IBamIODevice.h>
 #include "zlib.h"
 #include <cstdio>
 #include <string>
@@ -43,23 +44,27 @@ class BgzfStream {
     public:
         // closes BGZF file
         void Close(void);
-        // opens the BGZF file (mode is either "rb" for reading, or "wb" for writing)
+        bool IsOpen(void) const;
+        // opens the BGZF stream in requested mode
         bool Open(const std::string& filename, const char* mode);
+        bool Open(const std::string& filename, const IBamIODevice::OpenMode mode);
         // reads BGZF data into a byte buffer
-        int Read(char* data, const unsigned int dataLength);
+        unsigned int Read(char* data, const unsigned int dataLength);
         // seek to position in BGZF file
         bool Seek(const int64_t& position);
+        // sets IO device (closes previous, if any, but does not attempt to open)
+        void SetIODevice(IBamIODevice* device);
         // enable/disable compressed output
         void SetWriteCompressed(bool ok);
         // get file position in BGZF file
         int64_t Tell(void) const;
         // writes the supplied data into the BGZF buffer
-        unsigned int Write(const char* data, const unsigned int dataLen);
+        unsigned int Write(const char* data, const unsigned int dataLength);
 
     // internal methods
     private:
         // compresses the current block
-        int DeflateBlock(void);
+        unsigned int DeflateBlock(void);
         // flushes the data in the BGZF block
         void FlushBlock(void);
         // de-compresses the current block
@@ -74,17 +79,21 @@ class BgzfStream {
 
     // data members
     public:
-        unsigned int UncompressedBlockSize;
-        unsigned int CompressedBlockSize;
-        unsigned int BlockLength;
-        unsigned int BlockOffset;
-        uint64_t BlockAddress;
-        bool IsOpen;
-        bool IsWriteOnly;
-        bool IsWriteCompressed;
-        FILE* Stream;
-        char* UncompressedBlock;
-        char* CompressedBlock;
+        unsigned int m_uncompressedBlockSize;
+        unsigned int m_compressedBlockSize;
+        unsigned int m_blockLength;
+        unsigned int m_blockOffset;
+        uint64_t     m_blockAddress;
+
+        char* m_uncompressedBlock;
+        char* m_compressedBlock;
+
+        bool m_isOpen;
+        bool m_isWriteOnly;
+        bool m_isWriteCompressed;
+
+        IBamIODevice* m_device;
+        FILE* m_stream;
 };
 
 // -------------------------------------------------------------
index 6e3cb39e5a69fca28ef2196cdb0407671e8805c0..6380bb07afe145decd3c13602685c724f9bf1d66 100644 (file)
     #endif
 #endif // BAMTOOLS_TYPES
 
+#include <cassert>
+#include <stdexcept>
+#ifndef BAMTOOLS_ASSERTS
+#define BT_ASSERT_UNREACHABLE assert( false )
+#define BT_ASSERT_X( condition, message ) if (!( condition )) throw std::runtime_error( message );
+#endif // BAMTOOLS_ASSERTS
+
 #endif // BAMTOOLS_GLOBAL_H
index 3320e33351ceca803fed906d4af9c883ecce2120..71d46830df6667895a3ad8a1fcc02fa2652b7784 100644 (file)
@@ -3,7 +3,7 @@
 // Marth Lab, Department of Biology, Boston College
 // All rights reserved.
 // ---------------------------------------------------------------------------
-// Last modified: 9 June 2011
+// Last modified: 8 September 2011
 // ---------------------------------------------------------------------------
 // Provides general utilities used by BamTools sub-tools.
 // ***************************************************************************
 
 #include <api/BamAux.h>
 #include <utils/utils_global.h>
-#include <cassert>
-#include <stdexcept>
 #include <string>
 #include <vector>
 
-#define BAMTOOLS_ASSERT_UNREACHABLE assert( false )
-#define BAMTOOLS_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
+#define BAMTOOLS_ASSERT_UNREACHABLE BT_ASSERT_UNREACHABLE
+#define BAMTOOLS_ASSERT_MESSAGE( condition, message ) BT_ASSERT_X( condition, message )
 
 namespace BamTools {