// File: Alcaro[P]bridges/arlib/string.cpp
// Function: cstring::isutf8() const
bool cstring::isutf8() const
{
	const uint8_t * bytes = ptr();
	const uint8_t * end = bytes + length();
	
	while (bytes < end)
	{
		uint8_t head = *bytes++;
		if (LIKELY(head < 0x80)) continue;
		
		uint32_t bits = head;
		while (bytes != end && (*bytes&0xC0) == 0x80)
		{
			// if there are four or more continuations, the head will be shifted out of bits
			// it'll end up between 0x80808080 and 0xBFBFBFBF, which doesn't match any approved range below
			bits = bits<<8 | *bytes++;
		}
		
		if (bits >= 0xC280 && bits <= 0xDFBF) {}
		else if (bits >= 0xE0A080 && (bits^0x020000) <= 0xEF9FBF) {} // extra xor to catch utf16
		else if (bits >= 0xF0908080 && bits <= 0xF48FBFBF) {}
		else return false;
	}
	
	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x48(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0x70(%rbp)
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x68(%rbp)
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
callq 0x5cc0
movsbl %al, %eax
cmpl $0x0, %eax
jl 0x3d222
movq -0x68(%rbp), %rax
movq %rax, -0x18(%rbp)
jmp 0x3d22d
movq -0x68(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x70(%rbp), %rax
movq -0x18(%rbp), %rcx
movq %rcx, -0x50(%rbp)
movq -0x50(%rbp), %rcx
movq %rcx, -0x80(%rbp)
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x78(%rbp)
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
callq 0x5cc0
movsbl %al, %eax
cmpl $0x0, %eax
jl 0x3d281
movq -0x78(%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 0x3d28b
movq -0x78(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x2c(%rbp)
movq -0x80(%rbp), %rax
movl -0x2c(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x50(%rbp), %rax
cmpq -0x58(%rbp), %rax
jae 0x3d382
movq -0x50(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x50(%rbp)
movb (%rax), %al
movb %al, -0x59(%rbp)
movzbl -0x59(%rbp), %eax
cmpl $0x80, %eax
setl %al
xorb $-0x1, %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x3d2d1
jmp 0x3d2d3
jmp 0x3d299
movzbl -0x59(%rbp), %eax
movl %eax, -0x60(%rbp)
movq -0x50(%rbp), %rcx
xorl %eax, %eax
cmpq -0x58(%rbp), %rcx
movb %al, -0x81(%rbp)
je 0x3d306
movq -0x50(%rbp), %rax
movzbl (%rax), %eax
andl $0xc0, %eax
cmpl $0x80, %eax
sete %al
movb %al, -0x81(%rbp)
movb -0x81(%rbp), %al
testb $0x1, %al
jne 0x3d312
jmp 0x3d331
movl -0x60(%rbp), %eax
shll $0x8, %eax
movq -0x50(%rbp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, -0x50(%rbp)
movzbl (%rcx), %ecx
orl %ecx, %eax
movl %eax, -0x60(%rbp)
jmp 0x3d2da
cmpl $0xc280, -0x60(%rbp)    # imm = 0xC280
jb 0x3d345
cmpl $0xdfbf, -0x60(%rbp)    # imm = 0xDFBF
ja 0x3d345
jmp 0x3d37d
cmpl $0xe0a080, -0x60(%rbp)  # imm = 0xE0A080
jb 0x3d35f
movl -0x60(%rbp), %eax
xorl $0x20000, %eax          # imm = 0x20000
cmpl $0xef9fbf, %eax         # imm = 0xEF9FBF
ja 0x3d35f
jmp 0x3d37b
cmpl $0xf0908080, -0x60(%rbp) # imm = 0xF0908080
jb 0x3d373
cmpl $0xf48fbfbf, -0x60(%rbp) # imm = 0xF48FBFBF
ja 0x3d373
jmp 0x3d379
movb $0x0, -0x39(%rbp)
jmp 0x3d386
jmp 0x3d37b
jmp 0x3d37d
jmp 0x3d299
movb $0x1, -0x39(%rbp)
movb -0x39(%rbp), %al
andb $0x1, %al
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)