Click here to Skip to main content
15,879,535 members
Articles / Database Development / SQL Server

C++ Object Oriented Database Generator

Rate me:
Please Sign up or sign in to vote.
4.38/5 (7 votes)
17 Nov 19993 min read 129.9K   1.2K   37  
This project is a code generator to produce CObject-dervied data classes for Object-Oriented database management
// ObGenDlg.cpp : implementation file
//

#include "stdafx.h"
#include "ObGen.h"
#include "ObGenDlg.h"
//#include "DelphiFunctions.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CString GetType(CString strMember);
CString GetInit(CString strMember);
CString GetBase(CString strMember);
CString GetPrefix(CString strMember);
BOOL ValidName(CString s);

CString ChangeFileExt(CString s, CString strExtension)
{
	int nLength, n;
	CString strNew;
	nLength = s.GetLength();
	n = nLength - 1;
	while (n >= 0 && s.GetAt(n) != '.') --n;
	if (n == 0 || nLength - n > 4) strNew = s + "." + strExtension;
	else strNew = s.Left(n) + "." + strExtension;
	return strNew;
}

BOOL FileExists(CString s)
{ // returns TRUE if the file exists
	CFileStatus fStat;
	return (CFile::GetStatus(LPCTSTR(s), fStat));
}


/////////////////////////////////////////////////////////////////////////////
// CObGenDlg dialog

CObGenDlg::CObGenDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CObGenDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CObGenDlg)
	m_strFileName = _T("");
	m_strNewMember = _T("");
	m_strNewIndex = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CObGenDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CObGenDlg)
	DDX_Control(pDX, LBX_INDEX_LIST, m_IndexListBox);
	DDX_Control(pDX, LBX_MEMBERS, m_ListBox);
	DDX_Text(pDX, ET_CPP_FILENAME, m_strFileName);
	DDX_Text(pDX, ET_NEW_MEMBER, m_strNewMember);
	DDX_Text(pDX, ET_NEW_INDEX, m_strNewIndex);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CObGenDlg, CDialog)
	//{{AFX_MSG_MAP(CObGenDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDB_SELECT, OnSelect)
	ON_BN_CLICKED(IDB_ADD, OnAdd)
	ON_BN_CLICKED(IDB_DELETE, OnDelete)
	ON_BN_CLICKED(IDB_GENERATE, OnGenerate)
	ON_BN_CLICKED(IDB_CLEAR, OnClear)
	ON_BN_CLICKED(IDB_INDEX_CLEAR, OnIndexClear)
	ON_BN_CLICKED(IDB_INDEX_DELETE, OnIndexDelete)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CObGenDlg message handlers

BOOL CObGenDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here

	m_IndexListBox.AddString("m_dtDate");
	m_IndexListBox.AddString("m_strLocationID");
	m_IndexListBox.AddString("m_nOrder");

	m_ListBox.AddString("m_strCustomerName");
	m_ListBox.AddString("m_dtBirthDate");
	m_ListBox.AddString("m_rgbColor");
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}


// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CObGenDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CObGenDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CObGenDlg::OnSelect() 
{
	static char BASED_CODE szFilter[] = 
		"CPP Files (*.cpp) |*.cpp|All Files (*.*) |*.*||";

	CFileDialog SaveDlg(FALSE, "cpp", NULL, OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 
		(LPCTSTR)szFilter, NULL);
	
	if (SaveDlg.DoModal() != IDOK) return;
	
	// User selected a file name so:
	// 1.  Set File Combo Box text
	// 2.  Add name to recent file import list
	// 3.  Check for SUITES.TXT file in directory
	// 4.  If it exists, load combo box with suites
	
	SetDlgItemText(ET_CPP_FILENAME, LPCTSTR(SaveDlg.GetPathName()));
}

void CObGenDlg::OnAdd() 
{
	UpdateData(TRUE);
	if (m_strNewMember.GetLength() > 0)
	{
		if (!ValidName(m_strNewMember))
		{
			MessageBox("The selected name is not valid.");
			return;
		}
		m_ListBox.AddString(m_strNewMember);
		m_strNewMember = "";
		UpdateData(FALSE);
		GetDlgItem(ET_NEW_MEMBER)->SetFocus();
	}
	else if (m_strNewIndex.GetLength() > 0)
	{
		if (!ValidName(m_strNewIndex))
		{
			MessageBox("The selected Index name is not valid.");
			return;
		}
		m_IndexListBox.AddString(m_strNewIndex);
		m_strNewIndex = "";
		UpdateData(FALSE);
		GetDlgItem(ET_NEW_INDEX)->SetFocus();
	}

}

void CObGenDlg::OnDelete() 
{
	int nCurSel = m_ListBox.GetCurSel();
	if (nCurSel == LB_ERR) return;
	m_ListBox.DeleteString(nCurSel);
}

void CObGenDlg::OnIndexDelete() 
{
	int nCurSel = m_IndexListBox.GetCurSel();
	if (nCurSel == LB_ERR) return;
	m_IndexListBox.DeleteString(nCurSel);
}


void CObGenDlg::OnClear() 
{
	m_ListBox.ResetContent();
}



void CObGenDlg::OnIndexClear() 
{
	m_IndexListBox.ResetContent();
}



void CObGenDlg::OnGenerate() 
{
	UpdateData(TRUE);

	m_ListBox.AddString("m_dtCreated");
	m_ListBox.AddString("m_dtLastModified");

  char drive[_MAX_DRIVE];
  char dir[_MAX_DIR];
  char fname[_MAX_FNAME];
  char ext[_MAX_EXT];
	const char *path = _pgmptr ;
  _splitpath(m_strFileName, drive, dir, fname, ext );

	m_strCppFile = m_strFileName;
	m_strHeaderFile = ChangeFileExt(m_strFileName, "h");
	m_strClassBaseName.Format("%s", fname);

	TRACE("CPP file name is %s\n", m_strCppFile);
	TRACE("H file name is %s\n", m_strHeaderFile);
	TRACE("Class name is C%s with base of %s\n", m_strClassBaseName, m_strClassBaseName);

	WriteHeaderFile();
	WriteSourceFile();
	AfxMessageBox("Done");
	
}

void CObGenDlg::WriteListClassHeader(CStdioFile& f)
{
	CString s;

	s.Format("\nclass C%s;\n\n\n", m_strClassBaseName); // class forward declaration
	f.WriteString(s);

	s.Format("class C%sList : public CObList\n", m_strClassBaseName);
	f.WriteString(s);

	f.WriteString("{\n");
	f.WriteString("public:\n");
	
	s.Format("\tC%s* Find%s(%s);\n", m_strClassBaseName, m_strClassBaseName, GetIndexParamDeclaration());
	f.WriteString(s);

	s.Format("\tPOSITION Find%sPos(%s);\n", m_strClassBaseName, GetIndexParamDeclaration());
	f.WriteString(s);
	
	s.Format("\tPOSITION Find%sPosBruteForce(%s);\n", m_strClassBaseName, GetIndexParamDeclaration());
	f.WriteString(s);

	s.Format("\tvoid Add%s(C%s* pNew);\n", m_strClassBaseName, m_strClassBaseName);
	f.WriteString(s);
	
	s.Format("\tvoid Remove%s(%s);\n", m_strClassBaseName, GetIndexParamDeclaration());
	f.WriteString(s);

	s.Format("\tvirtual void Serialize(CArchive& ar);\n\tvoid ClearAndDelete();\n};\n\n\n\n");
	f.WriteString(s);
}


void CObGenDlg::WriteHeaderFile()
{
	if (FileExists(m_strHeaderFile))
	{
		int nReply = AfxMessageBox("Overwrite existing header file " + m_strHeaderFile + "?",
			MB_YESNO | MB_ICONQUESTION);
		if (nReply == IDNO) return;
	}

	CString s, sTemp;
	CStdioFile f(m_strHeaderFile, CFile::modeWrite | CFile::typeText | CFile::modeCreate);

	s.Format("///////////////////////////////////////////////////////////////////////////\n");
	f.WriteString(s);

	s.Format("// C%s -- Interface for C%s object\n", m_strClassBaseName, m_strClassBaseName);
	f.WriteString(s);

	f.WriteString("\n");
	f.WriteString("\n");
	f.WriteString("\n");

	// define directives
	sTemp = m_strClassBaseName;
	sTemp.MakeUpper();
	s.Format("#ifndef __%s_H__\n", sTemp);
	f.WriteString(s);
	s.Format("#define __%s_H__\n", sTemp);
	f.WriteString(s);
	f.WriteString("\n");

	if (m_IndexListBox.GetCount() > 0) WriteListClassHeader(f);
		

	// beginning of class declaration
	s.Format("class C%s : public CObject\n", m_strClassBaseName);
	f.WriteString(s);
	s.Format("{\n");
	f.WriteString(s);
	s.Format("// construction\n");
	f.WriteString(s);
	s.Format("public:\n");
	f.WriteString(s);
	s.Format("\tDECLARE_SERIAL(C%s);\n", m_strClassBaseName);
	f.WriteString(s);
	s.Format("\tC%s();\n", m_strClassBaseName);
	f.WriteString(s);

	// if there are indexes, then add constructor with parameter
	if (m_IndexListBox.GetCount() > 0) 
	{
		s.Format("\tC%s(%s);\n", m_strClassBaseName, GetIndexParamDeclaration());
		f.WriteString(s);
	}


	s.Format("\t~C%s();\n", m_strClassBaseName);
	f.WriteString(s);
	f.WriteString("\n");


	s.Format("// Attributes\n");
	f.WriteString(s);
	s.Format("public:\n");
	f.WriteString(s);
	f.WriteString("\n");
	f.WriteString("\n");
	f.WriteString("\n");


	// write the declarations of the protected members
	s.Format("protected:\n");
	f.WriteString(s);

	int nIndex;
	for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
	{
		m_IndexListBox.GetText(nIndex, sTemp);
		s.Format("\t%s %s;\n", GetType(sTemp), sTemp);
		f.WriteString(s);
	}
	for (nIndex = 0; nIndex < m_ListBox.GetCount(); ++nIndex)
	{
		m_ListBox.GetText(nIndex, sTemp);
		s.Format("\t%s %s;\n", GetType(sTemp), sTemp);
		f.WriteString(s);
	}

	f.WriteString("\n");
	f.WriteString("\n");

	// write the operations
	s.Format("// Operations\n");
	f.WriteString(s);
	s.Format("public:\n");
	f.WriteString(s);
	s.Format("\tvirtual void Serialize(CArchive& ar);\n");
	f.WriteString(s);
	s.Format("\tvoid Duplicate(C%s* pSource);\n", m_strClassBaseName);
	f.WriteString(s);
	s.Format("\tvoid Clear();\n");
	f.WriteString(s);
	
	if (m_IndexListBox.GetCount() > 0)
	{
		s.Format("\tint Compare(%s);\n", GetIndexParamDeclaration());
		f.WriteString(s);
		s.Format("\tint Compare(C%s* pTest);\n", m_strClassBaseName);
		f.WriteString(s);
	}

	f.WriteString("\n");
	f.WriteString("\n");

	f.WriteString("// Diagnostics\n");
	f.WriteString("#ifdef _DEBUG\n");
	s.Format("\tvoid AssertValid() const;\n");
	f.WriteString(s);
	f.WriteString("\tvirtual void Dump(CDumpContext& dc) const;\n");
	f.WriteString("#endif\n");

	s.Format("protected:\n");
	f.WriteString("\n");
	f.WriteString("\n");


	// write the inlines
	s.Format("// inlines\n");
	f.WriteString(s);
	s.Format("public:");
	f.WriteString(s);
	f.WriteString("\n");


	for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
	{
		m_IndexListBox.GetText(nIndex, sTemp);
		s.Format("\tinline void Set%s(%s %sNew) {\n", 
			GetBase(sTemp), GetType(sTemp), GetPrefix(sTemp));
		f.WriteString(s);
		s.Format("\t\tm_dtLastModified = COleDateTime::GetCurrentTime();\n");
		f.WriteString(s);
		if (GetPrefix(sTemp) == "str")
		{
			s.Format("\t\t%s = strNew;\n", sTemp);
			f.WriteString(s);
			s.Format("\t\t%s.FreeExtra(); }\n", sTemp);
			f.WriteString(s);
		}
		else
		{
			s.Format("\t\t%s = %sNew; }\n", sTemp, GetPrefix(sTemp));
			f.WriteString(s);
		}
		
		s.Format("\tinline %s Get%s() {;\n", GetType(sTemp), GetBase(sTemp));
		f.WriteString(s);
		s.Format("\t\treturn %s; }\n\n", sTemp);
		f.WriteString(s);
	}

	for (nIndex = 0; nIndex < m_ListBox.GetCount(); ++nIndex)
	{
		m_ListBox.GetText(nIndex, sTemp);
		s.Format("\tinline void Set%s(%s %sNew) {\n", 
			GetBase(sTemp), GetType(sTemp), GetPrefix(sTemp));
		f.WriteString(s);
		s.Format("\t\tm_dtLastModified = COleDateTime::GetCurrentTime();\n");
		f.WriteString(s);
		if (GetPrefix(sTemp) == "str")
		{
			s.Format("\t\t%s = strNew;\n", sTemp);
			f.WriteString(s);
			s.Format("\t\t%s.FreeExtra(); }\n", sTemp);
			f.WriteString(s);
		}
		else
		{
			s.Format("\t\t%s = %sNew; }\n", sTemp, GetPrefix(sTemp));
			f.WriteString(s);
		}
		
		s.Format("\tinline %s Get%s() {;\n", GetType(sTemp), GetBase(sTemp));
		f.WriteString(s);
		s.Format("\t\treturn %s; }\n\n", sTemp);
		f.WriteString(s);
	}

	f.WriteString("\n");
	f.WriteString("\n");



	// finish up the class declaration	
	s.Format("};\n");
	f.WriteString(s);

	f.WriteString("\n");
	f.WriteString("\n");

	// finish up the #endif
	sTemp = m_strClassBaseName;
	sTemp.MakeUpper();
	s.Format("#endif // #define __%s_H__\n", sTemp);
	f.WriteString(s);

	f.Close();
}



/////////////////////////////////////////////////////////////////
// Functions to write source

void CObGenDlg::WriteListClassSource(CStdioFile& f)
{
	CString s;
	s.Format("\n\n////////////////////////////////////////////////////////////\n");
	f.WriteString(s);
	s.Format("// C%sList class members\n\n\n", m_strClassBaseName);
	f.WriteString(s);
	
	// find entry function
	s.Format("C%s* C%sList::Find%s(%s)\n", m_strClassBaseName, m_strClassBaseName, m_strClassBaseName, GetIndexParamDeclaration());
	f.WriteString(s);
	f.WriteString("{\n");
	s.Format("\tPOSITION Pos = Find%sPos(%s);\n", m_strClassBaseName, GetIndexParamPassing());
	f.WriteString(s);
	f.WriteString("\tif (Pos == NULL) return NULL;\n");
	s.Format("\treturn (C%s*)GetAt(Pos);\n", m_strClassBaseName);
	f.WriteString(s);
	f.WriteString("}\n\n\n");

	// FindEntryPos function
	s.Format("POSITION C%sList::Find%sPos(%s)\n", m_strClassBaseName, m_strClassBaseName, GetIndexParamDeclaration()); f.WriteString(s);
	s.Format("{\n"); f.WriteString(s);
	s.Format("\tPOSITION Pos;\n"); f.WriteString(s);
	s.Format("\tC%s* p%s;\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\tdiv_t divresult;\n\n"); f.WriteString(s);
	s.Format("\tint nCurrent, nHigh, nLow, nCompareResult, nLastCurrent = -1;\n"); f.WriteString(s);
	s.Format("\tnLow = 0;\n"); f.WriteString(s);
	s.Format("\tnHigh = GetCount();\n"); f.WriteString(s);
	s.Format("\tdivresult = div(nHigh - nLow, 2);\n"); f.WriteString(s);
	s.Format("\tnCurrent = nLow + divresult.quot;\n\n"); f.WriteString(s);

	s.Format("\tif (nHigh <= 0) goto l_NotFound;  // no items in the list\n"); f.WriteString(s);
	s.Format("\twhile (TRUE)\n"); f.WriteString(s);
	s.Format("\t{\n"); f.WriteString(s);
	s.Format("\t\tPos = FindIndex(nCurrent);\n"); f.WriteString(s);
	s.Format("\t\tp%s = (C%s*)GetAt(Pos);\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\t\tnCompareResult = p%s->Compare(%s);\n", m_strClassBaseName, GetIndexParamPassing()); f.WriteString(s);
	s.Format("\t\tif (nCompareResult == 0)\n"); f.WriteString(s);
	s.Format("\t\t{\n"); f.WriteString(s);
	s.Format("\t\t\treturn Pos;\n"); f.WriteString(s);
	s.Format("\t\t}\n"); f.WriteString(s);
	s.Format("\t\tif (nCompareResult > 0) // we are in lower half of test range\n"); f.WriteString(s);
	s.Format("\t\t{\n"); f.WriteString(s);
	s.Format("\t\t\tnHigh = nCurrent;\n"); f.WriteString(s);
	s.Format("\t\tdivresult = div(nHigh - nLow, 2);\n"); f.WriteString(s);
	s.Format("\t\tnCurrent = nLow + divresult.quot;\n"); f.WriteString(s);
	s.Format("\t\t}\n"); f.WriteString(s);
	s.Format("\t\telse // we are in upper half of test range\n"); f.WriteString(s);
	s.Format("\t\t{\n"); f.WriteString(s);
	s.Format("\t\t\tnLow = nCurrent;\n"); f.WriteString(s);
	s.Format("\t\tdivresult = div(nHigh - nLow, 2);\n"); f.WriteString(s);
	s.Format("\t\tnCurrent = nLow + divresult.quot;\n"); f.WriteString(s);
	s.Format("\t\t}\n"); f.WriteString(s);
	s.Format("\t\tif (nCurrent == nLastCurrent) goto l_NotFound;\n"); f.WriteString(s);
	s.Format("\t\tnLastCurrent = nCurrent;\n"); f.WriteString(s);
	s.Format("\t}\n\n"); f.WriteString(s);

	s.Format("\tl_NotFound:;\n\n"); f.WriteString(s);

	s.Format("#ifdef _DEBUG\n"); f.WriteString(s);
	s.Format("\tPos = Find%sPosBruteForce(%s);\n", m_strClassBaseName, GetIndexParamPassing()); f.WriteString(s);
	s.Format("\tif (Pos != NULL) TRACE(\"Searching algorithm failed\\n\");\n"); f.WriteString(s);
	s.Format("#endif\n\n"); f.WriteString(s);

	s.Format("\treturn NULL;\n"); f.WriteString(s);
	s.Format("} // end of Find%sPos\n\n\n\n", m_strClassBaseName); f.WriteString(s);

	// FindEntryPosBruteForce function
	s.Format("POSITION C%sList::Find%sPosBruteForce(%s)\n", m_strClassBaseName, m_strClassBaseName, GetIndexParamDeclaration()); f.WriteString(s);
	s.Format("{\n"); f.WriteString(s);
	s.Format("\tC%s* p%s;\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\tPOSITION Pos = GetHeadPosition();\n"); f.WriteString(s);
	s.Format("\twhile (Pos)\n"); f.WriteString(s);
	s.Format("\t{\n"); f.WriteString(s);
	s.Format("\t\tp%s = (C%s*)GetNext(Pos);\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\t\tif (p%s->Compare(%s) == 0)\n", m_strClassBaseName, GetIndexParamPassing()); f.WriteString(s);
	s.Format("\t\t{\n"); f.WriteString(s);
	s.Format("\t\t\treturn Pos;\n"); f.WriteString(s);
	s.Format("\t\t}\n"); f.WriteString(s);
	s.Format("\t}\n"); f.WriteString(s);
	s.Format("\treturn NULL;\n"); f.WriteString(s);
	s.Format("} // end of Find%sPosBruteForce\n\n\n\n", m_strClassBaseName); f.WriteString(s);
	

	// Add function
	s.Format("void C%sList::Add%s(C%s* pNew)\n", m_strClassBaseName, m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("{\n"); f.WriteString(s);
	s.Format("\tC%s* p%s;\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\tint nCompareResult;\n"); f.WriteString(s);
	s.Format("\tPOSITION Pos;\n\n"); f.WriteString(s);

	s.Format("\t// need to search through list and add in the proper sorted order\n"); f.WriteString(s);
	s.Format("\tASSERT_VALID(pNew);\n"); f.WriteString(s);
	s.Format("\tASSERT(Find(pNew) == NULL);\n\n"); f.WriteString(s);

	s.Format("\t// start from end because it is more likely to be added to the end\n"); f.WriteString(s);
	s.Format("\tPos = GetTailPosition();\n"); f.WriteString(s);
	s.Format("\twhile (Pos)\n"); f.WriteString(s);
	s.Format("\t{\n"); f.WriteString(s);
	s.Format("\t\tp%s = (C%s*)GetAt(Pos);\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\t\tnCompareResult = p%s->Compare(pNew);\n", m_strClassBaseName); f.WriteString(s);
	s.Format("\t\tASSERT(nCompareResult != 0);\n"); f.WriteString(s);
	s.Format("\t\tif (nCompareResult == 0) return;\n"); f.WriteString(s);
	s.Format("\t\tif (nCompareResult == -1)\n"); f.WriteString(s);
	s.Format("\t\t{\n"); f.WriteString(s);
	s.Format("\t\t\tInsertAfter(Pos, pNew);\n"); f.WriteString(s);
	s.Format("\t\t\treturn;\n"); f.WriteString(s);
	s.Format("\t\t}\n"); f.WriteString(s);
	s.Format("\t\tGetPrev(Pos);\n"); f.WriteString(s);
	s.Format("\t}\n"); f.WriteString(s);
	s.Format("\tAddHead(pNew);\n"); f.WriteString(s);
	s.Format("\treturn;\n"); f.WriteString(s);
	s.Format("}\n\n\n"); f.WriteString(s);


	// Remove function
	s.Format("void C%sList::Remove%s(%s)\n", m_strClassBaseName, m_strClassBaseName, GetIndexParamDeclaration()); f.WriteString(s);
	s.Format("{\n"); f.WriteString(s);
	s.Format("\tPOSITION Pos = Find%sPos(%s);\n", m_strClassBaseName, GetIndexParamPassing()); f.WriteString(s);
	s.Format("\tif (Pos) RemoveAt(Pos);\n"); f.WriteString(s);
	s.Format("}\n\n\n\n"); f.WriteString(s);


	// List Serialization
	s.Format("void C%sList::Serialize(CArchive& ar)\n", m_strClassBaseName); f.WriteString(s);
	s.Format("{\n"); f.WriteString(s);
	s.Format("\t// NOTE:  Do not call the base class!\n"); f.WriteString(s);
	s.Format("\tDWORD dwVersion = 0x00000000;\n"); f.WriteString(s);
	s.Format("\tint n, nCount;\n"); f.WriteString(s);
	s.Format("\tPOSITION Pos;\n"); f.WriteString(s);
	s.Format("\tC%s* p%s;\n\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);

	s.Format("\tif (ar.IsStoring())\n"); f.WriteString(s);
	s.Format("\t{\n"); f.WriteString(s);
	s.Format("\t\tar<<dwVersion;\n\n"); f.WriteString(s);

	s.Format("\t\tnCount = GetCount();\n"); f.WriteString(s);
	s.Format("\t\tar<<nCount;\n"); f.WriteString(s);
	s.Format("\t\tPos = GetHeadPosition();\n"); f.WriteString(s);
	s.Format("\t\twhile (Pos)\n"); f.WriteString(s);
	s.Format("\t\t{\n"); f.WriteString(s);
	s.Format("\t\t\tp%s = (C%s*)GetNext(Pos);\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\t\t\tp%s->Serialize(ar);\n", m_strClassBaseName); f.WriteString(s);
	s.Format("\t\t}\n"); f.WriteString(s);
	s.Format("\t}\n"); f.WriteString(s);
	s.Format("\telse\n"); f.WriteString(s);
	s.Format("\t{\n"); f.WriteString(s);
	s.Format("\t\tar>>dwVersion;\n"); f.WriteString(s);
	s.Format("\t\tASSERT(GetCount() == 0);\n"); f.WriteString(s);
	s.Format("\t\tar>>nCount;\n"); f.WriteString(s);
	s.Format("\t\tfor (n = 0; n < nCount; ++n)\n"); f.WriteString(s);
	s.Format("\t\t{\n"); f.WriteString(s);
	s.Format("\t\t\tp%s = new C%s();\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\t\t\tif (p%s == NULL)\n", m_strClassBaseName); f.WriteString(s);
	s.Format("\t\t\tTHROW(new CMemoryException());\n"); f.WriteString(s);
	s.Format("\t\t\tp%s->Serialize(ar);\n", m_strClassBaseName); f.WriteString(s);
	s.Format("\t\t\tAddTail(p%s);\n", m_strClassBaseName); f.WriteString(s);
	s.Format("\t\t}\n"); f.WriteString(s);
	s.Format("\t}\n"); f.WriteString(s);
	s.Format("} // end of Serialize\n\n\n\n"); f.WriteString(s);


	// Clear and delete function
	s.Format("void C%sList::ClearAndDelete()\n", m_strClassBaseName); f.WriteString(s);
	s.Format("{\n"); f.WriteString(s);
	s.Format("\tC%s* p%s;\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\tPOSITION Pos = GetHeadPosition();\n"); f.WriteString(s);
	s.Format("\twhile (Pos)\n"); f.WriteString(s);
	s.Format("\t{\n"); f.WriteString(s);
	s.Format("\t\tp%s = (C%s*)GetNext(Pos);\n", m_strClassBaseName, m_strClassBaseName); f.WriteString(s);
	s.Format("\t\tASSERT_VALID(p%s);\n", m_strClassBaseName); f.WriteString(s);
	s.Format("\t\tdelete p%s;\n", m_strClassBaseName); f.WriteString(s);
	s.Format("\t}\n"); f.WriteString(s);
	s.Format("\tRemoveAll();\n"); f.WriteString(s);
	s.Format("}\n\n\n\n"); f.WriteString(s);


	s.Format("////////////////////////////////////////////////////////////\n");
	f.WriteString(s);
	s.Format("// C%s class members\n", m_strClassBaseName);
	f.WriteString(s);
}

void CObGenDlg::WriteSourceFile()
{
	if (FileExists(m_strCppFile))
	{
		int nReply = AfxMessageBox("Overwrite existing source file " + m_strCppFile + "?",
			MB_YESNO | MB_ICONQUESTION);
		if (nReply == IDNO) return;
	}

	CString s, sTemp;
	CStdioFile f(m_strCppFile, CFile::modeWrite | CFile::typeText | CFile::modeCreate);

	s.Format("///////////////////////////////////////////////////////////////////////////\n");
	f.WriteString(s);

	s.Format("// C%s -- Implementation for C%s object\n", m_strClassBaseName, m_strClassBaseName);
	f.WriteString(s);

	f.WriteString("\n");
	f.WriteString("\n");

	s.Format("#include \"stdafx.h\"\n");
	f.WriteString(s);
	s.Format("#include \"%s.h\"\n", m_strClassBaseName);
	f.WriteString(s);

	f.WriteString("\n");
	s.Format("IMPLEMENT_SERIAL(C%s, CObject, 0);\n", m_strClassBaseName);
	f.WriteString(s);

	if (m_IndexListBox.GetCount() > 0) WriteListClassSource(f);

	f.WriteString("\n");
	f.WriteString("\n");
	f.WriteString("\n");

	f.WriteString("////////////////////////////////////////////\n");
	s.Format("// C%s construction/destruction \n", m_strClassBaseName);
	f.WriteString(s);

	f.WriteString("\n");
	f.WriteString("\n");

	// write the constructor, initializing values
	s.Format("// Construction\n");
	f.WriteString(s);
	s.Format("C%s::C%s()\n", m_strClassBaseName, m_strClassBaseName);
	f.WriteString(s);
	s.Format("{\n");
	f.WriteString(s);
	s.Format("\tClear();\n");
	f.WriteString(s);
	s.Format("\tm_dtCreated = COleDateTime::GetCurrentTime();\n");
	f.WriteString(s);
	s.Format("}\n");
	f.WriteString(s);

	// Constructor with parameters
	if (m_IndexListBox.GetCount() > 0) 	
	{
		s.Format("\n\nC%s::C%s(%s)\n", m_strClassBaseName, m_strClassBaseName, GetIndexParamDeclaration());
		f.WriteString(s);
		s.Format("{\n");
		f.WriteString(s);
		s.Format("\tClear();\n");
		f.WriteString(s);
		s.Format("\tm_dtCreated = COleDateTime::GetCurrentTime();\n");
		f.WriteString(s);

		int nIndex;
		for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
		{
			m_IndexListBox.GetText(nIndex, sTemp);
			s.Format("\t%s = %s;\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
			f.WriteString(s);
		}

		s.Format("}\n");
		f.WriteString(s);
	}

	f.WriteString("\n");
	f.WriteString("\n");

	s.Format("// Initialization\n");
	f.WriteString(s);
	s.Format("void C%s::Clear()\n", m_strClassBaseName);
	f.WriteString(s);
	s.Format("{\n");
	f.WriteString(s);

	int nIndex;
	for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
	{
		m_IndexListBox.GetText(nIndex, sTemp);
		s.Format("\t%s\n", GetInit(sTemp));
		f.WriteString(s);
	}

	for (nIndex = 0; nIndex < m_ListBox.GetCount(); ++nIndex)
	{
		m_ListBox.GetText(nIndex, sTemp);
		s.Format("\t%s\n", GetInit(sTemp));
		f.WriteString(s);
	}

	s.Format("}\n");
	f.WriteString(s);

	f.WriteString("\n");
	f.WriteString("\n");
	f.WriteString("\n");

	s.Format("// Destruction\n");
	f.WriteString(s);
	s.Format("C%s::~C%s()\n", m_strClassBaseName, m_strClassBaseName);
	f.WriteString(s);
	s.Format("{\n");
	f.WriteString(s);
	f.WriteString("\n");
	f.WriteString("\n");
	f.WriteString("\n");
	s.Format("}\n");
	f.WriteString(s);
	f.WriteString("\n");
	f.WriteString("\n");

	// Diagnostics
	f.WriteString("\n");
	f.WriteString("\n");

	f.WriteString("////////////////////////////////////////////\n");
	s.Format("// C%s Diagnostics \n\n", m_strClassBaseName);
	f.WriteString(s);

	f.WriteString("#ifdef _DEBUG\n\n");
	s.Format("void C%s::Dump(CDumpContext& dc) const\n", m_strClassBaseName);
	f.WriteString(s);
	f.WriteString("{\n");
	f.WriteString("\tdc.SetDepth(1);\n");

	// dump object here
	for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
	{
		m_IndexListBox.GetText(nIndex, sTemp);
		s.Format("\tdc <<\"%s = \" << %s;\n", GetBase(sTemp), sTemp);
		f.WriteString(s);
	}
	for (nIndex = 0; nIndex < m_ListBox.GetCount(); ++nIndex)
	{
		m_ListBox.GetText(nIndex, sTemp);
		s.Format("\tdc <<\"%s = \" << %s;\n", GetBase(sTemp), sTemp);
		f.WriteString(s);
	}


	f.WriteString("}\n\n");

	s.Format("void C%s::AssertValid() const\n", m_strClassBaseName);
	f.WriteString(s);
	f.WriteString("{\n");
  f.WriteString("\tCObject::AssertValid();\n");
	f.WriteString("\n\t// TODO:  Add validity checking here\n");
	f.WriteString("}\n");

	f.WriteString("#endif\n\n");

	f.WriteString("\n");
	f.WriteString("\n");

	// Operations
	f.WriteString("\n");
	f.WriteString("\n");

	f.WriteString("////////////////////////////////////////////\n");
	s.Format("// C%s operations \n", m_strClassBaseName);
	f.WriteString(s);

	f.WriteString("\n");
	f.WriteString("\n");


	// Serialization
	s.Format("void C%s::Serialize(CArchive& ar)\n", m_strClassBaseName);
	f.WriteString(s);
	s.Format("{\n");
	f.WriteString(s);
	s.Format("\tDWORD dwVersion = 0x00000000;\n");
	f.WriteString(s);
	f.WriteString("\n");
	s.Format("\tif (ar.IsStoring())\n");
	f.WriteString(s);
	s.Format("\t{\n");
	f.WriteString(s);

	// storing code
	s.Format("\t\tar<<dwVersion;");
	f.WriteString(s);
	f.WriteString("\n");

	f.WriteString("\t\tar");
	for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
	{
		m_IndexListBox.GetText(nIndex, sTemp);
		s.Format("<<%s", sTemp);
		f.WriteString(s);
	}
	for (nIndex = 0; nIndex < m_ListBox.GetCount(); ++nIndex)
	{
		m_ListBox.GetText(nIndex, sTemp);
		s.Format("<<%s", sTemp);
		f.WriteString(s);
	}
	f.WriteString(";\n");

	f.WriteString("\n");
	f.WriteString("\n");
	s.Format("\t}\n");
	f.WriteString(s);
	s.Format("\telse\n");
	f.WriteString(s);
	s.Format("\t{\n");
	f.WriteString(s);

	// reading code
	s.Format("\t\tar>>dwVersion;");
	f.WriteString(s);
	f.WriteString("\n");

	f.WriteString("\t\tar");
	for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
	{
		m_IndexListBox.GetText(nIndex, sTemp);
		s.Format(">>%s", sTemp);
		f.WriteString(s);
	}
	for (nIndex = 0; nIndex < m_ListBox.GetCount(); ++nIndex)
	{
		m_ListBox.GetText(nIndex, sTemp);
		s.Format(">>%s", sTemp);
		f.WriteString(s);
	}
	f.WriteString(";\n");

	f.WriteString("\n");
	f.WriteString("\n");
	s.Format("\t}\n");
	f.WriteString(s);
	s.Format("\tCObject::Serialize(ar);\n");
	f.WriteString(s);
	s.Format("} // end of Serialize\n");
	f.WriteString(s);
	f.WriteString("\n");
	f.WriteString("\n");

	// write duplicate function
	s.Format("void C%s::Duplicate(C%s* pSource)\n", m_strClassBaseName,
		m_strClassBaseName);
	f.WriteString(s);
	s.Format("{\n");
	f.WriteString(s);
		
	for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
	{
		m_IndexListBox.GetText(nIndex, sTemp);
		s.Format("\t%s = pSource->%s;\n", sTemp, sTemp);
		f.WriteString(s);
	}
	for (nIndex = 0; nIndex < m_ListBox.GetCount(); ++nIndex)
	{
		m_ListBox.GetText(nIndex, sTemp);
		s.Format("\t%s = pSource->%s;\n", sTemp, sTemp);
		f.WriteString(s);
	}
	s.Format("} // end of Duplicate\n");
	f.WriteString(s);
	f.WriteString("\n");
	f.WriteString("\n");


	// write comparison function
	if (m_IndexListBox.GetCount() > 0) 	
	{
		s.Format("int C%s::Compare(%s)\n{\n", m_strClassBaseName, GetIndexParamDeclaration());
		f.WriteString(s);
		f.WriteString("\tint nCompare;\n\n");

		for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
		{
			m_IndexListBox.GetText(nIndex, sTemp);
			if (sTemp.Find("m_dt") == 0)
			{
				s.Format("\tif (%s.m_status != COleDateTime::valid) return -1;\n", sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
				s.Format("\tif (%s < %s) return -1;\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
				s.Format("\tif (%s > %s) return 1;\n\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
			}
			else if (sTemp.Find("m_str") == 0)
			{
				s.Format("\tnCompare = %s.Compare(%s);\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
				s.Format("\tif (nCompare < 0) return -1;\n");
				f.WriteString(s);
				s.Format("\tif (nCompare > 0) return 1;\n\n");
				f.WriteString(s);
			}
			else if (sTemp.Find("m_n") == 0)
			{
				s.Format("\tif (%s < %s) return -1;\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
				s.Format("\tif (%s > %s) return 1;\n\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
			}
			else if (sTemp.Find("m_f") == 0)
			{
				s.Format("\tif (%s < %s) return -1;\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
				s.Format("\tif (%s > %s) return 1;\n\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
			}
			else if (sTemp.Find("m_rgb") == 0)
			{
				s.Format("\tif (%s < %s) return -1;\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
				s.Format("\tif (%s > %s) return 1;\n\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
			}
			else if (sTemp.Find("m_b") == 0)
			{
				s.Format("\tif (%s != %s) return -1;\n\n", sTemp, sTemp.Right(sTemp.GetLength() - 2));
				f.WriteString(s);
			}
		}
		f.WriteString("\treturn 0;\n}\n\n");

		// write the comparison function for the pointer
		s.Format("int C%s::Compare(C%s* pTest)\n{\n", m_strClassBaseName, m_strClassBaseName);
		f.WriteString(s);
		f.WriteString("	return Compare(");

		for (nIndex = 0; nIndex < m_IndexListBox.GetCount(); ++nIndex)
		{
			m_IndexListBox.GetText(nIndex, sTemp);
			s.Format("pTest->Get%s()", GetBase(sTemp));
			f.WriteString(s);
			if (nIndex < m_IndexListBox.GetCount() - 1) f.WriteString(", ");
		}
		f.WriteString(");\n}\n\n\n");
	}

	f.Close();

}


CString CObGenDlg::GetIndexParamDeclaration()
{
	CString s, sTemp;
	int n;
	for (n = 0; n < m_IndexListBox.GetCount(); ++n)
	{
		m_IndexListBox.GetText(n, sTemp);
		s = s + GetType(sTemp) + " " + sTemp.Right(sTemp.GetLength() - 2);
		if (n < m_IndexListBox.GetCount()-1) s = s + ", ";
	}
	return s;
}


CString CObGenDlg::GetIndexParamPassing()
{
	CString s, sTemp;
	int n;
	for (n = 0; n < m_IndexListBox.GetCount(); ++n)
	{
		m_IndexListBox.GetText(n, sTemp);
		s = s + sTemp.Right(sTemp.GetLength() - 2);
		if (n < m_IndexListBox.GetCount()-1) s = s + ", ";
	}
	return s;
}

CString GetType(CString strMember)
{
	if (strMember.Find("m_str") == 0) return "CString";
	if (strMember.Find("m_dt") == 0) return "COleDateTime";
	if (strMember.Find("m_n") == 0) return "int";
	if (strMember.Find("m_f") == 0) return "double";
	if (strMember.Find("m_rgb") == 0) return "COLORREF";
	if (strMember.Find("m_b") == 0) return "BOOL";
	return "";
}

CString GetInit(CString strMember)
{
	CString sInit;
	if (strMember.Find("m_str") == 0) sInit.Format("%s = _T(\"\");", strMember);
	else if (strMember.Find("m_dt") == 0) sInit.Format("%s = 0.0;", strMember);
	else if (strMember.Find("m_n") == 0) sInit.Format("%s = 0;", strMember);
	else if (strMember.Find("m_f") == 0) sInit.Format("%s = 0.0;", strMember);
	else if (strMember.Find("m_rgb") == 0) sInit.Format("%s = 0;", strMember);
	else if (strMember.Find("m_b") == 0) sInit.Format("%s = FALSE;", strMember);
	return sInit;
}



CString GetBase(CString strMember)
{
	if (strMember.Find("m_str") == 0) return strMember.Right(strMember.GetLength() - 5);
	if (strMember.Find("m_dt") == 0) return strMember.Right(strMember.GetLength() - 4);
	if (strMember.Find("m_n") == 0) return strMember.Right(strMember.GetLength() - 3);
	if (strMember.Find("m_f") == 0) return strMember.Right(strMember.GetLength() - 3);
	if (strMember.Find("m_rgb") == 0) return strMember.Right(strMember.GetLength() - 5);
	if (strMember.Find("m_b") == 0) return strMember.Right(strMember.GetLength() - 3);
	return "";
}


CString GetPrefix(CString strMember)
{
	if (strMember.Find("m_str") == 0) return "str";
	if (strMember.Find("m_dt") == 0) return "dt";
	if (strMember.Find("m_n") == 0) return "n";
	if (strMember.Find("m_f") == 0) return "f";
	if (strMember.Find("m_rgb") == 0) return "rgb";
	if (strMember.Find("m_b") == 0) return "b";
	return "";
}


BOOL ValidName(CString s)
{
	if (s.Find("m_str") != 0 &&
			s.Find("m_dt") != 0 &&
			s.Find("m_n") != 0 &&
			s.Find("m_f") != 0 &&
			s.Find("m_rgb") != 0 &&
			s.Find("m_b") != 0) return FALSE;

	int n = 0;
	for (n = 0; n < s.GetLength(); ++n)
	{
		if ((s.GetAt(n) <= 'Z' && s.GetAt(n) >= 'A') ||
			(s.GetAt(n) <= 'z' && s.GetAt(n) >= 'a') ||
			(s.GetAt(n) <= '9' && s.GetAt(n) >= '1') ||
			s.GetAt(n) == '_') continue;
		else return FALSE;
	}
	return TRUE;
}			
			


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
President Starpoint Software Inc.
United States United States
Bob Pittenger is founder and President of Starpoint Software Inc. He holds a B.A. degree from Miami University, M.S. and Ph.D. degrees from Purdue University, and an MBA from Xavier University. He has been programming since 1993, starting with Windows application development in C++/MFC and moving to C# and .NET around 2005 and is a .NET Microsoft Certified Professional Developer.

Bob is the author of two books:
Billionaire: How the Ultra-Rich Built Their Fortunes Through Good and Evil and What You Can Learn from Them
and
Wealthonomics: The Most Important Economic and Financial Concepts that Can Make You Rich Fast.
Visit http://www.billionairebook.net for more information.

Comments and Discussions