// File: VanAndelInstitute[P]intent/src/edlib.cpp
// Function: edlibAlignmentToCigar
char* edlibAlignmentToCigar(const unsigned char* const alignment, const int alignmentLength,
                                       const EdlibCigarFormat cigarFormat) {
    if (cigarFormat != EDLIB_CIGAR_EXTENDED && cigarFormat != EDLIB_CIGAR_STANDARD) {
        return 0;
    }

    // Maps move code from alignment to char in cigar.
    //                        0    1    2    3
    char moveCodeToChar[] = {'=', 'I', 'D', 'X'};
    if (cigarFormat == EDLIB_CIGAR_STANDARD) {
        moveCodeToChar[0] = moveCodeToChar[3] = 'M';
    }

    vector<char>* cigar = new vector<char>();
    char lastMove = 0;  // Char of last move. 0 if there was no previous move.
    int numOfSameMoves = 0;
    for (int i = 0; i <= alignmentLength; i++) {
        // if new sequence of same moves started
        if (i == alignmentLength || (moveCodeToChar[alignment[i]] != lastMove && lastMove != 0)) {
            // Write number of moves to cigar string.
            int numDigits = 0;
            for (; numOfSameMoves; numOfSameMoves /= 10) {
                cigar->push_back('0' + numOfSameMoves % 10);
                numDigits++;
            }
            reverse(cigar->end() - numDigits, cigar->end());
            // Write code of move to cigar string.
            cigar->push_back(lastMove);
            // If not at the end, start new sequence of moves.
            if (i < alignmentLength) {
                // Check if alignment has valid values.
                if (alignment[i] > 3) {
                    delete cigar;
                    return 0;
                }
                numOfSameMoves = 0;
            }
        }
        if (i < alignmentLength) {
            lastMove = moveCodeToChar[alignment[i]];
            numOfSameMoves++;
        }
    }
    cigar->push_back(0);  // Null character termination.
    char* cigar_ = static_cast<char *>(malloc(cigar->size() * sizeof(char)));
    memcpy(cigar_, &(*cigar)[0], cigar->size() * sizeof(char));
    delete cigar;

    return cigar_;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
cmpl $0x1, -0x18(%rbp)
je 0x6715e
cmpl $0x0, -0x18(%rbp)
je 0x6715e
movq $0x0, -0x8(%rbp)
jmp 0x6739f
movl 0x9605(%rip), %eax      # 0x70769
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x18(%rbp)
jne 0x67175
movb $0x4d, -0x19(%rbp)
movb $0x4d, -0x1c(%rbp)
movl $0x18, %edi
callq 0x8550
movq %rax, %rdi
movq %rdi, -0x70(%rbp)
xorl %esi, %esi
movl $0x18, %edx
callq 0x8330
movq -0x70(%rbp), %rdi
callq 0x47a90
movq -0x70(%rbp), %rax
movq %rax, -0x28(%rbp)
movb $0x0, -0x29(%rbp)
movl $0x0, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x14(%rbp), %eax
jg 0x67306
movl -0x34(%rbp), %eax
cmpl -0x14(%rbp), %eax
je 0x671f3
movq -0x10(%rbp), %rax
movslq -0x34(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movsbl -0x1c(%rbp,%rax), %eax
movsbl -0x29(%rbp), %ecx
cmpl %ecx, %eax
je 0x672d2
movsbl -0x29(%rbp), %eax
cmpl $0x0, %eax
je 0x672d2
movl $0x0, -0x38(%rbp)
cmpl $0x0, -0x30(%rbp)
je 0x67239
movq -0x28(%rbp), %rdi
movl -0x30(%rbp), %eax
movl $0xa, %ecx
cltd
idivl %ecx
addl $0x30, %edx
movb %dl, %al
movb %al, -0x39(%rbp)
leaq -0x39(%rbp), %rsi
callq 0x52e60
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
movl -0x30(%rbp), %eax
movl $0xa, %ecx
cltd
idivl %ecx
movl %eax, -0x30(%rbp)
jmp 0x671fa
movq -0x28(%rbp), %rdi
callq 0x48f40
movq %rax, -0x50(%rbp)
movslq -0x38(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x49df0
movq %rax, -0x48(%rbp)
movq -0x28(%rbp), %rdi
callq 0x48f40
movq %rax, -0x58(%rbp)
movq -0x48(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x68f00
movq -0x28(%rbp), %rdi
leaq -0x29(%rbp), %rsi
callq 0x68f40
movl -0x34(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x672d0
movq -0x10(%rbp), %rax
movslq -0x34(%rbp), %rcx
movzbl (%rax,%rcx), %eax
cmpl $0x3, %eax
jle 0x672c9
movq -0x28(%rbp), %rax
movq %rax, -0x78(%rbp)
cmpq $0x0, %rax
je 0x672bc
movq -0x78(%rbp), %rdi
callq 0x47c00
movq -0x78(%rbp), %rdi
movl $0x18, %esi
callq 0x8560
movq $0x0, -0x8(%rbp)
jmp 0x6739f
movl $0x0, -0x30(%rbp)
jmp 0x672d2
movl -0x34(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x672f6
movq -0x10(%rbp), %rax
movslq -0x34(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movb -0x1c(%rbp,%rax), %al
movb %al, -0x29(%rbp)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x672f8
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x671b5
movq -0x28(%rbp), %rdi
movb $0x0, -0x59(%rbp)
leaq -0x59(%rbp), %rsi
callq 0x52e60
movq -0x28(%rbp), %rdi
callq 0x4bd30
movq %rax, %rdi
shlq $0x0, %rdi
callq 0x8770
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x28(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x68fb0
movq %rax, -0x88(%rbp)
movq -0x28(%rbp), %rdi
callq 0x4bd30
movq -0x90(%rbp), %rdi
movq -0x88(%rbp), %rsi
movq %rax, %rdx
shlq $0x0, %rdx
callq 0x8480
movq -0x28(%rbp), %rax
movq %rax, -0x80(%rbp)
cmpq $0x0, %rax
je 0x67397
movq -0x80(%rbp), %rdi
callq 0x47c00
movq -0x80(%rbp), %rdi
movl $0x18, %esi
callq 0x8560
movq -0x68(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x90, %rsp
popq %rbp
retq
nopl (%rax)