// File: WojciechMula[P]utf16utf8/src/random_utf8.cpp
// Function: RandomUTF8::generate(unsigned long)
std::vector<uint8_t> RandomUTF8::generate(size_t output_bytes)
{
    std::vector<uint8_t> result;
    result.reserve(output_bytes);
    uint8_t candidate, head;
    while (result.size() < output_bytes) {
        auto b = bytes_count(gen);
        switch (b) {
            case 0: // 1 byte
                candidate = val_7bit(gen);
                while(candidate == 0) {// though strictly speaking, a stream of nulls is UTF8, it tends to break some code
                    candidate = val_7bit(gen);
                }
                result.push_back(candidate);
                break;
            case 1: // 2 bytes
                candidate = 0xc0 | val_5bit(gen);
                while(candidate < 0xC2) {
                    candidate = 0xc0 | val_5bit(gen);
                }
                result.push_back(candidate);
                result.push_back(0x80 | val_6bit(gen));
                break;
            case 2: // 3 bytes
                head = 0xe0 | val_4bit(gen);
                result.push_back(head);
                candidate = 0x80 | val_6bit(gen);
                if(head == 0xE0) {
                    while(candidate < 0xA0) {
                        candidate = 0x80 | val_6bit(gen);
                    }
                } else if (head == 0xED) {
                    while(candidate > 0x9F) {
                        candidate = 0x80 | val_6bit(gen);
                    }
                }
                result.push_back(candidate);
                result.push_back(0x80 | val_6bit(gen));
                break;
            case 3: // 4 bytes
                head = 0xf0 | val_3bit(gen);
                while(head > 0xF4) {
                    head = 0xf0 | val_3bit(gen);
                }
                result.push_back(head);
                candidate = 0x80 | val_6bit(gen);
                if(head == 0xF0) {
                    while(candidate < 0x90) {
                        candidate = 0x80 | val_6bit(gen);
                    }
                } else if (head == 0xF4) {
                    while(candidate > 0x8F) {
                        candidate = 0x80 | val_6bit(gen);
                    }
                }
                result.push_back(candidate);
                result.push_back(0x80 | val_6bit(gen));
                result.push_back(0x80 | val_6bit(gen));
                break;
        }
    }
    result.push_back(0); // EOS for scalar code

    return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x48(%rbp)
movq %rdi, %rax
movq %rax, -0x58(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x50(%rbp)
movb $0x0, -0x19(%rbp)
callq 0xb440
movq -0x48(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xb460
jmp 0xaf62
jmp 0xaf64
movq -0x48(%rbp), %rdi
callq 0xb540
cmpq -0x18(%rbp), %rax
jae 0xb371
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x1388, %rdi           # imm = 0x1388
callq 0x7810
movl %eax, -0x5c(%rbp)
jmp 0xaf8f
movl -0x5c(%rbp), %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
movq %rax, -0x68(%rbp)
subq $0x3, %rax
ja 0xb36c
movq -0x68(%rbp), %rax
leaq 0xe2d7(%rip), %rcx      # 0x19288
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x48(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0xb630
jmp 0xb3a4
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13b8, %rdi           # imm = 0x13B8
callq 0xb560
movb %al, -0x69(%rbp)
jmp 0xafec
movb -0x69(%rbp), %al
movb %al, -0x2d(%rbp)
movzbl -0x2d(%rbp), %eax
cmpl $0x0, %eax
jne 0xb01b
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13b8, %rdi           # imm = 0x13B8
callq 0xb560
movb %al, -0x6a(%rbp)
jmp 0xb013
movb -0x6a(%rbp), %al
movb %al, -0x2d(%rbp)
jmp 0xaff2
movq -0x48(%rbp), %rdi
leaq -0x2d(%rbp), %rsi
callq 0xb590
jmp 0xb02a
jmp 0xb36c
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13bc, %rdi           # imm = 0x13BC
callq 0xb560
movb %al, -0x6b(%rbp)
jmp 0xb047
movb -0x6b(%rbp), %al
movzbl %al, %eax
orl $0xc0, %eax
movb %al, -0x2d(%rbp)
movzbl -0x2d(%rbp), %eax
cmpl $0xc2, %eax
jge 0xb088
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13bc, %rdi           # imm = 0x13BC
callq 0xb560
movb %al, -0x6c(%rbp)
jmp 0xb078
movb -0x6c(%rbp), %al
movzbl %al, %eax
orl $0xc0, %eax
movb %al, -0x2d(%rbp)
jmp 0xb055
movq -0x48(%rbp), %rdi
leaq -0x2d(%rbp), %rsi
callq 0xb590
jmp 0xb097
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x6d(%rbp)
jmp 0xb0af
movq -0x48(%rbp), %rdi
movb -0x6d(%rbp), %al
orb $-0x80, %al
movb %al, -0x35(%rbp)
leaq -0x35(%rbp), %rsi
callq 0xb600
jmp 0xb0c6
jmp 0xb36c
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13be, %rdi           # imm = 0x13BE
callq 0xb560
movb %al, -0x6e(%rbp)
jmp 0xb0e3
movq -0x48(%rbp), %rdi
movb -0x6e(%rbp), %al
orb $-0x20, %al
movb %al, -0x2e(%rbp)
leaq -0x2e(%rbp), %rsi
callq 0xb590
jmp 0xb0fa
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x6f(%rbp)
jmp 0xb112
movb -0x6f(%rbp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, -0x2d(%rbp)
movzbl -0x2e(%rbp), %eax
cmpl $0xe0, %eax
jne 0xb162
jmp 0xb12d
movzbl -0x2d(%rbp), %eax
cmpl $0xa0, %eax
jge 0xb160
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x70(%rbp)
jmp 0xb150
movb -0x70(%rbp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, -0x2d(%rbp)
jmp 0xb12d
jmp 0xb1a6
movzbl -0x2e(%rbp), %eax
cmpl $0xed, %eax
jne 0xb1a4
jmp 0xb16f
movzbl -0x2d(%rbp), %eax
cmpl $0x9f, %eax
jle 0xb1a2
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x71(%rbp)
jmp 0xb192
movb -0x71(%rbp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, -0x2d(%rbp)
jmp 0xb16f
jmp 0xb1a4
jmp 0xb1a6
movq -0x48(%rbp), %rdi
leaq -0x2d(%rbp), %rsi
callq 0xb590
jmp 0xb1b5
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x72(%rbp)
jmp 0xb1cd
movq -0x48(%rbp), %rdi
movb -0x72(%rbp), %al
orb $-0x80, %al
movb %al, -0x36(%rbp)
leaq -0x36(%rbp), %rsi
callq 0xb600
jmp 0xb1e4
jmp 0xb36c
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13c0, %rdi           # imm = 0x13C0
callq 0xb560
movb %al, -0x73(%rbp)
jmp 0xb201
movb -0x73(%rbp), %al
movzbl %al, %eax
orl $0xf0, %eax
movb %al, -0x2e(%rbp)
movzbl -0x2e(%rbp), %eax
cmpl $0xf4, %eax
jle 0xb242
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13c0, %rdi           # imm = 0x13C0
callq 0xb560
movb %al, -0x74(%rbp)
jmp 0xb232
movb -0x74(%rbp), %al
movzbl %al, %eax
orl $0xf0, %eax
movb %al, -0x2e(%rbp)
jmp 0xb20f
movq -0x48(%rbp), %rdi
leaq -0x2e(%rbp), %rsi
callq 0xb590
jmp 0xb251
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x75(%rbp)
jmp 0xb269
movb -0x75(%rbp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, -0x2d(%rbp)
movzbl -0x2e(%rbp), %eax
cmpl $0xf0, %eax
jne 0xb2b9
jmp 0xb284
movzbl -0x2d(%rbp), %eax
cmpl $0x90, %eax
jge 0xb2b7
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x76(%rbp)
jmp 0xb2a7
movb -0x76(%rbp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, -0x2d(%rbp)
jmp 0xb284
jmp 0xb2fd
movzbl -0x2e(%rbp), %eax
cmpl $0xf4, %eax
jne 0xb2fb
jmp 0xb2c6
movzbl -0x2d(%rbp), %eax
cmpl $0x8f, %eax
jle 0xb2f9
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x77(%rbp)
jmp 0xb2e9
movb -0x77(%rbp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, -0x2d(%rbp)
jmp 0xb2c6
jmp 0xb2fb
jmp 0xb2fd
movq -0x48(%rbp), %rdi
leaq -0x2d(%rbp), %rsi
callq 0xb590
jmp 0xb30c
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x78(%rbp)
jmp 0xb324
movq -0x48(%rbp), %rdi
movb -0x78(%rbp), %al
orb $-0x80, %al
movb %al, -0x37(%rbp)
leaq -0x37(%rbp), %rsi
callq 0xb600
jmp 0xb33b
movq -0x50(%rbp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xb560
movb %al, -0x79(%rbp)
jmp 0xb353
movq -0x48(%rbp), %rdi
movb -0x79(%rbp), %al
orb $-0x80, %al
movb %al, -0x38(%rbp)
leaq -0x38(%rbp), %rsi
callq 0xb600
jmp 0xb36a
jmp 0xb36c
jmp 0xaf64
movq -0x48(%rbp), %rdi
movb $0x0, -0x39(%rbp)
leaq -0x39(%rbp), %rsi
callq 0xb600
jmp 0xb384
movb $0x1, -0x19(%rbp)
testb $0x1, -0x19(%rbp)
jne 0xb397
movq -0x48(%rbp), %rdi
callq 0xb630
movq -0x58(%rbp), %rax
addq $0x80, %rsp
popq %rbp
retq
movq -0x28(%rbp), %rdi
callq 0x22e0
nopl (%rax)