// File: /workspace/github_c_makefile_star2_O0/canboat[P]canboat/analyzer/../common/utf.c
// Function: decode_utf8
static codepoint_t decode_utf8(utf8_t const *utf8, size_t len, size_t *index)
{
  utf8_t leading = utf8[*index];

  // The number of bytes that are used to encode the codepoint
  int encoding_len = 0;
  // The pattern of the leading byte
  utf8_pattern leading_pattern;
  // If the leading byte matches the current leading pattern
  bool matches = false;

  do
  {
    encoding_len++;
    leading_pattern = utf8_leading_bytes[encoding_len - 1];

    matches = (leading & leading_pattern.mask) == leading_pattern.value;

  } while (!matches && encoding_len < UTF8_LEADING_BYTES_LEN);

  // Leading byte doesn't match any known pattern, consider it invalid
  if (!matches)
    return INVALID_CODEPOINT;

  codepoint_t codepoint = leading & ~leading_pattern.mask;

  for (int i = 0; i < encoding_len - 1; i++)
  {
    // String ended before all continuation bytes were found
    // Invalid encoding
    if (*index + 1 >= len)
      return INVALID_CODEPOINT;

    utf8_t continuation = utf8[*index + 1];

    // Number of continuation bytes not the same as advertised on the leading byte
    // Invalid encoding
    if ((continuation & UTF8_CONTINUATION_MASK) != UTF8_CONTINUATION_VALUE)
      return INVALID_CODEPOINT;

    codepoint <<= UTF8_CONTINUATION_CODEPOINT_BITS;
    codepoint |= continuation & ~UTF8_CONTINUATION_MASK;

    (*index)++;
  }

  int proper_len = calculate_utf8_len(codepoint);

  // Overlong encoding: too many bytes were used to encode a short codepoint
  // Invalid encoding
  if (proper_len != encoding_len)
    return INVALID_CODEPOINT;

  // Surrogates are invalid Unicode codepoints, and should only be used in UTF-16
  // Invalid encoding
  if (codepoint < BMP_END && (codepoint & GENERIC_SURROGATE_MASK) == GENERIC_SURROGATE_VALUE)
    return INVALID_CODEPOINT;

  // UTF-8 can encode codepoints larger than the Unicode standard allows
  // Invalid encoding
  if (codepoint > UNICODE_MAX)
    return INVALID_CODEPOINT;

  return codepoint;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq -0x20(%rbp), %rcx
movq (%rcx), %rcx
movb (%rax,%rcx), %al
movb %al, -0x21(%rbp)
movl $0x0, -0x28(%rbp)
movb $0x0, -0x2b(%rbp)
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
movl -0x28(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rcx
leaq 0x1306b(%rip), %rax     # 0x36194
movw (%rax,%rcx,2), %ax
movw %ax, -0x2a(%rbp)
movzbl -0x21(%rbp), %eax
movzbl -0x2a(%rbp), %ecx
andl %ecx, %eax
movzbl -0x29(%rbp), %ecx
cmpl %ecx, %eax
sete %al
andb $0x1, %al
movb %al, -0x2b(%rbp)
xorl %eax, %eax
testb $0x1, -0x2b(%rbp)
movb %al, -0x3d(%rbp)
jne 0x2315e
cmpl $0x4, -0x28(%rbp)
setl %al
movb %al, -0x3d(%rbp)
movb -0x3d(%rbp), %al
testb $0x1, %al
jne 0x23110
testb $0x1, -0x2b(%rbp)
jne 0x23177
movl $0xfffd, -0x4(%rbp)     # imm = 0xFFFD
jmp 0x2326f
movzbl -0x21(%rbp), %eax
movzbl -0x2a(%rbp), %ecx
xorl $-0x1, %ecx
andl %ecx, %eax
movl %eax, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
movl -0x28(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x2321a
movq -0x20(%rbp), %rax
movq (%rax), %rax
addq $0x1, %rax
cmpq -0x18(%rbp), %rax
jb 0x231b8
movl $0xfffd, -0x4(%rbp)     # imm = 0xFFFD
jmp 0x2326f
movq -0x10(%rbp), %rax
movq -0x20(%rbp), %rcx
movq (%rcx), %rcx
movb 0x1(%rax,%rcx), %al
movb %al, -0x35(%rbp)
movzbl -0x35(%rbp), %eax
andl $0xc0, %eax
cmpl $0x80, %eax
je 0x231e6
movl $0xfffd, -0x4(%rbp)     # imm = 0xFFFD
jmp 0x2326f
movl -0x30(%rbp), %eax
shll $0x6, %eax
movl %eax, -0x30(%rbp)
movzbl -0x35(%rbp), %eax
andl $0xffffff3f, %eax       # imm = 0xFFFFFF3F
orl -0x30(%rbp), %eax
movl %eax, -0x30(%rbp)
movq -0x20(%rbp), %rax
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x2318e
movl -0x30(%rbp), %edi
callq 0x22f00
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x28(%rbp), %eax
je 0x23236
movl $0xfffd, -0x4(%rbp)     # imm = 0xFFFD
jmp 0x2326f
cmpl $0xffff, -0x30(%rbp)    # imm = 0xFFFF
jae 0x23257
movl -0x30(%rbp), %eax
andl $0xf800, %eax           # imm = 0xF800
cmpl $0xd800, %eax           # imm = 0xD800
jne 0x23257
movl $0xfffd, -0x4(%rbp)     # imm = 0xFFFD
jmp 0x2326f
cmpl $0x10ffff, -0x30(%rbp)  # imm = 0x10FFFF
jbe 0x23269
movl $0xfffd, -0x4(%rbp)     # imm = 0xFFFD
jmp 0x2326f
movl -0x30(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax,%rax)