#include "stdafx.h"
#include "CeString.h"
// For an empty string, m_pchData will point here
// (note: avoids special case of checking for NULL m_pchData)
// empty string data (and locked)
int CeStringRep::s_rgNullData[] = { 0, 0, 0 };
CeStringRep* CeStringRep::s_cerepNullRep = (CeStringRep*) s_rgNullData;
LPCTSTR CeStringRep::s_lpszCeEmpty = (LPCTSTR)(((BYTE*)&s_rgNullData)+sizeof(CeStringRep));
///////////////////////////////////////////////////////////////////////////////
// Windows CE specific conversion
wchar_t* wce_AsciiToWide( wchar_t* ws, const char* s )
{
wchar_t* pszSave = ws;
while (*ws++ = (wchar_t) *s++)
;
return (pszSave);
}
#ifdef _WIN32_WCE
const CeString& CeString::operator= (const char *lps)
{
Release();
int nLen = strlen(lps);
CeStringRep* pRep = CeStringRep::AllocBuf(nLen);
m_pStr = pRep->GetString();
wce_AsciiToWide(m_pStr, lps);
return *this;
}
#endif
const CeString& CeString::operator= (const CeString& strSrc)
{
if (strSrc.m_pStr != m_pStr)
{
Release(); // checks for null
m_pStr = strSrc.m_pStr;
if (0 != GetRep()->GetLength())
GetRep()->AddRef();
}
return *this;
}
const CeString& CeString::operator= (LPCTSTR lpsz)
{
Assign(lpsz);
return *this;
}
void CeString::Append(LPCTSTR lpsz, int nChars/*=-1*/)
{
if (-1 == nChars)
nChars = lstrlen(lpsz);
// concatenating an empty string is a no-op!
if (nChars == 0)
return;
if (0 == Length())
Assign(lpsz, nChars);
else
{
// allocate and concatinate strings
CeStringRep* pRep = CeStringRep::AllocBuf(Length() + nChars);
memcpy(pRep->GetString(), m_pStr, GetRep()->GetLength() * sizeof TCHAR);
memcpy(pRep->GetString() + GetRep()->GetLength(), lpsz, nChars * sizeof TCHAR);
// free reference to old string
Release();
// assign
m_pStr = pRep->GetString();
}
}
const CeString& CeString::operator+ (const CeString& T)
{
Append(T);
return *this;
}
const CeString& CeString::operator+ (LPCTSTR str)
{
Append(str);
return *this;
}
void CeString::Set(char ch, int nChars)
{
// get rid of old
Release();
CeStringRep* pRep = CeStringRep::AllocBuf(nChars);
m_pStr = pRep->GetString();
for (int ii = 0; ii < nChars; ii++)
m_pStr[ii] = ch;
}
void CeString::Set(char ch)
{
CopyOnWrite();
_tcsset (m_pStr, ch);
}
#ifdef UNICODE
# ifndef _ltot
# define _ltot _ltow
# define _itot _itow
# define _ultot _ultow
# endif
#else
# ifndef _ltot
# define _ltot _ltoa
# define _itot _itoa
# define _ultot _ultoa
# endif
#endif
void CeString::SetShort(short s, int b/*=10*/)
{
// maximum of 33 characters according to doco
TCHAR szBuf[33];
Assign( _itot(s, szBuf, b) );
}
void CeString::SetLong(long l, int b/*=10*/)
{
// maximum of 33 characters according to doco
TCHAR szBuf[33];
Assign( _ltot(l, szBuf, b) );
}
void CeString::SetULong(unsigned long ul, int b/*=10*/)
{
// maximum of 33 characters according to doco
TCHAR szBuf[33];
Assign( _ultot(ul, szBuf, b) );
}
void CeString::SetDouble(double dValue, int nPrecision)
{
TCHAR szOut[33];
TCHAR* pszBuf = szOut;
int nDecimal;
int nSign;
char* pszResult = _fcvt( dValue, nPrecision, &nDecimal, &nSign );
if (nSign)
*pszBuf++ = _T('-');
if (nDecimal <= 0)
{
*pszBuf++ = _T('0');
*pszBuf++ = _T('.');
for (int ii = nDecimal; ii < 0; ii++)
*pszBuf++ = _T('0');
}
else
{
for (int ii = 0; ii < nDecimal; ii++)
*pszBuf++ = *pszResult++;
*pszBuf++ = _T('.');
}
// append the remaining characters
while (*pszResult)
*pszBuf++ = *pszResult++;
*pszBuf++ = 0;
Assign(szOut, pszBuf - szOut - 1);
}
void CeString::Truncate(int nLen)
{
// check for noop
if (GetRep()->GetLength() >= nLen || nLen < 0)
return;
// copy to the new
CeStringRep* pRep = CeStringRep::AllocBuf(nLen);
memcpy(pRep->GetString(), m_pStr, Length() * sizeof TCHAR);
// Get rid of the old
Release();
// assign new
m_pStr = pRep->GetString();
}
void CeString::Trim()
{
RTrim();
LTrim();
}
void CeString::LTrim()
{
if (*m_pStr == 0 || ! _istspace(*m_pStr))
// noop
return;
int nLen = GetRep()->GetLength();
for (int ii = 0; ii < nLen && _istspace(m_pStr[ii]) ; ii++)
;
if (ii != nLen)
{
// all white space, set empty and release
Release();
}
else
{
// create a new string from the old
CeStringRep* pRep = CeStringRep::AllocBuf(nLen - ii);
memcpy(pRep->GetString(), m_pStr + ii, sizeof(TCHAR) * (nLen - ii + 1));
// free/release reference
Release();
// assign new reference
m_pStr = pRep->GetString();
}
}
void CeString::RTrim()
{
if (*m_pStr == 0 || ! _istspace(m_pStr[Length()-1]))
// noop
return;
for (int ii = GetRep()->GetLength()-1; ii >= 0 && _istspace(m_pStr[ii]) ; ii--)
;
if (ii < 0)
{
// all white space, set empty and release
Release();
}
else
{
// create a new string from the old
CeStringRep* pRep = CeStringRep::AllocBuf(ii);
memcpy(pRep->GetString(), m_pStr, sizeof(TCHAR) * (ii + 1));
// free/release reference
Release();
// assign new reference
m_pStr = pRep->GetString();
}
}
// Utility functions
// Use this function to retrieve the system error message string
// for a system error ID, e.g. Win32, COM or ActiveX error ID.
void CeString::FormatMessage(DWORD dwSystemErrorID)
{
LPVOID lpMsgBuf;
DWORD dwSize = ::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwSystemErrorID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf,
0,
NULL
);
if (0 != dwSize)
{
Assign((LPCTSTR)lpMsgBuf, dwSize);
// Free the buffer.
LocalFree(lpMsgBuf);
}
else
{
Format(_T("Error %d occured"), dwSystemErrorID);
}
}
LPTSTR CeString::GetBuffer(int nMinLen)
{
ASSERT(nMinLen >= 0);
if (0 == nMinLen)
return NULL;
if (nMinLen > Length())
{
// remove duplicate if any
CopyOnWrite();
// allocate a new copy and get the window text
CeStringRep* pRep = CeStringRep::AllocBuf(nMinLen);
return m_pStr = pRep->GetString();
}
else
return m_pStr;
}
LPTSTR CeString::GetBufferSetLength(int nLen)
{
ASSERT(nLen >= 0);
if (Length() == nLen && nLen > 0)
return m_pStr;
// get rid of any duplicates
Release();
if (0 == nLen)
// zero length buffer
return m_pStr;
// allocate a new copy and get the window text
CeStringRep* pRep = CeStringRep::AllocBuf(nLen);
return m_pStr = pRep->GetString();
}
void CeString::ReleaseBuffer()
{
int nLen = _tcslen(m_pStr);
if (nLen <= 0)
{
Release();
}
else if (nLen != Length())
{
// allocate a new copy and get the window text
CeStringRep* pRep = CeStringRep::AllocBuf(nLen);
memcpy(pRep->GetString(), m_pStr, nLen * sizeof TCHAR);
Release();
m_pStr = pRep->GetString();
}
}
void CeString::Format(LPCTSTR szFormat, ...)
{
TCHAR sz[1024];
va_list va;
va_start(va, szFormat);
int nOut = wvsprintf(sz, szFormat, va);
va_end(va);
Assign(sz, nOut);
}