fld.cpp

// MField - example field classes, version 1
//
//
#include <fstream.h>
#include <assert.h>
#include <string.h>		// for memset and strlen
#include <stdio.h>		// for sprintf
#include <stdlib.h>		// for atoi
#include <ctype.h>		// for isdigit

// Our base class - MField
class MField
{
public:
	// Constructor and destructor
	MField( char *NewName=0, int NewSize=0, int NewOffset=0 );
	virtual ~MField() { delete [] Data;	delete [] Name; }

	// Data getting and setting
	virtual char* GetAsString() const =0;	// Pure virtual
	virtual void SetFromString(char* Src) =0;	// Pure virtual

	// Basic interface routines
	char *GetName() { return(Name?Name:""); }
	int GetSize()	{ return( Size ); }
	void Clear()	{ memset( Data, 0, Size ); }

	// A routine to help identify data type
	virtual char * GetType() const = 0;	// Pure virtual function, MField is 'abstract'
	
protected:
	// Can be called only by this and derived classes
	void SetName( char* NewName );
	void* GetDataPntr() const { return( Data ); }

private:
	int Offset, Size;
	char * Data; // char * instead of void pointer, for simplicity
	char * Name;
};

// Constructor
MField::MField( char *NewName, int NewSize, int NewOffset )
{
	Name = 0;
	SetName(NewName);
	Data = new char[ NewSize ];
	assert( Data != 0 );
	Size = NewSize;
	Offset = NewOffset;
	Clear();
}

void MField::SetName( char* NewName )
{
	assert( NewName!=0 && *NewName!='\0' );
	delete [] Name;
	Name = new char[ strlen( NewName ) + 1 ];
	assert( Name!= 0 );
	strcpy( Name, NewName );
}

////////////////////////////////////////////////////////////////////////
class MDateField : public MField
{
	typedef struct { short Y; char M, D; } MyDate;
public:
	MDateField( char* NewName=0, int Offset=0 ) : MField(NewName, sizeof(MyDate), Offset ) {}
	
	// Provide the functions that are pure virtual in our class:
	virtual char* GetAsString() const;
	virtual void SetFromString(char* Src);
	virtual char * GetType() const { return( "Date" ); }
};

// Returns a char pointer for the contents of the field
char* MDateField::GetAsString() const
{
	static char Perm[11];
	MyDate * Tmp = (MyDate*)GetDataPntr();
	sprintf( Perm, "%02d/%02d/%04d", Tmp->M, Tmp->D, Tmp->Y );
	return( Perm );
}

void MDateField::SetFromString(char* Src)
{
	MyDate * Tmp = (MyDate*)GetDataPntr();
	Tmp->M = Tmp->D = 0;
	Tmp->Y = 0;
	Tmp->M = atoi(Src);
	while( isdigit(*Src) )
		Src++;
	while( *Src && !isdigit( *Src ) )
		Src++;
	Tmp->D = atoi(Src);
	while( isdigit(*Src) )
		Src++;
	while( *Src && !isdigit( *Src ) )
		Src++;
	Tmp->Y = atoi(Src);
}
///////////////////////////////////////////////////////////////////////	
class MShortField : public MField
{
public:
	MShortField( char* NewName=0, int NewOffset=0 ) : MField(NewName, sizeof(short), NewOffset ) {}
	
	char* GetAsString() const;
	void SetFromString(char* Src);

	virtual char * GetType() const { return( "Short" ); }
};

char* MShortField::GetAsString() const
{
	static char Perm[7];
	sprintf( Perm, "%d", *(short*) GetDataPntr() );
	return( Perm );
}

void MShortField::SetFromString(char* Src)
{
	*(short*) GetDataPntr() = atoi(Src);
}
///////////////////////////////////////////////////////////////////////	
void main()
{
	MField * Record[2];

	Record[0] = new MDateField( "BDay");
	Record[1] = new MShortField( "Qty" );
	
	Record[0]->SetFromString("1/1/1997");
	Record[1]->SetFromString("12");

	cout << "[" << Record[0]->GetAsString() << "]" << endl;
	Record[0]->Clear();
	cout << "[" << Record[0]->GetAsString() << "]" << endl;	
}