// File: Alcaro[P]bridges/arlib/string.cpp
// Function: cstring::codepoint_at(unsigned int&) const
uint32_t cstring::codepoint_at(uint32_t& idx) const
{
	const uint8_t * bytes = ptr();
	uint32_t remaining = length()-idx;
	
	uint8_t head = bytes[idx];
	if (LIKELY(head < 0x80)) { idx++; return head; }
	
	uint32_t bits = 0; // same general idea as isutf8, but a little more careful
	uint8_t iter = head; // valid codepoint followed by continuation should report valid codepoint
	int n = 0;
	do {
		bits = bits<<8 | bytes[idx + n];
		n++;
		iter <<= 1;
	} while ((iter & 0x80) && --remaining && (bytes[idx+n]&0xC0) == 0x80);
	
	if (bits >= 0xC280 && bits <= 0xDFBF) {}
	else if (bits >= 0xE0A080 && (bits^0x020000) <= 0xEF9FBF) bits &= ~0x200000; // otherwise that bit becomes 0x8000 in codepoint
	else if (bits >= 0xF0908080 && bits <= 0xF48FBFBF) {} // for other top bytes, the fixed bits are zero or masked off
	else
	{
		idx++;
		return 0xDC00 | head;
	}
	
	idx += n;
	bits = (bits&0x003f003f) | (bits&0x0f003f00)>>2;
	bits = (bits&0x00000fff) | (bits&0x0fff0000)>>4;
	return bits;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x48(%rbp)
movq %rsi, -0x50(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0x80(%rbp)
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x78(%rbp)
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5cc0
movsbl %al, %eax
cmpl $0x0, %eax
jl 0x3d3e6
movq -0x78(%rbp), %rax
movq %rax, -0x18(%rbp)
jmp 0x3d3f1
movq -0x78(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x80(%rbp), %rax
movq -0x18(%rbp), %rcx
movq %rcx, -0x58(%rbp)
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x88(%rbp)
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
callq 0x5cc0
movsbl %al, %eax
cmpl $0x0, %eax
jl 0x3d443
movq -0x88(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x5cc0
movsbl %al, %eax
xorl $0xf, %eax
movzbl %al, %eax
movl %eax, -0x2c(%rbp)
jmp 0x3d450
movq -0x88(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movq -0x50(%rbp), %rcx
subl (%rcx), %eax
movl %eax, -0x5c(%rbp)
movq -0x58(%rbp), %rax
movq -0x50(%rbp), %rcx
movl (%rcx), %ecx
movb (%rax,%rcx), %al
movb %al, -0x5d(%rbp)
movzbl -0x5d(%rbp), %eax
cmpl $0x80, %eax
setl %al
xorb $-0x1, %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x3d482
jmp 0x3d499
movq -0x50(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movzbl -0x5d(%rbp), %eax
movl %eax, -0x3c(%rbp)
jmp 0x3d5eb
movl $0x0, -0x64(%rbp)
movb -0x5d(%rbp), %al
movb %al, -0x65(%rbp)
movl $0x0, -0x6c(%rbp)
movl -0x64(%rbp), %eax
shll $0x8, %eax
movq -0x58(%rbp), %rcx
movq -0x50(%rbp), %rdx
movl (%rdx), %edx
addl -0x6c(%rbp), %edx
movl %edx, %edx
movzbl (%rcx,%rdx), %ecx
orl %ecx, %eax
movl %eax, -0x64(%rbp)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
movzbl -0x65(%rbp), %eax
shll %eax
movb %al, -0x65(%rbp)
movzbl -0x65(%rbp), %ecx
andl $0x80, %ecx
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, -0x89(%rbp)
je 0x3d530
movl -0x5c(%rbp), %ecx
addl $-0x1, %ecx
movl %ecx, -0x5c(%rbp)
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, -0x89(%rbp)
je 0x3d530
movq -0x58(%rbp), %rax
movq -0x50(%rbp), %rcx
movl (%rcx), %ecx
addl -0x6c(%rbp), %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
andl $0xc0, %eax
cmpl $0x80, %eax
sete %al
movb %al, -0x89(%rbp)
movb -0x89(%rbp), %al
testb $0x1, %al
jne 0x3d4ad
cmpl $0xc280, -0x64(%rbp)    # imm = 0xC280
jb 0x3d552
cmpl $0xdfbf, -0x64(%rbp)    # imm = 0xDFBF
ja 0x3d552
jmp 0x3d5a8
cmpl $0xe0a080, -0x64(%rbp)  # imm = 0xE0A080
jb 0x3d577
movl -0x64(%rbp), %eax
xorl $0x20000, %eax          # imm = 0x20000
cmpl $0xef9fbf, %eax         # imm = 0xEF9FBF
ja 0x3d577
movl -0x64(%rbp), %eax
andl $0xffdfffff, %eax       # imm = 0xFFDFFFFF
movl %eax, -0x64(%rbp)
jmp 0x3d5a6
cmpl $0xf0908080, -0x64(%rbp) # imm = 0xF0908080
jb 0x3d58b
cmpl $0xf48fbfbf, -0x64(%rbp) # imm = 0xF48FBFBF
ja 0x3d58b
jmp 0x3d5a4
movq -0x50(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movzbl -0x5d(%rbp), %eax
orl $0xdc00, %eax           # imm = 0xDC00
movl %eax, -0x3c(%rbp)
jmp 0x3d5eb
jmp 0x3d5a6
jmp 0x3d5a8
movl -0x6c(%rbp), %ecx
movq -0x50(%rbp), %rax
addl (%rax), %ecx
movl %ecx, (%rax)
movl -0x64(%rbp), %eax
andl $0x3f003f, %eax         # imm = 0x3F003F
movl -0x64(%rbp), %ecx
andl $0xf003f00, %ecx        # imm = 0xF003F00
shrl $0x2, %ecx
orl %ecx, %eax
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %eax
andl $0xfff, %eax            # imm = 0xFFF
movl -0x64(%rbp), %ecx
andl $0xfff0000, %ecx        # imm = 0xFFF0000
shrl $0x4, %ecx
orl %ecx, %eax
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %eax
movl %eax, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
nopw (%rax,%rax)