// File: WojciechMula[P]utf16utf8/tests/unittest.cpp
// Function: validate_from_utf8(std::vector<unsigned char, std::allocator<unsigned char>>&)
bool validate_from_utf8(std::vector<uint8_t>& input) {
    size_t actual_length = input.size();
    for(size_t i = 0; i < input.size(); i++) {
        if(input[i] ==0) {
            actual_length = i;
            break;
        }
    }
    // reference
    std::vector<uint16_t> tmp;
    tmp.resize(4 * input.size());
    size_t len = strlen_utf8_to_utf16(input.data());
    utf8_to_utf16(input.data(), (uint16_t*)tmp.data());
    const std::vector<uint16_t> reference(tmp.data(), tmp.data() + len);

    // SSE
    tmp.clear();
    tmp.resize(8 * input.size());
    const size_t output_size = sse_convert_valid_utf8_to_utf16_lemire(input.data(), actual_length, (uint16_t*)tmp.data());
    const std::vector<uint16_t> sse(tmp.data(), tmp.data() + output_size);

    if( sse != reference ) {
        printf("input:");display<uint8_t>(input);
        printf("ref  :");display<uint16_t>(reference);
        printf("sse  :");display<uint16_t>(sse);
        printf("BUG\n");
        return false;
    }
    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x120, %rsp            # imm = 0x120
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
callq 0x62c0
movq %rax, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0x10(%rbp), %rdi
callq 0x62c0
movq %rax, %rcx
movq -0xa0(%rbp), %rax
cmpq %rcx, %rax
jae 0xd0f6
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xe2e0
movzbl (%rax), %eax
cmpl $0x0, %eax
jne 0xd0e6
movq -0x20(%rbp), %rax
movq %rax, -0x18(%rbp)
jmp 0xd0f6
jmp 0xd0e8
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0xd0a4
leaq -0x38(%rbp), %rdi
movq %rdi, -0xa8(%rbp)
callq 0x2920
movq -0x10(%rbp), %rdi
callq 0x62c0
movq -0xa8(%rbp), %rdi
movq %rax, %rsi
shlq $0x2, %rsi
callq 0xe230
jmp 0xd124
movq -0x10(%rbp), %rdi
callq 0xe300
movq %rax, %rdi
callq 0xd430
movq %rax, -0xb0(%rbp)
jmp 0xd13e
movq -0xb0(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rdi
callq 0xe300
movq %rax, -0xb8(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xe320
movq -0xb8(%rbp), %rdi
movq %rax, %rsi
callq 0xd4a0
jmp 0xd173
leaq -0x38(%rbp), %rdi
movq %rdi, -0xd8(%rbp)
callq 0xe320
movq -0xd8(%rbp), %rdi
movq %rax, -0xd0(%rbp)
callq 0xe320
movq -0x50(%rbp), %rcx
leaq (%rax,%rcx,2), %rax
movq %rax, -0xc8(%rbp)
leaq -0x69(%rbp), %rdi
movq %rdi, -0xc0(%rbp)
callq 0x2e90
movq -0xd0(%rbp), %rsi
movq -0xc8(%rbp), %rdx
movq -0xc0(%rbp), %rcx
leaq -0x68(%rbp), %rdi
callq 0xe340
jmp 0xd1d5
leaq -0x69(%rbp), %rdi
callq 0x5180
leaq -0x38(%rbp), %rdi
movq %rdi, -0xe0(%rbp)
callq 0xe3c0
movq -0x10(%rbp), %rdi
callq 0x62c0
movq -0xe0(%rbp), %rdi
movq %rax, %rsi
shlq $0x3, %rsi
callq 0xe230
jmp 0xd20c
movq -0x10(%rbp), %rdi
callq 0xe300
movq %rax, -0xf8(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0xf0(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xe320
movq -0xf8(%rbp), %rdi
movq -0xf0(%rbp), %rsi
movq %rax, %rdx
callq 0xa500
movq %rax, -0xe8(%rbp)
jmp 0xd24f
movq -0xe8(%rbp), %rax
movq %rax, -0x78(%rbp)
leaq -0x38(%rbp), %rdi
movq %rdi, -0x118(%rbp)
callq 0xe320
movq -0x118(%rbp), %rdi
movq %rax, -0x110(%rbp)
callq 0xe320
movq -0x78(%rbp), %rcx
leaq (%rax,%rcx,2), %rax
movq %rax, -0x108(%rbp)
leaq -0x91(%rbp), %rdi
movq %rdi, -0x100(%rbp)
callq 0x2e90
movq -0x110(%rbp), %rsi
movq -0x108(%rbp), %rdx
movq -0x100(%rbp), %rcx
leaq -0x90(%rbp), %rdi
callq 0xe340
jmp 0xd2c2
leaq -0x91(%rbp), %rdi
callq 0x5180
leaq -0x90(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0xe3e0
movb %al, -0x119(%rbp)
jmp 0xd2e6
movb -0x119(%rbp), %al
testb $0x1, %al
jne 0xd2f5
jmp 0xd3d6
leaq 0x8092(%rip), %rdi      # 0x1538e
xorl %eax, %eax
callq 0x2030
jmp 0xd305
movq -0x10(%rbp), %rdi
callq 0xe410
jmp 0xd310
leaq 0x807e(%rip), %rdi      # 0x15395
xorl %eax, %eax
callq 0x2030
jmp 0xd320
leaq -0x68(%rbp), %rdi
callq 0xe080
jmp 0xd32b
leaq 0x806a(%rip), %rdi      # 0x1539c
xorl %eax, %eax
callq 0x2030
jmp 0xd33b
leaq -0x90(%rbp), %rdi
callq 0xe080
jmp 0xd349
leaq 0x8053(%rip), %rdi      # 0x153a3
xorl %eax, %eax
callq 0x2030
jmp 0xd359
movb $0x0, -0x1(%rbp)
movl $0x1, -0x98(%rbp)
jmp 0xd3e4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0xd419
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x69(%rbp), %rdi
callq 0x5180
jmp 0xd419
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0xd410
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x91(%rbp), %rdi
callq 0x5180
jmp 0xd410
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x2af0
jmp 0xd410
movb $0x1, -0x1(%rbp)
movl $0x1, -0x98(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x2af0
leaq -0x68(%rbp), %rdi
callq 0x2af0
leaq -0x38(%rbp), %rdi
callq 0x2af0
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x120, %rsp            # imm = 0x120
popq %rbp
retq
leaq -0x68(%rbp), %rdi
callq 0x2af0
leaq -0x38(%rbp), %rdi
callq 0x2af0
movq -0x40(%rbp), %rdi
callq 0x2280
nopl (%rax,%rax)