// File: rhoot[P]sp/tests/../include/sp.hpp
// Function: sp::parse_format(sp::StringView const&, sp::FormatFlags*)
inline bool parse_format(const StringView& fmt, FormatFlags* flags)
    {
        enum State {
            STATE_ALIGN,
            STATE_SIGN,
            STATE_ALTERNATE,
            STATE_WIDTH,
            STATE_PRECISION,
            STATE_TYPE,
            STATE_DONE,
        };

        auto state = STATE_ALIGN;
        auto next = fmt.ptr;
        auto term = fmt.ptr + fmt.length;
        *flags = FormatFlags{};

        while (next < term) {
            const auto ptr = next++;
            const auto ch = *ptr;

            switch (state) {
            case STATE_ALIGN: {
                const auto isAlign = [](char ch) {
                    return (ch >= '<' && ch <= '>') || ch == '^';
                };

                if (next < term && isAlign(*next)) {
                    flags->fill = ch;
                    flags->align = *next++;
                } else if (isAlign(ch)) {
                    flags->align = ch;
                } else {
                    --next;
                }

                state = STATE_SIGN;
                break;
            }

            case STATE_SIGN:
                switch (ch) {
                case '+':
                case '-':
                case ' ':
                    flags->sign = ch;
                    break;
                default:
                    --next;
                    break;
                }
                state = STATE_ALTERNATE;
                break;

            case STATE_ALTERNATE:
                if (ch == '#') {
                    flags->alternate = true;
                } else {
                    --next;
                }
                state = STATE_WIDTH;
                break;

            case STATE_WIDTH:
                if (ch >= '0' && ch <= '9') {
                    if (flags->width < 0) {
                        if (ch == '0') {
                            flags->fill = flags->fill ? flags->fill : '0';
                            flags->align = flags->align ? flags->align : '=';
                        }
                        flags->width = 0;
                    }
                    flags->width = (flags->width * 10) + (ch - '0');
                } else {
                    state = STATE_PRECISION;
                    --next;
                }
                break;

            case STATE_PRECISION: {
                const auto isDigit = [](char ch) {
                    return ch >= '0' && ch <= '9';
                };

                if (ch == '.') {
                    const char nextCh = (next < term) ? *next : 0;

                    if (flags->precision < 0 && isDigit(nextCh)) {
                        flags->precision = 0;
                        continue;
                    }
                } else if (isDigit(ch)) {
                    if (flags->precision >= 0) {
                        flags->precision = (flags->precision * 10) + (ch - '0');
                        continue;
                    }
                }

                state = STATE_TYPE;
                --next;
                break;
            }

            case STATE_TYPE:
                switch (ch) {
                case 'b':
                case 'd':
                case 'c':
                case 'e':
                case 'E':
                case 'f':
                case 'F':
                case 'g':
                case 'G':
                case 'o':
                case 's':
                case 'x':
                case 'X':
                case '%':
                    flags->type = ch;
                    break;
                default:
                    --next;
                    break;
                }
                state = STATE_DONE;
                break;

            case STATE_DONE:
                // if we get here, it means there's stuff in there after the
                // flags, in which case we should fail.
                return false;
            }
        }

        return true;
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq -0x10(%rbp), %rcx
movslq 0x8(%rcx), %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
leaq -0x40(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x1070
leaq -0x40(%rbp), %rdi
callq 0x15a20
movq -0x18(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, (%rax)
movl -0x38(%rbp), %ecx
movl %ecx, 0x8(%rax)
movb -0x34(%rbp), %cl
movb %cl, 0xc(%rax)
movq -0x28(%rbp), %rax
cmpq -0x30(%rbp), %rax
jae 0x15da8
movq -0x28(%rbp), %rax
movq %rax, %rcx
incq %rcx
movq %rcx, -0x28(%rbp)
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movb (%rax), %al
movb %al, -0x49(%rbp)
movl -0x1c(%rbp), %eax
movq %rax, -0x58(%rbp)
subq $0x6, %rax
ja 0x15da3
movq -0x58(%rbp), %rax
leaq 0xd5e3(%rip), %rcx      # 0x230e0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x28(%rbp), %rax
cmpq -0x30(%rbp), %rax
jae 0x15b49
movq -0x28(%rbp), %rax
leaq -0x4a(%rbp), %rdi
movsbl (%rax), %esi
callq 0x16410
testb $0x1, %al
jne 0x15b26
jmp 0x15b49
movb -0x49(%rbp), %cl
movq -0x18(%rbp), %rax
movb %cl, (%rax)
movq -0x28(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x28(%rbp)
movb (%rax), %cl
movq -0x18(%rbp), %rax
movb %cl, 0x1(%rax)
jmp 0x15b76
leaq -0x4a(%rbp), %rdi
movsbl -0x49(%rbp), %esi
callq 0x16410
testb $0x1, %al
jne 0x15b5c
jmp 0x15b68
movb -0x49(%rbp), %cl
movq -0x18(%rbp), %rax
movb %cl, 0x1(%rax)
jmp 0x15b74
movq -0x28(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x15b76
movl $0x1, -0x1c(%rbp)
jmp 0x15da3
movsbl -0x49(%rbp), %eax
movl %eax, -0x5c(%rbp)
subl $0x20, %eax
je 0x15ba4
jmp 0x15b90
movl -0x5c(%rbp), %eax
subl $0x2b, %eax
je 0x15ba4
jmp 0x15b9a
movl -0x5c(%rbp), %eax
subl $0x2d, %eax
jne 0x15bb0
jmp 0x15ba4
movb -0x49(%rbp), %cl
movq -0x18(%rbp), %rax
movb %cl, 0x2(%rax)
jmp 0x15bbc
movq -0x28(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x28(%rbp)
movl $0x2, -0x1c(%rbp)
jmp 0x15da3
movsbl -0x49(%rbp), %eax
cmpl $0x23, %eax
jne 0x15bdb
movq -0x18(%rbp), %rax
movb $0x1, 0x3(%rax)
jmp 0x15be7
movq -0x28(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x28(%rbp)
movl $0x3, -0x1c(%rbp)
jmp 0x15da3
movsbl -0x49(%rbp), %eax
cmpl $0x30, %eax
jl 0x15c90
movsbl -0x49(%rbp), %eax
cmpl $0x39, %eax
jg 0x15c90
movq -0x18(%rbp), %rax
cmpl $0x0, 0x4(%rax)
jge 0x15c76
movsbl -0x49(%rbp), %eax
cmpl $0x30, %eax
jne 0x15c6b
movq -0x18(%rbp), %rax
cmpb $0x0, (%rax)
je 0x15c34
movq -0x18(%rbp), %rax
movb (%rax), %al
movb %al, -0x5d(%rbp)
jmp 0x15c3b
movb $0x30, %al
movb %al, -0x5d(%rbp)
jmp 0x15c3b
movb -0x5d(%rbp), %cl
movq -0x18(%rbp), %rax
movb %cl, (%rax)
movq -0x18(%rbp), %rax
cmpb $0x0, 0x1(%rax)
je 0x15c5a
movq -0x18(%rbp), %rax
movb 0x1(%rax), %al
movb %al, -0x5e(%rbp)
jmp 0x15c61
movb $0x3d, %al
movb %al, -0x5e(%rbp)
jmp 0x15c61
movb -0x5e(%rbp), %cl
movq -0x18(%rbp), %rax
movb %cl, 0x1(%rax)
movq -0x18(%rbp), %rax
movl $0x0, 0x4(%rax)
movq -0x18(%rbp), %rax
imull $0xa, 0x4(%rax), %ecx
movsbl -0x49(%rbp), %eax
subl $0x30, %eax
addl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x4(%rax)
jmp 0x15ca3
movl $0x4, -0x1c(%rbp)
movq -0x28(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x15da3
movsbl -0x49(%rbp), %eax
cmpl $0x2e, %eax
jne 0x15d03
movq -0x28(%rbp), %rax
cmpq -0x30(%rbp), %rax
jae 0x15cc7
movq -0x28(%rbp), %rax
movsbl (%rax), %eax
movl %eax, -0x64(%rbp)
jmp 0x15cce
xorl %eax, %eax
movl %eax, -0x64(%rbp)
jmp 0x15cce
movl -0x64(%rbp), %eax
movb %al, -0x4c(%rbp)
movq -0x18(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jge 0x15d01
leaq -0x4b(%rbp), %rdi
movsbl -0x4c(%rbp), %esi
callq 0x16450
testb $0x1, %al
jne 0x15cf1
jmp 0x15d01
movq -0x18(%rbp), %rax
movl $0x0, 0x8(%rax)
jmp 0x15ab8
jmp 0x15d41
leaq -0x4b(%rbp), %rdi
movsbl -0x49(%rbp), %esi
callq 0x16450
testb $0x1, %al
jne 0x15d16
jmp 0x15d3f
movq -0x18(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jl 0x15d3d
movq -0x18(%rbp), %rax
imull $0xa, 0x8(%rax), %ecx
movsbl -0x49(%rbp), %eax
subl $0x30, %eax
addl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x8(%rax)
jmp 0x15ab8
jmp 0x15d3f
jmp 0x15d41
movl $0x5, -0x1c(%rbp)
movq -0x28(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x15da3
movsbl -0x49(%rbp), %eax
addl $-0x25, %eax
movl %eax, %ecx
movq %rcx, -0x70(%rbp)
subl $0x53, %eax
ja 0x15d88
movq -0x70(%rbp), %rax
leaq 0xd389(%rip), %rcx      # 0x230fc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movb -0x49(%rbp), %cl
movq -0x18(%rbp), %rax
movb %cl, 0xc(%rax)
jmp 0x15d94
movq -0x28(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x28(%rbp)
movl $0x6, -0x1c(%rbp)
jmp 0x15da3
movb $0x0, -0x1(%rbp)
jmp 0x15dac
jmp 0x15ab8
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x70, %rsp
popq %rbp
retq
nopw (%rax,%rax)