489 lines
14 KiB
C++
489 lines
14 KiB
C++
//------------------------------------------------------------------------------
|
|
// FILE NAME: StringParser.cpp
|
|
// HEADER: StringParser.h
|
|
//
|
|
// PURPOSE: Implementation of the CStringParser class.
|
|
//
|
|
// DESCRIPTION: This class acepts a string and immediately parses it into
|
|
// separate fields based on the delimiter character specified by
|
|
// the programmer. The separated fields are stored in a
|
|
// CStringArray, and the 0th element in the array contains the
|
|
// original string. Access to the separated fields is 1-based
|
|
// (the first field is in index 1, and so on).
|
|
//
|
|
// If you are parsing quoted strings, it is IMPARATIVE that the
|
|
// quoted strings be formatted correctly. Otherwise you will get
|
|
// what appears to be bizarre results.
|
|
//
|
|
// DISCLAIMER: At first glance, it may seem like the code is somewhat verbose
|
|
// and I might have taken the long way around to perform some
|
|
// tasks, but I think it makes it easier for someone else to follow
|
|
// when I do that. Maintainability is probably the most important
|
|
// aspect of coding (after reliability of course).
|
|
//
|
|
// CHANGE HISTORY:
|
|
// DATE INIT CHANGE DESCRIPTION
|
|
// -------- ---- --------------------------------------------------------
|
|
// 07/20/2000 jms Initial code completed.
|
|
// 08/09/2000 jms Added a way to submit a new string to facilitate the use
|
|
// of the same object instance when a subsewquent string
|
|
// needs to be parsed.
|
|
// 01/12/2001 jms Added a way to find strings withion the parsed results.
|
|
// 01/20/2001 jms Added support for quoted strings.
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "StringParser.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::CStringParser()
|
|
//
|
|
// PURPOSE: Constructor - initializes the array of strings and calls the
|
|
// ParseString() function.
|
|
//
|
|
// PARMETERS: CString sString The string to be parsed
|
|
// char cDelimiter The delimiter character used to parse the
|
|
// string
|
|
//
|
|
// RETURNS: N/A
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- -----------------------------------------------------------
|
|
// 07/20/2000 jms Initial development.
|
|
//------------------------------------------------------------------------------
|
|
CStringParser::CStringParser(CString sString, char cDelimiter)
|
|
{
|
|
m_aStrings.SetSize(0,10);
|
|
ResetOriginalString(sString, cDelimiter);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::CStringParser()
|
|
//
|
|
// PURPOSE: Constructor - initializes the array of strings and calls the
|
|
// ParseString() function.
|
|
//
|
|
// PARMETERS: CString sString The string to be parsed.
|
|
// char cDelimiter The delimiter character used to parse the
|
|
// string.
|
|
// char cQuoter The quote character we should be looking
|
|
// for.
|
|
//
|
|
// RETURNS: N/A
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- --------------------------------------------------------
|
|
// 01/20/2001 jms Added overloaded version of constructor to support
|
|
// quoted strings.
|
|
//------------------------------------------------------------------------------
|
|
CStringParser::CStringParser(CString sString, char cDelimiter, char cQuoter)
|
|
{
|
|
m_aStrings.SetSize(0,10);
|
|
ResetOriginalString(sString, cDelimiter, cQuoter);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::CStringParser()
|
|
//
|
|
// PURPOSE: Constructor - does nothing
|
|
//
|
|
// PARMETERS: CString sString The string to be parsed.
|
|
//
|
|
// RETURNS: N/A
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- --------------------------------------------------------
|
|
// 04/25/2001 jc Added overloaded version of constructor to support
|
|
// initialization without other data
|
|
//------------------------------------------------------------------------------
|
|
CStringParser::CStringParser()
|
|
{
|
|
m_aStrings.SetSize(0,10);
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::~CStringParser()
|
|
//
|
|
// PURPOSE: Destructor - removes all of the array elements from the
|
|
// CStringArray.
|
|
//
|
|
// PARMETERS: None
|
|
//
|
|
// RETURNS: None
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- -----------------------------------------------------------
|
|
// 07/20/2000 jms Initial development.
|
|
// 08/09/2000 jms Added call to new Clear() function.
|
|
//------------------------------------------------------------------------------
|
|
CStringParser::~CStringParser()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::Clear()
|
|
//
|
|
// PURPOSE: Clears the string table.
|
|
//
|
|
// PARMETERS: None
|
|
//
|
|
// RETURNS: None
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- -----------------------------------------------------------
|
|
// 08/09/2000 jms Added function.
|
|
//------------------------------------------------------------------------------
|
|
void CStringParser::Clear()
|
|
{
|
|
if (m_nCount > 0)
|
|
{
|
|
m_aStrings.RemoveAll();
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::ResetOriginalString()
|
|
//
|
|
// PURPOSE: Clears the string table.
|
|
//
|
|
// PARMETERS: None
|
|
//
|
|
// RETURNS: None
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- -----------------------------------------------------------
|
|
// 08/09/2000 jms Added function.
|
|
//------------------------------------------------------------------------------
|
|
void CStringParser::ResetOriginalString(CString sString, char cDelimiter)
|
|
{
|
|
Clear();
|
|
m_aStrings.Add(sString);
|
|
m_cDelimiter = cDelimiter;
|
|
m_cQuoter = '\0';
|
|
m_nCount = 0;
|
|
ParseString();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::ResetOriginalString()
|
|
//
|
|
// PURPOSE: Clears the string table.
|
|
//
|
|
// PARMETERS: None
|
|
//
|
|
// RETURNS: None
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- -----------------------------------------------------------
|
|
// 08/09/2000 jms Added function.
|
|
//------------------------------------------------------------------------------
|
|
void CStringParser::ResetOriginalString(CString sString, char cDelimiter, char cQuoter)
|
|
{
|
|
Clear();
|
|
m_aStrings.Add(sString);
|
|
m_cDelimiter = cDelimiter;
|
|
m_cQuoter = cQuoter;
|
|
m_nCount = 0;
|
|
ParseStringWithQuoter();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::GetField()
|
|
//
|
|
// PURPOSE: Returns the CString stored in the array element specified by
|
|
// the nIndex parameter. If the specified index is greater than
|
|
// the number of elements, it is an error.
|
|
//
|
|
// PARMETERS: int nIndex The index of the desired array item.
|
|
//
|
|
// RETURNS: CString sBuffer the string retrieved from the array.
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- -----------------------------------------------------------
|
|
// 07/20/2000 jms Initial development.
|
|
//------------------------------------------------------------------------------
|
|
CString CStringParser::GetField(int nIndex)
|
|
{
|
|
CString sBuffer;
|
|
sBuffer.Empty();
|
|
if (m_nCount >= nIndex)
|
|
{
|
|
sBuffer = m_aStrings.GetAt(nIndex);
|
|
}
|
|
else
|
|
{
|
|
sBuffer = "ERROR: Array index out of range.";
|
|
}
|
|
return sBuffer;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::ParseString()
|
|
//
|
|
// PURPOSE: Separates the fields out of a copy of the original string by
|
|
// searching for the specified delimiter character. As the string
|
|
// is searched, it becomes shorter by deleting the most recently
|
|
// found field (and the next delimiter, if one exists) from the
|
|
// beginning of itself.
|
|
//
|
|
// PARMETERS: None
|
|
//
|
|
// RETURNS: int The number of fields found in the original string.
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- -----------------------------------------------------------
|
|
// 07/20/2000 jms Initial development.
|
|
//------------------------------------------------------------------------------
|
|
int CStringParser::ParseString()
|
|
{
|
|
// get a copy of the string
|
|
CString sWorkString = GetOriginalString();
|
|
CString sBuffer;
|
|
int pos = 0;
|
|
|
|
m_nCount = 0;
|
|
|
|
// while the string is not empty...
|
|
while (!sWorkString.IsEmpty())
|
|
{
|
|
// find the position of the next delimiter
|
|
pos = sWorkString.Find(m_cDelimiter);
|
|
// if a delimiter is found
|
|
if (pos >= 0)
|
|
{
|
|
// store the field
|
|
sBuffer = sWorkString.Left(pos);
|
|
// delete the field and the found delimiter
|
|
sWorkString = sWorkString.Mid(pos + 1);
|
|
}
|
|
// otherwise, if a delimiter isn't found
|
|
else
|
|
{
|
|
// the rest of the string is a field
|
|
sBuffer = sWorkString;
|
|
// and make the string empty
|
|
sWorkString.Empty();
|
|
}
|
|
// add the field to the CStringArray
|
|
m_aStrings.Add(sBuffer);
|
|
// increment the counter
|
|
m_nCount++;
|
|
}
|
|
return m_nCount;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::ParseStringWithQuoter()
|
|
//
|
|
// PURPOSE: Separates the fields out of a copy of the original string by
|
|
// searching for the specified delimiter character. As the string
|
|
// is searched, it becomes shorter by deleting the most recently
|
|
// found field (and the next delimiter, if one exists) from the
|
|
// beginning of itself.
|
|
//
|
|
// This version of ParseString handles a quoted string. A quoted
|
|
// string may have the specified delimiter in an embedded between
|
|
// quote characters, and this instance of the delimiter must be
|
|
// ignored.
|
|
//
|
|
// PARMETERS: None
|
|
//
|
|
// RETURNS: int The number of fields found in the original string.
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- -----------------------------------------------------------
|
|
// 01/20/2001 jms Added this function.
|
|
//------------------------------------------------------------------------------
|
|
int CStringParser::ParseStringWithQuoter()
|
|
{
|
|
// get a copy of the string
|
|
CString sWorkString = GetOriginalString();
|
|
CString sBuffer;
|
|
int pos = 0;
|
|
|
|
m_nCount = 0;
|
|
|
|
// while the string is not empty...
|
|
while (!sWorkString.IsEmpty())
|
|
{
|
|
// find the position of the next delimiter
|
|
pos = sWorkString.Find(m_cDelimiter);
|
|
// if a delimiter is found
|
|
if (pos >= 0)
|
|
{
|
|
// if the first character is the specified quoter
|
|
if (sWorkString.GetAt(0) == m_cQuoter)
|
|
{
|
|
// we have work to do
|
|
sBuffer.Empty();
|
|
int nLength = 0;
|
|
BOOL bDone = FALSE;
|
|
|
|
do
|
|
{
|
|
//add the next character
|
|
sBuffer += CString(sWorkString.GetAt(nLength));
|
|
nLength++;
|
|
|
|
// if string is longer than one char and both ends are the quote char
|
|
if (nLength > 1 && sBuffer.GetAt(nLength - 1) == m_cQuoter)
|
|
{
|
|
// we are done
|
|
bDone = TRUE;
|
|
}
|
|
} while (!bDone);
|
|
|
|
// adjust our work string
|
|
sWorkString = sWorkString.Mid(nLength + 1);
|
|
}
|
|
else
|
|
{
|
|
sBuffer = sWorkString.Left(pos);
|
|
sWorkString = sWorkString.Mid(pos + 1);
|
|
}
|
|
}
|
|
// otherwise, if a delimiter isn't found
|
|
else
|
|
{
|
|
// the rest of the string is a field
|
|
sBuffer = sWorkString;
|
|
// and make the string empty
|
|
sWorkString.Empty();
|
|
}
|
|
// add the field to the CStringArray
|
|
m_aStrings.Add(sBuffer);
|
|
// increment the counter
|
|
m_nCount++;
|
|
}
|
|
|
|
return m_nCount;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::FindExact()
|
|
//
|
|
// PURPOSE: Searches the entire array (excluding item 0) for an exact match
|
|
// of the specified string.
|
|
//
|
|
// PARMETERS: CString sText The string we're looking for
|
|
// int& nElement The element number of the found string
|
|
// or SP_NOTFOUND if not found.
|
|
// BOOL bCaseSensitive Case sensitivity matters
|
|
//
|
|
// RETURNS: CString The matching string if any.
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// ---------- ---- -----------------------------------------------------------
|
|
// 01/12/2001 jms Added function.
|
|
//------------------------------------------------------------------------------
|
|
CString CStringParser::FindExact(CString sText, int* nElement, BOOL bCaseSensitive/*=FALSE*/)
|
|
{
|
|
if (!bCaseSensitive)
|
|
{
|
|
sText.MakeUpper();
|
|
}
|
|
*nElement = SP_NOTFOUND;
|
|
|
|
CString sResult = "";
|
|
BOOL bFound = FALSE;
|
|
|
|
for (int i = 1; i <= m_nCount; i++)
|
|
{
|
|
sResult = m_aStrings.GetAt(i);
|
|
if (!bCaseSensitive)
|
|
{
|
|
sResult.MakeUpper();
|
|
}
|
|
if (sResult == sText)
|
|
{
|
|
*nElement = i;
|
|
sResult = m_aStrings.GetAt(i);
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
sResult.Empty();
|
|
}
|
|
return sResult;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// NAME: CStringParser::Find()
|
|
//
|
|
// PURPOSE: Searches the entire array (excluding item 0) for any string that
|
|
// contains the specified string.
|
|
//
|
|
// PARMETERS: CString sText The string we're looking for
|
|
// int& nElement The element number of the found string
|
|
// or SP_NOTFOUND if not found.
|
|
// BOOL bCaseSensitive Case sensitivity matters
|
|
//
|
|
// RETURNS: CString The matching string if any.
|
|
//
|
|
// CHANGE LOG:
|
|
// DATE INIT DESCRIPTION
|
|
// -------- ---- -------------------------------------------------------------
|
|
// 01/12/01 jms Added function.
|
|
//------------------------------------------------------------------------------
|
|
CString CStringParser::Find(CString sText, int* nElement, BOOL bCaseSensitive/*=FALSE*/)
|
|
{
|
|
if (!bCaseSensitive)
|
|
{
|
|
sText.MakeUpper();
|
|
}
|
|
*nElement = SP_NOTFOUND;
|
|
|
|
CString sResult = "";
|
|
BOOL bFound = FALSE;
|
|
for (int i = 1; i <= m_nCount; i++)
|
|
{
|
|
sResult = m_aStrings.GetAt(i);
|
|
if (!bCaseSensitive)
|
|
{
|
|
sResult.MakeUpper();
|
|
}
|
|
if (sResult.Find(sText) >= 0)
|
|
{
|
|
//save the position at which we found the string
|
|
*nElement = i;
|
|
// get it again (so we can get it in it's native form)
|
|
sResult = m_aStrings.GetAt(i);
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
sResult.Empty();
|
|
}
|
|
return sResult;
|
|
}
|
|
|