// File: Ciaxur[P]yagb-emu/include/imgui/imgui_widgets.cpp
// Function: ImGui::DataTypeApplyOpFromText(char const*, char const*, int, void*, char const*)
bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format)
{
    while (ImCharIsBlankA(*buf))
        buf++;

    // We don't support '-' op because it would conflict with inputing negative value.
    // Instead you can use +-100 to subtract from an existing value
    char op = buf[0];
    if (op == '+' || op == '*' || op == '/')
    {
        buf++;
        while (ImCharIsBlankA(*buf))
            buf++;
    }
    else
    {
        op = 0;
    }
    if (!buf[0])
        return false;

    // Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all.
    const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
    ImGuiDataTypeTempStorage data_backup;
    memcpy(&data_backup, p_data, type_info->Size);

    if (format == NULL)
        format = type_info->ScanFmt;

    // FIXME-LEGACY: The aim is to remove those operators and write a proper expression evaluator at some point..
    int arg1i = 0;
    if (data_type == ImGuiDataType_S32)
    {
        int* v = (int*)p_data;
        int arg0i = *v;
        float arg1f = 0.0f;
        if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
            return false;
        // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision
        if (op == '+')      { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); }                   // Add (use "+-" to subtract)
        else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); }                   // Multiply
        else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); }  // Divide
        else                { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; }                           // Assign constant
    }
    else if (data_type == ImGuiDataType_Float)
    {
        // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
        format = "%f";
        float* v = (float*)p_data;
        float arg0f = *v, arg1f = 0.0f;
        if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
            return false;
        if (sscanf(buf, format, &arg1f) < 1)
            return false;
        if (op == '+')      { *v = arg0f + arg1f; }                    // Add (use "+-" to subtract)
        else if (op == '*') { *v = arg0f * arg1f; }                    // Multiply
        else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
        else                { *v = arg1f; }                            // Assign constant
    }
    else if (data_type == ImGuiDataType_Double)
    {
        format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis
        double* v = (double*)p_data;
        double arg0f = *v, arg1f = 0.0;
        if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
            return false;
        if (sscanf(buf, format, &arg1f) < 1)
            return false;
        if (op == '+')      { *v = arg0f + arg1f; }                    // Add (use "+-" to subtract)
        else if (op == '*') { *v = arg0f * arg1f; }                    // Multiply
        else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
        else                { *v = arg1f; }                            // Assign constant
    }
    else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
    {
        // All other types assign constant
        // We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future.
        sscanf(buf, format, p_data);
    }
    else
    {
        // Small types need a 32-bit buffer to receive the result from scanf()
        int v32;
        sscanf(buf, format, &v32);
        if (data_type == ImGuiDataType_S8)
            *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX);
        else if (data_type == ImGuiDataType_U8)
            *(ImU8*)p_data = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX);
        else if (data_type == ImGuiDataType_S16)
            *(ImS16*)p_data = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX);
        else if (data_type == ImGuiDataType_U16)
            *(ImU16*)p_data = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX);
        else
            IM_ASSERT(0);
    }

    return memcmp(&data_backup, p_data, type_info->Size) != 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq -0x10(%rbp), %rax
movsbl (%rax), %edi
callq 0x140f20
testb $0x1, %al
jne 0x140a00
jmp 0x140a0e
movq -0x10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x10(%rbp)
jmp 0x1409ee
movq -0x10(%rbp), %rax
movb (%rax), %al
movb %al, -0x31(%rbp)
movsbl -0x31(%rbp), %eax
cmpl $0x2b, %eax
je 0x140a32
movsbl -0x31(%rbp), %eax
cmpl $0x2a, %eax
je 0x140a32
movsbl -0x31(%rbp), %eax
cmpl $0x2f, %eax
jne 0x140a60
movq -0x10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movsbl (%rax), %edi
callq 0x140f20
testb $0x1, %al
jne 0x140a50
jmp 0x140a5e
movq -0x10(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x10(%rbp)
jmp 0x140a3e
jmp 0x140a64
movb $0x0, -0x31(%rbp)
movq -0x10(%rbp), %rax
cmpb $0x0, (%rax)
jne 0x140a76
movb $0x0, -0x1(%rbp)
jmp 0x140f07
movl -0x1c(%rbp), %edi
callq 0x13fc60
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rsi
movq -0x40(%rbp), %rax
movq (%rax), %rdx
leaq -0x48(%rbp), %rdi
callq 0xd0a0
cmpq $0x0, -0x30(%rbp)
jne 0x140aa9
movq -0x40(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x30(%rbp)
movl $0x0, -0x4c(%rbp)
cmpl $0x4, -0x1c(%rbp)
jne 0x140be0
movq -0x28(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x5c(%rbp)
xorps %xmm0, %xmm0
movss %xmm0, -0x60(%rbp)
cmpb $0x0, -0x31(%rbp)
je 0x140afa
movq -0x18(%rbp), %rdi
movq -0x30(%rbp), %rsi
leaq -0x5c(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x1, %eax
jge 0x140afa
movb $0x0, -0x1(%rbp)
jmp 0x140f07
movsbl -0x31(%rbp), %eax
cmpl $0x2b, %eax
jne 0x140b2f
movq -0x10(%rbp), %rdi
leaq 0x38eb9(%rip), %rsi     # 0x1799c7
leaq -0x4c(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x0, %eax
je 0x140b2a
movl -0x5c(%rbp), %ecx
addl -0x4c(%rbp), %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
jmp 0x140bdb
movsbl -0x31(%rbp), %eax
cmpl $0x2a, %eax
jne 0x140b69
movq -0x10(%rbp), %rdi
leaq 0x3bf1b(%rip), %rsi     # 0x17ca5e
leaq -0x60(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x0, %eax
je 0x140b67
cvtsi2ssl -0x5c(%rbp), %xmm0
mulss -0x60(%rbp), %xmm0
cvttss2si %xmm0, %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
jmp 0x140bd9
movsbl -0x31(%rbp), %eax
cmpl $0x2f, %eax
jne 0x140bb4
movq -0x10(%rbp), %rdi
leaq 0x3bee1(%rip), %rsi     # 0x17ca5e
leaq -0x60(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x0, %eax
je 0x140bb2
movss -0x60(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomiss %xmm1, %xmm0
jne 0x140b9e
jp 0x140b9e
jmp 0x140bb2
cvtsi2ssl -0x5c(%rbp), %xmm0
divss -0x60(%rbp), %xmm0
cvttss2si %xmm0, %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
jmp 0x140bd7
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
leaq -0x4c(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x1, %eax
jne 0x140bd5
movl -0x4c(%rbp), %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
jmp 0x140bd7
jmp 0x140bd9
jmp 0x140bdb
jmp 0x140ee8
cmpl $0x8, -0x1c(%rbp)
jne 0x140cd8
leaq 0x3be6d(%rip), %rax     # 0x17ca5e
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movss (%rax), %xmm0
movss %xmm0, -0x6c(%rbp)
xorps %xmm0, %xmm0
movss %xmm0, -0x70(%rbp)
cmpb $0x0, -0x31(%rbp)
je 0x140c39
movq -0x18(%rbp), %rdi
movq -0x30(%rbp), %rsi
leaq -0x6c(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x1, %eax
jge 0x140c39
movb $0x0, -0x1(%rbp)
jmp 0x140f07
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
leaq -0x70(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x1, %eax
jge 0x140c5a
movb $0x0, -0x1(%rbp)
jmp 0x140f07
movsbl -0x31(%rbp), %eax
cmpl $0x2b, %eax
jne 0x140c77
movss -0x6c(%rbp), %xmm0
addss -0x70(%rbp), %xmm0
movq -0x68(%rbp), %rax
movss %xmm0, (%rax)
jmp 0x140cd3
movsbl -0x31(%rbp), %eax
cmpl $0x2a, %eax
jne 0x140c94
movss -0x6c(%rbp), %xmm0
mulss -0x70(%rbp), %xmm0
movq -0x68(%rbp), %rax
movss %xmm0, (%rax)
jmp 0x140cd1
movsbl -0x31(%rbp), %eax
cmpl $0x2f, %eax
jne 0x140cc2
movss -0x70(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomiss %xmm1, %xmm0
jne 0x140cae
jp 0x140cae
jmp 0x140cc0
movss -0x6c(%rbp), %xmm0
divss -0x70(%rbp), %xmm0
movq -0x68(%rbp), %rax
movss %xmm0, (%rax)
jmp 0x140ccf
movss -0x70(%rbp), %xmm0
movq -0x68(%rbp), %rax
movss %xmm0, (%rax)
jmp 0x140cd1
jmp 0x140cd3
jmp 0x140ee6
cmpl $0x9, -0x1c(%rbp)
jne 0x140de6
leaq 0x4dcee(%rip), %rax     # 0x18e9d7
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x80(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x88(%rbp)
cmpb $0x0, -0x31(%rbp)
je 0x140d34
movq -0x18(%rbp), %rdi
movq -0x30(%rbp), %rsi
leaq -0x80(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x1, %eax
jge 0x140d34
movb $0x0, -0x1(%rbp)
jmp 0x140f07
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
leaq -0x88(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x1, %eax
jge 0x140d58
movb $0x0, -0x1(%rbp)
jmp 0x140f07
movsbl -0x31(%rbp), %eax
cmpl $0x2b, %eax
jne 0x140d78
movsd -0x80(%rbp), %xmm0
addsd -0x88(%rbp), %xmm0
movq -0x78(%rbp), %rax
movsd %xmm0, (%rax)
jmp 0x140de1
movsbl -0x31(%rbp), %eax
cmpl $0x2a, %eax
jne 0x140d98
movsd -0x80(%rbp), %xmm0
mulsd -0x88(%rbp), %xmm0
movq -0x78(%rbp), %rax
movsd %xmm0, (%rax)
jmp 0x140ddf
movsbl -0x31(%rbp), %eax
cmpl $0x2f, %eax
jne 0x140dcd
movsd -0x88(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x140db6
jp 0x140db6
jmp 0x140dcb
movsd -0x80(%rbp), %xmm0
divsd -0x88(%rbp), %xmm0
movq -0x78(%rbp), %rax
movsd %xmm0, (%rax)
jmp 0x140ddd
movsd -0x88(%rbp), %xmm0
movq -0x78(%rbp), %rax
movsd %xmm0, (%rax)
jmp 0x140ddf
jmp 0x140de1
jmp 0x140ee4
cmpl $0x5, -0x1c(%rbp)
je 0x140df8
cmpl $0x6, -0x1c(%rbp)
je 0x140df8
cmpl $0x7, -0x1c(%rbp)
jne 0x140e10
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x28(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
jmp 0x140ee2
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
leaq -0x8c(%rbp), %rdx
movb $0x0, %al
callq 0xd0d0
cmpl $0x0, -0x1c(%rbp)
jne 0x140e4e
movl -0x8c(%rbp), %edi
movl $0xffffff80, %esi       # imm = 0xFFFFFF80
movl $0x7f, %edx
callq 0x140f50
movb %al, %cl
movq -0x28(%rbp), %rax
movb %cl, (%rax)
jmp 0x140ee0
cmpl $0x1, -0x1c(%rbp)
jne 0x140e70
movl -0x8c(%rbp), %edi
xorl %esi, %esi
movl $0xff, %edx
callq 0x140f50
movb %al, %cl
movq -0x28(%rbp), %rax
movb %cl, (%rax)
jmp 0x140ede
cmpl $0x2, -0x1c(%rbp)
jne 0x140e97
movl -0x8c(%rbp), %edi
movl $0xffff8000, %esi       # imm = 0xFFFF8000
movl $0x7fff, %edx           # imm = 0x7FFF
callq 0x140f50
movw %ax, %cx
movq -0x28(%rbp), %rax
movw %cx, (%rax)
jmp 0x140edc
cmpl $0x3, -0x1c(%rbp)
jne 0x140ebb
movl -0x8c(%rbp), %edi
xorl %esi, %esi
movl $0xffff, %edx           # imm = 0xFFFF
callq 0x140f50
movw %ax, %cx
movq -0x28(%rbp), %rax
movw %cx, (%rax)
jmp 0x140eda
leaq 0x34248(%rip), %rdi     # 0x17510a
leaq 0x4d517(%rip), %rsi     # 0x18e3e0
movl $0x7b9, %edx            # imm = 0x7B9
leaq 0x4db06(%rip), %rcx     # 0x18e9db
callq 0xd180
jmp 0x140edc
jmp 0x140ede
jmp 0x140ee0
jmp 0x140ee2
jmp 0x140ee4
jmp 0x140ee6
jmp 0x140ee8
movq -0x28(%rbp), %rsi
movq -0x40(%rbp), %rax
movq (%rax), %rdx
leaq -0x48(%rbp), %rdi
callq 0xd9f0
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)