/*
 * Copyright (C) 2019 Intel Corporation. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

static unsigned char *
read_file_to_buffer(const char *filename, int *ret_size)
{
    unsigned char *buffer;
    FILE *file;
    int file_size, read_size;

    if (!(file = fopen(filename, "r")))
        return NULL;

    fseek(file, 0, SEEK_END);
    file_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    if (!(buffer = malloc(file_size))) {
        fclose(file);
        return NULL;
    }

    read_size = fread(buffer, 1, file_size, file);
    fclose(file);

    if (read_size < file_size) {
        free(buffer);
        return NULL;
    }

    *ret_size = file_size;

    return buffer;
}

static int
print_help()
{
    printf("Usage: binarydump -o <file> -n <name> input_file\n");
    printf("Options:\n");
    printf("  -o <file>      Place the output into <file>\n");
    printf("  -n <name>      The name of array <file>\n");

    return -1;
}

static bool
bin_file_dump(const unsigned char *file, int size, const char *bin_file_output,
              const char *array_name)
{
    unsigned i = 0;
    const unsigned char *p = file, *p_end = file + size;
    FILE *file_output = fopen(bin_file_output, "wb+");

    if (!file_output)
        return false;

    fprintf(file_output, "\nunsigned char __aligned(4) %s[] = {\n  ",
            array_name);

    while (p < p_end) {
        fprintf(file_output, "0x%02X", *p++);

        if (p == p_end)
            break;

        fprintf(file_output, ",");

        if ((++i % 12) != 0)
            fprintf(file_output, " ");
        else
            fprintf(file_output, "\n  ");
    }

    fprintf(file_output, "\n};\n");

    fclose(file_output);
    return true;
}

int
main(int argc, char *argv[])
{
    unsigned char *file;
    int size;
    bool ret;
    const char *bin_file_input, *array_file_output = NULL, *array_name = NULL;

    for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
        if (!strcmp(argv[0], "-o")) {
            ++argv;
            if (--argc == 0)
                return print_help();
            array_file_output = *argv;
        }
        else if (!strcmp(argv[0], "-n")) {
            ++argv;
            if (--argc == 0)
                return print_help();
            array_name = *argv;
        }
        else
            return print_help();
    }

    if (!array_file_output || !array_name)
        return print_help();

    bin_file_input = *argv;

    if (!(file = read_file_to_buffer(bin_file_input, &size)))
        return -1;

    ret = bin_file_dump(file, size, array_file_output, array_name);

    free(file);

    return ret ? 0 : -1;
}
