LastIndexOf similar C++ code?

  • Thread starter Thread starter Egbert Nierop \(MVP for IIS\)
  • Start date Start date
E

Egbert Nierop \(MVP for IIS\)

Hi,

I'm 'improving' CComBSTR (yes, I do still program unmanaged code in addition
to C# ) to contain features, not found in it.

Does anybody have good code which maches LastIndexOf()?

If this is ready, I will publish the full CComBSTR class on my weblog.



int LastIndexOf(const wchar_t *src, const int startIndex = -1, const bool
caseInsensitive = false) throw()

{

// use _wcsnicmp and wcsncmp instead?

int result = -1;


if (m_str != NULL && src != NULL)

{

SIZE_T compLen = wcslen(src);

SIZE_T maxLen = Length();

SIZE_T startIdx = startIndex == 0 ? maxLen : startIndex;

SIZE_T maxScan = maxLen - startIndex;

BSTR temp, findThis;

if (caseInsensitive)

{


temp = _wcslwr(Substring(startIndex));

findThis = _wcslwr(::SysAllocString(src));


}

else

{

temp = (PWSTR)m_str;

findThis = (PWSTR)src;

}

PWSTR found = 0;//wcsrchr(temp, findThis);

if (found != NULL)

result = found - temp;

if (caseInsensitive)

{

::SysFreeString(findThis);

::SysFreeString(temp);

}

}

return result;

}
 
Egbert Nierop (MVP for IIS) said:
Hi,

I'm 'improving' CComBSTR (yes, I do still program unmanaged code in
addition to C# ) to contain features, not found in it.

Does anybody have good code which maches LastIndexOf()?

Ok, ok, I did it myself, however it could be improved a little, still...

These improvements also has been optimized -not- to reallocate the string so
often as the original does with Append

/////////////////////////////////////////////////////////////////////////////
// CComBSTR

class CComBSTR
{
public:
BSTR m_str;
CComBSTR() throw()
{
m_str = NULL;
}
CComBSTR(int nSize)
{
//if (nSize == 0) //BUG it should be possible to assign a L"" string
// m_str = NULL;
m_str = ::SysAllocStringLen(NULL, nSize);
if (m_str == NULL)
AtlThrow(E_OUTOFMEMORY);

}
CComBSTR(int nSize, LPCOLESTR sz)
{
if (nSize == 0)
m_str = NULL;
else
{
m_str = ::SysAllocStringLen(sz, nSize);
if (m_str == NULL)
AtlThrow(E_OUTOFMEMORY);
}
}
CComBSTR(LPCOLESTR pSrc)
{
if (pSrc == NULL)
m_str = NULL;
else
{
m_str = ::SysAllocString(pSrc);
if (m_str == NULL)
AtlThrow(E_OUTOFMEMORY);
}
}
CComBSTR(const CComBSTR& src)
{
m_str = src.Copy();
if (!!src && m_str == NULL)
AtlThrow(E_OUTOFMEMORY);

}
CComBSTR(REFGUID guid)
{
OLECHAR szGUID[64];
::StringFromGUID2(guid, szGUID, 64);
m_str = ::SysAllocString(szGUID);
if (m_str == NULL)
AtlThrow(E_OUTOFMEMORY);
}

CComBSTR& operator=(const CComBSTR& src)
{
if (m_str != src.m_str)
{
if (::SysReAllocStringLen(&m_str, src, src.Length()) == FALSE)
AtlThrow(E_OUTOFMEMORY);
}
return *this;
}

CComBSTR& operator=(LPCOLESTR pSrc)
{
if (pSrc != m_str)
{
if (pSrc != NULL)
{
if (::SysReAllocString(&m_str, pSrc) == FALSE)
AtlThrow(E_OUTOFMEMORY);
}
else
{
::SysFreeString(m_str);
m_str = NULL;
}
}
return *this;
}

~CComBSTR() throw()
{
::SysFreeString(m_str);
}
unsigned int Length() const throw()
{
return (m_str == NULL)? 0 : SysStringLen(m_str);
}
unsigned int ByteLength() const throw()
{
return (m_str == NULL)? 0 : SysStringByteLen(m_str);
}
operator BSTR() const throw()
{
return m_str;
}
BSTR* operator&() throw()
{
return &m_str;
}
BSTR Copy() const throw()
{
if (m_str == NULL)
return NULL;
return ::SysAllocStringByteLen((char*)m_str, ::SysStringByteLen(m_str));
}
HRESULT CopyTo(BSTR* pbstr) throw()
{
ATLASSERT(pbstr != NULL);
if (pbstr == NULL)
return E_POINTER;
*pbstr = Copy();
if ((*pbstr == NULL) && (m_str != NULL))
return E_OUTOFMEMORY;
return S_OK;
}

/* added by may 2005 e.n. needs #include 'wchar.h'*/
HRESULT __cdecl Format(PCWSTR pszFormat, ...) throw()
{
va_list args;
HRESULT hr = S_OK;

va_start( args, pszFormat );

int len = _vscwprintf( pszFormat, args );
if (::SysReAllocStringLen(&m_str, NULL, len) == FALSE)
hr = E_OUTOFMEMORY;
else
vswprintf( m_str, (SIZE_T)Length(), pszFormat, args );
va_end(args);

return hr;
}

BSTR Substring(const int startIndex) throw()
{
int maxIdx = Length();
if (m_str != NULL && startIndex >= 0 && startIndex <= maxIdx)
{
return ::SysAllocStringLen(m_str + startIndex, maxIdx - startIndex);
}
else
return NULL;
}

BSTR Substring(const int startIndex, int length) throw()
{
int maxIdx = Length();
if (length < 0) length = 0;
if (startIndex + length > maxIdx)
length = maxIdx - startIndex;
if (m_str != NULL && startIndex > 0 && startIndex <= maxIdx)
{
return ::SysAllocStringLen(m_str + startIndex, length);
}
else
return NULL;
}
int LastIndexOf(const wchar_t *src, const unsigned int startIndex = 0,
const bool caseInsensitive = false) throw()
{
// use _wcsnicmp and wcsncmp
int result = -1;

if (m_str != NULL && src != NULL)
{
int compLen = ocslen(src);
int maxLen = Length();

for(int x = maxLen - compLen; x >= 0; x--)
{
if (
(caseInsensitive ? _wcsnicmp(m_str + x, src, compLen) : wcsncmp(m_str
+ x, src, compLen)
) == 0)
{
result = x;
break;
}
}



}
return result;
}

int IndexOf(const wchar_t src, const unsigned int startIndex = 0, const
bool caseInsensitive = false) throw()
{
int result = -1;
if (m_str != NULL)
{
unsigned int maxLen = Length();
unsigned int startIdx = startIndex > maxLen ? maxLen : startIndex;

unsigned int maxScan = maxLen - startIndex;

BSTR temp;
wchar_t src2;
if (caseInsensitive)
{
wchar_t tol[2] = {src, 0};
_wcslwr(tol);
src2 = tol[0];

temp = _wcslwr(Substring((UINT)startIdx));
}
else
{
temp = m_str;
src2 = src;
}

wchar_t *found = wmemchr(temp, src2, maxScan);

if (found != NULL)
result = PtrToInt(found - temp);

if (caseInsensitive)
::SysFreeString(temp);
}
return result;
}

/*
* Addded by E.N.
*/
int IndexOf(const PWSTR src, const unsigned int startIndex = 0, const bool
caseInsensitive = false) throw()
{
int result = -1;

if (src != NULL && m_str != NULL)
{
unsigned int maxLen = Length();
unsigned int startIdx = startIndex > maxLen ? maxLen : startIndex;
BSTR temp, findThis;
if (caseInsensitive)
{
temp = _wcslwr(Substring(startIdx));
findThis = _wcslwr(::SysAllocString(src));
}
else
{
temp = m_str + startIdx;
findThis = src;
}
wchar_t *found = wcsstr(temp, findThis);


if (found != NULL)
result = PtrToInt(found - temp);

if (caseInsensitive)
{
::SysFreeString(temp);
::SysFreeString(findThis);
}
}
return result;

}

// copy BSTR to VARIANT
HRESULT CopyTo(VARIANT *pvarDest) throw()
{
ATLASSERT(pvarDest != NULL);
HRESULT hRes = E_POINTER;
if (pvarDest != NULL)
{
pvarDest->vt = VT_BSTR;
pvarDest->bstrVal = Copy();
if (pvarDest->bstrVal == NULL && m_str != NULL)
hRes = E_OUTOFMEMORY;
else
hRes = S_OK;
}
return hRes;
}
void Attach(BSTR src) throw()
{
if (m_str != src)
{
::SysFreeString(m_str);
m_str = src;
}
}
BSTR Detach() throw()
{
BSTR s = m_str;
m_str = NULL;
return s;
}
void Empty() throw()
{
::SysFreeString(m_str);
m_str = NULL;
}
bool operator!() const throw()
{
return (m_str == NULL);
}
HRESULT Append(const CComBSTR& bstrSrc) throw()
{
return AppendBSTR(bstrSrc.m_str);
}
HRESULT Append(LPCOLESTR lpsz) throw()
{
return Append(lpsz, UINT(ocslen(lpsz)));
}
// a BSTR is just a LPCOLESTR so we need a special version to signify
// that we are appending a BSTR
HRESULT AppendBSTR(BSTR p) throw()
{
return Append((LPCOLESTR)p, ::SysStringLen(p));
}
HRESULT Append(LPCOLESTR lpsz, int nLen) throw()
{
if (lpsz == NULL || (m_str != NULL && nLen == 0))
return S_OK;
int n1 = Length();
if ( ::SysReAllocStringLen(&m_str, NULL, n1+nLen) == FALSE)
return E_OUTOFMEMORY;
memcpy(m_str+n1, lpsz, nLen*sizeof(OLECHAR));
return S_OK;
}
HRESULT Append(char ch) throw()
{
OLECHAR chO = ch;

return( Append( &chO, 1 ) );
}
HRESULT Append(wchar_t ch) throw()
{
return( Append( &ch, 1 ) );
}
HRESULT AppendBytes(const char* lpsz, int nLen) throw()
{
if (lpsz == NULL || nLen == 0)
return S_OK;
int n1 = ByteLength();
BSTR b;
b = ::SysAllocStringByteLen(NULL, n1+nLen);
if (b == NULL)
return E_OUTOFMEMORY;
memcpy(b, m_str, n1);
memcpy(((char*)b)+n1, lpsz, nLen);
*((OLECHAR*)(((char*)b)+n1+nLen)) = NULL;
SysFreeString(m_str);
m_str = b;
return S_OK;
}
HRESULT AssignBSTR(const BSTR bstrSrc) throw()
{
HRESULT hr = S_OK;
if (m_str != bstrSrc)
{

if (bstrSrc != NULL)
{
if (::SysReAllocStringLen(&m_str, bstrSrc, ::SysStringLen(bstrSrc)) ==
FALSE)
hr = E_OUTOFMEMORY;
}
else
m_str = NULL;
}

return hr;
}
HRESULT ToLower() throw()
{
if (m_str != NULL)
{
#ifdef _UNICODE
// Convert in place
CharLowerBuff(m_str, Length());
#else
// Cannot use conversion macros due to possible embedded NULLs
UINT _acp = _AtlGetConversionACP();
int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0,
NULL, NULL);
CTempBuffer<char> pszA;
ATLTRY(pszA.Allocate(_convert));
if (pszA == NULL)
return E_OUTOFMEMORY;

int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert,
NULL, NULL);
if (nRet == 0)
{
ATLASSERT(0);
return AtlHresultFromLastError();
}

CharLowerBuff(pszA, nRet);

_convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0);

CTempBuffer<WCHAR> pszW;
ATLTRY(pszW.Allocate(_convert));
if (pszW == NULL)
return E_OUTOFMEMORY;

nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert);
if (nRet == 0)
{
ATLASSERT(0);
return AtlHresultFromLastError();
}

if (::SysReAllocStringLen(&m_str, pszW, nRet) == FALSE)
return E_OUTOFMEMORY;
#endif
}
return S_OK;
}
HRESULT ToUpper() throw()
{
if (m_str != NULL)
{
#ifdef _UNICODE
// Convert in place
CharUpperBuff(m_str, Length());
#else
// Cannot use conversion macros due to possible embedded NULLs
UINT _acp = _AtlGetConversionACP();
int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0,
NULL, NULL);
CTempBuffer<char> pszA;
ATLTRY(pszA.Allocate(_convert));
if (pszA == NULL)
return E_OUTOFMEMORY;

int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert,
NULL, NULL);
if (nRet == 0)
{
ATLASSERT(0);
return AtlHresultFromLastError();
}

CharUpperBuff(pszA, nRet);

_convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0);

CTempBuffer<WCHAR> pszW;
ATLTRY(pszW.Allocate(_convert));
if (pszW == NULL)
return E_OUTOFMEMORY;

nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert);
if (nRet == 0)
{
ATLASSERT(0);
return AtlHresultFromLastError();
}

if (::SysReAllocStringLen(&m_str, pszW, nRet) == FALSE);
return E_OUTOFMEMORY;

#endif
}
return S_OK;
}
bool LoadString(HINSTANCE hInst, UINT nID) throw()
{
::SysFreeString(m_str);
m_str = NULL;
return LoadStringResource(hInst, nID, m_str);
}
bool LoadString(UINT nID) throw()
{
::SysFreeString(m_str);
m_str = NULL;
return LoadStringResource(nID, m_str);
}

CComBSTR& operator+=(const CComBSTR& bstrSrc)
{
HRESULT hr;
hr = AppendBSTR(bstrSrc.m_str);
if (FAILED(hr))
AtlThrow(hr);
return *this;
}
CComBSTR& operator+=(LPCOLESTR pszSrc)
{
HRESULT hr;
hr = Append(pszSrc);
if (FAILED(hr))
AtlThrow(hr);
return *this;
}

bool operator<(const CComBSTR& bstrSrc) const throw()
{
return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) ==
VARCMP_LT;
}
bool operator<(LPCOLESTR pszSrc) const
{
CComBSTR bstr2(pszSrc);
return operator<(bstr2);
}
bool operator<(LPOLESTR pszSrc) const
{
return operator<((LPCOLESTR)pszSrc);
}

bool operator>(const CComBSTR& bstrSrc) const throw()
{
return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) ==
VARCMP_GT;
}
bool operator>(LPCOLESTR pszSrc) const
{
CComBSTR bstr2(pszSrc);
return operator>(bstr2);
}
bool operator>(LPOLESTR pszSrc) const
{
return operator>((LPCOLESTR)pszSrc);
}

bool operator!=(const CComBSTR& bstrSrc) const throw()
{
return !operator==(bstrSrc);
}
bool operator!=(LPCOLESTR pszSrc) const
{
return !operator==(pszSrc);
}
bool operator!=(int nNull) const throw()
{
return !operator==(nNull);
}
bool operator!=(LPOLESTR pszSrc) const
{
return operator!=((LPCOLESTR)pszSrc);
}

bool operator==(const CComBSTR& bstrSrc) const throw()
{
return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) ==
VARCMP_EQ;
}
bool operator==(LPCOLESTR pszSrc) const
{
CComBSTR bstr2(pszSrc);
return operator==(bstr2);
}
bool operator==(LPOLESTR pszSrc) const
{
return operator==((LPCOLESTR)pszSrc);
}

bool operator==(int nNull) const throw()
{
ATLASSERT(nNull == NULL);
(void)nNull;
return (m_str == NULL);
}
CComBSTR(LPCSTR pSrc)
{
if (pSrc != NULL)
{
m_str = A2WBSTR(pSrc);
if (m_str == NULL)
AtlThrow(E_OUTOFMEMORY);
}
else
m_str = NULL;
}

CComBSTR(int nSize, LPCSTR sz)
{
if (nSize != 0 && sz == NULL)
{
m_str = ::SysAllocStringLen(NULL, nSize);
if (m_str == NULL)
AtlThrow(E_OUTOFMEMORY);
return;
}

m_str = A2WBSTR(sz, nSize);
if (m_str == NULL && nSize != 0)
AtlThrow(E_OUTOFMEMORY);
}

HRESULT Append(LPCSTR lpsz) throw()
{
if (lpsz == NULL)
return S_OK;

CComBSTR bstrTemp;
ATLTRY(bstrTemp = lpsz);
if (bstrTemp.m_str == NULL)
return E_OUTOFMEMORY;
return Append(bstrTemp);
}

CComBSTR& operator=(LPCSTR pSrc)
{
::SysFreeString(m_str);
m_str = A2WBSTR(pSrc);
if (m_str == NULL && pSrc != NULL)
AtlThrow(E_OUTOFMEMORY);
return *this;
}
bool operator<(LPCSTR pszSrc) const
{
CComBSTR bstr2(pszSrc);
return operator<(bstr2);
}
bool operator>(LPCSTR pszSrc) const
{
CComBSTR bstr2(pszSrc);
return operator>(bstr2);
}
bool operator!=(LPCSTR pszSrc) const
{
return !operator==(pszSrc);
}
bool operator==(LPCSTR pszSrc) const
{
CComBSTR bstr2(pszSrc);
return operator==(bstr2);
}
HRESULT WriteToStream(IStream* pStream) throw()
{
ATLASSERT(pStream != NULL);
if(pStream == NULL)
return E_INVALIDARG;

ULONG cb;
ULONG cbStrLen = ULONG(m_str ? SysStringByteLen(m_str)+sizeof(OLECHAR) :
0);
HRESULT hr = pStream->Write((void*) &cbStrLen, sizeof(cbStrLen), &cb);
if (FAILED(hr))
return hr;
return cbStrLen ? pStream->Write((void*) m_str, cbStrLen, &cb) : S_OK;
}
HRESULT ReadFromStream(IStream* pStream) throw()
{
ATLASSERT(pStream != NULL);
if(pStream == NULL)
return E_INVALIDARG;

ATLASSERT(m_str == NULL); // should be empty
Empty();

ULONG cbStrLen = 0;
HRESULT hr = pStream->Read((void*) &cbStrLen, sizeof(cbStrLen), NULL);
if ((hr == S_OK) && (cbStrLen != 0))
{
//subtract size for terminating NULL which we wrote out
//since SysAllocStringByteLen overallocates for the NULL
m_str = SysAllocStringByteLen(NULL, cbStrLen-sizeof(OLECHAR));
if (m_str == NULL)
hr = E_OUTOFMEMORY;
else
hr = pStream->Read((void*) m_str, cbStrLen, NULL);
// If SysAllocStringByteLen or IStream::Read failed, reset seek
// pointer to start of BSTR size.
if (hr != S_OK)
{
LARGE_INTEGER nOffset;
nOffset.QuadPart = -(static_cast<LONGLONG>(sizeof(cbStrLen)));
pStream->Seek(nOffset, STREAM_SEEK_CUR, NULL);
}
}
if (hr == S_FALSE)
hr = E_FAIL;
return hr;
}
static bool LoadStringResource(HINSTANCE hInstance, UINT uID, BSTR&
bstrText) throw()
{
const ATLSTRINGRESOURCEIMAGE* pImage;

ATLASSERT(bstrText == NULL);

pImage = AtlGetStringResourceImage(hInstance, uID);
if (pImage != NULL)
{
bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength);
}

return (bstrText != NULL) ? true : false;
}

static bool LoadStringResource(UINT uID, BSTR& bstrText) throw()
{
const ATLSTRINGRESOURCEIMAGE* pImage;

ATLASSERT(bstrText == NULL);

pImage = AtlGetStringResourceImage(uID);
if (pImage != NULL)
{
bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength);
}

return (bstrText != NULL) ? true : false;
}



// each character in BSTR is copied to each element in SAFEARRAY
HRESULT BSTRToArray(LPSAFEARRAY *ppArray) throw()
{
return VectorFromBstr(m_str, ppArray);
}

// first character of each element in SAFEARRAY is copied to BSTR
HRESULT ArrayToBSTR(const SAFEARRAY *pSrc) throw()
{
::SysFreeString(m_str);
return BstrFromVector((LPSAFEARRAY)pSrc, &m_str);
}
};
 
Back
Top