/*
 crmscrunch V1.0 by Michael Mutschler

This is just an example program of how to use the CrM.library from C.
All it does is crunch a file in LZH & sample mode.

note: you have to link with crm.lib!

History:
V1.0 - first release
*/

#include <libraries/crm.h>
#include <libraries/dos.h>
#include <dos/dos.h>
#include	<stdio.h>
#include <stdlib.h>
#include <clib/crm_protos.h>

#define ERR_template 20
#define ERR_nolib    19
#define ERR_struct   18
#define ERR_lock		17
#define ERR_NofibMem	16
#define ERR_Nofmem	15
#define ERR_read		14
#define ERR_crunchfail 13
#define ERR_write		12
#define ERR_file		11

struct cmCrunchStruct *crunchstruct;
struct Library *CrMBase;
BPTR	handle;
BPTR	lock;
struct FileInfoBlock *fib;
ULONG	flen;
APTR	fmem;
ULONG len, newlen;
struct DataHeader dataheader;
char *version = "$VER: crmscrunch V1.0 by Michael Mutschler";

void end(int err);

main(int argc, char** argv)
{
	if (argc!=3) end(ERR_template);

/* open the library */
	if (!(CrMBase = OpenLibrary("CrM.library",0))) end(ERR_nolib);

/* now allocate the crunchstruct.
 * cmF_Sample means use sample mode
 * cmF_Overlay means to use the same buffer for in- and output
 */
	if (!(crunchstruct =
         cmAllocCrunchStruct(CMCS_Algo,cm_LZH | cmF_Sample | cmF_Overlay,TAG_DONE)))
		   end(ERR_struct);
/* get the input-file */
	if (!(lock = Lock(argv[1],ACCESS_READ))) end(ERR_lock);
	if (!(fib = malloc(sizeof(struct FileInfoBlock)))) end(ERR_NofibMem);
	Examine(lock, fib);
	flen = fib->fib_Size;
	if (!(fmem = malloc(flen))) end(ERR_Nofmem);
	UnLock(lock);
	lock = NULL;
	handle = Open(argv[1], MODE_OLDFILE);
	len = Read(handle, fmem, flen);
	if (len != flen) end(ERR_read);
	Close(handle);
	handle = NULL;

/* now I have the file. Just write the stuff in the crunchstruct: */
	crunchstruct->cmcr_Src    = crunchstruct->cmcr_Dest    = fmem;
	crunchstruct->cmcr_SrcLen = crunchstruct->cmcr_DestLen = flen;
	crunchstruct->cmcr_DataHdr = &dataheader;

/* OK, now I can crunch the buffer */
	if (!(newlen = cmCrunchData(crunchstruct))) end(ERR_crunchfail);

/* At last, save it */
	if (!(handle = Open(argv[2], MODE_NEWFILE))) end(ERR_file);
	len = Write(handle, &dataheader, sizeof(struct DataHeader));
	if (len != sizeof(struct DataHeader)) end(ERR_write);
	len = Write(handle, fmem, newlen);
	if (len != newlen) end(ERR_write);

/* now a little information of our work */
	printf("oldfile: %s  length: %ld\n",argv[1],flen);
	printf("newfile: %s  length: %ld\n",argv[2],newlen);
	end(0);
}

void end(int err)
{
/* detailed error report: */
	if (err == ERR_write)		printf("Error while writing!\n");
	if (err == ERR_file)			printf("Dest File open failed!\n");
	if (err == ERR_crunchfail)	printf("crunching failed!\n");
	if (err == ERR_read)			printf("Error while reading!\n");
	if (err == ERR_Nofmem)		printf("No Mem!\n");
	if (err == ERR_template)	printf("Usage: crmscrunch <infile> <outfile>\n");
	if (err == ERR_nolib)		printf("couldn't open Library!\n");
	if (err == ERR_struct)		printf("couldn't allocate struct!\n");
	if (err == ERR_lock)			printf("file not found!\n");
	if (err == ERR_NofibMem)	printf("No Mem!\n");

	if (handle) Close(handle);
	if (fmem) free(fmem);
	if (fib) free(fib);
	if (lock) UnLock(lock);
	if (crunchstruct) cmFreeCrunchStruct(crunchstruct);
	if (CrMBase) CloseLibrary(CrMBase);
	exit(err);
}
