// File: Fohlen[P]cubescript-standalone/stream.cpp
// Function: decodeutf8(unsigned char*, unsigned long, unsigned char const*, unsigned long, unsigned long*)
size_t decodeutf8(uchar *dstbuf, size_t dstlen, const uchar *srcbuf, size_t srclen, size_t *carry)
{
    uchar *dst = dstbuf, *dstend = &dstbuf[dstlen];
    const uchar *src = srcbuf, *srcend = &srcbuf[srclen];
    if(dstbuf == srcbuf)
    {
        int len = min(dstlen, srclen);
        for(const uchar *end4 = &srcbuf[len&~3]; src < end4; src += 4) if(*(const int *)src & 0x80808080) goto decode;
        for(const uchar *end = &srcbuf[len]; src < end; src++) if(*src & 0x80) goto decode;
        if(carry) *carry += len;
        return len;
    }

decode:
    dst += src - srcbuf;
    while(src < srcend && dst < dstend)
    {
        int c = *src++;
        if(c < 0x80) *dst++ = c;
        else if(c >= 0xC0)
        {
            int uni;
            if(c >= 0xE0)
            {
                if(c >= 0xF0)
                {
                    if(c >= 0xF8)
                    {
                        if(c >= 0xFC)
                        {
                            if(c >= 0xFE) continue;
                            uni = c&1; if(srcend - src < 5) break;
                            c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
                        }
                        else { uni = c&3; if(srcend - src < 4) break; }
                        c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
                    }
                    else { uni = c&7; if(srcend - src < 3) break; }
                    c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
                }
                else { uni = c&0xF; if(srcend - src < 2) break; }
                c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
            }
            else { uni = c&0x1F; if(srcend - src < 1) break; }
            c = *src; if((c&0xC0) != 0x80) continue; src++; uni = (uni<<6) | (c&0x3F);
            c = uni2cube(uni);
            if(!c) continue;
            *dst++ = c;
        }
    }
    if(carry) *carry += src - srcbuf;
    return dst - dstbuf;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rax
addq -0x18(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x20(%rbp), %rax
addq -0x28(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rax
cmpq -0x20(%rbp), %rax
jne 0x17b33
movq -0x18(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x17e40
movl %eax, -0x54(%rbp)
movq -0x20(%rbp), %rax
movl -0x54(%rbp), %ecx
andl $-0x4, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x48(%rbp), %rax
cmpq -0x60(%rbp), %rax
jae 0x17ad5
movq -0x48(%rbp), %rax
movl (%rax), %eax
andl $0x80808080, %eax       # imm = 0x80808080
cmpl $0x0, %eax
je 0x17ac5
jmp 0x17b35
jmp 0x17ac7
movq -0x48(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x48(%rbp)
jmp 0x17aa9
movq -0x20(%rbp), %rax
movslq -0x54(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x68(%rbp)
movq -0x48(%rbp), %rax
cmpq -0x68(%rbp), %rax
jae 0x17b11
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x17b01
jmp 0x17b35
jmp 0x17b03
movq -0x48(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x48(%rbp)
jmp 0x17ae4
cmpq $0x0, -0x30(%rbp)
je 0x17b26
movslq -0x54(%rbp), %rcx
movq -0x30(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
movslq -0x54(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x17e25
jmp 0x17b35
movq -0x48(%rbp), %rax
movq -0x20(%rbp), %rcx
subq %rcx, %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x48(%rbp), %rcx
xorl %eax, %eax
cmpq -0x50(%rbp), %rcx
movb %al, -0x71(%rbp)
jae 0x17b65
movq -0x38(%rbp), %rax
cmpq -0x40(%rbp), %rax
setb %al
movb %al, -0x71(%rbp)
movb -0x71(%rbp), %al
testb $0x1, %al
jne 0x17b71
jmp 0x17dfa
movq -0x48(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x48(%rbp)
movzbl (%rax), %eax
movl %eax, -0x6c(%rbp)
cmpl $0x80, -0x6c(%rbp)
jge 0x17baa
movl -0x6c(%rbp), %eax
movb %al, %cl
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x38(%rbp)
movb %cl, (%rax)
jmp 0x17df5
cmpl $0xc0, -0x6c(%rbp)
jl 0x17df3
cmpl $0xe0, -0x6c(%rbp)
jl 0x17d6b
cmpl $0xf0, -0x6c(%rbp)
jl 0x17d0d
cmpl $0xf8, -0x6c(%rbp)
jl 0x17caf
cmpl $0xfc, -0x6c(%rbp)
jl 0x17c51
cmpl $0xfe, -0x6c(%rbp)
jl 0x17bf5
jmp 0x17b48
movl -0x6c(%rbp), %eax
andl $0x1, %eax
movl %eax, -0x70(%rbp)
movq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
subq %rcx, %rax
cmpq $0x5, %rax
jge 0x17c14
jmp 0x17dfa
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
andl $0xc0, %eax
cmpl $0x80, %eax
je 0x17c32
jmp 0x17b48
movq -0x48(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x48(%rbp)
movl -0x70(%rbp), %eax
shll $0x6, %eax
movl -0x6c(%rbp), %ecx
andl $0x3f, %ecx
orl %ecx, %eax
movl %eax, -0x70(%rbp)
jmp 0x17c72
movl -0x6c(%rbp), %eax
andl $0x3, %eax
movl %eax, -0x70(%rbp)
movq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
subq %rcx, %rax
cmpq $0x4, %rax
jge 0x17c70
jmp 0x17dfa
jmp 0x17c72
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
andl $0xc0, %eax
cmpl $0x80, %eax
je 0x17c90
jmp 0x17b48
movq -0x48(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x48(%rbp)
movl -0x70(%rbp), %eax
shll $0x6, %eax
movl -0x6c(%rbp), %ecx
andl $0x3f, %ecx
orl %ecx, %eax
movl %eax, -0x70(%rbp)
jmp 0x17cd0
movl -0x6c(%rbp), %eax
andl $0x7, %eax
movl %eax, -0x70(%rbp)
movq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
subq %rcx, %rax
cmpq $0x3, %rax
jge 0x17cce
jmp 0x17dfa
jmp 0x17cd0
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
andl $0xc0, %eax
cmpl $0x80, %eax
je 0x17cee
jmp 0x17b48
movq -0x48(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x48(%rbp)
movl -0x70(%rbp), %eax
shll $0x6, %eax
movl -0x6c(%rbp), %ecx
andl $0x3f, %ecx
orl %ecx, %eax
movl %eax, -0x70(%rbp)
jmp 0x17d2e
movl -0x6c(%rbp), %eax
andl $0xf, %eax
movl %eax, -0x70(%rbp)
movq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
subq %rcx, %rax
cmpq $0x2, %rax
jge 0x17d2c
jmp 0x17dfa
jmp 0x17d2e
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
andl $0xc0, %eax
cmpl $0x80, %eax
je 0x17d4c
jmp 0x17b48
movq -0x48(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x48(%rbp)
movl -0x70(%rbp), %eax
shll $0x6, %eax
movl -0x6c(%rbp), %ecx
andl $0x3f, %ecx
orl %ecx, %eax
movl %eax, -0x70(%rbp)
jmp 0x17d89
movl -0x6c(%rbp), %eax
andl $0x1f, %eax
movl %eax, -0x70(%rbp)
movq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
subq %rcx, %rax
cmpq $0x1, %rax
jge 0x17d87
jmp 0x17dfa
jmp 0x17d89
movq -0x48(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
andl $0xc0, %eax
cmpl $0x80, %eax
je 0x17da7
jmp 0x17b48
movq -0x48(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x48(%rbp)
movl -0x70(%rbp), %eax
shll $0x6, %eax
movl -0x6c(%rbp), %ecx
andl $0x3f, %ecx
orl %ecx, %eax
movl %eax, -0x70(%rbp)
movl -0x70(%rbp), %edi
callq 0x17e70
movzbl %al, %eax
movl %eax, -0x6c(%rbp)
cmpl $0x0, -0x6c(%rbp)
jne 0x17ddd
jmp 0x17b48
movl -0x6c(%rbp), %eax
movb %al, %cl
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x38(%rbp)
movb %cl, (%rax)
jmp 0x17df5
jmp 0x17b48
cmpq $0x0, -0x30(%rbp)
je 0x17e16
movq -0x48(%rbp), %rcx
movq -0x20(%rbp), %rax
subq %rax, %rcx
movq -0x30(%rbp), %rax
addq (%rax), %rcx
movq %rcx, (%rax)
movq -0x38(%rbp), %rax
movq -0x10(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x80, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)