// File: /workspace/github_cpp_makefile_star2_O2/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 0x1fe52
movq %r8, %rbx
movq %rsi, %r15
movl %edi, %r13d
movzbl 0xd(%rsi), %ebp
cmpl $0x3, %ebp
je 0x1fb63
cmpl $0x2, %ebp
je 0x1fb5a
cmpl $0x1, %ebp
jne 0x1fb6e
leaq 0x24e0(%rip), %rsi      # 0x22038
jmp 0x1fb6a
leaq 0x24dd(%rip), %rsi      # 0x2203e
jmp 0x1fb6a
leaq 0x24dd(%rip), %rsi      # 0x22047
xorl %eax, %eax
jmp 0x1fb72
xorl %esi, %esi
movb $0x1, %al
cmpb $0x3, %r13b
je 0x1fb98
movzbl %r13b, %edi
cmpl $0x2, %edi
je 0x1fb8f
cmpl $0x1, %edi
jne 0x1fba4
leaq 0x24ab(%rip), %rdi      # 0x22038
jmp 0x1fb9f
leaq 0x24a8(%rip), %rdi      # 0x2203e
jmp 0x1fb9f
leaq 0x24a8(%rip), %rdi      # 0x22047
xorl %r8d, %r8d
jmp 0x1fba9
movb $0x1, %r8b
xorl %edi, %edi
cmpq %rdi, %rsi
je 0x1fc0f
orb %r8b, %al
cmpb $0x1, %al
jne 0x1fc4f
testb %cl, %cl
je 0x1fe52
pushq $0x28
popq %rdi
callq 0x115e0
movq %rax, %rbx
leaq 0x248d(%rip), %rsi      # 0x22060
leaq 0x20(%rsp), %rdi
leaq 0x18(%rsp), %rdx
callq 0x128f0
movb $0x1, %bpl
leaq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0x11300
xorl %ebp, %ebp
movq 0xc3ed(%rip), %rsi      # 0x2bfe8
movq 0xc346(%rip), %rdx      # 0x2bf48
movq %rbx, %rdi
callq 0x12920
jmp 0x1feac
leaq (%rdx,%rbx), %rsi
movq (%r14), %rdi
movq 0x8(%r14), %rax
subq %rdi, %rax
cmpq %rsi, %rax
jae 0x1fc31
movq %r14, %rdi
callq 0x11f70
movq (%r14), %rdi
movl 0x8(%r15), %edx
addq %rbx, %rdi
cmpb $0x0, 0xe(%r15)
movq %r15, %rsi
jne 0x1fc41
movq (%r15), %rsi
callq 0x11bf0
movl 0x8(%r15), %eax
jmp 0x1fe54
movl %ecx, 0xc(%rsp)
callq 0x11aa0
cmpq $-0x1, %rax
je 0x1fd77
movq %rax, %r12
movl 0x8(%r15), %esi
movq %rsi, 0x18(%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 0x1fcb1
movq %r14, %rdi
callq 0x11f70
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 0x1fcc6
movq (%r15), %r15
leaq 0x50(%rsp), %r13
movq %r15, (%r13)
xorl %ebp, %ebp
leaq 0x18(%rsp), %r15
movq %r12, 0x40(%rsp)
addq %rbp, %rax
addq %rbx, %rax
movq %rax, 0x48(%rsp)
movq %r12, %rdi
movq %r13, %rsi
movq %r15, %rdx
leaq 0x48(%rsp), %rcx
leaq 0x10(%rsp), %r8
callq 0x129b0
testq %rax, %rax
je 0x1fdd0
movq %rax, %rbp
callq 0x11090
movl (%rax), %eax
cmpl $0x7, %eax
je 0x1fd29
cmpl $0x54, %eax
je 0x1fde9
cmpl $0x16, %eax
jne 0x1fd6f
jmp 0x1fe43
movq 0x8(%r14), %rbp
subq (%r14), %rbp
movq 0x18(%rsp), %rax
movq %rbx, %r12
movq %r15, %rbx
movq %r13, %r15
leaq (,%rax,4), %r13
addq %rbp, %r13
movq %r14, %rdi
movq %r13, %rsi
callq 0x11f70
subq 0x10(%rsp), %rbp
subq %rbp, %r13
movq %r13, 0x10(%rsp)
movq %r15, %r13
movq %rbx, %r15
movq %r12, %rbx
movq 0x40(%rsp), %r12
movq (%r14), %rax
jmp 0x1fcdb
cmpb $0x0, 0xc(%rsp)
je 0x1fe52
pushq $0x28
popq %rdi
callq 0x115e0
movq %rax, %rbx
leaq 0x22f9(%rip), %rsi      # 0x2208d
leaq 0x20(%rsp), %rdi
leaq 0x18(%rsp), %rdx
callq 0x128f0
movb $0x1, %bpl
leaq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0x11300
xorl %ebp, %ebp
movq 0xc22c(%rip), %rsi      # 0x2bfe8
movq 0xc185(%rip), %rdx      # 0x2bf48
movq %rbx, %rdi
callq 0x12920
jmp 0x1feac
movq %r12, %rdi
callq 0x11b50
addq 0x10(%rsp), %rbx
movq 0x8(%r14), %rax
addq (%r14), %rbx
subq %rbx, %rax
jmp 0x1fe54
movq %r12, %rdi
callq 0x11b50
cmpb $0x0, 0xc(%rsp)
je 0x1fe52
pushq $0x28
popq %rdi
callq 0x115e0
movq %rax, %rbx
leaq 0x22f4(%rip), %rsi      # 0x220fe
leaq 0x20(%rsp), %rdi
leaq 0xb(%rsp), %rdx
callq 0x128f0
movb $0x1, %bpl
leaq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0x11300
xorl %ebp, %ebp
movq 0xc1b6(%rip), %rsi      # 0x2bfe8
movq 0xc10f(%rip), %rdx      # 0x2bf48
movq %rbx, %rdi
callq 0x12920
jmp 0x1feac
movq %r12, %rdi
callq 0x11b50
cmpb $0x0, 0xc(%rsp)
jne 0x1fe63
xorl %eax, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x28
popq %rdi
callq 0x115e0
movq %rax, %rbx
leaq 0x2254(%rip), %rsi      # 0x220c9
leaq 0x20(%rsp), %rdi
leaq 0xb(%rsp), %rdx
callq 0x128f0
movb $0x1, %bpl
leaq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0x11300
xorl %ebp, %ebp
movq 0xc14b(%rip), %rsi      # 0x2bfe8
movq 0xc0a4(%rip), %rdx      # 0x2bf48
movq %rbx, %rdi
callq 0x12920
jmp 0x1feb8
jmp 0x1fecc
jmp 0x1feb8
jmp 0x1fecc
jmp 0x1feb8
jmp 0x1fecc
movq %rax, %r14
leaq 0x20(%rsp), %rdi
callq 0x12cd8
testb %bpl, %bpl
jne 0x1fecf
jmp 0x1fed7
movq %rax, %r14
movq %rbx, %rdi
callq 0x119b0
movq %r14, %rdi
callq 0x12990
nop