From: derek Date: Sat, 10 Sep 2011 02:05:02 +0000 (-0400) Subject: Merge branches 'master' and 'iodevice' into iodevice X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=c1fc1c5423ca73a1b5bcbe790650821d73e5959c;hp=72f5b82ad353b4cc9d6f8153f1ad19cc387b9597;p=bamtools.git Merge branches 'master' and 'iodevice' into iodevice --- diff --git a/src/api/BamConstants.h b/src/api/BamConstants.h index 1107371..ac672a6 100644 --- a/src/api/BamConstants.h +++ b/src/api/BamConstants.h @@ -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 diff --git a/src/api/CMakeLists.txt b/src/api/CMakeLists.txt index 10c46d6..5a03712 100644 --- a/src/api/CMakeLists.txt +++ b/src/api/CMakeLists.txt @@ -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 index 0000000..99454b2 --- /dev/null +++ b/src/api/IBamIODevice.h @@ -0,0 +1,81 @@ +#ifndef IBAMIODEVICE_H +#define IBAMIODEVICE_H + +#include +#include + +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 index 0000000..da0daad --- /dev/null +++ b/src/api/internal/BamDeviceFactory_p.cpp @@ -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 +#include +#include +#include +#include +using namespace BamTools; +using namespace BamTools::Internal; + +#include +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 index 0000000..f126831 --- /dev/null +++ b/src/api/internal/BamDeviceFactory_p.h @@ -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 +#include + +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 index 0000000..6cb5be4 --- /dev/null +++ b/src/api/internal/BamFile_p.cpp @@ -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 +using namespace BamTools; +using namespace BamTools::Internal; + +#include +#include +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 index 0000000..fd25a3e --- /dev/null +++ b/src/api/internal/BamFile_p.h @@ -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 +#include + +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 index 0000000..f957197 --- /dev/null +++ b/src/api/internal/BamFtp_p.cpp @@ -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 +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 index 0000000..d410201 --- /dev/null +++ b/src/api/internal/BamFtp_p.h @@ -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 +#include + +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 diff --git a/src/api/internal/BamHeader_p.cpp b/src/api/internal/BamHeader_p.cpp index 48b8c09..45dc379 100644 --- a/src/api/internal/BamHeader_p.cpp +++ b/src/api/internal/BamHeader_p.cpp @@ -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 index 0000000..532194b --- /dev/null +++ b/src/api/internal/BamHttp_p.cpp @@ -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 +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 index 0000000..e1d2403 --- /dev/null +++ b/src/api/internal/BamHttp_p.h @@ -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 +#include + +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 index 0000000..62fd789 --- /dev/null +++ b/src/api/internal/BamPipe_p.cpp @@ -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 +using namespace BamTools; +using namespace BamTools::Internal; + +#include +#include +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 index 0000000..a9725be --- /dev/null +++ b/src/api/internal/BamPipe_p.h @@ -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 +#include + +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 diff --git a/src/api/internal/BamRandomAccessController_p.cpp b/src/api/internal/BamRandomAccessController_p.cpp index a599f7c..a44563f 100644 --- a/src/api/internal/BamRandomAccessController_p.cpp +++ b/src/api/internal/BamRandomAccessController_p.cpp @@ -133,6 +133,8 @@ void BamRandomAccessController::Close(void) { } void BamRandomAccessController::ClearIndex(void) { + if ( m_index == 0 ) + return; delete m_index; m_index = 0; } diff --git a/src/api/internal/BamReader_p.cpp b/src/api/internal/BamReader_p.cpp index 65b19f3..384e2fe 100644 --- a/src/api/internal/BamReader_p.cpp +++ b/src/api/internal/BamReader_p.cpp @@ -9,6 +9,8 @@ #include #include +#include +#include #include #include #include @@ -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(); diff --git a/src/api/internal/BamWriter_p.cpp b/src/api/internal/BamWriter_p.cpp index e77c099..c9199b9 100644 --- a/src/api/internal/BamWriter_p.cpp +++ b/src/api/internal/BamWriter_p.cpp @@ -9,6 +9,7 @@ #include #include +#include #include 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 diff --git a/src/api/internal/BgzfStream_p.cpp b/src/api/internal/BgzfStream_p.cpp index 36599b5..3b70749 100644 --- a/src/api/internal/BgzfStream_p.cpp +++ b/src/api/internal/BgzfStream_p.cpp @@ -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 #include using namespace BamTools; using namespace BamTools::Internal; #include #include +#include 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 diff --git a/src/api/internal/BgzfStream_p.h b/src/api/internal/BgzfStream_p.h index 838f30c..f7ea268 100644 --- a/src/api/internal/BgzfStream_p.h +++ b/src/api/internal/BgzfStream_p.h @@ -24,6 +24,7 @@ #include #include +#include #include "zlib.h" #include #include @@ -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 index 0000000..9e9a2b3 --- /dev/null +++ b/src/api/internal/ILocalIODevice_p.cpp @@ -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 +using namespace BamTools; +using namespace BamTools::Internal; + +#include +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 index 0000000..1e64899 --- /dev/null +++ b/src/api/internal/ILocalIODevice_p.h @@ -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 + +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 index 0000000..e69de29 diff --git a/src/api/internal/IRemoteIODevice_p.h b/src/api/internal/IRemoteIODevice_p.h new file mode 100644 index 0000000..e69de29 diff --git a/src/shared/bamtools_global.h b/src/shared/bamtools_global.h index e9181ce..1b2a8af 100644 --- a/src/shared/bamtools_global.h +++ b/src/shared/bamtools_global.h @@ -75,4 +75,11 @@ #endif #endif // BAMTOOLS_TYPES +#include +#include +#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 diff --git a/src/utils/bamtools_utilities.h b/src/utils/bamtools_utilities.h index 52098d0..d9a3192 100644 --- a/src/utils/bamtools_utilities.h +++ b/src/utils/bamtools_utilities.h @@ -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. // *************************************************************************** @@ -12,13 +12,11 @@ #include #include -#include -#include #include #include -#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 {