// File: zeeev[P]DASVC/bamtools/src/api/BamAlignment.cpp
// Function: BamTools::BamAlignment::SkipToNextTag(char, char*&, unsigned int&) const
bool BamAlignment::SkipToNextTag(const char storageType,
                                 char*& pTagData,
                                 unsigned int& numBytesParsed) const
{
    switch (storageType) {

        case (Constants::BAM_TAG_TYPE_ASCII) :
        case (Constants::BAM_TAG_TYPE_INT8)  :
        case (Constants::BAM_TAG_TYPE_UINT8) :
            ++numBytesParsed;
            ++pTagData;
            break;

        case (Constants::BAM_TAG_TYPE_INT16)  :
        case (Constants::BAM_TAG_TYPE_UINT16) :
            numBytesParsed += sizeof(uint16_t);
            pTagData       += sizeof(uint16_t);
            break;

        case (Constants::BAM_TAG_TYPE_FLOAT)  :
        case (Constants::BAM_TAG_TYPE_INT32)  :
        case (Constants::BAM_TAG_TYPE_UINT32) :
            numBytesParsed += sizeof(uint32_t);
            pTagData       += sizeof(uint32_t);
            break;

        case (Constants::BAM_TAG_TYPE_STRING) :
        case (Constants::BAM_TAG_TYPE_HEX)    :
            while( *pTagData ) {
                ++numBytesParsed;
                ++pTagData;
            }
            // increment for null-terminator
            ++numBytesParsed;
            ++pTagData;
            break;

        case (Constants::BAM_TAG_TYPE_ARRAY) :

        {
            // read array type
            const char arrayType = *pTagData;
            ++numBytesParsed;
            ++pTagData;

            // read number of elements
            int32_t numElements;
            memcpy(&numElements, pTagData, sizeof(uint32_t)); // already endian-swapped, if needed
            numBytesParsed += sizeof(uint32_t);
            pTagData       += sizeof(uint32_t);

            // calculate number of bytes to skip
            int bytesToSkip = 0;
            switch (arrayType) {
                case (Constants::BAM_TAG_TYPE_INT8)  :
                case (Constants::BAM_TAG_TYPE_UINT8) :
                    bytesToSkip = numElements;
                    break;
                case (Constants::BAM_TAG_TYPE_INT16)  :
                case (Constants::BAM_TAG_TYPE_UINT16) :
                    bytesToSkip = numElements*sizeof(uint16_t);
                    break;
                case (Constants::BAM_TAG_TYPE_FLOAT)  :
                case (Constants::BAM_TAG_TYPE_INT32)  :
                case (Constants::BAM_TAG_TYPE_UINT32) :
                    bytesToSkip = numElements*sizeof(uint32_t);
                    break;
                default:
                    const string message = string("invalid binary array type: ") + arrayType;
                    SetErrorString("BamAlignment::SkipToNextTag", message);
                    return false;
            }

            // skip binary array contents
            numBytesParsed += bytesToSkip;
            pTagData       += bytesToSkip;
            break;
        }

        default:
            const string message = string("invalid tag type: ") + storageType;
            SetErrorString("BamAlignment::SkipToNextTag", message);
            return false;
    }

    // if we get here, tag skipped OK - return success
    return true;
}

// Assembly:
subq $0x168, %rsp            # imm = 0x168
movb %sil, %al
movq %rdi, 0x158(%rsp)
movb %al, 0x157(%rsp)
movq %rdx, 0x148(%rsp)
movq %rcx, 0x140(%rsp)
movq 0x158(%rsp), %rax
movq %rax, 0x30(%rsp)
movsbl 0x157(%rsp), %eax
addl $-0x41, %eax
movl %eax, %ecx
movq %rcx, 0x38(%rsp)
subl $0x32, %eax
ja 0x87b42
movq 0x38(%rsp), %rax
leaq 0x6299f(%rip), %rcx     # 0xea13c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x140(%rsp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movq 0x148(%rsp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
jmp 0x87ca2
movq 0x140(%rsp), %rax
movl (%rax), %ecx
addq $0x2, %rcx
movl %ecx, (%rax)
movq 0x148(%rsp), %rax
movq (%rax), %rcx
addq $0x2, %rcx
movq %rcx, (%rax)
jmp 0x87ca2
movq 0x140(%rsp), %rax
movl (%rax), %ecx
addq $0x4, %rcx
movl %ecx, (%rax)
movq 0x148(%rsp), %rax
movq (%rax), %rcx
addq $0x4, %rcx
movq %rcx, (%rax)
jmp 0x87ca2
jmp 0x8781c
movq 0x148(%rsp), %rax
movq (%rax), %rax
cmpb $0x0, (%rax)
je 0x8784f
movq 0x140(%rsp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movq 0x148(%rsp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
jmp 0x8781c
movq 0x140(%rsp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movq 0x148(%rsp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
jmp 0x87ca2
movq 0x148(%rsp), %rax
movq (%rax), %rax
movb (%rax), %al
movb %al, 0x13f(%rsp)
movq 0x140(%rsp), %rax
movl (%rax), %ecx
incl %ecx
movl %ecx, (%rax)
movq 0x148(%rsp), %rax
movq (%rax), %rcx
incq %rcx
movq %rcx, (%rax)
movq 0x148(%rsp), %rax
movq (%rax), %rax
movl (%rax), %eax
movl %eax, 0x138(%rsp)
movq 0x140(%rsp), %rax
movl (%rax), %ecx
addl $0x4, %ecx
movl %ecx, (%rax)
movq 0x148(%rsp), %rax
movq (%rax), %rcx
addq $0x4, %rcx
movq %rcx, (%rax)
movl $0x0, 0x134(%rsp)
movsbl 0x13f(%rsp), %eax
movl %eax, 0x2c(%rsp)
subl $0x43, %eax
je 0x8793d
jmp 0x878fb
movl 0x2c(%rsp), %eax
subl $0x49, %eax
je 0x87967
jmp 0x87906
movl 0x2c(%rsp), %eax
subl $0x53, %eax
je 0x87950
jmp 0x87911
movl 0x2c(%rsp), %eax
subl $0x63, %eax
je 0x8793d
jmp 0x8791c
movl 0x2c(%rsp), %eax
subl $0x66, %eax
je 0x87967
jmp 0x87927
movl 0x2c(%rsp), %eax
subl $0x69, %eax
je 0x87967
jmp 0x87932
movl 0x2c(%rsp), %eax
subl $0x73, %eax
je 0x87950
jmp 0x8797f
movl 0x138(%rsp), %eax
movl %eax, 0x134(%rsp)
jmp 0x87b0f
movslq 0x138(%rsp), %rax
shlq %rax
movl %eax, 0x134(%rsp)
jmp 0x87b0f
movslq 0x138(%rsp), %rax
shlq $0x2, %rax
movl %eax, 0x134(%rsp)
jmp 0x87b0f
leaq 0xef(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x7b5f0
movq 0x20(%rsp), %rdx
leaq 0x628b9(%rip), %rsi     # 0xea256
leaq 0xf0(%rsp), %rdi
callq 0x78e70
jmp 0x879ac
movsbl 0x13f(%rsp), %edx
leaq 0x110(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x74830
jmp 0x879cb
leaq 0xf0(%rsp), %rdi
callq 0x7cce8
jmp 0x879da
leaq 0xef(%rsp), %rdi
callq 0x76f80
leaq 0xb7(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x7b5f0
movq 0x18(%rsp), %rdx
leaq 0x62899(%rip), %rsi     # 0xea29e
leaq 0xb8(%rsp), %rdi
callq 0x78e70
jmp 0x87a14
movq 0x30(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
leaq 0x110(%rsp), %rdx
callq 0x71210
jmp 0x87a30
leaq 0xb8(%rsp), %rdi
callq 0x7cce8
jmp 0x87a3f
leaq 0xb7(%rsp), %rdi
callq 0x76f80
movb $0x0, 0x167(%rsp)
leaq 0x110(%rsp), %rdi
callq 0x7cce8
jmp 0x87caa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0x87aa1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x7cce8
jmp 0x87a9f
jmp 0x87aa1
leaq 0xef(%rsp), %rdi
callq 0x76f80
jmp 0x87cbb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0x87aee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x7cce8
jmp 0x87aec
jmp 0x87aee
leaq 0xb7(%rsp), %rdi
callq 0x76f80
leaq 0x110(%rsp), %rdi
callq 0x7cce8
jmp 0x87b0a
jmp 0x87cbb
movl 0x134(%rsp), %ecx
movq 0x140(%rsp), %rax
addl (%rax), %ecx
movl %ecx, (%rax)
movl 0x134(%rsp), %edx
movq 0x148(%rsp), %rax
movq (%rax), %rcx
movslq %edx, %rdx
addq %rdx, %rcx
movq %rcx, (%rax)
jmp 0x87ca2
leaq 0x6f(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x7b5f0
movq 0x10(%rsp), %rdx
leaq 0x62715(%rip), %rsi     # 0xea272
leaq 0x70(%rsp), %rdi
callq 0x78e70
jmp 0x87b69
movsbl 0x157(%rsp), %edx
leaq 0x90(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x74830
jmp 0x87b85
leaq 0x70(%rsp), %rdi
callq 0x7cce8
jmp 0x87b91
leaq 0x6f(%rsp), %rdi
callq 0x76f80
leaq 0x47(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x7b5f0
movq 0x8(%rsp), %rdx
leaq 0x626e8(%rip), %rsi     # 0xea29e
leaq 0x48(%rsp), %rdi
callq 0x78e70
jmp 0x87bc2
movq 0x30(%rsp), %rdi
leaq 0x48(%rsp), %rsi
leaq 0x90(%rsp), %rdx
callq 0x71210
jmp 0x87bdb
leaq 0x48(%rsp), %rdi
callq 0x7cce8
jmp 0x87be7
leaq 0x47(%rsp), %rdi
callq 0x76f80
movb $0x0, 0x167(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x7cce8
jmp 0x87caa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0x87c43
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x7cce8
jmp 0x87c41
jmp 0x87c43
leaq 0x6f(%rsp), %rdi
callq 0x76f80
jmp 0x87cbb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0x87c87
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
leaq 0x48(%rsp), %rdi
callq 0x7cce8
jmp 0x87c85
jmp 0x87c87
leaq 0x47(%rsp), %rdi
callq 0x76f80
leaq 0x90(%rsp), %rdi
callq 0x7cce8
jmp 0x87ca0
jmp 0x87cbb
movb $0x1, 0x167(%rsp)
movb 0x167(%rsp), %al
andb $0x1, %al
addq $0x168, %rsp            # imm = 0x168
retq
movq 0xe0(%rsp), %rdi
callq 0x7b550
movq %rax, %rdi
callq 0x88ef0