//------------------------------- relation.h -------------------------------

#ifndef _RELATION_H_
#define _RELATION_H_

#include <exception>
using namespace std;
#include <string.h>
#include <stdio.h>
#include "parseline.h"
#include "speclist.h"


class Relation {
     enum { MAXNAME =  50, MAXFORMAT = 100, MAXWORD = 100,
            MAXFILENAME = 100, MAXFIELD = 200, MAXFIELDS = 500,
            MAXWIDTHLIST = 500,
            MAXLINE = 1000, MAXDBLLINE = 2000, MAXLINES = 5000,
            MAXRECORDS = 100000 };
     struct {
          char name[MAXNAME];
          char datatype;
          int position;
          int printwidth;
     } dict[MAXFIELDS];
     Parseline *records[MAXRECORDS];
     void print (FILE *fp);
     char relfilename[MAXFILENAME];
     Relation* istats (int whichfield);
     Relation* dstats (int whichfield);
     int current;   // current record num

     // Support functions

     void copydict (Relation *source, Relation *dest);
     void copydict2 (Relation *source1, Relation *source2, Relation *dest);
     int xmatch1c (Parseline *x, int pos, char *comparison, char *fieldvalueC);
     int xmatch1i (Parseline *x, int pos, char *comparison, char *fieldvalueC);
     int xmatch1d (Parseline *x, int pos, char *comparison, char *fieldvalueC);
     int match1 (Parseline *x, Spec comparison);
     int match (Parseline *x, Speclist comps);
     void makewidthline (char *line);

public:

     int numrecords, numfields;
     Relation () { numrecords = numfields = 0; }
     Relation* select (Speclist specs);
     void addfield (char *name, int pos, char type, int width);
     void addfieldvalue (char *newfield, int recnum, char *newvalue);
     void delrecord (int recnum);
     void append (Relation *other);
     Relation* difference (char *field1, Relation *other, char *field2);
     Relation* copy ();
     Relation* project (char *numlist);
     void addrecord (Parseline *newrec);
     void addrecord (char *someline);
     void addrecord ();
     void print ();
     void printheader (FILE *fp);
	 void printfields (FILE *fp);
     void load (char *filename);
     void save (char *filename);
     Relation* cross (Relation *other);
     Relation* ejoin (Relation *other, char *whichf1, char *whichf2);
     void sort (char *whichfield, bool ascending);
     void sort ();
     Relation* addseqnums ();
     Relation* summarystats (char *whichfield);
     int findfield (char *whichfield);
     char getfieldtype (char *whichfield);
     void showdict ();
     void print1record (int recnum);
     void info ();
     void unique ();
     void changefieldname (char *fieldname, char *newname);
     void changefieldwidth (char *fieldname, int newwidth);
     int getfieldwidth (char *fieldname);

     // These will be useful for programs that directly deal with Relations
     // (as opposed to the interface program).

     int whichrec () { return current; }
     int findrecord (char *fieldname, char *value);
     int findrecord (char *fieldname, int value);
     int findrecord (char *fieldname, double value);
     void setcurrent (int recnum);
     void advance ();
     bool atend ();
     char *getvalueC (char *fieldname);
     int getvalueI (char *fieldname);
     double getvalueD (char *fieldname);
     void setvalue (char *fieldname, char *newvalueC);
     void setvalue (char *fieldname, int newvalueI);
     void setvalue (char *fieldname, double newvalueD);
     void formatvalue (int recnum, int fieldnum, char *result, 
                       size_t resultmaxlen);


/*
	class RelationExcp: public exception
	{
	public:

		RelationExcp(char * content): exception() {strncpy(excp_content, content, SIZE-1);}
		const char *what() {
			return excp_content;
		}
	private:
		enum {SIZE = 20 };
		char excp_content[SIZE];

	};
*/
};

#endif
