|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name: Shell String Class Implementation
shstr.cpp
Author:
Zeke Lucas (zekel) 27-Oct-96
Environment:
User Mode - Win32
Revision History:
Abstract:
this allows automatic resizing and stuff.
NOTE: this class is specifically designed to be used as a stack variable
--*/
#include "stock.h"
#pragma hdrstop
#include <shstr.h>
#include <strsafe.h>
#define MALLOC(c) LocalAlloc(LPTR, (c))
#define FREE(p) LocalFree(p)
//
// ShStr Public Methods
//
//
// Constructors
//
ShStr :: ShStr () { _szDefaultBuffer[0] = '\0'; _pszStr = _szDefaultBuffer; _cchSize = ARRAYSIZE(_szDefaultBuffer); }
/**************
StrStr SetStr() methods
Return: Success - a pointer to the object Failure - NULL **************/
HRESULT ShStr :: SetStr (LPCSTR pszStr) { Reset(); return _SetStr(pszStr);
}
HRESULT ShStr :: SetStr (LPCSTR pszStr, DWORD cchStr) { Reset(); return _SetStr(pszStr, cchStr);
}
HRESULT ShStr :: SetStr (LPCWSTR pwszStr, DWORD cchStr) { Reset(); return _SetStr(pwszStr, cchStr);
}
HRESULT ShStr :: Append(LPCTSTR pszStr, DWORD cchStr) { HRESULT hr = S_OK;
if(pszStr) { DWORD cchLen = GetLen();
if(cchStr == (DWORD) -1) cchStr = lstrlen(pszStr);
//
// StrCpyN automagically appends the null term,
// so we need to give room for it
//
cchStr++;
if(SUCCEEDED(SetSize(cchStr + cchLen))) StrCpyN(_pszStr + cchLen, pszStr, cchStr); else hr = E_OUTOFMEMORY; } else hr = E_INVALIDARG;
return hr; }
ShStr * ShStr :: Clone() { ShStr *pshstr = new ShStr;
if (pshstr) { pshstr->SetStr(_pszStr); if(pshstr->IsValid()) return pshstr; }
if(pshstr) delete pshstr;
return NULL; }
LPSTR ShStr :: CloneStrA() #ifdef UNICODE
{ LPSTR pszStr = NULL;
if(_pszStr) { DWORD cchStr; cchStr = WideCharToMultiByte(CP_ACP, 0, _pszStr, -1, NULL, 0, NULL, NULL);
ASSERT(cchStr);
if(cchStr) { pszStr = (LPSTR) MALLOC (CbFromCch(cchStr +1));
if(pszStr) { cchStr = WideCharToMultiByte(CP_ACP, 0, _pszStr, -1, pszStr, cchStr, NULL, NULL); ASSERT (cchStr); } } }
return pszStr; }
#else //!UNICODE
{return _pszStr ? StrDupA(_pszStr) : NULL;} #endif //UNICODE
#ifdef UNICODE
#endif
LPWSTR ShStr :: CloneStrW() #ifdef UNICODE
{return _pszStr ? StrDupW(_pszStr) : NULL;} #else //!UNICODE
{ LPWSTR pwsz; DWORD cch = lstrlenA(_pszStr) +1;
pwsz = (LPWSTR) MALLOC (sizeof(WCHAR) * cch); if(pwsz) MultiByteToWideChar(CP_ACP, 0, _pszStr, -1, pwsz, cch);
return pwsz; } #endif //UNICODE
/**************
ShStr Utility methods
**************/
/**************
ShStr SetSize method
Sets the size of the internal buffer if larger than default
Return: Success - a pointer to the object Failure - NULL **************/ HRESULT ShStr :: SetSize(DWORD cchSize) { HRESULT hr = S_OK; DWORD cchNewSize = _cchSize;
ASSERT(!(_cchSize % DEFAULT_SHSTR_LENGTH));
// so that we always allocate in increments
while (cchSize > cchNewSize) cchNewSize <<= 2; if(cchNewSize != _cchSize) { if(cchNewSize > DEFAULT_SHSTR_LENGTH) { LPTSTR psz;
psz = (LPTSTR) LocalAlloc(LPTR, CbFromCch(cchNewSize)); if(psz) { StrCpyN(psz, _pszStr, cchSize); Reset(); _cchSize = cchNewSize; _pszStr = psz; } else hr = E_OUTOFMEMORY; } else { if (_pszStr && _cchSize) StrCpyN(_szDefaultBuffer, _pszStr, ARRAYSIZE(_szDefaultBuffer));
Reset();
_pszStr = _szDefaultBuffer; } }
return hr; }
#ifdef DEBUG
BOOL ShStr :: IsValid() { BOOL fRet = TRUE;
if(!_pszStr) fRet = FALSE;
ASSERT( ((_cchSize != ARRAYSIZE(_szDefaultBuffer)) && (_pszStr != _szDefaultBuffer)) || ((_cchSize == ARRAYSIZE(_szDefaultBuffer)) && (_pszStr == _szDefaultBuffer)) );
ASSERT(!(_cchSize % DEFAULT_SHSTR_LENGTH));
return fRet; } #endif //DEBUG
VOID ShStr :: Reset() { if (_pszStr && (_cchSize != ARRAYSIZE(_szDefaultBuffer))) LocalFree(_pszStr);
_szDefaultBuffer[0] = TEXT('\0'); _pszStr = _szDefaultBuffer; _cchSize = ARRAYSIZE(_szDefaultBuffer); }
#define IsWhite(c) ((DWORD) (c) > 32 ? FALSE : TRUE)
VOID ShStr :: Trim() {
if(_pszStr) { // APPCOMPAT - NETSCAPE compatibility - zekel 29-JAN-97
// we want to leave one space in the string
TCHAR chFirst = *_pszStr;
// first trim the backside
TCHAR *pchLastWhite = NULL; LPTSTR pch = _pszStr; // the front side
while (*pch && IsWhite(*pch)) pch = CharNext(pch);
if (pch > _pszStr) { LPTSTR pchDst = _pszStr;
while (*pchDst = *pch) { pch = CharNext(pch); pchDst = CharNext(pchDst); } }
// then the backside
for (pch = _pszStr; *pch; pch = CharNext(pch)) { if(pchLastWhite && !IsWhite(*pch)) pchLastWhite = NULL; else if(!pchLastWhite && IsWhite(*pch)) pchLastWhite = pch; }
if(pchLastWhite) *pchLastWhite = TEXT('\0');
if(TEXT(' ') == chFirst && !*_pszStr) { _pszStr[0] = TEXT(' '); _pszStr[1] = TEXT('\0'); } } }
//
// ShStr Private Methods
//
/**************
StrStr Set* methods
Return: Success - a pointer to the object Failure - NULL **************/ HRESULT ShStr :: _SetStr(LPCSTR pszStr) { HRESULT hr = S_FALSE;
if(pszStr) { DWORD cchStr;
cchStr = lstrlenA(pszStr); if(cchStr) { hr = SetSize(cchStr +1);
if (SUCCEEDED(hr)) #ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, pszStr, -1, _pszStr, _cchSize); #else //!UNICODE
StringCchCopyA(_pszStr, cchStr+1, pszStr); #endif //UNICODE
} }
return hr; }
HRESULT ShStr :: _SetStr(LPCSTR pszStr, DWORD cchStr) { HRESULT hr = S_FALSE;
if(pszStr && cchStr) { if (cchStr == (DWORD) -1) cchStr = lstrlenA(pszStr);
hr = SetSize(cchStr +1);
if(SUCCEEDED(hr)) { #ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, pszStr, cchStr, _pszStr, _cchSize); _pszStr[cchStr] = TEXT('\0');
#else //!UNICODE
StrCpyN(_pszStr, pszStr, (++cchStr < _cchSize ? cchStr : _cchSize) ); #endif //UNICODE
} }
return hr; }
HRESULT ShStr :: _SetStr (LPCWSTR pwszStr, DWORD cchStrIn) { DWORD cchStr = cchStrIn; HRESULT hr = S_FALSE;
if(pwszStr && cchStr) { if (cchStr == (DWORD) -1) #ifdef UNICODE
cchStr = lstrlen(pwszStr); #else //!UNICODE
cchStr = WideCharToMultiByte(CP_ACP, 0, pwszStr, cchStrIn, NULL, 0, NULL, NULL); #endif //UNICODE
if(cchStr) { hr = SetSize(cchStr +1);
if(SUCCEEDED(hr)) { #ifdef UNICODE
StrCpyN(_pszStr, pwszStr, (cchStr + 1< _cchSize ? cchStr + 1: _cchSize)); #else //!UNICODE
cchStr = WideCharToMultiByte(CP_ACP, 0, pwszStr, cchStrIn, _pszStr, _cchSize, NULL, NULL); _pszStr[cchStr < _cchSize ? cchStr : _cchSize] = TEXT('\0'); ASSERT (cchStr); #endif //UNICODE
} } #ifdef DEBUG
else { DWORD dw; dw = GetLastError(); } #endif //DEBUG
} #ifdef DEBUG
else { DWORD dw; dw = GetLastError(); } #endif //DEBUG
return hr; }
#if 0 //DISABLED until i have written the SHUrl* functions - zekel 7-Nov-96
//
// UrlStr Methods
//
UrlStr & UrlStr::SetUrl(LPCSTR pszUrl) { return SetUrl(pszUrl, (DWORD) -1); }
UrlStr & UrlStr::SetUrl(LPCWSTR pwszUrl) { return SetUrl(pwszUrl, (DWORD) -1); }
UrlStr & UrlStr::SetUrl(LPCSTR pszUrl, DWORD cchUrl) { _strUrl.SetStr(pszUrl, cchUrl); return *this; }
UrlStr & UrlStr::SetUrl(LPCWSTR pwszUrl, DWORD cchUrl) { _strUrl.SetStr(pwszUrl, cchUrl); return *this; }
UrlStr::operator LPCTSTR() { return _strUrl.GetStr(); }
UrlStr::operator SHSTR() { return _strUrl; }
HRESULT UrlStr::Combine(LPCTSTR pszUrl, DWORD dwFlags) { SHSTR strRel; SHSTR strOut; HRESULT hr;
strRel.SetStr(pszUrl);
hr = UrlCombine(_strUrl.GetStr(), hr = SHUrlParse(&_strUrl, &strRel, &strOut, NULL, URL_PARSE_CREATE);
if(SUCCEEDED(hr)) _strUrl = strOut;
return hr; }
/*
ShStr &GetLocation(); ShStr &GetAnchor(); ShStr &GetQuery();
HRESULT Canonicalize(DWORD dwFlags); HRESULT Combine(LPCTSTR pszUrl, DWORD dwFlags); HRESULT Encode(DWORD dwFlags); HRESULT EncodeSpaces() {return Encode(URL_ENCODE_SPACES_ONLY)} HRESULT Decode(DWORD dwFlags) */ #endif //DISABLED
|