/*
 * testset.c: test program for the hash-based set module.
 *
 * (C) Duncan C. White, 2008 new addition to the fold..
 */

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

#include <mem.h>

#include "set.h"


static void myPrint( FILE *out, key k )
{
	fprintf( out, "%s,", k );
}


static set s1;

static int verbose = 0;


void test( key k, int expected )
{
	if( setIn( s1, k ) )
	{
		if( ! expected )
		{
			printf( "error: '%s' in when it shouldn't be\n", k );
		} else if( verbose )
		{
			printf( "'%s' in set, correct\n", k );
		}
	} else
	{
		if( expected )
		{
			printf( "error: '%s' not in when it should be\n", k );
		} else if( verbose )
		{
			printf( "'%s' not in set, correct\n", k );
		}
	}
}


void lookuptest( int x1, int x2, int x3, int x4, int x5, int x6 )
{
	printf( "lookup tests:\n" );
	test( "a", x1 );
	test( "b", x2 );
	test( "c", x3 );
	test( "d", x4 );
	test( "e", x5 );
	test( "f", x6 );
}


/* 
 * each_cb: print out an item to the FILE *
 *	    hidden in the arg; used in the main
 *	    program to print the hash ourselves.
 */

static void each_cb( key k, void *arg )
{
	fprintf( (FILE *)arg, "<%s>", k );
}


static void modify( set s, char *setname, key changes )
{
	printf( "\n%s = ", setname );
	setDump( stdout, s );
	printf( " %s", changes );
	setModify( s, changes );
	printf( "\n%*c = ", (int)strlen(setname), ' ' );
	setDump( stdout, s );
	printf( "\n" );
}


int main( int argc, char **argv )
{
	s1 = setCreate( myPrint );

	if( argc > 1 )
	{
		if( argc > 2 )
		{
			malloc(strlen(argv[2])); /* and don't free it! */
		}
		verbose = 1;
	}

	setInclude( s1, "a" );
	setInclude( s1, "b" );
	setInclude( s1, "c" );
	setInclude( s1, "d" );

	printf( "s1=" ); setDump( stdout, s1 ); printf( "\n" );

	lookuptest( 1, 1, 1, 1, 0, 0 );

	modify( s1, "s1", "-aardvark-b-wo-d+e+f+g-golly" );

	lookuptest( 1, 0, 1, 0, 1, 1 );

	printf( "\nprint s1 out using an explicit foreach loop: " );
	setForeach( s1, &each_cb, stdout );
	printf( "\n\n" );

	printf( "\ns2 = s1 " ); set s2 = setCopy( s1 );
	printf( "\n   = " ); setDump( stdout, s2 ); printf( "\n" );

	modify( s1, "s1", "+j+k+x+y+z" );
	modify( s2, "s2", "-a-e+b+h+i+j+z" );

	printf( "\nus = s1 " ); set us = setCopy( s1 );
	printf( "\n   = " ); setDump( stdout, us ); printf( "\n" );
	printf( "\nu2 = s2 " ); set u2 = setCopy( s2 );
	printf( "\n   = " ); setDump( stdout, u2 ); printf( "\n" );

	printf( "\nus = us union u2 = " );
	setDump( stdout, us ); printf( " union " ); setDump( stdout, u2 );
	setUnion( us, u2 );
	printf( "\n   = " ); setDump( stdout, us ); printf( "\n" );

	printf( "\nfree u2\n" );
	setFree( u2 );

	printf( "\nis = s1 " ); set is = setCopy( s1 );
	printf( "\n   = " ); setDump( stdout, is ); printf( "\n" );
	printf( "\ni2 = s2 " ); set i2 = setCopy( s2 );
	printf( "\n   = " ); setDump( stdout, i2 ); printf( "\n" );

	printf( "\nis = is intersect i2 = " );
	setDump( stdout, is ); printf( " intersect " ); setDump( stdout, i2 );
	setIntersection( is, i2 );
	printf( "\n   = " ); setDump( stdout, is ); printf( "\n" );

	printf( "\nfree i2\n" );
	setFree( i2 );

	printf( "\nbs = s1 " ); set bs = setCopy( s1 );
	printf( "\n   = " ); setDump( stdout, bs ); printf( "\n" );
	printf( "\nb2 = s2 " ); set b2 = setCopy( s2 );
	printf( "\n   = " ); setDump( stdout, b2 ); printf( "\n" );

	printf( "\nbs = bs - b2 = " );
	setDump( stdout, bs ); printf( " - " ); setDump( stdout, b2 );
	setSubtraction( bs, b2 );
	printf( "\n   = " ); setDump( stdout, bs ); printf( "\n" );

	printf( "\nfree s2\n" );
	setFree( b2 );

	printf( "\nd1 = s1 " ); set d1 = setCopy( s1 );
	printf( "\n   = " ); setDump( stdout, d1 ); printf( "\n" );
	printf( "\nd2 = s2 " ); set d2 = setCopy( s2 );
	printf( "\n   = " ); setDump( stdout, d2 ); printf( "\n" );

	printf( "\nsetdiff( d1, d2 ) = setdiff( " );
	setDump( stdout, d1 ); printf( ", " ); setDump( stdout, d2 );
	setDiff( d1, d2 );
	printf( "\nd1 = " ); setDump( stdout, d1 );
	printf( "\nd2 = " ); setDump( stdout, d2 ); printf( "\n" );

	printf( "\nfinally:\n\n" );
	printf( "s1=" ); setDump( stdout, s1 ); printf( "\n" );
	printf( "s2=" ); setDump( stdout, s2 ); printf( "\n" );
	printf( "us=" ); setDump( stdout, us ); printf( "\n" );
	printf( "is=" ); setDump( stdout, is ); printf( "\n" );
	printf( "bs=" ); setDump( stdout, bs ); printf( "\n" );
	printf( "d1=" ); setDump( stdout, d1 ); printf( "\n" );
	printf( "d2=" ); setDump( stdout, d2 ); printf( "\n" );

	setFree( s1 );
	setFree( s2 );
	setFree( us );
	setFree( is );
	setFree( bs );
	setFree( d1 );
	setFree( d2 );

	exit(0);
	return 0;
}
