// File: /workspace/github_cpp_makefile_star2_O2/jansucan[P]diff-dd/src/create.cpp
// Function: diffsTryMerge(Diff&, Diff&, unsigned long, unsigned long)
MergeState
diffsTryMerge(Diff &diff_a, Diff &diff_b, size_t max_merge_gap, size_t max_size)
{
    if (diff_a.isEmpty()) {
        // Do not merge to an empty diff
        return MergeState::Finished;
    }

    if (diff_b.isEmpty()) {
        // Nothing to merge from an empty diff
        return MergeState::Finished;
    }

    assert(diff_a.getEnd() <= diff_b.getStart());
    const size_t gap{diff_b.getStart() - diff_a.getEnd()};
    if (gap > max_merge_gap) {
        // B is too far away
        return MergeState::Finished;
    }

    if ((diff_a.getSize() + gap) >= max_size) {
        // No space in A
        return MergeState::Finished;
    }

    // Can be merged

    // Adjust the diff start and end offsets

    // There is always at least 1 byte free in A here
    const size_t free{max_size - (diff_a.getSize() + gap)};
    const size_t to_merge{std::min(free, diff_b.getSize())};
    // There is always at least 1 byte to merge from B here

    // Enlarge A
    diff_a.m_end += gap + to_merge;
    // Shrink B
    diff_b.m_start += to_merge;

    // Add B's page to A if needed

    // Non-empty A must have only the first, or both pages
    assert(diff_a.hasPage(0));
    // Non-empty B must have only the first page
    assert(diff_b.hasPage(0) && !diff_b.hasPage(1));

    // If A has both pages, B's page must only be the same as A's second
    // page. No setting of pages in A is needed in this case
    assert(!diff_a.hasPage(1) || (diff_b.m_pages[0] == diff_a.m_pages[1]));
    if (!diff_a.hasPage(1)) {
        // If A has only the first page, B's page must only be the same as the
        // A's first page or following it
        const bool b_follows{
            (diff_b.m_pages[0].getData() != diff_a.m_pages[0].getData()) &&
            (diff_b.m_pages[0].getStart() == diff_a.m_pages[0].getEnd())};
        assert((diff_b.m_pages[0] == diff_a.m_pages[0]) || b_follows);
        if (b_follows) {
            diff_a.m_pages[1] = diff_b.m_pages[0];
        }
    }

    return (diff_a.getSize() >= max_size) ? MergeState::Finished
                                          : MergeState::Incomplete;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rdi, %r14
movq 0x48(%rdi), %r8
xorl %eax, %eax
movq %r8, %rdi
subq 0x40(%r14), %rdi
je 0x44b3
movq %rcx, %rbx
movq %rsi, %r15
movq 0x40(%rsi), %rcx
movq 0x48(%rsi), %rsi
subq %rcx, %rsi
je 0x44b3
movq %rcx, %r9
subq %r8, %r9
jb 0x44c2
cmpq %rdx, %r9
ja 0x44b3
addq %rdi, %r9
movq %rbx, %rdx
subq %r9, %rdx
jbe 0x44b3
cmpq %rdx, %rsi
cmovbq %rsi, %rdx
addq %rcx, %rdx
movq %rdx, 0x48(%r14)
movq %rdx, 0x40(%r15)
movq %r14, %rdi
xorl %esi, %esi
callq 0x498c
testb %al, %al
je 0x4500
movq %r15, %rdi
xorl %esi, %esi
callq 0x498c
testb %al, %al
je 0x44e1
pushq $0x1
popq %rsi
movq %r15, %rdi
callq 0x498c
testb %al, %al
jne 0x44e1
pushq $0x1
popq %rsi
movq %r14, %rdi
callq 0x498c
testb %al, %al
je 0x441d
leaq 0x20(%r14), %rsi
movq %r15, %rdi
callq 0x432c
testb %al, %al
je 0x453e
pushq $0x1
popq %rsi
movq %r14, %rdi
callq 0x498c
testb %al, %al
jne 0x44a3
leaq 0x18(%rsp), %r12
movq %r12, %rdi
movq %r15, %rsi
callq 0x3f8e
leaq 0x8(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0x3f8e
movq (%r12), %rax
cmpq (%r13), %rax
setne %al
movq 0x18(%r14), %rcx
cmpq %rcx, 0x10(%r15)
sete %bpl
andb %al, %bpl
leaq 0x10(%rsp), %rdi
callq 0x3ed0
leaq 0x20(%rsp), %rdi
callq 0x3ed0
movq %r15, %rdi
movq %r14, %rsi
callq 0x432c
testb %bpl, %bpl
jne 0x4492
testb %al, %al
je 0x451f
testb %bpl, %bpl
je 0x44a3
leaq 0x20(%r14), %rdi
movq %r15, %rsi
callq 0x49cc
movq 0x48(%r14), %rcx
subq 0x40(%r14), %rcx
xorl %eax, %eax
cmpq %rbx, %rcx
setb %al
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3e63(%rip), %rdi      # 0x832c
leaq 0x3e81(%rip), %rsi      # 0x8351
leaq 0x3e85(%rip), %rcx      # 0x835c
movl $0xb3, %edx
callq 0x3160
leaq 0x3ebf(%rip), %rdi      # 0x83a7
leaq 0x3e62(%rip), %rsi      # 0x8351
leaq 0x3e66(%rip), %rcx      # 0x835c
movl $0xd2, %edx
callq 0x3160
leaq 0x3e8e(%rip), %rdi      # 0x8395
leaq 0x3e43(%rip), %rsi      # 0x8351
leaq 0x3e47(%rip), %rcx      # 0x835c
movl $0xd0, %edx
callq 0x3160
leaq 0x3ee8(%rip), %rdi      # 0x840e
leaq 0x3e24(%rip), %rsi      # 0x8351
leaq 0x3e28(%rip), %rcx      # 0x835c
movl $0xdd, %edx
callq 0x3160
leaq 0x3e8a(%rip), %rdi      # 0x83cf
leaq 0x3e05(%rip), %rsi      # 0x8351
leaq 0x3e09(%rip), %rcx      # 0x835c
movl $0xd6, %edx
callq 0x3160