// File: zeeev[P]DASVC/bamtools/src/api/internal/bam/BamReader_p.cpp
// Function: BamTools::Internal::BamReaderPrivate::LoadNextAlignment(BamTools::BamAlignment&)
bool BamReaderPrivate::LoadNextAlignment(BamAlignment& alignment) {

    // read in the 'block length' value, make sure it's not zero
    char buffer[sizeof(uint32_t)];
    fill_n(buffer, sizeof(uint32_t), 0);
    m_stream.Read(buffer, sizeof(uint32_t));
    alignment.SupportData.BlockLength = BamTools::UnpackUnsignedInt(buffer);
    if ( m_isBigEndian ) BamTools::SwapEndian_32(alignment.SupportData.BlockLength);
    if ( alignment.SupportData.BlockLength == 0 )
        return false;

    // read in core alignment data, make sure the right size of data was read
    char x[Constants::BAM_CORE_SIZE];
    if ( m_stream.Read(x, Constants::BAM_CORE_SIZE) != Constants::BAM_CORE_SIZE )
        return false;

    // swap core endian-ness if necessary
    if ( m_isBigEndian ) {
        for ( unsigned int i = 0; i < Constants::BAM_CORE_SIZE; i+=sizeof(uint32_t) )
            BamTools::SwapEndian_32p(&x[i]);
    }

    // set BamAlignment 'core' and 'support' data
    alignment.RefID    = BamTools::UnpackSignedInt(&x[0]);
    alignment.Position = BamTools::UnpackSignedInt(&x[4]);

    unsigned int tempValue = BamTools::UnpackUnsignedInt(&x[8]);
    alignment.Bin        = tempValue >> 16;
    alignment.MapQuality = tempValue >> 8 & 0xff;
    alignment.SupportData.QueryNameLength = tempValue & 0xff;

    tempValue = BamTools::UnpackUnsignedInt(&x[12]);
    alignment.AlignmentFlag = tempValue >> 16;
    alignment.SupportData.NumCigarOperations = tempValue & 0xffff;

    alignment.SupportData.QuerySequenceLength = BamTools::UnpackUnsignedInt(&x[16]);
    alignment.MateRefID    = BamTools::UnpackSignedInt(&x[20]);
    alignment.MatePosition = BamTools::UnpackSignedInt(&x[24]);
    alignment.InsertSize   = BamTools::UnpackSignedInt(&x[28]);

    // set BamAlignment length
    alignment.Length = alignment.SupportData.QuerySequenceLength;

    // read in character data - make sure proper data size was read
    bool readCharDataOK = false;
    const unsigned int dataLength = alignment.SupportData.BlockLength - Constants::BAM_CORE_SIZE;
    RaiiBuffer allCharData(dataLength);

    if ( m_stream.Read(allCharData.Buffer, dataLength) == dataLength ) {

        // store 'allCharData' in supportData structure
        alignment.SupportData.AllCharData.assign((const char*)allCharData.Buffer, dataLength);

        // set success flag
        readCharDataOK = true;

        // save CIGAR ops
        // need to calculate this here so that  BamAlignment::GetEndPosition() performs correctly,
        // even when GetNextAlignmentCore() is called
        const unsigned int cigarDataOffset = alignment.SupportData.QueryNameLength;
        uint32_t* cigarData = (uint32_t*)(allCharData.Buffer + cigarDataOffset);
        CigarOp op;
        alignment.CigarData.clear();
        alignment.CigarData.reserve(alignment.SupportData.NumCigarOperations);
        for ( unsigned int i = 0; i < alignment.SupportData.NumCigarOperations; ++i ) {

            // swap endian-ness if necessary
            if ( m_isBigEndian ) BamTools::SwapEndian_32(cigarData[i]);

            // build CigarOp structure
            op.Length = (cigarData[i] >> Constants::BAM_CIGAR_SHIFT);
            op.Type   = Constants::BAM_CIGAR_LOOKUP[ (cigarData[i] & Constants::BAM_CIGAR_MASK) ];

            // save CigarOp
            alignment.CigarData.push_back(op);
        }
    }

    // return success/failure
    return readCharDataOK;
}

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0x98(%rsp)
movq %rsi, 0x90(%rsp)
movq 0x98(%rsp), %rax
movq %rax, 0x10(%rsp)
leaq 0x8c(%rsp), %rdi
movl $0x0, 0x88(%rsp)
movl $0x4, %esi
leaq 0x88(%rsp), %rdx
callq 0x719f0
movq 0x10(%rsp), %rdi
addq $0x1e8, %rdi            # imm = 0x1E8
leaq 0x8c(%rsp), %rsi
movl $0x4, %edx
callq 0x79a30
leaq 0x8c(%rsp), %rdi
callq 0x754e0
movl %eax, %edx
movq 0x10(%rsp), %rax
movq 0x90(%rsp), %rcx
movl %edx, 0x120(%rcx)
testb $0x1, 0x40(%rax)
je 0xaac77
movq 0x90(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
addq $0x20, %rdi
callq 0x77400
movq 0x90(%rsp), %rax
cmpl $0x0, 0x120(%rax)
jne 0xaac95
movb $0x0, 0xa7(%rsp)
jmp 0xaaffa
movq 0x10(%rsp), %rdi
addq $0x1e8, %rdi            # imm = 0x1E8
leaq 0x60(%rsp), %rsi
movl $0x20, %edx
callq 0x79a30
cmpq $0x20, %rax
je 0xaacc3
movb $0x0, 0xa7(%rsp)
jmp 0xaaffa
movq 0x10(%rsp), %rax
testb $0x1, 0x40(%rax)
je 0xaacfe
movl $0x0, 0x5c(%rsp)
cmpl $0x20, 0x5c(%rsp)
jae 0xaacfc
movl 0x5c(%rsp), %eax
leaq 0x60(%rsp), %rdi
addq %rax, %rdi
callq 0x7a7d0
movl 0x5c(%rsp), %eax
addq $0x4, %rax
movl %eax, 0x5c(%rsp)
jmp 0xaacd6
jmp 0xaacfe
leaq 0x60(%rsp), %rdi
callq 0x7c910
movl %eax, %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0xa8(%rax)
leaq 0x64(%rsp), %rdi
callq 0x7c910
movl %eax, %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0xac(%rax)
leaq 0x68(%rsp), %rdi
callq 0x754e0
movl %eax, 0x58(%rsp)
movw 0x5a(%rsp), %cx
movq 0x90(%rsp), %rax
movw %cx, 0xb0(%rax)
movzbl 0x59(%rsp), %eax
movw %ax, %cx
movq 0x90(%rsp), %rax
movw %cx, 0xb2(%rax)
movzbl 0x58(%rsp), %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0x128(%rax)
leaq 0x6c(%rsp), %rdi
callq 0x754e0
movl %eax, 0x58(%rsp)
movzwl 0x5a(%rsp), %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0xb4(%rax)
movzwl 0x58(%rsp), %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0x124(%rax)
leaq 0x70(%rsp), %rdi
callq 0x754e0
movl %eax, %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0x12c(%rax)
leaq 0x74(%rsp), %rdi
callq 0x7c910
movl %eax, %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0xd0(%rax)
leaq 0x78(%rsp), %rdi
callq 0x7c910
movl %eax, %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0xd4(%rax)
leaq 0x7c(%rsp), %rdi
callq 0x7c910
movl %eax, %ecx
movq 0x90(%rsp), %rax
movl %ecx, 0xd8(%rax)
movq 0x90(%rsp), %rax
movl 0x12c(%rax), %ecx
movl %ecx, 0x20(%rax)
movb $0x0, 0x57(%rsp)
movq 0x90(%rsp), %rax
movl 0x120(%rax), %eax
addl $-0x20, %eax
movl %eax, 0x50(%rsp)
movl 0x50(%rsp), %eax
movl %eax, %esi
leaq 0x40(%rsp), %rdi
callq 0x76550
movq 0x10(%rsp), %rdi
addq $0x1e8, %rdi            # imm = 0x1E8
movq 0x40(%rsp), %rsi
movl 0x50(%rsp), %eax
movl %eax, %edx
callq 0x79a30
movq %rax, 0x8(%rsp)
jmp 0xaae78
movq 0x8(%rsp), %rax
movl 0x50(%rsp), %ecx
cmpq %rcx, %rax
jne 0xaafdf
movq 0x90(%rsp), %rdi
addq $0x100, %rdi            # imm = 0x100
movq 0x40(%rsp), %rsi
movl 0x50(%rsp), %eax
movl %eax, %edx
callq 0x78b50
jmp 0xaaeab
movb $0x1, 0x57(%rsp)
movq 0x90(%rsp), %rax
movl 0x128(%rax), %eax
movl %eax, 0x30(%rsp)
movq 0x40(%rsp), %rax
movl 0x30(%rsp), %ecx
addq %rcx, %rax
movq %rax, 0x28(%rsp)
movl $0x0, 0x1c(%rsp)
leaq 0x20(%rsp), %rdi
xorl %esi, %esi
leaq 0x1c(%rsp), %rdx
callq 0x75750
jmp 0xaaeee
movq 0x90(%rsp), %rdi
addq $0xb8, %rdi
callq 0x72e50
jmp 0xaaf04
movq 0x90(%rsp), %rax
movq %rax, %rdi
addq $0xb8, %rdi
movl 0x124(%rax), %eax
movl %eax, %esi
callq 0x79440
jmp 0xaaf25
movl $0x0, 0x18(%rsp)
movl 0x18(%rsp), %eax
movq 0x90(%rsp), %rcx
cmpl 0x124(%rcx), %eax
jae 0xaafdd
movq 0x10(%rsp), %rax
testb $0x1, 0x40(%rax)
je 0xaaf80
movq 0x28(%rsp), %rax
movl 0x18(%rsp), %ecx
leaq (%rax,%rcx,4), %rdi
callq 0x77400
jmp 0xaaf64
jmp 0xaaf80
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x38(%rsp)
movl %eax, 0x34(%rsp)
leaq 0x40(%rsp), %rdi
callq 0x7a450
jmp 0xaaff8
movq 0x28(%rsp), %rax
movl 0x18(%rsp), %ecx
movl (%rax,%rcx,4), %eax
shrl $0x4, %eax
movl %eax, 0x24(%rsp)
movq 0x28(%rsp), %rax
movl 0x18(%rsp), %ecx
movl (%rax,%rcx,4), %eax
andl $0xf, %eax
leaq 0x3fd99(%rip), %rcx     # 0xead42
movb (%rax,%rcx), %al
movb %al, 0x20(%rsp)
movq 0x90(%rsp), %rdi
addq $0xb8, %rdi
leaq 0x20(%rsp), %rsi
callq 0x777e0
jmp 0xaafcb
jmp 0xaafcd
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0xaaf2d
jmp 0xaafdf
movb 0x57(%rsp), %al
andb $0x1, %al
movb %al, 0xa7(%rsp)
leaq 0x40(%rsp), %rdi
callq 0x7a450
jmp 0xaaffa
jmp 0xab00b
movb 0xa7(%rsp), %al
andb $0x1, %al
addq $0xa8, %rsp
retq
movq 0x38(%rsp), %rdi
callq 0x7b550
movq %rax, %rdi
callq 0x88ef0
nopl (%rax)