// File: /workspace/github_cpp_makefile_star2_O2/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 $0x198, %rsp            # imm = 0x198
movq %rsi, %r15
movq %rdi, %rbx
movq %rsi, %rdi
callq 0x350c0
testb %al, %al
je 0x66b3e
movl 0xac(%r15), %ebp
leaq 0x28(%rsp), %rdi
movq %r15, %rsi
callq 0x66c78
movq 0xc0(%r15), %rax
subq 0xb8(%r15), %rax
movq %rax, %r13
shrq $0x3, %r13
shlq $0x1d, %rax
movabsq $-0x100000000, %rcx     # imm = 0xFFFFFFFF00000000
addq %rax, %rcx
sarq $0x20, %rcx
movq %rcx, 0x20(%rsp)
movabsq $-0x200000000, %rcx     # imm = 0xFFFFFFFE00000000
addq %rax, %rcx
sarq $0x20, %rcx
movq %rcx, 0x18(%rsp)
xorl %r14d, %r14d
testl %r13d, %r13d
cmovlel %r14d, %r13d
leaq 0xb8(%r15), %rax
movq %rax, 0x10(%rsp)
movb $0x1, %r15b
movl $0x0, 0xc(%rsp)
cmpq %r14, %r13
je 0x66b23
movq 0x10(%rsp), %rdi
movq %r14, %rsi
callq 0x66caa
movq %rax, %r12
movzbl (%rax), %eax
cmpl $0x44, %eax
je 0x66a6d
cmpl $0x49, %eax
je 0x66a4c
cmpl $0x53, %eax
je 0x66a4c
cmpl $0x4e, %eax
je 0x66a5e
cmpl $0x4d, %eax
jne 0x66af8
movl 0x4(%r12), %eax
addl %ebp, %eax
movl 0x4(%rbx), %ecx
cmpl %ecx, %eax
jle 0x66ae9
andw $0x0, 0x184(%rsp)
movb $0x0, 0x186(%rsp)
movl 0xc(%rsp), %edx
subl %ebp, %edx
addl %ecx, %edx
movl %edx, 0x180(%rsp)
cmpl %ecx, %ebp
setne %dl
notb %r15b
orb %dl, %r15b
testb $0x1, %r15b
jne 0x669e9
movb $0x1, 0x190(%rsp)
decl %eax
cmpl %ecx, %eax
jne 0x66ae9
cmpq 0x20(%rsp), %r14
jge 0x66ae1
leaq 0x1(%r14), %rsi
movq 0x10(%rsp), %rdi
callq 0x66caa
movzbl (%rax), %ecx
cmpl $0x53, %ecx
je 0x66ae1
cmpl $0x48, %ecx
je 0x66ae1
cmpl $0x49, %ecx
je 0x66aa5
cmpl $0x4e, %ecx
je 0x66ae1
cmpl $0x44, %ecx
jne 0x66ae9
movb $0x1, 0x185(%rsp)
movl 0x4(%rax), %eax
movl %eax, 0x188(%rsp)
jmp 0x66ab7
movl 0xc(%rsp), %ecx
addl 0x4(%r12), %ecx
movl %ecx, 0xc(%rsp)
jmp 0x66af8
addl 0x4(%r12), %ebp
movb $0x1, %r15b
movb $0x4e, %al
jmp 0x66b13
movl 0x4(%r12), %ecx
addl %ebp, %ecx
movl 0x4(%rbx), %edx
movb $0x44, %al
cmpl %edx, %ecx
jle 0x66a9e
movw $0x1, 0x184(%rsp)
movb $0x1, 0x186(%rsp)
movl 0xc(%rsp), %esi
subl %ebp, %esi
addl %edx, %esi
movl %esi, 0x180(%rsp)
xorl %r15d, %r15d
movl %ecx, %ebp
jmp 0x66b13
movb $0x1, 0x186(%rsp)
movl 0x4(%rax), %eax
movl %eax, 0x18c(%rsp)
cmpq 0x18(%rsp), %r14
jge 0x66ae1
leaq 0x2(%r14), %rsi
movq 0x10(%rsp), %rdi
callq 0x66caa
movzbl (%rax), %eax
addl $-0x48, %eax
cmpl $0xb, %eax
ja 0x66ae9
movl $0x841, %ecx            # imm = 0x841
btl %eax, %ecx
jae 0x66ae9
movb $0x1, 0x191(%rsp)
movl 0x4(%r12), %eax
addl %eax, %ebp
addl %eax, 0xc(%rsp)
movb (%r12), %al
movzbl %al, %ecx
addl $-0x48, %ecx
cmpl $0xb, %ecx
ja 0x66b10
movb $0x1, %r15b
movl $0x841, %edx            # imm = 0x841
btl %ecx, %edx
jb 0x66b13
xorl %r15d, %r15d
incq %r14
cmpl 0x4(%rbx), %ebp
jle 0x66955
cmpb $0x4e, %al
je 0x66b34
addq $0x28, %rbx
leaq 0x28(%rsp), %rsi
movq %rbx, %rdi
callq 0x66ccc
leaq 0x28(%rsp), %rdi
callq 0x35940
addq $0x198, %rsp            # imm = 0x198
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x66b56
jmp 0x66b56
jmp 0x66b56
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x35940
movq %rbx, %rdi
callq 0x35b50
movq %rax, %rdi
callq 0x3a198
nop