|
|
//
// IISCStringImpl.cpp
//
//////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#pragma warning(disable:4786) // Disable warning for names > 256
#include "common.h"
#include <algorithm>
#include <deque>
#include <TCHAR.h>
#include "IISCString.h"
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Constructors
///////////////////////////////////////////////////////////////////////////
CString::CString() : std::basic_string<TCHAR>() { }
CString::CString(const CString& strInput) : std::basic_string<TCHAR>(strInput) { }
CString::CString(const std::basic_string<TCHAR>& strInput) : std::basic_string<TCHAR>(strInput) { }
CString::CString(TCHAR ch, int nRepeat /* = 1*/) : std::basic_string<TCHAR>(nRepeat, ch) { }
CString::CString(LPCTSTR p) : std::basic_string<TCHAR>(p) { }
#ifdef _UNICODE
CString::CString(LPCSTR strInput) { int len = strlen(strInput); TCHAR * buf = (TCHAR *)_alloca(len * (sizeof(TCHAR) + 1)); if (0 != MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, strInput, len, buf, len)) { assign(buf); } else { ATLASSERT(FALSE); } } #endif
#ifndef _UNICODE
CString::CString(LPCWSTR strInput) { int len = wstrlen(strInput); int buflen = len * (sizeof(TCHAR) + 1); TCHAR * buf = (TCHAR *)_alloca(buflen); if (0 != WideCharToMultiByte(CP_THREAD_ACP, 0, strInput, len, buf, buflen)) { assign(buf); } else { ATLASSERT(FALSE); } } #endif
CString::CString(const CComBSTR& bstr) { assign((LPCTSTR)bstr.m_str); }
CString::~CString() { }
///////////////////////////////////////////////////////////////////////////
// The string as an array
///////////////////////////////////////////////////////////////////////////
int CString::GetLength() const { return length(); };
bool CString::IsEmpty() const { return empty(); };
void CString::Empty() { erase(); };
TCHAR CString::GetAt(int nIndex) const { ATLASSERT(nIndex >= 0); return at(nIndex); };
TCHAR CString::operator[](int nIndex) const { // same as GetAt
ATLASSERT(nIndex >= 0); return at(nIndex); }
void CString::SetAt(int nIndex, TCHAR ch) { at(nIndex) = ch; };
const CString& CString::operator=(const CString& stringSrc) { assign(stringSrc); return *this; }
const CString& CString::operator=(LPCTSTR p) { // Here we will have a problem if NULL pointer is passed because
// later STL will call wcslen(NULL) which uses *p without test.
// We will emulate the result by erasing current string
if (p == NULL) erase(); // another problem is when we assign string to self, like str = str.c_str()
// STL deletes data and then assign it resulting in garbage
else if (p != this->data()) assign(p); return *this; }
#ifdef _UNICODE
const CString& CString::operator=(const unsigned char * lpsz) { int len = strlen((const char *)lpsz); TCHAR * buf = (TCHAR *)_alloca(len * (sizeof(TCHAR) + 1)); if (0 != MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, (const char *)lpsz, -1, buf, len)) { assign(buf); } else { ATLASSERT(FALSE); } return *this; } #endif
const CString& CString::operator=(TCHAR c) { assign(1, c); return *this; }
#ifdef _UNICODE
const CString& CString::operator+=(char ch) { *this += (TCHAR)ch; return *this; }
const CString& CString::operator=(char ch) { *this = (TCHAR)ch; return *this; }
CString __stdcall operator+(const CString& string, char ch) { return string + (TCHAR)ch; }
CString __stdcall operator+(char ch, const CString& string) { return (TCHAR)ch + string; } #endif
const CString& CString::operator+=(TCHAR ch) { append(1, ch); return *this; }
const CString& CString::operator+=(const CString& s) { append(s); return *this; }
const CString& CString::operator+=(LPCTSTR p) { append(p); return *this; }
static int __stdcall _LoadString(HINSTANCE hInstance, UINT nID, LPTSTR lpszBuf, UINT nMaxBuf) { #ifdef _DEBUG
// LoadString without annoying warning from the Debug kernel if the
// segment containing the string is not present
if (::FindResource(hInstance, MAKEINTRESOURCE((nID>>4)+1), RT_STRING) == NULL) { lpszBuf[0] = '\0'; return 0; // not found
} #endif //_DEBUG
int nLen = ::LoadString(hInstance, nID, lpszBuf, nMaxBuf); if (nLen == 0) lpszBuf[0] = '\0'; return nLen; }
#ifdef _UNICODE
#define CHAR_FUDGE 1 // one TCHAR unused is good enough
#else
#define CHAR_FUDGE 2 // two BYTES unused for case of DBC last char
#endif
#define INITIAL_SIZE 256
BOOL CString::LoadString(HINSTANCE hInstance, UINT id) { // try fixed buffer first (to avoid wasting space in the heap)
TCHAR szTemp[INITIAL_SIZE]; int nCount = sizeof(szTemp) / sizeof(szTemp[0]); int nLen = _LoadString(hInstance, id, szTemp, nCount); if (nCount - nLen > CHAR_FUDGE) { *this = szTemp; return nLen > 0; }
// try buffer size of 512, then larger size until entire string is retrieved
int nSize = INITIAL_SIZE; LPTSTR p = NULL; do { nSize += INITIAL_SIZE; p = get_allocator().allocate(nSize, p); nLen = _LoadString(hInstance, id, p, nSize - 1); } while (nSize - nLen <= CHAR_FUDGE); if (nLen > 0) assign(p, nLen);
return nLen > 0; }
///////////////////////////////////////////////////////////////////////////
// Comparison
///////////////////////////////////////////////////////////////////////////
int CString::Compare(const TCHAR * psz) const { if (psz == NULL) return this->empty() ? 0 : 1; return compare(psz); };
int CString::CompareNoCase(const TCHAR * psz) const { if (psz == NULL) return this->empty() ? 0 : 1; return _tcsicmp(c_str(), psz); };
int CString::Collate(const TCHAR * psz) const { if (psz == NULL) return this->empty() ? 0 : 1; return _tcscoll(c_str(), psz); };
///////////////////////////////////////////////////////////////////////////
// Extraction
///////////////////////////////////////////////////////////////////////////
CString CString::Mid(int nFirst) const { return substr(nFirst); };
CString CString::Mid(int nFirst, int nCount) const { return substr(nFirst, nCount); };
CString CString::Left(int nCount) const { return substr(0, nCount); };
CString CString::Right(int nCount) const { return substr(length() - nCount, nCount); };
CString CString::SpanIncluding(const TCHAR * pszCharSet) const { return substr(0, find_first_not_of(pszCharSet)); };
CString CString::SpanExcluding(const TCHAR * pszCharSet) const { return substr(0, find_first_of(pszCharSet)); };
///////////////////////////////////////////////////////////////////////////
// Other Conversions
///////////////////////////////////////////////////////////////////////////
void CString::MakeUpper() { std::for_each(begin(), end(), _totupper); };
void CString::MakeLower() { std::for_each(begin(), end(), _totlower); };
void CString::MakeReverse() { std::reverse(begin(), end()); };
void CString::TrimLeft() { while (_istspace(at(0))) erase(0, 1); };
void CString::TrimRight() { while (_istspace(at(length() - 1))) erase(length() - 1, 1); };
#define BUFFER_SIZE 1024
void __cdecl CString::FormatV(LPCTSTR lpszFormat, va_list argList) { TCHAR buf[BUFFER_SIZE]; if (-1 != _vsntprintf(buf, BUFFER_SIZE, lpszFormat, argList)) { buf[BUFFER_SIZE - 1] = L'\0'; // null terminate the string
assign(buf); } }
// formatting (using wsprintf style formatting)
void __cdecl CString::Format(LPCTSTR lpszFormat, ...) { va_list argList; va_start(argList, lpszFormat); FormatV(lpszFormat, argList); va_end(argList); }
void __cdecl CString::Format(HINSTANCE hInst, UINT nFormatID, ...) { CString strFormat; BOOL bRet = strFormat.LoadString(hInst, nFormatID); bRet; // ref
ATLASSERT(bRet != 0);
va_list argList; va_start(argList, nFormatID); FormatV(strFormat, argList); va_end(argList); }
// formatting (using FormatMessage style formatting)
BOOL CString::FormatMessage(LPCTSTR lpszFormat, ...) { // format message into temporary buffer lpszTemp
va_list argList; va_start(argList, lpszFormat); LPTSTR lpszTemp; BOOL bRet = TRUE;
if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL) bRet = FALSE;
// assign lpszTemp into the resulting string and free the temporary
*this = lpszTemp; LocalFree(lpszTemp); va_end(argList); return bRet; }
BOOL CString::FormatMessage(HINSTANCE hInst, UINT nFormatID, ...) { // get format string from string table
CString strFormat; BOOL bRetTmp = strFormat.LoadString(hInst, nFormatID); bRetTmp; // ref
ATLASSERT(bRetTmp != 0);
// format message into temporary buffer lpszTemp
va_list argList; va_start(argList, nFormatID); LPTSTR lpszTemp; BOOL bRet = TRUE;
if (::FormatMessage( FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL ) bRet = FALSE;
// assign lpszTemp into the resulting string and free lpszTemp
*this = lpszTemp; LocalFree(lpszTemp); va_end(argList); return bRet; }
///////////////////////////////////////////////////////////////////////////
// Searching
///////////////////////////////////////////////////////////////////////////
int CString::Find(TCHAR ch) const { return find(ch); };
int CString::Find(const TCHAR * psz) const { if (psz == NULL) return -1; return find(psz); };
int CString::ReverseFind(TCHAR ch) const { return rfind(ch); };
int CString::FindOneOf(const TCHAR * psz) const { if (psz == NULL) return -1; return find_first_of(psz); };
///////////////////////////////////////////////////////////////////////////
// Operators
///////////////////////////////////////////////////////////////////////////
CString::operator const TCHAR *() const { return c_str(); };
|