// File: /workspace/github_cpp_makefile_star2_O1/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 %rsi, %r15
movl 0x8(%rsi), %esi
testq %rsi, %rsi
je 0x1cf9a
movq %r8, %rbx
movq %rdx, %r14
movl %edi, %r13d
movzbl 0xd(%r15), %ebp
cmpl $0x3, %ebp
je 0x1cd32
cmpl $0x2, %ebp
je 0x1cd29
cmpl $0x1, %ebp
jne 0x1cd3e
leaq 0x32f1(%rip), %rax      # 0x20018
jmp 0x1cd39
leaq 0x32ee(%rip), %rax      # 0x2001e
jmp 0x1cd39
leaq 0x32ee(%rip), %rax      # 0x20027
xorl %r8d, %r8d
jmp 0x1cd43
xorl %eax, %eax
movb $0x1, %r8b
cmpb $0x3, %r13b
je 0x1cd69
movzbl %r13b, %edx
cmpl $0x2, %edx
je 0x1cd60
cmpl $0x1, %edx
jne 0x1cd74
leaq 0x32ba(%rip), %rdi      # 0x20018
jmp 0x1cd70
leaq 0x32b7(%rip), %rdi      # 0x2001e
jmp 0x1cd70
leaq 0x32b7(%rip), %rdi      # 0x20027
xorl %edx, %edx
jmp 0x1cd78
movb $0x1, %dl
xorl %edi, %edi
cmpq %rdi, %rax
je 0x1cded
orb %dl, %r8b
cmpb $0x1, %r8b
jne 0x1ce29
testb %cl, %cl
je 0x1cf9a
movl $0x28, %edi
callq 0xb3b0
movq %rax, %rbx
leaq 0x28(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x3291(%rip), %rsi      # 0x20040
leaq 0x32b6(%rip), %rdx      # 0x2006c
leaq 0x18(%rsp), %rdi
callq 0xb2e0
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0xb1d0
xorl %ebp, %ebp
movq 0xb20f(%rip), %rsi      # 0x27fe8
movq 0xb168(%rip), %rdx      # 0x27f48
movq %rbx, %rdi
callq 0xbe60
jmp 0x1d0b4
addq %rbx, %rsi
movq 0x8(%r14), %rax
subq (%r14), %rax
cmpq %rsi, %rax
jae 0x1ce04
movq %r14, %rdi
callq 0xb980
movq %r15, %rsi
addq (%r14), %rbx
cmpb $0x0, 0xe(%r15)
jne 0x1ce14
movq (%r15), %rsi
movl 0x8(%r15), %edx
movq %rbx, %rdi
callq 0xb790
movl 0x8(%r15), %eax
jmp 0x1cf9c
movl %ecx, 0xc(%rsp)
movq %rax, %rsi
callq 0xb6c0
cmpq $-0x1, %rax
je 0x1cf8f
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 0x8(%r14), %rax
subq (%r14), %rax
cmpq %rax, %rsi
jbe 0x1ce7b
movq %r14, %rdi
callq 0xb980
movq 0x8(%r14), %rax
movq (%r14), %rcx
addq %rbx, %rcx
subq %rcx, %rax
movq %rax, 0x10(%rsp)
cmpb $0x0, 0xe(%r15)
jne 0x1ce97
movq (%r15), %r15
leaq 0x50(%rsp), %rax
movq %r15, (%rax)
movq %rax, %r15
xorl %ebp, %ebp
movq %rbx, 0x40(%rsp)
addq (%r14), %rbp
addq %rbx, %rbp
movq %rbp, 0x48(%rsp)
movq %r12, %rdi
movq %r15, %rsi
leaq 0x38(%rsp), %rdx
leaq 0x48(%rsp), %rcx
leaq 0x10(%rsp), %r8
callq 0xbeb0
testq %rax, %rax
je 0x1cf09
movq %rax, %rbp
callq 0xb070
movl (%rax), %eax
xorl %r13d, %r13d
cmpl $0x7, %eax
je 0x1cf2d
cmpl $0x54, %eax
je 0x1cf13
cmpl $0x16, %eax
jne 0x1cf67
movq %r12, %rdi
callq 0xb720
movl $0x1, %r13d
cmpb $0x0, 0xc(%rsp)
je 0x1cf67
jmp 0x1cfab
movl $0x3, %r13d
xorl %ebp, %ebp
jmp 0x1cf67
movq %r12, %rdi
callq 0xb720
movl $0x1, %r13d
cmpb $0x0, 0xc(%rsp)
je 0x1cf67
jmp 0x1d006
movq 0x8(%r14), %rbp
subq (%r14), %rbp
movq 0x38(%rsp), %rax
movq %r15, %rbx
leaq (,%rax,4), %r15
addq %rbp, %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0xb980
subq 0x10(%rsp), %rbp
subq %rbp, %r15
movq %r15, 0x10(%rsp)
movq %rbx, %r15
movq 0x40(%rsp), %rbx
testl %r13d, %r13d
je 0x1cea9
cmpl $0x3, %r13d
jne 0x1cf9a
movq %r12, %rdi
callq 0xb720
addq 0x10(%rsp), %rbx
movq 0x8(%r14), %rax
addq (%r14), %rbx
subq %rbx, %rax
jmp 0x1cf9c
cmpb $0x0, 0xc(%rsp)
jne 0x1d05e
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 0x30e1(%rip), %rsi      # 0x200a9
leaq 0x310e(%rip), %rdx      # 0x200dd
leaq 0x18(%rsp), %rdi
callq 0xb2e0
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0xb1d0
xorl %ebp, %ebp
movq 0xaff6(%rip), %rsi      # 0x27fe8
movq 0xaf4f(%rip), %rdx      # 0x27f48
movq %rbx, %rdi
callq 0xbe60
jmp 0x1d0b4
movl $0x28, %edi
callq 0xb3b0
movq %rax, %rbx
leaq 0x28(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x30bb(%rip), %rsi      # 0x200de
leaq 0x30e5(%rip), %rdx      # 0x2010f
leaq 0x18(%rsp), %rdi
callq 0xb2e0
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0xb1d0
xorl %ebp, %ebp
movq 0xaf9b(%rip), %rsi      # 0x27fe8
movq 0xaef4(%rip), %rdx      # 0x27f48
movq %rbx, %rdi
callq 0xbe60
jmp 0x1d0b4
movl $0x28, %edi
callq 0xb3b0
movq %rax, %rbx
leaq 0x28(%rsp), %r15
movq %r15, -0x10(%r15)
leaq 0x2ff2(%rip), %rsi      # 0x2006d
leaq 0x3026(%rip), %rdx      # 0x200a8
leaq 0x18(%rsp), %rdi
callq 0xb2e0
movb $0x1, %bpl
leaq 0x18(%rsp), %rsi
movq %rbx, %rdi
callq 0xb1d0
xorl %ebp, %ebp
movq 0xaf43(%rip), %rsi      # 0x27fe8
movq 0xae9c(%rip), %rdx      # 0x27f48
movq %rbx, %rdi
callq 0xbe60
jmp 0x1d0c0
jmp 0x1d0dc
jmp 0x1d0c0
jmp 0x1d0dc
jmp 0x1d0c0
jmp 0x1d0dc
movq %rax, %r14
movq 0x18(%rsp), %rdi
cmpq %r15, %rdi
je 0x1d0e2
movq 0x28(%rsp), %rsi
incq %rsi
callq 0xb940
jmp 0x1d0e2
movq %rax, %r14
movb $0x1, %bpl
testb %bpl, %bpl
je 0x1d0ef
movq %rbx, %rdi
callq 0xb610
movq %r14, %rdi
callq 0xbe90
nop