CString extension for directory names

 Download Source Code


Profound programming rule learned the hard way: Never assume anything. So I got pretty tired of always checking a path in a CString to ensure that it terminated in a backslash before adding any additional names. I wrote the CDirectoryString class to handle this for me, and as I was writing an installation program at the time, I added some macro's for obtaining current context directory names.

The macros:

[windowsdir] - the windows directory
[systemdir] - the windows system directory
[currentdir] - the current directory
[datedir] - a directory name based on the current date

The CDirectoryString class will always check your termination and append the backslash if its missing. If you include one or more of the macros it will translate them during assigment or concatenation.

Also included are four public member functions:

void GetWindowsDirectory();
void GetSystemDirectory();
void GetCurrentDirectory();
void GetDateDirectory();
Calling either of these functions will REPLACE the current string contents with the content described by the function name.

Example:
CDirectoryString strTarget="[systemdir]";
printf(strTarget);

//output:
c:\windows\system\

another example:
CDirectoryString strTarget="c:\\outbox\\sessions[datedir]\\incoming";
printf(strTarget);

//output:
d:\outbox\sessions\08061998\incoming\

last but not least:
CDirectoryString strTarget;
strTarget.GetCurrentDirectory();
printf(strTarget);

//output:
c:\Program Files\

If you have any changes, new macros or perhaps I missed something, please email me. The source code:

DirectoryString.h

class CDirectoryString : public CString  
{
	public:
		CDirectoryString();
		CDirectoryString(const CString& stringSrc);
		CDirectoryString(LPCTSTR lpsz);
		CDirectoryString(LPCWSTR lpsz);
		virtual ~CDirectoryString();
		const CString& operator=(const CString& stringSrc);
		const CString& operator=(LPCTSTR lpsz);
		const CString& operator+=(LPCTSTR lpsz);
		const CString& operator+=(TCHAR ch);
		const CString& operator+=(const CString& string);
		void GetWindowsDirectory();
		void GetSystemDirectory();
		void GetCurrentDirectory();
		void GetDateDirectory();
		void Fixate();
		void ProcessMacros(const char* szSrc);
	protected:
		void ExpandMacro(char* pchMacroString);
		int GetMacroIndex(char* pchMacroString);
		void Concat(const char* pchString);
		void GetDateString(char* pchBuffer);
};
DirectoryString.cpp

CDirectoryString::CDirectoryString()
{
}

CDirectoryString::CDirectoryString(const CString& stringSrc)
{
	ProcessMacros(stringSrc);
}

CDirectoryString::CDirectoryString(LPCTSTR lpsz)
{
	ProcessMacros(lpsz);
}

CDirectoryString::CDirectoryString(LPCWSTR lpsz)
{
	CString::CString(lpsz);
	ProcessMacros(m_pchData);
}

CDirectoryString::~CDirectoryString()
{
}

const CString& CDirectoryString::operator=(const CString& stringSrc)
{	
	ProcessMacros(stringSrc);
	return *this;
}

const CString& CDirectoryString::operator=(LPCTSTR lpsz)
{	
	ProcessMacros(lpsz);
	return *this;
}

const CString& CDirectoryString::operator+=(LPCTSTR lpsz)
{
	*(CString*)this+=(lpsz);
	ProcessMacros(m_pchData);
	return *this;
}

const CString& CDirectoryString::operator+=(TCHAR ch)
{
	*(CString*)this+=(ch);
	ProcessMacros(m_pchData);
	return *this;
}

const CString& CDirectoryString::operator+=(const CString& string)
{
	*(CString*)this+=(string);
	ProcessMacros(m_pchData);
	return *this;
}

void CDirectoryString::ProcessMacros(const char* szSrc)
{
	if(!szSrc)
	{
		return;
	}
	int nOriginalLength=strlen(szSrc);

	char* pchOriginal=new char[nOriginalLength+1];
	strcpy(pchOriginal,szSrc);
	Release();

	char* pchAnchor=pchOriginal;
	char* pchLead=strchr(pchOriginal,'[');
	while(pchLead)
	{
		if(pchLead!=pchAnchor)
		{
			pchLead[0]=0;
			Concat(pchAnchor);
			pchLead[0]='[';
		}
		pchAnchor=pchLead;
		//scan through to the end of macro
		pchLead=strchr(pchLead,']');
		if(pchLead)
		{
			pchLead[0]=0;
			pchAnchor++;
			ExpandMacro(pchAnchor);
			pchLead[0]=']';
			pchAnchor=pchLead;
			pchAnchor++;
			pchLead=strchr(pchLead,'[');
		}
		else
		{
			break;
		}
	}
	if(strlen(pchAnchor))
	{
		Concat(pchAnchor);
	}
	delete[] pchOriginal;
	Fixate();
}

void CDirectoryString::ExpandMacro(char* pchMacroString)
{
	if(pchMacroString)
	{
		char szTemp[MAX_PATH];
		switch(GetMacroIndex(pchMacroString))
		{
			case 0:
				::GetWindowsDirectory(szTemp,MAX_PATH);
				break;
			case 1:
				::GetSystemDirectory(szTemp,MAX_PATH);
				break;
			case 2:
				::GetCurrentDirectory(MAX_PATH,szTemp);
				break;
			case 3:
				GetDateString(szTemp);
				break;
			default:
				//unknown macro, return
				return;
		}
		if(szTemp[strlen(szTemp)-1]!=92)
		{
			strcat(szTemp,"\\");
		}
		Concat(szTemp);
	}
}

void CDirectoryString::Concat(const char* pchString)
{
	CStringData* pOldData = GetData();
	ConcatCopy(GetData()->nDataLength, m_pchData, strlen(pchString),pchString);
	ASSERT(pOldData != NULL);
	CString::Release(pOldData);
}

void CDirectoryString::GetWindowsDirectory()
{
	char szTemp[MAX_PATH];
	::GetWindowsDirectory(szTemp,MAX_PATH);
	*this=szTemp;
	Fixate();
}

void CDirectoryString::GetSystemDirectory()
{
	char szTemp[MAX_PATH];
	::GetSystemDirectory(szTemp,MAX_PATH);
	*this=szTemp;
	Fixate();
}

void CDirectoryString::GetCurrentDirectory()
{
	char szTemp[MAX_PATH];
	::GetCurrentDirectory(MAX_PATH,szTemp);
	*this=szTemp;
	Fixate();
}

void CDirectoryString::GetDateDirectory()
{
	char szTemp[MAX_PATH];
	GetDateString(szTemp);
	*this=szTemp;
	Fixate();
}

void CDirectoryString::GetDateString(char* pchBuffer)
{
	if(!pchBuffer)
	{
		return;
	}
	char szTemp[5];
	SYSTEMTIME now;
	GetLocalTime(&now);
	sprintf(pchBuffer,"%02d",now.wDay);
	sprintf(szTemp,"%02d",now.wMonth);
	strcat(pchBuffer,szTemp);
	sprintf(szTemp,"%04d",now.wYear);
	strcat(pchBuffer,szTemp);
}

void CDirectoryString::Fixate()
{
	if(m_pchData[GetLength()-1]!=92)
	{
		*this+="\\";	
	}
}

int CDirectoryString::GetMacroIndex(char* pchMacroString)
{
	if(!pchMacroString)
	{
		return -1;
	}
	if(strcmp(pchMacroString,"windowsdir")==0)
	{
		return 0;
	}
	if(strcmp(pchMacroString,"systemdir")==0)
	{
		return 1;
	}
	if(strcmp(pchMacroString,"currentdir")==0)
	{
		return 2;
	}
	if(strcmp(pchMacroString,"datedir")==0)
	{
		return 3;
	}
	return -1;
}

Last updated: 8 July 1998



Comments

  • Program Files directory

    Posted by Legacy on 05/08/2003 12:00am

    Originally posted by: Evolutiv Sequence

    CString bname;
    
    HKEY hKey = 0;
    DWORD dwBufSize=MAX_PATH,dwType;
    char szObject[MAX_PATH];
    szObject[0]=0;

    HRESULT hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"), 0,KEY_READ, &hKey);
    if (hr == ERROR_SUCCESS)
    {
    if(RegQueryValueEx(hKey,"ProgramFilesDir",NULL, &dwType, (unsigned char*)szObject,&dwBufSize)==ERROR_SUCCESS)
    bname = szObject;
    RegCloseKey(hKey);
    AfxMessageBox(bname);
    }

    Reply
  • More fields!

    Posted by Legacy on 03/15/1999 12:00am

    Originally posted by: Victor Boctor

    I would suggest addition of the following fie:
    1. Program Files directory.
    2. Current user profile directory.
    3. System/System32 directories.
    4. Windows temp directory.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Live Event Date: October 29, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this eSeminar, Gene Kim will discuss these survey findings and will share woeful tales of artifact management gone wrong! Gene will also share examples of how …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds