// File: zeeev[P]DASVC/bamtools/include/api/BamAlignment.h
// Function: bool BamTools::BamAlignment::AddTag<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, int const&)
inline bool BamAlignment::AddTag(const std::string& tag, const std::string& type, const T& value) {

    // if char data not populated, do that first
    if ( SupportData.HasCoreOnly )
        BuildCharData();

    // check tag/type size
    if ( !IsValidSize(tag, type) ) {
        // TODO: set error string?
        return false;
    }

    // check that storage type code is OK for T
    if ( !TagTypeHelper<T>::CanConvertTo(type.at(0)) ) {
        // 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;

    // if tag already exists, return false
    // use EditTag explicitly instead
    if ( FindTag(tag, pTagData, tagDataLength, numBytesParsed) ) {
        // TODO: set error string?
        return false;
    }

    // otherwise, convert value to string
    union { T value; char valueBuffer[sizeof(T)]; } un;
    un.value = value;

    // copy original tag data to temp buffer
    const std::string newTag = tag + type;
    const size_t newTagDataLength = tagDataLength + newTag.size() + sizeof(T); // leave room for new T
    RaiiBuffer originalTagData(newTagDataLength);
    memcpy(originalTagData.Buffer, TagData.c_str(), tagDataLength + 1);    // '+1' for TagData null-term

    // append newTag
    strcat(originalTagData.Buffer + tagDataLength, newTag.data());
    memcpy(originalTagData.Buffer + tagDataLength + newTag.size(), un.valueBuffer, sizeof(T));

    // store temp buffer back in TagData
    const char* newTagData = (const char*)originalTagData.Buffer;
    TagData.assign(newTagData, newTagDataLength);
    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x98(%rbp)
testb $0x1, 0x130(%rax)
je 0x1195b
movq -0x98(%rbp), %rdi
callq 0x2b6e0
movq -0x98(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x2d880
testb $0x1, %al
jne 0x1197c
movb $0x0, -0x1(%rbp)
jmp 0x11b5b
movq -0x20(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x66d0
movsbl (%rax), %edi
callq 0x14fd0
testb $0x1, %al
jne 0x1199e
movb $0x0, -0x1(%rbp)
jmp 0x11b5b
movq -0x98(%rbp), %rdi
addq $0x88, %rdi
callq 0x62c0
movq -0x98(%rbp), %rdi
movq %rax, -0x30(%rbp)
addq $0x88, %rdi
callq 0x6390
movq -0x98(%rbp), %rdi
movl %eax, -0x34(%rbp)
movl $0x0, -0x38(%rbp)
movq -0x18(%rbp), %rsi
leaq -0x30(%rbp), %rdx
leaq -0x34(%rbp), %rcx
leaq -0x38(%rbp), %r8
callq 0x2c5f0
testb $0x1, %al
jne 0x119f4
jmp 0x119fd
movb $0x0, -0x1(%rbp)
jmp 0x11b5b
movq -0x28(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x3c(%rbp)
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
leaq -0x60(%rbp), %rdi
movq %rdi, -0xa8(%rbp)
callq 0x14ff0
movq -0xa8(%rbp), %rdi
movl -0x34(%rbp), %eax
movq %rax, -0xa0(%rbp)
callq 0x6390
movq %rax, %rcx
movq -0xa0(%rbp), %rax
leaq 0x4(%rax,%rcx), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rsi
leaq -0x78(%rbp), %rdi
callq 0x15070
jmp 0x11a56
movq -0x98(%rbp), %rdi
movq -0x78(%rbp), %rax
movq %rax, -0xd0(%rbp)
addq $0x88, %rdi
movq %rdi, -0xb0(%rbp)
callq 0x61f0
movq -0xd0(%rbp), %rdi
movq %rax, %rsi
movl -0x34(%rbp), %eax
incl %eax
movl %eax, %edx
callq 0x6450
movq -0x78(%rbp), %rax
movl -0x34(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0xc8(%rbp)
leaq -0x60(%rbp), %rdi
movq %rdi, -0xc0(%rbp)
callq 0x6780
movq -0xc8(%rbp), %rdi
movq %rax, %rsi
callq 0x6a30
movq -0xc0(%rbp), %rdi
movq -0x78(%rbp), %rax
movl -0x34(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0xb8(%rbp)
callq 0x6390
movq -0xb8(%rbp), %rcx
movq -0xb0(%rbp), %rdi
movl -0x3c(%rbp), %edx
movl %edx, (%rax,%rcx)
movq -0x78(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rsi
movq -0x68(%rbp), %rdx
callq 0x67e0
jmp 0x11b0f
movb $0x1, -0x1(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x150c0
leaq -0x60(%rbp), %rdi
callq 0x6ba8
jmp 0x11b5b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x11b50
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x150c0
leaq -0x60(%rbp), %rdi
callq 0x6ba8
jmp 0x11b69
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xd0, %rsp
popq %rbp
retq
movq -0x80(%rbp), %rdi
callq 0x6a10
nopw %cs:(%rax,%rax)
nopl (%rax)