// File: /workspace/github_c_makefile_star2_O2/chriso[P]columnix/lib/reader.c
// Function: cx_row_group_reader_new
struct cx_row_group_reader *cx_row_group_reader_new(const char *path)
{
    struct cx_row_group_reader *reader = calloc(1, sizeof(*reader));
    if (!reader)
        return NULL;
    reader->file = fopen(path, "rb");
    if (!reader->file)
        goto error;

    // get file size
    int fd = fileno(reader->file);
    struct stat stat;
    if (fstat(fd, &stat))
        goto error;
    size_t file_size = stat.st_size;
    if (!file_size)
        goto error;
    reader->file_size = file_size;

    // mmap the file
    void *mmap_ptr = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (mmap_ptr == MAP_FAILED)
        goto error;
    reader->mmap_ptr = mmap_ptr;

    // check the footer
    if (file_size < sizeof(struct cx_footer))
        goto error;
    const struct cx_footer *footer =
        cx_row_group_reader_at(reader, file_size - sizeof(*footer));
    if (footer->magic != CX_FILE_MAGIC || footer->size < sizeof(*footer))
        goto error;

    // future extensions
    if (footer->version != CX_FILE_VERSION)
        goto error;

    // check the file contains the row group headers, column descriptors and
    // string repository
    size_t row_group_headers_size =
        footer->row_group_count * sizeof(struct cx_row_group_header);
    size_t descriptors_size =
        footer->column_count * sizeof(struct cx_column_descriptor);
    size_t headers_size =
        row_group_headers_size + descriptors_size + footer->size;
    if (file_size < headers_size)
        goto error;

    // load strings
    if (footer->strings_offset + footer->strings_size > file_size)
        goto error;
    const void *strings =
        cx_row_group_reader_at(reader, footer->strings_offset);
    reader->strings = cx_column_new_mmapped(CX_COLUMN_STR, CX_ENCODING_NONE,
                                            strings, footer->strings_size, 0);
    if (!reader->strings)
        goto error;

    // cache counts and header locations
    reader->row_count = footer->row_count;
    reader->columns.count = footer->column_count;
    reader->row_groups.count = footer->row_group_count;
    reader->columns.descriptors = cx_row_group_reader_at(
        reader, file_size - footer->size - descriptors_size);
    reader->row_groups.headers =
        cx_row_group_reader_at(reader, file_size - headers_size);
    reader->metadata = footer->metadata;

    return reader;
error:
    if (reader->mmap_ptr)
        munmap(reader->mmap_ptr, reader->file_size);
    if (reader->file)
        fclose(reader->file);
    if (reader->strings)
        cx_column_free(reader->strings);
    free(reader);
    return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rdi, %r14
pushq $0x1
popq %rdi
pushq $0x50
popq %rsi
callq 0x5480
testq %rax, %rax
je 0x8d0b
movq %rax, %rbx
leaq 0x3312(%rip), %rsi      # 0xbfe0
movq %r14, %rdi
callq 0x5500
movq %rax, (%rbx)
testq %rax, %rax
je 0x8d03
movq %rax, %r14
movq %rax, %rdi
callq 0x5570
movl %eax, %ebp
leaq 0x8(%rsp), %rsi
movl %eax, %edi
callq 0x5950
testl %eax, %eax
je 0x8d22
movq %r14, %rdi
callq 0x5210
movq %rbx, %rdi
callq 0x5090
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x38(%rsp), %r15
testq %r15, %r15
je 0x8cfb
movq %r15, 0x10(%rbx)
pushq $0x1
popq %rdx
pushq $0x2
popq %rcx
xorl %edi, %edi
movq %r15, %rsi
movl %ebp, %r8d
xorl %r9d, %r9d
callq 0x55a0
cmpq $-0x1, %rax
je 0x8cfb
movq %rax, %r12
movq %rax, 0x8(%rbx)
cmpq $0x38, %r15
jb 0x8e1d
movabsq $0x7863040378630201, %rax # imm = 0x7863040378630201
cmpq %rax, -0x8(%r15,%r12)
jne 0x8e1d
movl -0x10(%r12,%r15), %eax
cmpq $0x38, %rax
jb 0x8e1d
cmpl $0x1, -0xc(%r12,%r15)
jne 0x8e1d
movl -0x20(%r12,%r15), %r13d
movl -0x1c(%r12,%r15), %ecx
shlq $0x4, %r13
imulq $0x18, %rcx, %rbp
addq %rax, %r13
addq %rbp, %r13
cmpq %r13, %r15
jb 0x8e1d
movq -0x38(%r12,%r15), %rdx
movq -0x30(%r12,%r15), %rcx
leaq (%rcx,%rdx), %rax
cmpq %r15, %rax
ja 0x8e1d
addq %r12, %rdx
pushq $0x5
popq %rdi
xorl %esi, %esi
xorl %r8d, %r8d
callq 0x56e0
movq %rax, 0x20(%rbx)
testq %rax, %rax
je 0x8e1d
movq %r12, %rax
addq %r15, %rax
movq -0x18(%r12,%r15), %rcx
movq %rcx, 0x18(%rbx)
movl -0x1c(%r12,%r15), %ecx
movq %rcx, 0x30(%rbx)
movl -0x20(%r12,%r15), %ecx
movq %rcx, 0x40(%rbx)
movl -0x10(%r12,%r15), %ecx
addq %rcx, %rbp
movq %rax, %rcx
subq %rbp, %rcx
movq %rcx, 0x28(%rbx)
subq %r13, %rax
movq %rax, 0x38(%rbx)
movl -0x28(%r12,%r15), %eax
movl %eax, 0x48(%rbx)
jmp 0x8d0d
testq %r12, %r12
je 0x8cfb
movq %r12, %rdi
movq %r15, %rsi
callq 0x5740
jmp 0x8cfb