]> git.donarmstrong.com Git - bamtools.git/commitdiff
Merge branches 'master' and 'iodevice' into iodevice
authorderek <derekwbarnett@gmail.com>
Sat, 10 Sep 2011 02:05:02 +0000 (22:05 -0400)
committerderek <derekwbarnett@gmail.com>
Sat, 10 Sep 2011 02:05:02 +0000 (22:05 -0400)
25 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/api/internal/ILocalIODevice_p.cpp [new file with mode: 0644]
src/api/internal/ILocalIODevice_p.h [new file with mode: 0644]
src/api/internal/IRemoteIODevice_p.cpp [new file with mode: 0644]
src/api/internal/IRemoteIODevice_p.h [new file with mode: 0644]
src/shared/bamtools_global.h
src/utils/bamtools_utilities.h

index 1107371ec703d74af78fa30454f55a1cd61ef1f6..ac672a667a4350b970692c67fe8fc07c6f2a48b3 100644 (file)
@@ -2,7 +2,7 @@
 // BamConstants.h (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 19 April 2011 (DB)
+// Last modified: 9 September 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides basic constants for handling BAM files.
 // ***************************************************************************
@@ -26,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;
@@ -118,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..5a0371269b0d24a640ebd00d7aa2939c1f3aa6b7 100644 (file)
@@ -25,15 +25,22 @@ 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
         internal/BamToolsIndex_p.cpp
         internal/BamWriter_p.cpp
         internal/BgzfStream_p.cpp
+        internal/ILocalIODevice_p.cpp
+        internal/IRemoteIODevice_p.cpp
         internal/SamFormatParser_p.cpp
         internal/SamFormatPrinter_p.cpp
         internal/SamHeaderValidator_p.cpp
@@ -68,6 +75,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..99454b2
--- /dev/null
@@ -0,0 +1,81 @@
+#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:
+
+        // pure virtuals
+        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;
+
+        // default implementation provided
+        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..6cb5be4
--- /dev/null
@@ -0,0 +1,68 @@
+// ***************************************************************************
+// BamFile_p.cpp (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 9 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides BAM file-specific IO behavior
+// ***************************************************************************
+
+#include <api/internal/BamFile_p.h>
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+#include <cstdio>
+#include <iostream>
+using namespace std;
+
+BamFile::BamFile(const string& filename)
+    : ILocalIODevice()
+    , m_filename(filename)
+{ }
+
+BamFile::~BamFile(void) { }
+
+void BamFile::Close(void) {
+    if ( IsOpen() ) {
+        m_filename.clear();
+        ILocalIODevice::Close();
+    }
+}
+
+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;
+}
+
+bool BamFile::Seek(const int64_t& position) {
+    BT_ASSERT_X( m_stream, "BamFile::Seek() - null stream" );
+    cerr << "BamFile::Seek() - about to attempt seek" << endl;
+    return ( fseek64(m_stream, position, SEEK_SET) == 0);
+}
diff --git a/src/api/internal/BamFile_p.h b/src/api/internal/BamFile_p.h
new file mode 100644 (file)
index 0000000..fd25a3e
--- /dev/null
@@ -0,0 +1,51 @@
+// ***************************************************************************
+// BamFile_p.h (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 9 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides BAM file-specific IO behavior
+// ***************************************************************************
+
+#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/internal/ILocalIODevice_p.h>
+#include <string>
+
+namespace BamTools {
+namespace Internal {
+
+class BamFile : public ILocalIODevice {
+
+    // ctor & dtor
+    public:
+        BamFile(const std::string& filename);
+        ~BamFile(void);
+
+    // ILocalIODevice implementation
+    public:
+        void Close(void);
+        bool IsRandomAccess(void) const;
+        bool Open(const IBamIODevice::OpenMode mode);
+        bool Seek(const int64_t& position);
+
+    // data members
+    private:
+        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 48b8c0908d7f16707b8eb832e98e601a97ddfca5..45dc379f52327c6cc9a77d232e1b53a9b83bd56e 100644 (file)
@@ -31,7 +31,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..62fd789
--- /dev/null
@@ -0,0 +1,68 @@
+// ***************************************************************************
+// BamPipe_p.cpp (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 9 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides BAM pipe-specific IO behavior
+// ***************************************************************************
+
+#include <api/internal/BamPipe_p.h>
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+#include <cstdio>
+#include <iostream>
+using namespace std;
+
+BamPipe::BamPipe(void) : ILocalIODevice() { }
+
+BamPipe::~BamPipe(void) { }
+
+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;
+}
+
+bool BamPipe::Seek(const int64_t& position) {
+//    (void)position; // suppress compiler warning about unused variable
+//    return false;   // seeking not allowed in pipe
+
+    BT_ASSERT_X( m_stream, "BamFile::Seek() - null stream" );
+    cerr << "BamPipe::Seek() - about to attempt seek" << endl;
+    bool result = ( fseek64(m_stream, position, SEEK_SET) == 0);
+    if ( !result ) {
+        cerr << "BamPipe can't be seeked in" << endl;
+    }
+    return result;
+
+//    return ( fseek64(m_stream, position, SEEK_SET) == 0);
+
+}
diff --git a/src/api/internal/BamPipe_p.h b/src/api/internal/BamPipe_p.h
new file mode 100644 (file)
index 0000000..a9725be
--- /dev/null
@@ -0,0 +1,46 @@
+// ***************************************************************************
+// BamPipe_p.h (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides BAM pipe-specific IO behavior
+// ***************************************************************************
+
+#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/internal/ILocalIODevice_p.h>
+#include <string>
+
+namespace BamTools {
+namespace Internal {
+
+class BamPipe : public ILocalIODevice {
+
+    // ctor & dtor
+    public:
+        BamPipe(void);
+        ~BamPipe(void);
+
+    // IBamIODevice implementation
+    public:
+        bool IsRandomAccess(void) const;
+        bool Open(const IBamIODevice::OpenMode mode);
+        bool Seek(const int64_t& position);
+};
+
+} // namespace Internal
+} // namespace BamTools
+
+#endif // BAMPIPE_P_H
index a599f7c48704a7361576e47e7705d486813944b9..a44563f5489952fb13a1f0e7d8fc0cac35db1b8c 100644 (file)
@@ -133,6 +133,8 @@ void BamRandomAccessController::Close(void) {
 }
 
 void BamRandomAccessController::ClearIndex(void) {
+    if ( m_index == 0 )
+        return;
     delete m_index;
     m_index = 0;
 }
index 65b19f330a60c7fe9ac00cc1b992a98ce7b186d6..384e2fe59d50b5912b6bb2091a413813dd6339ae 100644 (file)
@@ -9,6 +9,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>
@@ -96,6 +98,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() )
@@ -164,7 +169,7 @@ bool BamReaderPrivate::HasIndex(void) const {
 }
 
 bool BamReaderPrivate::IsOpen(void) const {
-    return m_stream.IsOpen;
+    return m_stream.IsOpen();
 }
 
 // load BAM header data
@@ -189,7 +194,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]);
     }
 
@@ -219,7 +224,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);
@@ -300,12 +305,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;
     }
@@ -339,14 +343,23 @@ bool BamReaderPrivate::OpenIndex(const std::string& indexFilename) {
 // returns BAM file pointer to beginning of alignment data
 bool BamReaderPrivate::Rewind(void) {
 
+    if ( !m_stream.IsOpen() ) {
+        cerr << "BRP::Rewind() - stream not open" << endl;
+        return false;
+    }
+
     // attempt rewind to first alignment
-    if ( !m_stream.Seek(m_alignmentsBeginOffset) )
+    if ( !m_stream.Seek(m_alignmentsBeginOffset) ) {
+        cerr << "BRP::Rewind() - could not seek to ABO (1st time)" << endl;
         return false;
+    }
 
     // verify that we can read first alignment
     BamAlignment al;
-    if ( !LoadNextAlignment(al) )
+    if ( !LoadNextAlignment(al) ) {
+        cerr << "BRP::Rewind() - could not read first alignment" << endl;
         return false;
+    }
 
     // reset region
     m_randomAccessController.ClearRegion();
index e77c099f8a53b6488e39c6c2e3a630c3e1884570..c9199b9a7b7859dfbfd4b0ef48f0de8aa58dc0f3 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <api/BamAlignment.h>
 #include <api/BamConstants.h>
+#include <api/IBamIODevice.h>
 #include <api/internal/BamWriter_p.h>
 using namespace BamTools;
 using namespace BamTools::Internal;
@@ -124,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
@@ -133,7 +134,7 @@ bool BamWriterPrivate::Open(const string& filename,
                             const RefVector& referenceSequences)
 {
     // open the BGZF file for writing, return failure if error
-    if ( !m_stream.Open(filename, "wb") )
+    if ( !m_stream.Open(filename, IBamIODevice::WriteOnly) )
         return false;
 
     // write BAM file 'metadata' components
index 36599b5b363fd6241fcd9fe6dff9a5c3b168235d..3b7074950031b7e0a92fd1c653348a69b2e63174 100644 (file)
@@ -2,38 +2,41 @@
 // BgzfStream_p.cpp (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// 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);
@@ -42,38 +45,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;
@@ -86,12 +91,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 ) {
 
@@ -99,7 +104,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;
@@ -157,22 +162,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;
@@ -181,14 +186,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);
@@ -196,7 +203,7 @@ void BgzfStream::FlushBlock(void) {
         }
 
         // update block data
-        BlockAddress += blockLength;
+        m_blockAddress += blockLength;
     }
 }
 
@@ -207,10 +214,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 ) {
@@ -235,17 +242,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;
@@ -253,31 +294,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 stream not open for reading (or empty request)
-    if ( !IsOpen || IsWriteOnly || dataLength == 0 )
+    if ( dataLength == 0 )
+        return 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
@@ -286,31 +331,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;
@@ -319,20 +364,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;
     }
@@ -345,29 +393,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;
@@ -376,61 +424,67 @@ 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()*/ ) {
+        cerr << "BgzfStream::Seek() - device not open" << endl;
+        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 ) {
-        fprintf(stderr, "BgzfStream ERROR: unable to seek in file\n");
+    if ( !m_device->Seek(blockAddress) ) {
+        cerr << "BgzfStream ERROR: unable to seek in file" << endl;
         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 838f30cde3f2f2a163fa72cd2852ea00315a4887..f7ea268b8de25cbda9ab88ad3728ac6957bac874 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <api/BamAux.h>
 #include <api/BamConstants.h>
+#include <api/IBamIODevice.h>
 #include "zlib.h"
 #include <cstdio>
 #include <string>
@@ -42,23 +43,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
@@ -73,17 +78,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;
 };
 
 // -------------------------------------------------------------
diff --git a/src/api/internal/ILocalIODevice_p.cpp b/src/api/internal/ILocalIODevice_p.cpp
new file mode 100644 (file)
index 0000000..9e9a2b3
--- /dev/null
@@ -0,0 +1,56 @@
+// ***************************************************************************
+// ILocalIODevice_p.cpp (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides shared behavior for files & pipes
+// ***************************************************************************
+
+#include <api/internal/ILocalIODevice_p.h>
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+#include <cstdio>
+using namespace std;
+
+ILocalIODevice::ILocalIODevice(void)
+    : IBamIODevice()
+    , m_stream(0)
+{ }
+
+ILocalIODevice::~ILocalIODevice(void) {
+    Close();
+}
+
+void ILocalIODevice::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;
+}
+
+size_t ILocalIODevice::Read(char* data, const unsigned int numBytes) {
+    BT_ASSERT_X( m_stream, "ILocalIODevice::Read() - null stream" );
+    BT_ASSERT_X( (m_mode == IBamIODevice::ReadOnly), "ILocalIODevice::Read() - device not in read-only mode");
+    return fread(data, sizeof(char), numBytes, m_stream);
+}
+
+int64_t ILocalIODevice::Tell(void) const {
+    BT_ASSERT_X( m_stream, "ILocalIODevice::Tell() - null stream" );
+    return ftell64(m_stream);
+}
+
+size_t ILocalIODevice::Write(const char* data, const unsigned int numBytes) {
+    BT_ASSERT_X( m_stream, "ILocalIODevice::Write() - null stream" );
+    BT_ASSERT_X( (m_mode == IBamIODevice::WriteOnly), "ILocalIODevice::Write() - device not in write-only mode" );
+    return fwrite(data, sizeof(char), numBytes, m_stream);
+}
diff --git a/src/api/internal/ILocalIODevice_p.h b/src/api/internal/ILocalIODevice_p.h
new file mode 100644 (file)
index 0000000..1e64899
--- /dev/null
@@ -0,0 +1,50 @@
+// ***************************************************************************
+// ILocalIODevice_p.h (c) 2011 Derek Barnett
+// Marth Lab, Department of Biology, Boston College
+// ---------------------------------------------------------------------------
+// Last modified: 8 September 2011 (DB)
+// ---------------------------------------------------------------------------
+// Provides shared behavior for files & pipes
+// ***************************************************************************
+
+#ifndef ILOCALIODEVICE_P_H
+#define ILOCALIODEVICE_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>
+
+namespace BamTools {
+namespace Internal {
+
+class ILocalIODevice : public IBamIODevice {
+
+    // ctor & dtor
+    public:
+        ILocalIODevice(void);
+        virtual ~ILocalIODevice(void);
+
+    // IBamIODevice implementation
+    public:
+        virtual void Close(void);
+        virtual size_t Read(char* data, const unsigned int numBytes);
+        virtual int64_t Tell(void) const;
+        virtual size_t Write(const char* data, const unsigned int numBytes);
+
+    // data members
+    protected:
+        FILE* m_stream;
+};
+
+} // namespace Internal
+} // namespace BamTools
+
+#endif // ILOCALIODEVICE_P_H
diff --git a/src/api/internal/IRemoteIODevice_p.cpp b/src/api/internal/IRemoteIODevice_p.cpp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/api/internal/IRemoteIODevice_p.h b/src/api/internal/IRemoteIODevice_p.h
new file mode 100644 (file)
index 0000000..e69de29
index e9181ce0af412169225ae11b7d6e4b1ce1c38ef0..1b2a8af7834f7445d193f2bff5d14fb75ac22fe6 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 52098d0c4811c2977c360e573cd16c587b210551..d9a319271c1da6e856325cacc7371e20cc0a978a 100644 (file)
@@ -2,7 +2,7 @@
 // bamtools_utilities.h (c) 2010 Derek Barnett, Erik Garrison
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// 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 {