292 lines
6.7 KiB
C++
292 lines
6.7 KiB
C++
// ==========================================================================
|
|
// Class Implementation : COXString
|
|
// ==========================================================================
|
|
|
|
// Source file : stringx.cpp
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "xstring.h"
|
|
#include <ctype.h>
|
|
|
|
#include "UTBStrOp.h"
|
|
#include "UTB64Bit.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
#define DECIMAL_CHARACTER_STRING_LENGTH 2 // Including 0-termination
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Definition of static members
|
|
TCHAR pszDecimalDestination[2];
|
|
LPTSTR pszDecimalDefault = _T(",");
|
|
// ... The sequential-evaluation operator (comma operator) is used here
|
|
TCHAR COXString::cDecimalCharacter(
|
|
(::GetProfileString(_T("Intl"), _T("sDecimal"), pszDecimalDefault, pszDecimalDestination, DECIMAL_CHARACTER_STRING_LENGTH),
|
|
*pszDecimalDestination));
|
|
|
|
|
|
// Data members -------------------------------------------------------------
|
|
// protected:
|
|
// private:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
// public:
|
|
|
|
COXString::COXString()
|
|
{
|
|
}
|
|
|
|
COXString::COXString(LPCTSTR psz)
|
|
{
|
|
*((CString*)this) = psz;
|
|
}
|
|
|
|
COXString::COXString(const CString& sSource)
|
|
{
|
|
*((CString*)this) = sSource;
|
|
}
|
|
|
|
COXString::COXString(LONG nSource)
|
|
{
|
|
TCHAR pszBuffer[20];
|
|
UTBStr::ltot(nSource, pszBuffer, 20, 10);
|
|
*this = COXString(&pszBuffer[0]);
|
|
}
|
|
|
|
COXString::COXString(const COXString& sString)
|
|
: CString(sString)
|
|
{
|
|
|
|
}
|
|
|
|
COXString& COXString::operator=(const COXString& sString)
|
|
{
|
|
CString::operator=(sString);
|
|
|
|
return *this;
|
|
}
|
|
|
|
void COXString::LTrim()
|
|
{
|
|
int nStringIndex = 0;
|
|
int nLength = GetLength();
|
|
|
|
// find first non-space character
|
|
LPCTSTR lpsz = *this;
|
|
while (_istspace(*lpsz))
|
|
#ifdef WIN32
|
|
lpsz = _tcsinc(lpsz);
|
|
#else
|
|
lpsz++;
|
|
#endif
|
|
|
|
// fix up data and length
|
|
#if _MFC_VER < 0x0700
|
|
nStringIndex = lpsz - m_pchData;
|
|
#else
|
|
nStringIndex = PtrToInt(lpsz - GetBuffer());
|
|
#endif
|
|
if (nStringIndex == nLength)
|
|
*this = COXString(_T(""));
|
|
else
|
|
*this = Mid(nStringIndex);
|
|
}
|
|
|
|
void COXString::RTrim()
|
|
{
|
|
int nStringIndex = GetLength() - 1;
|
|
while((0 <= nStringIndex) && _istspace(GetAt(nStringIndex)) )
|
|
nStringIndex--;
|
|
*this = Left(nStringIndex + 1);
|
|
|
|
}
|
|
|
|
void COXString::XTrim()
|
|
{
|
|
// Optimisation :
|
|
// The output string sOut is initialized by the value of the string
|
|
// The real significant characters in sOut are from position 0 till nPosOut - 1
|
|
// Characters are thus added by overwriting a character in sOut and incrementing nPosOut by 1.
|
|
// Now memory is allocated only once (at initialisation of sOut)
|
|
// When you would start with an empty string and would concatenate characters
|
|
// then extra memory must be allocated frequently (overhead).
|
|
|
|
COXString sOut(*this);
|
|
int nPosIn = 0;
|
|
int nPosOut = 0;
|
|
BOOL bSpace = FALSE;
|
|
|
|
while (nPosIn < GetLength())
|
|
{
|
|
if (_istspace(GetAt(nPosIn)))
|
|
if (bSpace)
|
|
{
|
|
// ... Second white space character encountered
|
|
// Skip this character (do not copy)
|
|
nPosIn++;
|
|
}
|
|
else
|
|
{
|
|
// ... First white space character encountered
|
|
// Copy space (all white space characters are replaced by a space)
|
|
sOut.SetAt(nPosOut++, _T(' '));
|
|
nPosIn++;
|
|
bSpace = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// ... Copying a non white space character
|
|
sOut.SetAt(nPosOut++, GetAt(nPosIn++));
|
|
bSpace = FALSE;
|
|
}
|
|
}
|
|
*this = sOut.Left(nPosOut);
|
|
}
|
|
|
|
int COXString::GetInt() const
|
|
{
|
|
return _ttoi(*this);
|
|
}
|
|
|
|
long COXString::GetLongInt() const
|
|
{
|
|
return _ttol(*this);
|
|
}
|
|
|
|
BOOL COXString::IsInt()
|
|
{
|
|
for (int nIndex = 0; nIndex < GetLength(); nIndex++)
|
|
if (!_istdigit(GetAt(nIndex)))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COXString::IsNumber()
|
|
{
|
|
LPCTSTR pc = *this;
|
|
BOOL bDigit = FALSE;
|
|
|
|
// Skip white space characters
|
|
while (_istspace(*pc))
|
|
pc++;
|
|
// Skip sign
|
|
if ((*pc == _T('-')) || (*pc == _T('+')))
|
|
pc++;
|
|
// Skip digits
|
|
while (_istdigit(*pc))
|
|
{
|
|
pc++;
|
|
bDigit = TRUE;
|
|
}
|
|
// Skip decimal sign
|
|
if (*pc == cDecimalCharacter)
|
|
pc++;
|
|
if (!bDigit && !_istdigit(*pc))
|
|
return FALSE;
|
|
// Skip digits
|
|
while (_istdigit(*pc))
|
|
pc++;
|
|
// Skip exponent sign and rest
|
|
if ((*pc == _T('E')) || (*pc == _T('e')) || (*pc == _T('D')) || (*pc == _T('d')))
|
|
{
|
|
pc++;
|
|
// Skip sign
|
|
if ((*pc == _T('-')) || (*pc == _T('+')))
|
|
pc++;
|
|
// Skip digits
|
|
if (!_istdigit(*pc))
|
|
// Exponent sign is not followed by digits
|
|
return FALSE;
|
|
while (_istdigit(*pc))
|
|
pc++;
|
|
}
|
|
// Skip white space characters
|
|
while (_istspace(*pc))
|
|
pc++;
|
|
|
|
// Pointer should not be behind the end of the string
|
|
ASSERT(pc <= (((LPCTSTR)*this) + GetLength()));
|
|
|
|
// Must be at the end of the string by now, otherwise the number is not valid
|
|
return (*pc == _T('\0'));
|
|
}
|
|
|
|
void COXString::Format(LPCTSTR pszFormat, LPCTSTR* rgpsz, int nString)
|
|
{
|
|
// NOTE: will not work for strings > 255 characters
|
|
|
|
int nTotalLen = PtrToInt(_tcslen(pszFormat));
|
|
int i = 0;
|
|
for (i = 0; i < nString; i++)
|
|
{
|
|
if (rgpsz[i] != NULL)
|
|
nTotalLen += PtrToInt(_tcslen(rgpsz[i]));
|
|
}
|
|
|
|
LPCTSTR pchSrc = pszFormat;
|
|
LPTSTR pchDestBegin = GetBuffer(nTotalLen+1);
|
|
LPTSTR pchDest = pchDestBegin;
|
|
while (*pchSrc != '\0')
|
|
{
|
|
if (pchSrc[0] == _T('%') && (pchSrc[1] >= _T('1') && pchSrc[1] <= _T('9')))
|
|
{
|
|
i = pchSrc[1] - _T('1');
|
|
pchSrc += 2;
|
|
if (i >= nString)
|
|
{
|
|
TRACE1("COXString::Format : Illegal string index requested %d\n", i);
|
|
*pchDest++ = _T('?');
|
|
}
|
|
else if (rgpsz[i] != NULL)
|
|
{
|
|
UTBStr::tcscpy(pchDest, nTotalLen, rgpsz[i]);
|
|
pchDest += _tcslen(pchDest);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pchDest++ = *pchSrc++;
|
|
}
|
|
}
|
|
|
|
|
|
ReleaseBuffer((int)((LPCTSTR)pchDest - (LPCTSTR)pchDestBegin));
|
|
// Release will assert if we went too far
|
|
}
|
|
|
|
void COXString::BarToNull()
|
|
{
|
|
int nLength = GetLength();
|
|
LPTSTR pszData = GetBuffer(nLength);
|
|
while ((pszData = _tcschr(pszData, _T('|'))) != NULL)
|
|
*pszData++ = _T('\0');
|
|
ReleaseBuffer(nLength);
|
|
ASSERT(GetLength() == nLength);
|
|
}
|
|
|
|
COXString::~COXString()
|
|
{
|
|
}
|
|
|
|
// protected:
|
|
|
|
// private:
|
|
|
|
// ==========================================================================
|
|
|