/* Converts a binary file into a C integer array (for inclusion in
   a source file), having packed it with LZO1X-999 (for minilzo) */

#include <stdio.h>
#include <lzo1x.h>

// gcc -o bin2lzo2c bin2lzo2c.c -I /usr/local/include -L /usr/local/lib -llzo

unsigned char *indata, *outdata;
unsigned long insize, outsize, outmaxsize;

void writefile(char *ifn, char *id, char *ofn) {
	FILE *o;
	unsigned char buffer[2048];
	int red, left, lc, q;

	o = fopen(ofn, "w");
	if (!o) {
		printf("error: can't open input or output file\n");
		return;
	}


	fprintf(o,"/* Generated from %s by bin2c */\n/* Packed with LZO1X-999 to %lu bytes from %lu */\n\n",ifn, outsize, insize);
	fprintf(o, "unsigned char %s[] = {\n", id);

	lc = 0;
	for (q=0; q<outsize; q++) {
		fprintf(o, "%d, ", outdata[q]);
		if ((++lc) >= 30) {
			lc = 0;
			fprintf(o, "\n\t");
		}
	}

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

	fclose(o);
}


int
readfile(char *ifn)
{
	FILE *i;
	int left,nread;

	i = fopen(ifn, "r");
	if (!i) {
		printf("error: can't open input file\n");
		return;
	}
	fseek(i, 0, SEEK_END); insize = ftell(i); fseek(i, 0, SEEK_SET);
	// calculate worst-case for compressed data (nicked from LZO sample 'simple.c'
	outmaxsize = (insize +  insize / 64 + 16 + 3);

	indata = (unsigned char *)malloc(insize);
	outdata = (unsigned char *)malloc(outmaxsize);

	if(!indata || !outdata) {
		printf("error: can't malloc enough memory\n");
		return 0;
	}
	nread = fread(indata, 1, insize, i);
	if(nread != insize) {
		printf("Unfull read (%lu != %lu)\n",nread, insize);
		return 0;
	}
	fclose(i);
	printf("Alloced and read %lu bytes\n",nread);
}

int
compressdata()
{
	int r;
	lzo_byte *wrkmem;
	lzo_uint in_len;
	lzo_uint out_len;
	lzo_uint new_len;


	printf("\nLZO real-time data compression library (v%s, %s).\n",
	        lzo_version_string(), lzo_version_date());
	printf("Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer\n\n");

/*
 * Step 1: initialize the LZO library
 */
	if (lzo_init() != LZO_E_OK)
	{
		printf("lzo_init() failed !!!\n");
		return 4;
	}

/*
 * Step 2: allocate blocks and the work-memory
 */
	wrkmem = lzo_malloc(LZO1X_999_MEM_COMPRESS);
	if (wrkmem == NULL)
	{
		printf("out of memory\n");
		return 3;
	}

	in_len = insize;
	out_len = outmaxsize;

/*
 * Step 4: compress from `in' to `out' with LZO1X-1
 */
	r = lzo1x_999_compress(indata,in_len,outdata,&out_len,wrkmem);
	if (r == LZO_E_OK)
	{
		printf("compressed %lu bytes into %lu bytes\n",
			(long) in_len, (long) out_len);
			outsize = out_len;
	}
	else
	{
		/* this should NEVER happen */
		printf("internal error - compression failed: %d\n", r);
		return 2;
	}
	/* check for an incompressible block */
	if (out_len >= in_len)
	{
		printf("This block contains incompressible data.\n");
		return 0;
	}
}

int main(int argc, char **argv) {
	argc--;
	if (argc != 3) {
		printf("usage: bin2c <input> <identifier> <output>\n");
		return 0;
	}

	// read in the data to a buffer
	if(readfile(argv[1]) != 0)
	{
		compressdata();
		writefile(argv[1], argv[2], argv[3]);
	}
	
}


