/*******************************************************************\

Module:

Author: Dario Cattaruzza

Date: November 2017

\*******************************************************************/

#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <cstring>

/// Loads a binary file into a c array and creates c and h files to
/// access it from code.
///
/// This program takes two arguments, a `name` and a path to a file. It loads
/// the given file (usually a .jar file) and dumps to the standard output a
/// header file with two macros, looking like this:
///
/// ```
/// \#define MYNAME_DATA 0x01 0x23 0xf4 0x8e 0x9a
/// \#define MYNAME_SIZE 5
/// ```
/// The `name` is used as the prefix for the macros (`MYNAME` in the example
/// above). The output content, when included from a C/C++ file, can be used to
/// define an array initialized to the contents of the file, like this:
///
/// ```
/// const char myarray[] = { MYNAME_DATA };
/// const size_t myarray_size = MYNAME_SIZE;
/// ```
int main(int argc, char *argv[])
{
  if(argc<2 || strlen(argv[1])==0)
  {
    printf("Usage: converter VARNAME JAR_FILE\n\n");
    return 1;
  }

  std::size_t size=0;
  const char *varname=argv[1];

  printf("// File automatically generated by " __FILE__ "\n\n");

  printf("#define %s_DATA \\\n  ", varname);
  std::ifstream src((argc>2) ? argv[2] : "core-models.jar",
    std::ios_base::binary);
  std::istream &stream=(argc>2) ? src : std::cin;
  if(!stream.eof())
  {
    size++;
    printf("0x%02x", (unsigned char) stream.get());

    while(!stream.eof())
    {
      printf(", ");
      if(size % 16 == 0)
        printf("\\\n  ");
      printf("0x%02x", (unsigned char) stream.get());
      size++;
    }
    printf("\n");
  }

  std::cout << "\n#define " << varname << "_SIZE " << size << "\n";
  src.close();
  return 0;
}
