// File: zeeev[P]DASVC/bamtools/src/api/BamAlignment.h
// Function: bool BamTools::BamAlignment::GetTag<signed char>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::vector<signed char, std::allocator<signed char>>&) const
inline bool BamAlignment::GetTag(const std::string& tag, std::vector<T>& destination) const {

    // skip if alignment is core-only
    if ( SupportData.HasCoreOnly ) {
        // TODO: set error string?
        return false;
    }

    // skip if no tags present
    if ( TagData.empty() ) {
        // TODO: set error string?
        return false;
    }

    // localize the tag data
    char* pTagData = (char*)TagData.data();
    const unsigned int tagDataLength = TagData.size();
    unsigned int numBytesParsed = 0;

    // return false if tag not found
    if ( !FindTag(tag, pTagData, tagDataLength, numBytesParsed) ) {
        // TODO: set error string?
        return false;
    }

    // check that tag is array type
    const char tagType = *(pTagData - 1);
    if ( tagType != Constants::BAM_TAG_TYPE_ARRAY ) {
        SetErrorString("BamAlignment::GetTag", "cannot store a non-array tag in array destination");
        return false;
    }

    // fetch element type
    const char elementType = *pTagData;
    if ( !TagTypeHelper<T>::CanConvertFrom(elementType) ) {
        // TODO: set error string ?
        return false;
    }
    ++pTagData;

    // calculate length of each element in tag's array
    int elementLength = 0;
    switch ( elementType ) {
        case (Constants::BAM_TAG_TYPE_ASCII) :
        case (Constants::BAM_TAG_TYPE_INT8)  :
        case (Constants::BAM_TAG_TYPE_UINT8) :
            elementLength = sizeof(uint8_t);
            break;

        case (Constants::BAM_TAG_TYPE_INT16)  :
        case (Constants::BAM_TAG_TYPE_UINT16) :
            elementLength = sizeof(uint16_t);
            break;

        case (Constants::BAM_TAG_TYPE_INT32)  :
        case (Constants::BAM_TAG_TYPE_UINT32) :
        case (Constants::BAM_TAG_TYPE_FLOAT)  :
            elementLength = sizeof(uint32_t);
            break;

        // var-length types not supported for numeric destination
        case (Constants::BAM_TAG_TYPE_STRING) :
        case (Constants::BAM_TAG_TYPE_HEX)    :
        case (Constants::BAM_TAG_TYPE_ARRAY)  :
            SetErrorString("BamAlignment::GetTag",
                           "invalid array data, variable-length elements are not allowed");
            return false;

        // unknown tag type
        default:
            const std::string message = std::string("invalid array element type: ") + elementType;
            SetErrorString("BamAlignment::GetTag", message);
            return false;
    }

    // get number of elements
    int32_t numElements;
    memcpy(&numElements, pTagData, sizeof(int32_t));
    pTagData += 4;
    destination.clear();
    destination.reserve(numElements);

    // read in elements
    T value;
    for ( int i = 0 ; i < numElements; ++i ) {
        memcpy(&value, pTagData, sizeof(T));
        pTagData += sizeof(T);
        destination.push_back(value);
    }

    // return success
    return true;
}

// Assembly:
subq $0x1a8, %rsp            # imm = 0x1A8
movq %rdi, 0x198(%rsp)
movq %rsi, 0x190(%rsp)
movq %rdx, 0x188(%rsp)
movq 0x198(%rsp), %rax
movq %rax, 0x40(%rsp)
testb $0x1, 0x130(%rax)
je 0xfdd42
movb $0x0, 0x1a7(%rsp)
jmp 0xfe333
movq 0x40(%rsp), %rdi
addq $0x88, %rdi
callq 0x86c90
testb $0x1, %al
jne 0xfdd59
jmp 0xfdd66
movb $0x0, 0x1a7(%rsp)
jmp 0xfe333
movq 0x40(%rsp), %rdi
addq $0x88, %rdi
callq 0x86940
movq 0x40(%rsp), %rdi
movq %rax, 0x180(%rsp)
addq $0x88, %rdi
callq 0x86500
movq 0x40(%rsp), %rdi
movl %eax, 0x17c(%rsp)
movl $0x0, 0x178(%rsp)
movq 0x190(%rsp), %rsi
leaq 0x180(%rsp), %rdx
leaq 0x17c(%rsp), %rcx
leaq 0x178(%rsp), %r8
callq 0x868b0
testb $0x1, %al
jne 0xfdddd
movb $0x0, 0x1a7(%rsp)
jmp 0xfe333
movq 0x180(%rsp), %rax
movb -0x1(%rax), %al
movb %al, 0x177(%rsp)
movsbl 0x177(%rsp), %eax
cmpl $0x42, %eax
je 0xfdf3c
leaq 0x14f(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x86da0
movq 0x38(%rsp), %rdx
leaq 0x32032(%rip), %rsi     # 0x12fe50
leaq 0x150(%rsp), %rdi
callq 0x86a00
jmp 0xfde2d
leaq 0x117(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x86da0
movq 0x30(%rsp), %rdx
leaq 0x35647(%rip), %rsi     # 0x133492
leaq 0x118(%rsp), %rdi
callq 0x86a00
jmp 0xfde5a
movq 0x40(%rsp), %rdi
leaq 0x150(%rsp), %rsi
leaq 0x118(%rsp), %rdx
callq 0x86060
jmp 0xfde76
leaq 0x118(%rsp), %rdi
callq 0x86f68
jmp 0xfde85
leaq 0x117(%rsp), %rdi
callq 0x867b0
leaq 0x150(%rsp), %rdi
callq 0x86f68
jmp 0xfdea1
leaq 0x14f(%rsp), %rdi
callq 0x867b0
movb $0x0, 0x1a7(%rsp)
jmp 0xfe333
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0xfdf2a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0xfdf0c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0x118(%rsp), %rdi
callq 0x86f68
jmp 0xfdf0a
jmp 0xfdf0c
leaq 0x117(%rsp), %rdi
callq 0x867b0
leaq 0x150(%rsp), %rdi
callq 0x86f68
jmp 0xfdf28
jmp 0xfdf2a
leaq 0x14f(%rsp), %rdi
callq 0x867b0
jmp 0xfe344
movq 0x180(%rsp), %rax
movb (%rax), %al
movb %al, 0x116(%rsp)
movsbl 0x116(%rsp), %edi
callq 0xbe400
testb $0x1, %al
jne 0xfdf6b
movb $0x0, 0x1a7(%rsp)
jmp 0xfe333
movq 0x180(%rsp), %rax
incq %rax
movq %rax, 0x180(%rsp)
movl $0x0, 0x110(%rsp)
movsbl 0x116(%rsp), %eax
addl $-0x41, %eax
movl %eax, %ecx
movq %rcx, 0x28(%rsp)
subl $0x32, %eax
ja 0xfe125
movq 0x28(%rsp), %rax
leaq 0x348f8(%rip), %rcx     # 0x1328a8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x1, 0x110(%rsp)
jmp 0xfe297
movl $0x2, 0x110(%rsp)
jmp 0xfe297
movl $0x4, 0x110(%rsp)
jmp 0xfe297
leaq 0xef(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x86da0
movq 0x20(%rsp), %rdx
leaq 0x31e49(%rip), %rsi     # 0x12fe50
leaq 0xf0(%rsp), %rdi
callq 0x86a00
jmp 0xfe016
leaq 0xc7(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x86da0
movq 0x18(%rsp), %rdx
leaq 0x35490(%rip), %rsi     # 0x1334c4
leaq 0xc8(%rsp), %rdi
callq 0x86a00
jmp 0xfe043
movq 0x40(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
leaq 0xc8(%rsp), %rdx
callq 0x86060
jmp 0xfe05f
leaq 0xc8(%rsp), %rdi
callq 0x86f68
jmp 0xfe06e
leaq 0xc7(%rsp), %rdi
callq 0x867b0
leaq 0xf0(%rsp), %rdi
callq 0x86f68
jmp 0xfe08a
leaq 0xef(%rsp), %rdi
callq 0x867b0
movb $0x0, 0x1a7(%rsp)
jmp 0xfe333
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0xfe113
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0xfe0f5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0xc8(%rsp), %rdi
callq 0x86f68
jmp 0xfe0f3
jmp 0xfe0f5
leaq 0xc7(%rsp), %rdi
callq 0x867b0
leaq 0xf0(%rsp), %rdi
callq 0x86f68
jmp 0xfe111
jmp 0xfe113
leaq 0xef(%rsp), %rdi
callq 0x867b0
jmp 0xfe344
leaq 0x7f(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x86da0
movq 0x10(%rsp), %rdx
leaq 0x353c1(%rip), %rsi     # 0x133501
leaq 0x80(%rsp), %rdi
callq 0x86a00
jmp 0xfe14f
movsbl 0x116(%rsp), %edx
leaq 0xa0(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0xbe430
jmp 0xfe16e
leaq 0x80(%rsp), %rdi
callq 0x86f68
jmp 0xfe17d
leaq 0x7f(%rsp), %rdi
callq 0x867b0
leaq 0x57(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x86da0
movq 0x8(%rsp), %rdx
leaq 0x31cae(%rip), %rsi     # 0x12fe50
leaq 0x58(%rsp), %rdi
callq 0x86a00
jmp 0xfe1ae
movq 0x40(%rsp), %rdi
leaq 0x58(%rsp), %rsi
leaq 0xa0(%rsp), %rdx
callq 0x86060
jmp 0xfe1c7
leaq 0x58(%rsp), %rdi
callq 0x86f68
jmp 0xfe1d3
leaq 0x57(%rsp), %rdi
callq 0x867b0
movb $0x0, 0x1a7(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x86f68
jmp 0xfe333
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0xfe232
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0x80(%rsp), %rdi
callq 0x86f68
jmp 0xfe230
jmp 0xfe232
leaq 0x7f(%rsp), %rdi
callq 0x867b0
jmp 0xfe344
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
jmp 0xfe279
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x140(%rsp)
movl %eax, 0x13c(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x86f68
jmp 0xfe277
jmp 0xfe279
leaq 0x57(%rsp), %rdi
callq 0x867b0
leaq 0xa0(%rsp), %rdi
callq 0x86f68
jmp 0xfe292
jmp 0xfe344
movq 0x180(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x50(%rsp)
movq 0x180(%rsp), %rax
addq $0x4, %rax
movq %rax, 0x180(%rsp)
movq 0x188(%rsp), %rdi
callq 0xfe5c0
movq 0x188(%rsp), %rdi
movslq 0x50(%rsp), %rsi
callq 0xfe5e0
movl $0x0, 0x48(%rsp)
movl 0x48(%rsp), %eax
cmpl 0x50(%rsp), %eax
jge 0xfe32b
movq 0x180(%rsp), %rax
movb (%rax), %al
movb %al, 0x4f(%rsp)
movq 0x180(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x180(%rsp)
movq 0x188(%rsp), %rdi
leaq 0x4f(%rsp), %rsi
callq 0xfe6d0
movl 0x48(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x48(%rsp)
jmp 0xfe2e0
movb $0x1, 0x1a7(%rsp)
movb 0x1a7(%rsp), %al
andb $0x1, %al
addq $0x1a8, %rsp            # imm = 0x1A8
retq
movq 0x140(%rsp), %rdi
callq 0x86d80
movq %rax, %rdi
callq 0x91290
nopl (%rax)