// File: lemire[P]validateutf8-experiments/benchmarks/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) {
    switch (bytes_count(gen)) {
    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:
subq $0x78, %rsp
movq %rdi, 0x38(%rsp)
movq %rdi, %rax
movq %rax, 0x28(%rsp)
movq %rdi, 0x70(%rsp)
movq %rsi, 0x68(%rsp)
movq %rdx, 0x60(%rsp)
movq 0x68(%rsp), %rax
movq %rax, 0x30(%rsp)
movb $0x0, 0x5f(%rsp)
callq 0xfb360
movq 0x38(%rsp), %rdi
movq 0x60(%rsp), %rsi
callq 0xfb370
jmp 0xfad85
jmp 0xfad87
movq 0x38(%rsp), %rdi
callq 0xf9180
cmpq 0x60(%rsp), %rax
jae 0xfb1fc
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x1388, %rdi           # imm = 0x1388
callq 0xfb470
movl %eax, 0x24(%rsp)
jmp 0xfadb6
movl 0x24(%rsp), %eax
movl %eax, %ecx
movq %rcx, 0x18(%rsp)
subl $0x3, %eax
ja 0xfb1f7
movq 0x18(%rsp), %rax
leaq 0x49ea(%rip), %rcx      # 0xff7c0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x38(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x50(%rsp)
movl %eax, 0x4c(%rsp)
callq 0xf92a0
jmp 0xfb232
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13b8, %rdi           # imm = 0x13B8
callq 0xfb4a0
movb %al, 0x17(%rsp)
jmp 0xfae16
movb 0x17(%rsp), %al
movb %al, 0x4b(%rsp)
movzbl 0x4b(%rsp), %eax
cmpl $0x0, %eax
jne 0xfae4c
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13b8, %rdi           # imm = 0x13B8
callq 0xfb4a0
movb %al, 0x16(%rsp)
jmp 0xfae42
movb 0x16(%rsp), %al
movb %al, 0x4b(%rsp)
jmp 0xfae1e
movq 0x38(%rsp), %rdi
leaq 0x4b(%rsp), %rsi
callq 0xfb4d0
jmp 0xfae5d
jmp 0xfb1f7
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13bc, %rdi           # imm = 0x13BC
callq 0xfb4a0
movb %al, 0x15(%rsp)
jmp 0xfae7c
movb 0x15(%rsp), %al
movzbl %al, %eax
orl $0xc0, %eax
movb %al, 0x4b(%rsp)
movzbl 0x4b(%rsp), %eax
cmpl $0xc2, %eax
jge 0xfaec4
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13bc, %rdi           # imm = 0x13BC
callq 0xfb4a0
movb %al, 0x14(%rsp)
jmp 0xfaeb2
movb 0x14(%rsp), %al
movzbl %al, %eax
orl $0xc0, %eax
movb %al, 0x4b(%rsp)
jmp 0xfae8c
movq 0x38(%rsp), %rdi
leaq 0x4b(%rsp), %rsi
callq 0xfb4d0
jmp 0xfaed5
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0x13(%rsp)
jmp 0xfaeef
movq 0x38(%rsp), %rdi
movb 0x13(%rsp), %al
orb $-0x80, %al
movb %al, 0x49(%rsp)
leaq 0x49(%rsp), %rsi
callq 0xfb540
jmp 0xfaf0a
jmp 0xfb1f7
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13be, %rdi           # imm = 0x13BE
callq 0xfb4a0
movb %al, 0x12(%rsp)
jmp 0xfaf29
movq 0x38(%rsp), %rdi
movb 0x12(%rsp), %al
orb $-0x20, %al
movb %al, 0x4a(%rsp)
leaq 0x4a(%rsp), %rsi
callq 0xfb4d0
jmp 0xfaf44
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0x11(%rsp)
jmp 0xfaf5e
movb 0x11(%rsp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, 0x4b(%rsp)
movzbl 0x4a(%rsp), %eax
cmpl $0xe0, %eax
jne 0xfafb6
jmp 0xfaf7c
movzbl 0x4b(%rsp), %eax
cmpl $0xa0, %eax
jge 0xfafb4
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0x10(%rsp)
jmp 0xfafa2
movb 0x10(%rsp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, 0x4b(%rsp)
jmp 0xfaf7c
jmp 0xfb000
movzbl 0x4a(%rsp), %eax
cmpl $0xed, %eax
jne 0xfaffe
jmp 0xfafc4
movzbl 0x4b(%rsp), %eax
cmpl $0x9f, %eax
jle 0xfaffc
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0xf(%rsp)
jmp 0xfafea
movb 0xf(%rsp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, 0x4b(%rsp)
jmp 0xfafc4
jmp 0xfaffe
jmp 0xfb000
movq 0x38(%rsp), %rdi
leaq 0x4b(%rsp), %rsi
callq 0xfb4d0
jmp 0xfb011
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0xe(%rsp)
jmp 0xfb02b
movq 0x38(%rsp), %rdi
movb 0xe(%rsp), %al
orb $-0x80, %al
movb %al, 0x48(%rsp)
leaq 0x48(%rsp), %rsi
callq 0xfb540
jmp 0xfb046
jmp 0xfb1f7
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13c0, %rdi           # imm = 0x13C0
callq 0xfb4a0
movb %al, 0xd(%rsp)
jmp 0xfb065
movb 0xd(%rsp), %al
movzbl %al, %eax
orl $0xf0, %eax
movb %al, 0x4a(%rsp)
movzbl 0x4a(%rsp), %eax
cmpl $0xf4, %eax
jle 0xfb0ad
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13c0, %rdi           # imm = 0x13C0
callq 0xfb4a0
movb %al, 0xc(%rsp)
jmp 0xfb09b
movb 0xc(%rsp), %al
movzbl %al, %eax
orl $0xf0, %eax
movb %al, 0x4a(%rsp)
jmp 0xfb075
movq 0x38(%rsp), %rdi
leaq 0x4a(%rsp), %rsi
callq 0xfb4d0
jmp 0xfb0be
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0xb(%rsp)
jmp 0xfb0d8
movb 0xb(%rsp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, 0x4b(%rsp)
movzbl 0x4a(%rsp), %eax
cmpl $0xf0, %eax
jne 0xfb130
jmp 0xfb0f6
movzbl 0x4b(%rsp), %eax
cmpl $0x90, %eax
jge 0xfb12e
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0xa(%rsp)
jmp 0xfb11c
movb 0xa(%rsp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, 0x4b(%rsp)
jmp 0xfb0f6
jmp 0xfb17a
movzbl 0x4a(%rsp), %eax
cmpl $0xf4, %eax
jne 0xfb178
jmp 0xfb13e
movzbl 0x4b(%rsp), %eax
cmpl $0x8f, %eax
jle 0xfb176
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0x9(%rsp)
jmp 0xfb164
movb 0x9(%rsp), %al
movzbl %al, %eax
orl $0x80, %eax
movb %al, 0x4b(%rsp)
jmp 0xfb13e
jmp 0xfb178
jmp 0xfb17a
movq 0x38(%rsp), %rdi
leaq 0x4b(%rsp), %rsi
callq 0xfb4d0
jmp 0xfb18b
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0x8(%rsp)
jmp 0xfb1a5
movq 0x38(%rsp), %rdi
movb 0x8(%rsp), %al
orb $-0x80, %al
movb %al, 0x47(%rsp)
leaq 0x47(%rsp), %rsi
callq 0xfb540
jmp 0xfb1c0
movq 0x30(%rsp), %rsi
movq %rsi, %rdi
addq $0x13ba, %rdi           # imm = 0x13BA
callq 0xfb4a0
movb %al, 0x7(%rsp)
jmp 0xfb1da
movq 0x38(%rsp), %rdi
movb 0x7(%rsp), %al
orb $-0x80, %al
movb %al, 0x46(%rsp)
leaq 0x46(%rsp), %rsi
callq 0xfb540
jmp 0xfb1f5
jmp 0xfb1f7
jmp 0xfad87
movq 0x38(%rsp), %rdi
movb $0x0, 0x45(%rsp)
leaq 0x45(%rsp), %rsi
callq 0xfb540
jmp 0xfb212
movb $0x1, 0x5f(%rsp)
testb $0x1, 0x5f(%rsp)
jne 0xfb228
movq 0x38(%rsp), %rdi
callq 0xf92a0
movq 0x28(%rsp), %rax
addq $0x78, %rsp
retq
movq 0x50(%rsp), %rdi
callq 0x2260
nopl (%rax)