// File: /workspace/github_cpp_makefile_star2_O3/zeeev[P]DASVC/bamtools/src/utils/bamtools_pileup_engine.cpp
// Function: BamTools::PileupEngine::PileupEnginePrivate::ParseAlignmentCigar(BamTools::BamAlignment const&)
void PileupEngine::PileupEnginePrivate::ParseAlignmentCigar(const BamAlignment& al) {
  
    // skip if unmapped
    if ( !al.IsMapped() ) return;
    
    // intialize local variables
    int  genomePosition      = al.Position;
    int  positionInAlignment = 0;
    bool isNewReadSegment    = true;
    bool saveAlignment       = true;    
    PileupAlignment pileupAlignment(al);
    
    // iterate over CIGAR operations
    const int numCigarOps = (const int)al.CigarData.size();
    for (int i = 0; i < numCigarOps; ++i ) { 
        const CigarOp& op = al.CigarData.at(i);
      
        // if op is MATCH
        if ( op.Type == 'M' ) {
          
            // if match op overlaps current position
            if ( genomePosition + (int)op.Length > CurrentPosition ) {
              
                // set pileup data
                pileupAlignment.IsCurrentDeletion   = false;
                pileupAlignment.IsNextDeletion      = false;
                pileupAlignment.IsNextInsertion     = false;
                pileupAlignment.PositionInAlignment = positionInAlignment + (CurrentPosition - genomePosition);
                
                // check for beginning of read segment
                if ( genomePosition == CurrentPosition && isNewReadSegment ) 
                    pileupAlignment.IsSegmentBegin = true;
                
                // if we're at the end of a match operation
                if ( genomePosition + (int)op.Length - 1 == CurrentPosition ) {
                    
                    // if not last operation
                    if ( i < numCigarOps - 1 ) {
                        
                        // check next CIGAR op
                        const CigarOp& nextOp = al.CigarData.at(i+1);
                        
                        // if next CIGAR op is DELETION
                        if ( nextOp.Type == 'D') {
                            pileupAlignment.IsNextDeletion = true;
                            pileupAlignment.DeletionLength = nextOp.Length;
                        }
                        
                        // if next CIGAR op is INSERTION
                        else if ( nextOp.Type == 'I' ) {
                            pileupAlignment.IsNextInsertion = true;
                            pileupAlignment.InsertionLength = nextOp.Length;
                        }
                            
                        // if next CIGAR op is either DELETION or INSERTION
                        if ( nextOp.Type == 'D' || nextOp.Type == 'I' ) {

                            // if there is a CIGAR op after the DEL/INS
                            if ( i < numCigarOps - 2 ) {
                                const CigarOp& nextNextOp = al.CigarData.at(i+2);
                                
                                // if next CIGAR op is clipping or ref_skip
                                if ( nextNextOp.Type == 'S' || 
                                     nextNextOp.Type == 'N' ||
                                     nextNextOp.Type == 'H' )
                                    pileupAlignment.IsSegmentEnd = true;
                            } 
                            else {
                                pileupAlignment.IsSegmentEnd = true;
                                
                                // if next CIGAR op is clipping or ref_skip
                                if ( nextOp.Type == 'S' || 
                                     nextOp.Type == 'N' ||
                                     nextOp.Type == 'H' )
                                    pileupAlignment.IsSegmentEnd = true;
                            }
                        }
                        
                        // otherwise
                        else { 
                        
                            // if next CIGAR op is clipping or ref_skip
                            if ( nextOp.Type == 'S' || 
                                 nextOp.Type == 'N' ||
                                 nextOp.Type == 'H' )
                                pileupAlignment.IsSegmentEnd = true;
                        }
                    }
                    
                    // else this is last operation
                    else pileupAlignment.IsSegmentEnd = true;
                }
            }
          
            // increment markers
            genomePosition      += op.Length;
            positionInAlignment += op.Length;
        } 
        
        // if op is DELETION
        else if ( op.Type == 'D' ) {
          
            // if deletion op overlaps current position
            if ( genomePosition + (int)op.Length > CurrentPosition ) {
              
                // set pileup data
                pileupAlignment.IsCurrentDeletion   = true;
                pileupAlignment.IsNextDeletion      = false;
                pileupAlignment.IsNextInsertion     = true;
                pileupAlignment.PositionInAlignment = positionInAlignment + (CurrentPosition - genomePosition);
            }
            
            // increment marker
            genomePosition += op.Length;
        }

        // if op is REF_SKIP
        else if ( op.Type == 'N' ) {
            genomePosition += op.Length;
        }
        
        // if op is INSERTION or SOFT_CLIP
        else if ( op.Type == 'I' || op.Type == 'S' ) {
            positionInAlignment += op.Length;
        }
        
        // checl for beginning of new read segment
        if ( op.Type == 'N' ||
             op.Type == 'S' ||
             op.Type == 'H' )
            isNewReadSegment = true;
        else 
            isNewReadSegment = false;
      
        // if we've moved beyond current position
        if ( genomePosition > CurrentPosition ) {
            if ( op.Type == 'N' ) saveAlignment = false; // ignore alignment if REF_SKIP
            break;
        }
    }

    // save pileup position if flag is true
    if ( saveAlignment )
        CurrentPileupData.PileupAlignments.push_back( pileupAlignment );
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x178, %rsp            # imm = 0x178
movq %rsi, %r14
movq %rdi, %rbx
movq %rsi, %rdi
callq 0x270d0
testb %al, %al
je 0x652b4
movl 0xac(%r14), %r12d
leaq 0x8(%rsp), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x272b0
movl $0xffffffff, 0x158(%r15) # imm = 0xFFFFFFFF
xorl %eax, %eax
movw %ax, 0x15c(%r15)
movb $0x0, 0x15e(%r15)
movw %ax, 0x168(%r15)
movq $0x0, 0x160(%r15)
movq 0xb8(%r14), %rcx
movq 0xc0(%r14), %rsi
subq %rcx, %rsi
movq %rsi, %rdx
sarq $0x3, %rdx
testl %edx, %edx
jle 0x65299
movl 0x4(%rbx), %edi
shlq $0x1d, %rsi
movabsq $-0x200000000, %r8      # imm = 0xFFFFFFFE00000000
addq %rsi, %r8
sarq $0x20, %r8
movabsq $-0x100000000, %r9      # imm = 0xFFFFFFFF00000000
addq %rsi, %r9
sarq $0x20, %r9
movl %edx, %r10d
andl $0x7fffffff, %r10d      # imm = 0x7FFFFFFF
movb $0x1, %sil
movl $0x841, %ebp            # imm = 0x841
xorl %r11d, %r11d
cmpq %r11, %rdx
je 0x652c6
movzbl (%rcx,%r11,8), %r14d
cmpl $0x4c, %r14d
jle 0x651a9
cmpl $0x53, %r14d
je 0x651b5
cmpl $0x4e, %r14d
je 0x651d1
cmpl $0x4d, %r14d
jne 0x651ba
movl 0x4(%rcx,%r11,8), %r15d
leal (%r15,%r12), %r14d
cmpl %edi, %r14d
jle 0x65277
movw $0x0, 0x164(%rsp)
movb $0x0, 0x166(%rsp)
movl %eax, %r13d
subl %r12d, %r13d
addl %edi, %r13d
movl %r13d, 0x160(%rsp)
cmpl %edi, %r12d
setne %r12b
notb %sil
orb %r12b, %sil
testb $0x1, %sil
jne 0x65158
movb $0x1, 0x170(%rsp)
leal -0x1(%r14), %esi
cmpl %edi, %esi
jne 0x65277
cmpq %r9, %r11
jge 0x6526f
leaq 0x1(%r11), %rsi
cmpq %rsi, %rdx
jbe 0x652d7
movzbl 0x8(%rcx,%r11,8), %esi
cmpl $0x48, %esi
jle 0x65214
cmpl $0x49, %esi
je 0x65220
cmpl $0x4e, %esi
je 0x6526f
cmpl $0x53, %esi
je 0x6526f
jmp 0x65277
cmpl $0x44, %r14d
je 0x651e1
cmpl $0x49, %r14d
jne 0x651ba
addl 0x4(%rcx,%r11,8), %eax
addl $-0x48, %r14d
cmpl $0xb, %r14d
ja 0x651cd
movb $0x1, %sil
btl %r14d, %ebp
jb 0x651d9
xorl %esi, %esi
jmp 0x651d9
addl 0x4(%rcx,%r11,8), %r12d
movb $0x1, %sil
movl %r12d, %r14d
jmp 0x6527c
movl 0x4(%rcx,%r11,8), %r14d
addl %r12d, %r14d
cmpl %edi, %r14d
jle 0x6527a
movw $0x1, 0x164(%rsp)
movb $0x1, 0x166(%rsp)
movl %eax, %esi
subl %r12d, %esi
addl %edi, %esi
movl %esi, 0x160(%rsp)
jmp 0x6527a
cmpl $0x44, %esi
je 0x65236
cmpl $0x48, %esi
je 0x6526f
jmp 0x65277
movb $0x1, 0x166(%rsp)
movl 0xc(%rcx,%r11,8), %esi
movl %esi, 0x16c(%rsp)
jmp 0x6524a
movb $0x1, 0x165(%rsp)
movl 0xc(%rcx,%r11,8), %esi
movl %esi, 0x168(%rsp)
cmpq %r8, %r11
jge 0x6526f
leaq 0x2(%r11), %rsi
cmpq %rsi, %rdx
jbe 0x652e5
movzbl 0x10(%rcx,%r11,8), %esi
addl $-0x48, %esi
cmpl $0xb, %esi
ja 0x65277
btl %esi, %ebp
jae 0x65277
movb $0x1, 0x171(%rsp)
addl %r15d, %eax
xorl %esi, %esi
cmpl %edi, %r14d
jg 0x65292
incq %r11
movl %r14d, %r12d
cmpq %r11, %r10
jne 0x650d2
jmp 0x65299
cmpb $0x4e, (%rcx,%r11,8)
je 0x652aa
addq $0x28, %rbx
leaq 0x8(%rsp), %rsi
movq %rbx, %rdi
callq 0x6547a
leaq 0x8(%rsp), %rdi
callq 0x27920
addq $0x178, %rsp            # imm = 0x178
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xc499(%rip), %rdi      # 0x71766
movq %rdx, %rsi
xorl %eax, %eax
callq 0x278b0
leaq 0xc488(%rip), %rdi      # 0x71766
xorl %eax, %eax
callq 0x278b0
leaq 0xc47a(%rip), %rdi      # 0x71766
xorl %eax, %eax
callq 0x278b0
jmp 0x652f9
jmp 0x652f9
jmp 0x652f9
movq %rax, %rbx
leaq 0x8(%rsp), %rdi
callq 0x27920
movq %rbx, %rdi
callq 0x27b10
movq %rax, %rdi
callq 0x2e1cd