// File: andrakis[P]alisp/contrib/linenoise-ng/src/ConvertUTF.cpp
// Function: linenoise_ng::ConvertUTF8toUTF32(unsigned char const**, unsigned char const*, unsigned int**, unsigned int*, linenoise_ng::ConversionFlags)
ConversionResult ConvertUTF8toUTF32 (
        const UTF8** sourceStart, const UTF8* sourceEnd, 
        UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
    ConversionResult result = conversionOK;
    const UTF8* source = *sourceStart;
    UTF32* target = *targetStart;
    while (source < sourceEnd) {
        UTF32 ch = 0;
        unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
        if (source + extraBytesToRead >= sourceEnd) {
            result = sourceExhausted; break;
        }
        /* Do this check whether lenient or strict */
        if (! isLegalUTF8(source, extraBytesToRead+1)) {
            result = sourceIllegal;
            break;
        }
        /*
         * The cases all fall through. See "Note A" below.
         */
        switch (extraBytesToRead) {
            case 5: ch += *source++; ch <<= 6;
            case 4: ch += *source++; ch <<= 6;
            case 3: ch += *source++; ch <<= 6;
            case 2: ch += *source++; ch <<= 6;
            case 1: ch += *source++; ch <<= 6;
            case 0: ch += *source++;
        }
        ch -= offsetsFromUTF8[extraBytesToRead];

        if (target >= targetEnd) {
            source -= (extraBytesToRead+1); /* Back up the source pointer! */
            result = targetExhausted; break;
        }
        if (ch <= UNI_MAX_LEGAL_UTF32) {
            /*
             * UTF-16 surrogate values are illegal in UTF-32, and anything
             * over Plane 17 (> 0x10FFFF) is illegal.
             */
            if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
                if (flags == strictConversion) {
                    source -= (extraBytesToRead+1); /* return to the illegal value itself */
                    result = sourceIllegal;
                    break;
                } else {
                    *target++ = UNI_REPLACEMENT_CHAR;
                }
            } else {
                *target++ = ch;
            }
        } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
            result = sourceIllegal;
            *target++ = UNI_REPLACEMENT_CHAR;
        }
    }
    *sourceStart = source;
    *targetStart = target;
    return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movl $0x0, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
cmpq -0x10(%rbp), %rax
jae 0x1d1e3
movl $0x0, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movzbl (%rax), %eax
movl %eax, %ecx
leaq 0x1f8c2(%rip), %rax     # 0x3c8a0
movsbl (%rax,%rcx), %eax
movw %ax, -0x3e(%rbp)
movq -0x30(%rbp), %rax
movzwl -0x3e(%rbp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
cmpq -0x10(%rbp), %rax
jb 0x1d006
movl $0x1, -0x28(%rbp)
jmp 0x1d1e3
movq -0x30(%rbp), %rdi
movzwl -0x3e(%rbp), %esi
addl $0x1, %esi
callq 0x1c840
cmpb $0x0, %al
jne 0x1d026
movl $0x3, -0x28(%rbp)
jmp 0x1d1e3
movzwl -0x3e(%rbp), %eax
movq %rax, -0x48(%rbp)
subq $0x5, %rax
ja 0x1d109
movq -0x48(%rbp), %rax
leaq 0x1f839(%rip), %rcx     # 0x3c87c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x30(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x30(%rbp)
movzbl (%rax), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
shll $0x6, %eax
movl %eax, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x30(%rbp)
movzbl (%rax), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
shll $0x6, %eax
movl %eax, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x30(%rbp)
movzbl (%rax), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
shll $0x6, %eax
movl %eax, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x30(%rbp)
movzbl (%rax), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
shll $0x6, %eax
movl %eax, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x30(%rbp)
movzbl (%rax), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
shll $0x6, %eax
movl %eax, -0x3c(%rbp)
movq -0x30(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x30(%rbp)
movzbl (%rax), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
movzwl -0x3e(%rbp), %eax
movl %eax, %ecx
leaq 0x1f88a(%rip), %rax     # 0x3c9a0
movl (%rax,%rcx,4), %ecx
movl -0x3c(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x3c(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x20(%rbp), %rax
jb 0x1d151
movzwl -0x3e(%rbp), %ecx
addl $0x1, %ecx
movq -0x30(%rbp), %rax
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movl $0x2, -0x28(%rbp)
jmp 0x1d1e3
cmpl $0x10ffff, -0x3c(%rbp)  # imm = 0x10FFFF
ja 0x1d1c2
cmpl $0xd800, -0x3c(%rbp)    # imm = 0xD800
jb 0x1d1ac
cmpl $0xdfff, -0x3c(%rbp)    # imm = 0xDFFF
ja 0x1d1ac
cmpl $0x0, -0x24(%rbp)
jne 0x1d195
movzwl -0x3e(%rbp), %ecx
addl $0x1, %ecx
movq -0x30(%rbp), %rax
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movl $0x3, -0x28(%rbp)
jmp 0x1d1e3
movq -0x38(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x38(%rbp)
movl $0xfffd, (%rax)         # imm = 0xFFFD
jmp 0x1d1c0
movl -0x3c(%rbp), %ecx
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x4, %rdx
movq %rdx, -0x38(%rbp)
movl %ecx, (%rax)
jmp 0x1d1de
movl $0x3, -0x28(%rbp)
movq -0x38(%rbp), %rax
movq %rax, %rcx
addq $0x4, %rcx
movq %rcx, -0x38(%rbp)
movl $0xfffd, (%rax)         # imm = 0xFFFD
jmp 0x1cfb9
movq -0x30(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, (%rax)
movq -0x38(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movl -0x28(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)