]> git.donarmstrong.com Git - bamtools.git/blobdiff - src/api/internal/BamWriter_p.cpp
Minor cleanup
[bamtools.git] / src / api / internal / BamWriter_p.cpp
index 7147a33ff654918e720cd4ea9acf0036083a5213..e77c099f8a53b6488e39c6c2e3a630c3e1884570 100644 (file)
@@ -1,9 +1,8 @@
 // ***************************************************************************
 // BamWriter_p.cpp (c) 2010 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
-// All rights reserved.
 // ---------------------------------------------------------------------------
-// Last modified: 21 March 2011 (DB)
+// Last modified: 16 June 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides the basic functionality for producing BAM files
 // ***************************************************************************
@@ -70,6 +69,8 @@ void BamWriterPrivate::CreatePackedCigar(const vector<CigarOp>& cigarOperations,
             case (Constants::BAM_CIGAR_SOFTCLIP_CHAR) : cigarOp = Constants::BAM_CIGAR_SOFTCLIP; break;
             case (Constants::BAM_CIGAR_HARDCLIP_CHAR) : cigarOp = Constants::BAM_CIGAR_HARDCLIP; break;
             case (Constants::BAM_CIGAR_PAD_CHAR)      : cigarOp = Constants::BAM_CIGAR_PAD;      break;
+            case (Constants::BAM_CIGAR_SEQMATCH_CHAR) : cigarOp = Constants::BAM_CIGAR_SEQMATCH; break;
+            case (Constants::BAM_CIGAR_MISMATCH_CHAR) : cigarOp = Constants::BAM_CIGAR_MISMATCH; break;
             default:
               fprintf(stderr, "BamWriter ERROR: unknown cigar operation found: %c\n", coIter->Type);
               exit(1);
@@ -154,11 +155,14 @@ void BamWriterPrivate::SaveAlignment(const BamAlignment& al) {
         if ( m_isBigEndian ) BamTools::SwapEndian_32(blockSize);
         m_stream.Write((char*)&blockSize, Constants::BAM_SIZEOF_INT);
 
+        // re-calculate bin (in case BamAlignment's position has been previously modified)
+        const uint32_t alignmentBin = CalculateMinimumBin(al.Position, al.GetEndPosition());
+
         // assign the BAM core data
         uint32_t buffer[Constants::BAM_CORE_BUFFER_SIZE];
         buffer[0] = al.RefID;
         buffer[1] = al.Position;
-        buffer[2] = (al.Bin << 16) | (al.MapQuality << 8) | al.SupportData.QueryNameLength;
+        buffer[2] = (alignmentBin << 16) | (al.MapQuality << 8) | al.SupportData.QueryNameLength;
         buffer[3] = (al.AlignmentFlag << 16) | al.SupportData.NumCigarOperations;
         buffer[4] = al.SupportData.QuerySequenceLength;
         buffer[5] = al.MateRefID;
@@ -241,8 +245,10 @@ void BamWriterPrivate::SaveAlignment(const BamAlignment& al) {
         if ( m_isBigEndian ) {
             char* cigarData = (char*)calloc(sizeof(char), packedCigarLength);
             memcpy(cigarData, packedCigar.data(), packedCigarLength);
-            for (unsigned int i = 0; i < packedCigarLength; ++i)
-                if (m_isBigEndian) BamTools::SwapEndian_32p(&cigarData[i]);
+            if ( m_isBigEndian ) {
+                for ( unsigned int i = 0; i < packedCigarLength; ++i )
+                    BamTools::SwapEndian_32p(&cigarData[i]);
+            }
             m_stream.Write(cigarData, packedCigarLength);
             free(cigarData);
         }
@@ -254,7 +260,7 @@ void BamWriterPrivate::SaveAlignment(const BamAlignment& al) {
 
         // write the base qualities
         char* pBaseQualities = (char*)al.Qualities.data();
-        for(unsigned int i = 0; i < queryLength; i++)
+        for ( unsigned int i = 0; i < queryLength; ++i )
             pBaseQualities[i] -= 33; // FASTQ conversion
         m_stream.Write(pBaseQualities, queryLength);
 
@@ -295,11 +301,56 @@ void BamWriterPrivate::SaveAlignment(const BamAlignment& al) {
                     case(Constants::BAM_TAG_TYPE_HEX) :
                     case(Constants::BAM_TAG_TYPE_STRING) :
                         // no endian swapping necessary for hex-string/string data
-                        while (tagData[i]) { ++i; }
+                        while ( tagData[i] )
+                            ++i;
                         // increment one more for null terminator
                         ++i;
                         break;
 
+                    case(Constants::BAM_TAG_TYPE_ARRAY) :
+
+                    {
+                        // read array type
+                        const char arrayType = tagData[i];
+                        ++i;
+
+                        // swap endian-ness of number of elements in place, then retrieve for loop
+                        BamTools::SwapEndian_32p(&tagData[i]);
+                        int32_t numElements;
+                        memcpy(&numElements, &tagData[i], sizeof(uint32_t));
+                        i += sizeof(uint32_t);
+
+                        // swap endian-ness of array elements
+                        for ( int j = 0; j < numElements; ++j ) {
+                            switch (arrayType) {
+                                case (Constants::BAM_TAG_TYPE_INT8)  :
+                                case (Constants::BAM_TAG_TYPE_UINT8) :
+                                    // no endian-swapping necessary
+                                    ++i;
+                                    break;
+                                case (Constants::BAM_TAG_TYPE_INT16)  :
+                                case (Constants::BAM_TAG_TYPE_UINT16) :
+                                    BamTools::SwapEndian_16p(&tagData[i]);
+                                    i += sizeof(uint16_t);
+                                    break;
+                                case (Constants::BAM_TAG_TYPE_FLOAT)  :
+                                case (Constants::BAM_TAG_TYPE_INT32)  :
+                                case (Constants::BAM_TAG_TYPE_UINT32) :
+                                    BamTools::SwapEndian_32p(&tagData[i]);
+                                    i += sizeof(uint32_t);
+                                    break;
+                                default:
+                                    // error case
+                                    fprintf(stderr,
+                                            "BamWriter ERROR: unknown binary array type encountered: [%c]\n",
+                                            arrayType);
+                                    exit(1);
+                            }
+                        }
+
+                        break;
+                    }
+
                     default :
                         fprintf(stderr, "BamWriter ERROR: invalid tag value type\n"); // shouldn't get here
                         free(tagData);
@@ -368,6 +419,6 @@ void BamWriterPrivate::WriteSamHeaderText(const std::string& samHeaderText) {
     m_stream.Write((char*)&samHeaderLen, Constants::BAM_SIZEOF_INT);
 
     // write the SAM header text
-    if (samHeaderLen > 0)
+    if ( samHeaderLen > 0 )
         m_stream.Write(samHeaderText.data(), samHeaderLen);
 }