// File: Eba-M[P]E3DC-Control/cJSON.c
// Function: utf16_literal_to_utf8(unsigned char const*, unsigned char const*, unsigned char**)
static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
{
    long unsigned int codepoint = 0;
    unsigned int first_code = 0;
    const unsigned char *first_sequence = input_pointer;
    unsigned char utf8_length = 0;
    unsigned char utf8_position = 0;
    unsigned char sequence_length = 0;
    unsigned char first_byte_mark = 0;

    if ((input_end - first_sequence) < 6)
    {
        /* input ends unexpectedly */
        goto fail;
    }

    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);

    /* check that the code is valid */
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
    {
        goto fail;
    }

    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
    {
        const unsigned char *second_sequence = first_sequence + 6;
        unsigned int second_code = 0;
        sequence_length = 12; /* \uXXXX\uXXXX */

        if ((input_end - second_sequence) < 6)
        {
            /* input ends unexpectedly */
            goto fail;
        }

        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
        {
            /* missing second half of the surrogate pair */
            goto fail;
        }

        /* get the second utf16 sequence */
        second_code = parse_hex4(second_sequence + 2);
        /* check that the code is valid */
        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
        {
            /* invalid second half of the surrogate pair */
            goto fail;
        }


        /* calculate the unicode codepoint from the surrogate pair */
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
    }
    else
    {
        sequence_length = 6; /* \uXXXX */
        codepoint = first_code;
    }

    /* encode as UTF-8
     * takes at maximum 4 bytes to encode:
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
    if (codepoint < 0x80)
    {
        /* normal ascii, encoding 0xxxxxxx */
        utf8_length = 1;
    }
    else if (codepoint < 0x800)
    {
        /* two bytes, encoding 110xxxxx 10xxxxxx */
        utf8_length = 2;
        first_byte_mark = 0xC0; /* 11000000 */
    }
    else if (codepoint < 0x10000)
    {
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
        utf8_length = 3;
        first_byte_mark = 0xE0; /* 11100000 */
    }
    else if (codepoint <= 0x10FFFF)
    {
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
        utf8_length = 4;
        first_byte_mark = 0xF0; /* 11110000 */
    }
    else
    {
        /* invalid unicode codepoint */
        goto fail;
    }

    /* encode as utf8 */
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
    {
        /* 10xxxxxx */
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
        codepoint >>= 6;
    }
    /* encode first byte */
    if (utf8_length > 1)
    {
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
    }
    else
    {
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
    }

    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x48(%rsp)
movq %rsi, 0x40(%rsp)
movq %rdx, 0x38(%rsp)
movq $0x0, 0x30(%rsp)
movl $0x0, 0x2c(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x20(%rsp)
movb $0x0, 0x1f(%rsp)
movb $0x0, 0x1e(%rsp)
movb $0x0, 0x1d(%rsp)
movb $0x0, 0x1c(%rsp)
movq 0x40(%rsp), %rax
movq 0x20(%rsp), %rcx
subq %rcx, %rax
cmpq $0x6, %rax
jge 0x5d3da
jmp 0x5d5e8
movq 0x20(%rsp), %rdi
addq $0x2, %rdi
callq 0x5d600
movl %eax, 0x2c(%rsp)
cmpl $0xdc00, 0x2c(%rsp)     # imm = 0xDC00
jb 0x5d405
cmpl $0xdfff, 0x2c(%rsp)     # imm = 0xDFFF
ja 0x5d405
jmp 0x5d5e8
cmpl $0xd800, 0x2c(%rsp)     # imm = 0xD800
jb 0x5d4c5
cmpl $0xdbff, 0x2c(%rsp)     # imm = 0xDBFF
ja 0x5d4c5
movq 0x20(%rsp), %rax
addq $0x6, %rax
movq %rax, 0x10(%rsp)
movl $0x0, 0xc(%rsp)
movb $0xc, 0x1d(%rsp)
movq 0x40(%rsp), %rax
movq 0x10(%rsp), %rcx
subq %rcx, %rax
cmpq $0x6, %rax
jge 0x5d454
jmp 0x5d5e8
movq 0x10(%rsp), %rax
movzbl (%rax), %eax
cmpl $0x5c, %eax
jne 0x5d46f
movq 0x10(%rsp), %rax
movzbl 0x1(%rax), %eax
cmpl $0x75, %eax
je 0x5d474
jmp 0x5d5e8
movq 0x10(%rsp), %rdi
addq $0x2, %rdi
callq 0x5d600
movl %eax, 0xc(%rsp)
cmpl $0xdc00, 0xc(%rsp)      # imm = 0xDC00
jb 0x5d49a
cmpl $0xdfff, 0xc(%rsp)      # imm = 0xDFFF
jbe 0x5d49f
jmp 0x5d5e8
movl 0x2c(%rsp), %eax
andl $0x3ff, %eax            # imm = 0x3FF
shll $0xa, %eax
movl 0xc(%rsp), %ecx
andl $0x3ff, %ecx            # imm = 0x3FF
orl %ecx, %eax
addl $0x10000, %eax          # imm = 0x10000
movl %eax, %eax
movq %rax, 0x30(%rsp)
jmp 0x5d4d3
movb $0x6, 0x1d(%rsp)
movl 0x2c(%rsp), %eax
movq %rax, 0x30(%rsp)
cmpq $0x80, 0x30(%rsp)
jae 0x5d4e5
movb $0x1, 0x1f(%rsp)
jmp 0x5d535
cmpq $0x800, 0x30(%rsp)      # imm = 0x800
jae 0x5d4fc
movb $0x2, 0x1f(%rsp)
movb $-0x40, 0x1c(%rsp)
jmp 0x5d533
cmpq $0x10000, 0x30(%rsp)    # imm = 0x10000
jae 0x5d513
movb $0x3, 0x1f(%rsp)
movb $-0x20, 0x1c(%rsp)
jmp 0x5d531
cmpq $0x10ffff, 0x30(%rsp)   # imm = 0x10FFFF
ja 0x5d52a
movb $0x4, 0x1f(%rsp)
movb $-0x10, 0x1c(%rsp)
jmp 0x5d52f
jmp 0x5d5e8
jmp 0x5d531
jmp 0x5d533
jmp 0x5d535
movzbl 0x1f(%rsp), %eax
subl $0x1, %eax
movb %al, 0x1e(%rsp)
movzbl 0x1e(%rsp), %eax
cmpl $0x0, %eax
jle 0x5d588
movq 0x30(%rsp), %rax
orq $0x80, %rax
andq $0xbf, %rax
movb %al, %dl
movq 0x38(%rsp), %rax
movq (%rax), %rax
movzbl 0x1e(%rsp), %ecx
movb %dl, (%rax,%rcx)
movq 0x30(%rsp), %rax
shrq $0x6, %rax
movq %rax, 0x30(%rsp)
movb 0x1e(%rsp), %al
addb $-0x1, %al
movb %al, 0x1e(%rsp)
jmp 0x5d541
movzbl 0x1f(%rsp), %eax
cmpl $0x1, %eax
jle 0x5d5b3
movq 0x30(%rsp), %rax
movzbl 0x1c(%rsp), %ecx
orq %rcx, %rax
andq $0xff, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movq (%rax), %rax
movb %cl, (%rax)
jmp 0x5d5c8
movq 0x30(%rsp), %rax
andq $0x7f, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movq (%rax), %rax
movb %cl, (%rax)
movzbl 0x1f(%rsp), %edx
movq 0x38(%rsp), %rax
movq (%rax), %rcx
movslq %edx, %rdx
addq %rdx, %rcx
movq %rcx, (%rax)
movb 0x1d(%rsp), %al
movb %al, 0x57(%rsp)
jmp 0x5d5ed
movb $0x0, 0x57(%rsp)
movb 0x57(%rsp), %al
addq $0x58, %rsp
retq
nopw %cs:(%rax,%rax)