// File: /workspace/github_cpp_makefile_star2_O3/night-shift[P]Srl/src/lib/ToolsStrConv.cpp
// Function: Srl::Tools::conv_charset(Srl::Encoding, Srl::String const&, std::vector<unsigned char, std::allocator<unsigned char>>&, bool, unsigned long)
size_t Tools::conv_charset(Encoding target_encoding, const String& str_wrap,
                           vector<uint8_t>& buffer,  bool throw_error, size_t buffer_index)
{
    if(str_wrap.size() < 1) {
        return 0;
    }

    auto src_encoding = str_wrap.encoding();

    auto* cs_from = get_charset_string(src_encoding);
    auto* cs_to   = get_charset_string(target_encoding);

    if(cs_from == cs_to) {
        auto seg = str_wrap.size() + buffer_index;
        if(buffer.size() < seg) {
            buffer.resize(seg);
        }
        memcpy(&buffer[buffer_index], str_wrap.data(), str_wrap.size());

        return str_wrap.size();
    }

    if(cs_from == nullptr || cs_to == nullptr) {
        if(throw_error) {
            throw Exception("Unable to convert charset. Unknown encoding.");
        }
        return 0;
    }

    iconv_t desc = iconv_open(cs_to, cs_from);

    if(desc == (iconv_t)(-1)) {
        if(throw_error) {
            throw Exception("Unable to convert charset. Failed to open iconv descriptor.");
        }
        return 0;
    }

    size_t left_in = str_wrap.size();
    size_t reserve = left_in * (
        target_encoding < src_encoding ? 1 : src_encoding == Encoding::UTF16 ? 2 : 4
    );

    if(buffer_index + reserve > buffer.size()) {
        buffer.resize(buffer_index + reserve);
    }
    size_t left_out = buffer.size() - buffer_index;

    auto* src = (char*)str_wrap.data();
    size_t converted = 0;

    while(true) {
        auto* dst = (char*)&buffer[buffer_index + converted];
        converted = iconv(desc, &src, &left_in, &dst, &left_out);

        if(converted == 0) {
            /* all characters converted */
            break;
        }

        if(errno == EINVAL) {
            iconv_close(desc);
            if(throw_error) {
                throw Exception("Unable to convert charset. Incomplete byte sequence.");
            }
            return 0;
        }

        if(errno == EILSEQ) {
            iconv_close(desc);
            if(throw_error) {
                throw Exception("Unable to convert charset. Invalid byte sequence.");
            }
            return 0;
        }

        if (errno == E2BIG) {
            /* output buffer not big enough */
            auto current = buffer.size();
            auto new_size = buffer.size() + left_in * 4;
            buffer.resize(new_size);
            converted = current - left_out;
            left_out = new_size - converted;
        }
    }

    iconv_close(desc);

    return buffer.size() - buffer_index - left_out;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, %r14
movl 0x8(%rsi), %edx
testq %rdx, %rdx
je 0x1cc0f
movq %r8, %rbx
movq %rsi, %r15
movl %edi, %r13d
movzbl 0xd(%rsi), %ebp
cmpl $0x3, %ebp
je 0x1c8d2
cmpl $0x2, %ebp
je 0x1c8c9
cmpl $0x1, %ebp
jne 0x1c8dd
leaq 0x2751(%rip), %rsi      # 0x1f018
jmp 0x1c8d9
leaq 0x274e(%rip), %rsi      # 0x1f01e
jmp 0x1c8d9
leaq 0x274e(%rip), %rsi      # 0x1f027
xorl %eax, %eax
jmp 0x1c8e1
xorl %esi, %esi
movb $0x1, %al
cmpb $0x3, %r13b
je 0x1c907
movzbl %r13b, %edi
cmpl $0x2, %edi
je 0x1c8fe
cmpl $0x1, %edi
jne 0x1c913
leaq 0x271c(%rip), %rdi      # 0x1f018
jmp 0x1c90e
leaq 0x2719(%rip), %rdi      # 0x1f01e
jmp 0x1c90e
leaq 0x2719(%rip), %rdi      # 0x1f027
xorl %r8d, %r8d
jmp 0x1c918
movb $0x1, %r8b
xorl %edi, %edi
cmpq %rdi, %rsi
je 0x1c98b
orb %r8b, %al
cmpb $0x1, %al
jne 0x1c9cb
testb %cl, %cl
je 0x1cc0f
movl $0x28, %edi
callq 0xb3b0
movq %rax, %rbx
leaq 0x28(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x26f3(%rip), %rsi      # 0x1f040
leaq 0x2718(%rip), %rdx      # 0x1f06c
leaq 0x18(%rsp), %rdi
callq 0xb2e0
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0xb1d0
xorl %ebp, %ebp
movq 0xa671(%rip), %rsi      # 0x26fe8
movq 0xa5ca(%rip), %rdx      # 0x26f48
movq %rbx, %rdi
callq 0xbe60
jmp 0x1cc76
leaq (%rdx,%rbx), %rsi
movq (%r14), %rdi
movq 0x8(%r14), %rax
subq %rdi, %rax
cmpq %rsi, %rax
jae 0x1c9ad
movq %r14, %rdi
callq 0xb980
movq (%r14), %rdi
movl 0x8(%r15), %edx
addq %rbx, %rdi
cmpb $0x0, 0xe(%r15)
movq %r15, %rsi
jne 0x1c9bd
movq (%r15), %rsi
callq 0xb790
movl 0x8(%r15), %eax
jmp 0x1cc11
movl %ecx, 0xc(%rsp)
callq 0xb6c0
cmpq $-0x1, %rax
je 0x1cb33
movq %rax, %r12
movl 0x8(%r15), %esi
movq %rsi, 0x38(%rsp)
cmpb $0x2, %bpl
sete %al
movb $0x2, %cl
subb %al, %cl
xorl %eax, %eax
cmpb %r13b, %bpl
movzbl %cl, %ecx
cmoval %eax, %ecx
shlq %cl, %rsi
addq %rbx, %rsi
movq (%r14), %rcx
movq 0x8(%r14), %rdx
movq %rdx, %rdi
subq %rcx, %rdi
movq %rcx, %rax
cmpq %rdi, %rsi
jbe 0x1ca2d
movq %r14, %rdi
callq 0xb980
movq (%r14), %rcx
movq 0x8(%r14), %rdx
movq %rcx, %rax
addq %rbx, %rcx
subq %rcx, %rdx
movq %rdx, 0x10(%rsp)
cmpb $0x0, 0xe(%r15)
jne 0x1ca42
movq (%r15), %r15
leaq 0x50(%rsp), %rsi
movq %r15, (%rsi)
addq %rbx, %rax
leaq 0x40(%rsp), %rcx
movq %rax, (%rcx)
leaq 0x38(%rsp), %rdx
leaq 0x10(%rsp), %r8
movq %r12, %rdi
callq 0xbeb0
testq %rax, %rax
je 0x1cb17
movq %rax, %r13
callq 0xb070
movq %rax, %r15
leaq 0x50(%rsp), %rbp
movq %rax, 0x48(%rsp)
movl (%r15), %eax
cmpl $0x7, %eax
je 0x1caa0
cmpl $0x54, %eax
je 0x1cc00
cmpl $0x16, %eax
jne 0x1cae6
jmp 0x1cb99
movq 0x8(%r14), %r13
subq (%r14), %r13
movq 0x38(%rsp), %rax
movq %rbx, %r15
movq %r12, %rbx
movq %rbp, %r12
leaq (,%rax,4), %rbp
addq %r13, %rbp
movq %r14, %rdi
movq %rbp, %rsi
callq 0xb980
subq 0x10(%rsp), %r13
subq %r13, %rbp
movq %rbp, 0x10(%rsp)
movq %r12, %rbp
movq %rbx, %r12
movq %r15, %rbx
movq 0x48(%rsp), %r15
addq (%r14), %r13
addq %rbx, %r13
movq %r13, 0x40(%rsp)
movq %r12, %rdi
movq %rbp, %rsi
leaq 0x38(%rsp), %rdx
leaq 0x40(%rsp), %rcx
leaq 0x10(%rsp), %r8
callq 0xbeb0
movq %rax, %r13
testq %rax, %rax
jne 0x1ca85
movq %r12, %rdi
callq 0xb720
addq 0x10(%rsp), %rbx
movq 0x8(%r14), %rax
addq (%r14), %rbx
subq %rbx, %rax
jmp 0x1cc11
cmpb $0x0, 0xc(%rsp)
je 0x1cc0f
movl $0x28, %edi
callq 0xb3b0
movq %rax, %rbx
leaq 0x28(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x2512(%rip), %rsi      # 0x1f06d
leaq 0x2546(%rip), %rdx      # 0x1f0a8
leaq 0x18(%rsp), %rdi
callq 0xb2e0
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0xb1d0
xorl %ebp, %ebp
movq 0xa463(%rip), %rsi      # 0x26fe8
movq 0xa3bc(%rip), %rdx      # 0x26f48
movq %rbx, %rdi
callq 0xbe60
jmp 0x1cc76
movq %r12, %rdi
callq 0xb720
cmpb $0x0, 0xc(%rsp)
je 0x1cc0f
movl $0x28, %edi
callq 0xb3b0
movq %rax, %rbx
leaq 0x28(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x24e4(%rip), %rsi      # 0x1f0a9
leaq 0x2511(%rip), %rdx      # 0x1f0dd
leaq 0x18(%rsp), %rdi
callq 0xb2e0
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0xb1d0
xorl %ebp, %ebp
movq 0xa3f9(%rip), %rsi      # 0x26fe8
movq 0xa352(%rip), %rdx      # 0x26f48
movq %rbx, %rdi
callq 0xbe60
jmp 0x1cc76
movq %r12, %rdi
callq 0xb720
cmpb $0x0, 0xc(%rsp)
jne 0x1cc20
xorl %eax, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x28, %edi
callq 0xb3b0
movq %rax, %rbx
leaq 0x28(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x24a1(%rip), %rsi      # 0x1f0de
leaq 0x24cb(%rip), %rdx      # 0x1f10f
leaq 0x18(%rsp), %rdi
callq 0xb2e0
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0xb1d0
xorl %ebp, %ebp
movq 0xa381(%rip), %rsi      # 0x26fe8
movq 0xa2da(%rip), %rdx      # 0x26f48
movq %rbx, %rdi
callq 0xbe60
jmp 0x1cc82
jmp 0x1cca3
jmp 0x1cc82
jmp 0x1cca3
jmp 0x1cc82
jmp 0x1cca3
movq %rax, %r14
movq 0x18(%rsp), %rdi
cmpq %r15, %rdi
je 0x1cc9c
movq 0x28(%rsp), %rsi
incq %rsi
callq 0xb940
testb %bpl, %bpl
jne 0x1cca6
jmp 0x1ccae
movq %rax, %r14
movq %rbx, %rdi
callq 0xb610
movq %r14, %rdi
callq 0xbe90