]> 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)
1  2 
src/api/internal/BamHeader_p.cpp
src/api/internal/BamRandomAccessController_p.cpp
src/api/internal/BamReader_p.cpp
src/api/internal/BamWriter_p.cpp
src/api/internal/BgzfStream_p.cpp
src/api/internal/BgzfStream_p.h
src/shared/bamtools_global.h
src/utils/bamtools_utilities.h

index 2f4ef3480e20c5b93fc9e1c650a6dd0e21977af2,48b8c0908d7f16707b8eb832e98e601a97ddfca5..45dc379f52327c6cc9a77d232e1b53a9b83bd56e
@@@ -1,7 -1,6 +1,6 @@@
  // ***************************************************************************
  // BamHeader_p.cpp (c) 2010 Derek Barnett
  // Marth Lab, Department of Biology, Boston College
- // All rights reserved.
  // ---------------------------------------------------------------------------
  // Last modified: 21 March 2011 (DB)
  // ---------------------------------------------------------------------------
@@@ -32,7 -31,7 +31,7 @@@ bool BamHeader::CheckMagicNumber(BgzfSt
  
      // 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;
      }
index 9187b3a0025a919ab8932b7c28d723f7ae5da3e9,a599f7c48704a7361576e47e7705d486813944b9..a44563f5489952fb13a1f0e7d8fc0cac35db1b8c
@@@ -1,7 -1,6 +1,6 @@@
  // ***************************************************************************
  // BamRandomAccessController_p.cpp (c) 2011 Derek Barnett
  // Marth Lab, Department of Biology, Boston College
- // All rights reserved.
  // ---------------------------------------------------------------------------
  // Last modified: 5 April 2011(DB)
  // ---------------------------------------------------------------------------
@@@ -134,8 -133,6 +133,8 @@@ void BamRandomAccessController::Close(v
  }
  
  void BamRandomAccessController::ClearIndex(void) {
 +    if ( m_index == 0 )
 +        return;
      delete m_index;
      m_index = 0;
  }
index e4e2310bb451b0490f6086cb5f88ced80060f7aa,65b19f330a60c7fe9ac00cc1b992a98ce7b186d6..384e2fe59d50b5912b6bb2091a413813dd6339ae
@@@ -1,7 -1,6 +1,6 @@@
  // ***************************************************************************
  // BamReader_p.cpp (c) 2009 Derek Barnett
  // Marth Lab, Department of Biology, Boston College
- // All rights reserved.
  // ---------------------------------------------------------------------------
  // Last modified: 10 May 2011 (DB)
  // ---------------------------------------------------------------------------
@@@ -10,8 -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>
@@@ -99,9 -96,6 +98,9 @@@ bool BamReaderPrivate::GetNextAlignment
  // 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() )
@@@ -170,7 -164,7 +169,7 @@@ bool BamReaderPrivate::HasIndex(void) c
  }
  
  bool BamReaderPrivate::IsOpen(void) const {
 -    return m_stream.IsOpen;
 +    return m_stream.IsOpen();
  }
  
  // load BAM header data
@@@ -195,7 -189,7 +194,7 @@@ bool BamReaderPrivate::LoadNextAlignmen
  
      // 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]);
      }
  
      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);
@@@ -306,11 -300,12 +305,11 @@@ bool BamReaderPrivate::LocateIndex(cons
  // 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;
      }
@@@ -344,23 -339,14 +343,23 @@@ bool BamReaderPrivate::OpenIndex(const 
  // 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 8f1b167d26e42a021c934071cd1b5899d175b261,e77c099f8a53b6488e39c6c2e3a630c3e1884570..c9199b9a7b7859dfbfd4b0ef48f0de8aa58dc0f3
@@@ -1,7 -1,6 +1,6 @@@
  // ***************************************************************************
  // BamWriter_p.cpp (c) 2010 Derek Barnett
  // Marth Lab, Department of Biology, Boston College
- // All rights reserved.
  // ---------------------------------------------------------------------------
  // Last modified: 16 June 2011 (DB)
  // ---------------------------------------------------------------------------
@@@ -10,7 -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;
@@@ -126,7 -124,7 +125,7 @@@ void BamWriterPrivate::EncodeQuerySeque
  
  // 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
@@@ -135,7 -133,7 +134,7 @@@ bool BamWriterPrivate::Open(const strin
                              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 4db9b15e25bbda89cec73ce2a0b4f17d8eabba5c,36599b5b363fd6241fcd9fe6dff9a5c3b168235d..3b7074950031b7e0a92fd1c653348a69b2e63174
@@@ -1,43 -1,39 +1,42 @@@
  // ***************************************************************************
  // BgzfStream_p.cpp (c) 2011 Derek Barnett
  // Marth Lab, Department of Biology, Boston College
- // All rights reserved.
  // ---------------------------------------------------------------------------
 -// Last modified: 2 September 2011(DB)
 +// Last modified: 9 September 2011(DB)
  // ---------------------------------------------------------------------------
  // Based on BGZF routines developed at the Broad Institute.
  // Provides the basic functionality for reading & writing BGZF files
  // Replaces the old BGZF.* files to avoid clashing with other toolkits
  // ***************************************************************************
  
 +#include <api/internal/BamDeviceFactory_p.h>
  #include <api/internal/BgzfStream_p.h>
  using namespace BamTools;
  using namespace BamTools::Internal;
  
  #include <cstring>
  #include <algorithm>
 +#include <iostream>
  using namespace std;
  
  // constructor
  BgzfStream::BgzfStream(void)
 -    : UncompressedBlockSize(Constants::BGZF_DEFAULT_BLOCK_SIZE)
 -    , CompressedBlockSize(Constants::BGZF_MAX_BLOCK_SIZE)
 -    , BlockLength(0)
 -    , BlockOffset(0)
 -    , BlockAddress(0)
 -    , IsOpen(false)
 -    , IsWriteOnly(false)
 -    , IsWriteCompressed(true)
 -    , Stream(NULL)
 -    , UncompressedBlock(NULL)
 -    , CompressedBlock(NULL)
 +    : m_uncompressedBlockSize(Constants::BGZF_DEFAULT_BLOCK_SIZE)
 +    , m_compressedBlockSize(Constants::BGZF_MAX_BLOCK_SIZE)
 +    , m_blockLength(0)
 +    , m_blockOffset(0)
 +    , m_blockAddress(0)
 +    , m_uncompressedBlock(NULL)
 +    , m_compressedBlock(NULL)
 +    , m_isOpen(false)
 +    , m_isWriteOnly(false)
 +    , m_isWriteCompressed(true)
 +    , m_device(0)
 +    , m_stream(NULL)
  {
      try {
 -        CompressedBlock   = new char[CompressedBlockSize];
 -        UncompressedBlock = new char[UncompressedBlockSize];
 +        m_compressedBlock   = new char[m_compressedBlockSize];
 +        m_uncompressedBlock = new char[m_uncompressedBlockSize];
      } catch( std::bad_alloc& ba ) {
          fprintf(stderr, "BgzfStream ERROR: unable to allocate memory\n");
          exit(1);
  
  // 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;
      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 ) {
  
          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;
  
      // 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;
  // 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);
          }
  
          // update block data
 -        BlockAddress += blockLength;
 +        m_blockAddress += blockLength;
      }
  }
  
@@@ -215,10 -207,10 +214,10 @@@ int BgzfStream::InflateBlock(const int
      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 ) {
      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;
  
      // 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
      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;
  // 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;
      }
  
      // 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;
  // 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 04b6c34b88c0d122e3bc43f966b1cbafc4d39108,838f30cde3f2f2a163fa72cd2852ea00315a4887..f7ea268b8de25cbda9ab88ad3728ac6957bac874
@@@ -1,7 -1,6 +1,6 @@@
  // ***************************************************************************
  // BgzfStream_p.h (c) 2011 Derek Barnett
  // Marth Lab, Department of Biology, Boston College
- // All rights reserved.
  // ---------------------------------------------------------------------------
  // Last modified: 5 April 2011(DB)
  // ---------------------------------------------------------------------------
@@@ -25,7 -24,6 +24,7 @@@
  
  #include <api/BamAux.h>
  #include <api/BamConstants.h>
 +#include <api/IBamIODevice.h>
  #include "zlib.h"
  #include <cstdio>
  #include <string>
@@@ -44,27 -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
  
      // data members
      public:
 -        unsigned int UncompressedBlockSize;
 -        unsigned int CompressedBlockSize;
 -        unsigned int BlockLength;
 -        unsigned int BlockOffset;
 -        uint64_t BlockAddress;
 -        bool IsOpen;
 -        bool IsWriteOnly;
 -        bool IsWriteCompressed;
 -        FILE* Stream;
 -        char* UncompressedBlock;
 -        char* CompressedBlock;
 +        unsigned int m_uncompressedBlockSize;
 +        unsigned int m_compressedBlockSize;
 +        unsigned int m_blockLength;
 +        unsigned int m_blockOffset;
 +        uint64_t     m_blockAddress;
 +
 +        char* m_uncompressedBlock;
 +        char* m_compressedBlock;
 +
 +        bool m_isOpen;
 +        bool m_isWriteOnly;
 +        bool m_isWriteCompressed;
 +
 +        IBamIODevice* m_device;
 +        FILE* m_stream;
  };
  
  // -------------------------------------------------------------
index 6380bb07afe145decd3c13602685c724f9bf1d66,e9181ce0af412169225ae11b7d6e4b1ce1c38ef0..1b2a8af7834f7445d193f2bff5d14fb75ac22fe6
@@@ -1,7 -1,6 +1,6 @@@
  // ***************************************************************************
  // bamtools_global.h (c) 2010 Derek Barnett
  // Marth Lab, Department of Biology, Boston College
- // All rights reserved.
  // ---------------------------------------------------------------------------
  // Last modified: 3 March 2011 (DB)
  // ---------------------------------------------------------------------------
      #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 71d46830df6667895a3ad8a1fcc02fa2652b7784,52098d0c4811c2977c360e573cd16c587b210551..d9a319271c1da6e856325cacc7371e20cc0a978a
@@@ -1,9 -1,8 +1,8 @@@
  // ***************************************************************************
  // bamtools_utilities.h (c) 2010 Derek Barnett, Erik Garrison
  // Marth Lab, Department of Biology, Boston College
- // All rights reserved.
  // ---------------------------------------------------------------------------
 -// Last modified: 9 June 2011
 +// Last modified: 8 September 2011
  // ---------------------------------------------------------------------------
  // Provides general utilities used by BamTools sub-tools.
  // ***************************************************************************
  
  #include <api/BamAux.h>
  #include <utils/utils_global.h>
 -#include <cassert>
 -#include <stdexcept>
  #include <string>
  #include <vector>
  
 -#define BAMTOOLS_ASSERT_UNREACHABLE assert( false )
 -#define BAMTOOLS_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
 +#define BAMTOOLS_ASSERT_UNREACHABLE BT_ASSERT_UNREACHABLE
 +#define BAMTOOLS_ASSERT_MESSAGE( condition, message ) BT_ASSERT_X( condition, message )
  
  namespace BamTools {