// File: hzeller[P]FlaschenTaschen-PixelPusher-bridge/ppm-reader.cc
// Function: ReadImageData(char const*, unsigned long, ImageMetaInfo*)
const char *ReadImageData(const char *in_buffer, size_t buf_len,
                          struct ImageMetaInfo *info) {
    if (in_buffer[0] != 'P' || in_buffer[1] != '6' ||
        (!isspace(in_buffer[2]) && in_buffer[2] != '#')) {
        return in_buffer;  // raw image. No P6 magic header.
    }
    const char *const end = in_buffer + buf_len;
    const char *parse_buffer = in_buffer + 2;
    const int width = readNextNumber(&parse_buffer, end, info);
    if (parse_buffer == NULL) return in_buffer;
    const int height = readNextNumber(&parse_buffer, end, info);
    if (parse_buffer == NULL) return in_buffer;
    const int range = readNextNumber(&parse_buffer, end, info);
    if (parse_buffer == NULL) return in_buffer;
    if (!isspace(*parse_buffer++)) return in_buffer;   // last char before data
    // Now make sure that the rest of the buffer still makes sense
    const size_t expected_image_data = width * height * 3;
    const size_t actual_data = end - parse_buffer;
    if (actual_data < expected_image_data)
        return in_buffer;   // Uh, not enough data.
    if (actual_data > expected_image_data) {
        // Our extension: at the end of the binary data, we provide an optional
        // offset. We can't store it in the header, as it is fixed in number
        // of fields. But nobody cares what is at the end of the buffer.
        // Note, this also can be supplied in the specially formatted comment
        // in the header.
        parseOffsets(parse_buffer + expected_image_data, end, info);
    }
    info->width = width;
    info->height = height;
    info->range = range;
    return parse_buffer;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x50, %eax
jne 0x540c
movq -0x10(%rbp), %rax
movsbl 0x1(%rax), %eax
cmpl $0x36, %eax
jne 0x540c
movq -0x10(%rbp), %rax
movsbl 0x2(%rax), %edi
callq 0x2070
cmpl $0x0, %eax
jne 0x5419
movq -0x10(%rbp), %rax
movsbl 0x2(%rax), %eax
cmpl $0x23, %eax
je 0x5419
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5546
movq -0x10(%rbp), %rax
addq -0x18(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
leaq -0x30(%rbp), %rdi
callq 0x5550
movl %eax, -0x34(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x5459
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5546
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
leaq -0x30(%rbp), %rdi
callq 0x5550
movl %eax, -0x38(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x5481
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5546
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
leaq -0x30(%rbp), %rdi
callq 0x5550
movl %eax, -0x3c(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x54a9
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5546
movq -0x30(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x30(%rbp)
movsbl (%rax), %edi
callq 0x2070
cmpl $0x0, %eax
jne 0x54cf
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5546
movl -0x34(%rbp), %eax
imull -0x38(%rbp), %eax
imull $0x3, %eax, %eax
cltq
movq %rax, -0x48(%rbp)
movq -0x28(%rbp), %rax
movq -0x30(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
cmpq -0x48(%rbp), %rax
jae 0x5502
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5546
movq -0x50(%rbp), %rax
cmpq -0x48(%rbp), %rax
jbe 0x5521
movq -0x30(%rbp), %rdi
addq -0x48(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x55f0
movl -0x34(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, (%rax)
movl -0x38(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x4(%rax)
movl -0x3c(%rbp), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x30(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x50, %rsp
popq %rbp
retq