|
|
@@ -38,9 +38,7 @@ STRA::STRA(
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
|
-STRA::IsEmpty(
|
|
|
- VOID
|
|
|
-) const
|
|
|
+STRA::IsEmpty() const
|
|
|
{
|
|
|
return ( m_cchLen == 0 );
|
|
|
}
|
|
|
@@ -63,27 +61,16 @@ STRA::Equals(
|
|
|
|
|
|
BOOL
|
|
|
STRA::Equals(
|
|
|
- __in const STRA * pstrRhs,
|
|
|
- __in BOOL fIgnoreCase /*= FALSE*/
|
|
|
-) const
|
|
|
-{
|
|
|
- _ASSERTE( nullptr != pstrRhs );
|
|
|
- return Equals( pstrRhs->QueryStr(), fIgnoreCase );
|
|
|
-}
|
|
|
-
|
|
|
-BOOL
|
|
|
-STRA::Equals(
|
|
|
- __in const STRA & strRhs,
|
|
|
+ __in const STRA* pstrRhs,
|
|
|
__in BOOL fIgnoreCase /*= FALSE*/
|
|
|
) const
|
|
|
{
|
|
|
- return Equals( strRhs.QueryStr(), fIgnoreCase );
|
|
|
+ _ASSERTE(nullptr != pstrRhs);
|
|
|
+ return Equals(pstrRhs->QueryStr(), fIgnoreCase);
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
|
-STRA::QueryCB(
|
|
|
- VOID
|
|
|
-) const
|
|
|
+STRA::QueryCB() const
|
|
|
//
|
|
|
// Returns the number of bytes in the string excluding the terminating NULL
|
|
|
//
|
|
|
@@ -92,9 +79,7 @@ STRA::QueryCB(
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
|
-STRA::QueryCCH(
|
|
|
- VOID
|
|
|
-) const
|
|
|
+STRA::QueryCCH() const
|
|
|
//
|
|
|
// Returns the number of characters in the string excluding the terminating NULL
|
|
|
//
|
|
|
@@ -125,9 +110,7 @@ STRA::QuerySize(
|
|
|
__nullterminated
|
|
|
__bcount(this->m_cchLen)
|
|
|
CHAR *
|
|
|
-STRA::QueryStr(
|
|
|
- VOID
|
|
|
-) const
|
|
|
+STRA::QueryStr() const
|
|
|
//
|
|
|
// Return the string buffer
|
|
|
//
|
|
|
@@ -254,41 +237,6 @@ STRA::CopyW(
|
|
|
return CopyW( pszCopyW, cchLen );
|
|
|
}
|
|
|
|
|
|
-HRESULT
|
|
|
-STRA::CopyWTruncate(
|
|
|
- __in PCWSTR pszCopyWTruncate
|
|
|
-)
|
|
|
-{
|
|
|
- size_t cchLen;
|
|
|
- HRESULT hr = StringCchLengthW(pszCopyWTruncate,
|
|
|
- STRSAFE_MAX_CCH,
|
|
|
- &cchLen);
|
|
|
- if ( FAILED( hr ) )
|
|
|
- {
|
|
|
- return hr;
|
|
|
- }
|
|
|
- return CopyWTruncate( pszCopyWTruncate, cchLen );
|
|
|
-}
|
|
|
-
|
|
|
-HRESULT
|
|
|
-STRA::CopyWTruncate(
|
|
|
- __in_ecount(cchLen)
|
|
|
- PCWSTR pszCopyWTruncate,
|
|
|
- __in SIZE_T cchLen
|
|
|
-)
|
|
|
-//
|
|
|
-// The "Truncate" methods do not do proper conversion. They do a (CHAR) caste
|
|
|
-//
|
|
|
-{
|
|
|
- _ASSERTE( cchLen <= MAXDWORD );
|
|
|
-
|
|
|
- return AuxAppendWTruncate(
|
|
|
- pszCopyWTruncate,
|
|
|
- static_cast<DWORD>(cchLen),
|
|
|
- 0
|
|
|
- );
|
|
|
-}
|
|
|
-
|
|
|
HRESULT
|
|
|
STRA::Append(
|
|
|
__in PCSTR pszAppend
|
|
|
@@ -324,15 +272,6 @@ STRA::Append(
|
|
|
);
|
|
|
}
|
|
|
|
|
|
-HRESULT
|
|
|
-STRA::Append(
|
|
|
- __in const STRA * pstrRhs
|
|
|
-)
|
|
|
-{
|
|
|
- _ASSERTE( pstrRhs != nullptr );
|
|
|
- return Append( pstrRhs->QueryStr(), pstrRhs->QueryCCH() );
|
|
|
-}
|
|
|
-
|
|
|
HRESULT
|
|
|
STRA::Append(
|
|
|
__in const STRA & strRhs
|
|
|
@@ -341,44 +280,6 @@ STRA::Append(
|
|
|
return Append( strRhs.QueryStr(), strRhs.QueryCCH() );
|
|
|
}
|
|
|
|
|
|
-HRESULT
|
|
|
-STRA::AppendWTruncate(
|
|
|
- __in PCWSTR pszAppendWTruncate
|
|
|
-)
|
|
|
-{
|
|
|
- size_t cchLen;
|
|
|
- HRESULT hr = StringCchLengthW(pszAppendWTruncate,
|
|
|
- STRSAFE_MAX_CCH,
|
|
|
- &cchLen);
|
|
|
- if ( FAILED( hr ) )
|
|
|
- {
|
|
|
- return hr;
|
|
|
- }
|
|
|
- return AppendWTruncate( pszAppendWTruncate, cchLen );
|
|
|
-}
|
|
|
-
|
|
|
-HRESULT
|
|
|
-STRA::AppendWTruncate(
|
|
|
- __in_ecount(cchLen)
|
|
|
- PCWSTR pszAppendWTruncate,
|
|
|
- __in SIZE_T cchLen
|
|
|
-)
|
|
|
-//
|
|
|
-// The "Truncate" methods do not do proper conversion. They do a (CHAR) caste
|
|
|
-//
|
|
|
-{
|
|
|
- _ASSERTE( cchLen <= MAXDWORD );
|
|
|
- if ( cchLen == 0 )
|
|
|
- {
|
|
|
- return S_OK;
|
|
|
- }
|
|
|
- return AuxAppendWTruncate(
|
|
|
- pszAppendWTruncate,
|
|
|
- static_cast<DWORD>(cchLen),
|
|
|
- QueryCB()
|
|
|
- );
|
|
|
-}
|
|
|
-
|
|
|
HRESULT
|
|
|
STRA::CopyToBuffer(
|
|
|
__out_bcount(*pcb) CHAR* pszBuffer,
|
|
|
@@ -409,72 +310,6 @@ Finished:
|
|
|
return hr;
|
|
|
}
|
|
|
|
|
|
-HRESULT
|
|
|
-STRA::SetLen(
|
|
|
- __in DWORD cchLen
|
|
|
-)
|
|
|
-/*++
|
|
|
- *
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Set the length of the string and null terminate, if there
|
|
|
- is sufficient buffer already allocated. Will not reallocate.
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- cchLen - The number of characters in the new string.
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- HRESULT
|
|
|
-
|
|
|
---*/
|
|
|
-{
|
|
|
- if( cchLen >= QuerySizeCCH() )
|
|
|
- {
|
|
|
- return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
|
- }
|
|
|
-
|
|
|
- *( QueryStr() + cchLen ) = '\0';
|
|
|
- m_cchLen = cchLen;
|
|
|
-
|
|
|
- return S_OK;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-HRESULT
|
|
|
-STRA::SafeSnprintf(
|
|
|
- __in __format_string
|
|
|
- PCSTR pszFormatString,
|
|
|
- ...
|
|
|
-)
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Writes to a STRA, growing it as needed. It arbitrarily caps growth at 64k chars.
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- pszFormatString - printf format
|
|
|
- ... - printf args
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- HRESULT
|
|
|
-
|
|
|
---*/
|
|
|
-{
|
|
|
- va_list argsList;
|
|
|
- va_start( argsList, pszFormatString );
|
|
|
-
|
|
|
- HRESULT hr = SafeVsnprintf(pszFormatString, argsList);
|
|
|
-
|
|
|
-#pragma warning(suppress: 26477) // va_end uses 0
|
|
|
- va_end( argsList );
|
|
|
- return hr;
|
|
|
-}
|
|
|
-
|
|
|
HRESULT
|
|
|
STRA::SafeVsnprintf(
|
|
|
__in __format_string
|
|
|
@@ -582,516 +417,139 @@ Finished:
|
|
|
return hr;
|
|
|
}
|
|
|
|
|
|
-bool
|
|
|
-FShouldEscapeUtf8(
|
|
|
- BYTE ch
|
|
|
- )
|
|
|
-{
|
|
|
- if ( ( ch >= 128 ) )
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-bool
|
|
|
-FShouldEscapeUrl(
|
|
|
- BYTE ch
|
|
|
- )
|
|
|
+HRESULT
|
|
|
+STRA::CopyWToUTF8Unescaped(
|
|
|
+ __in LPCWSTR cpchStr
|
|
|
+)
|
|
|
{
|
|
|
- if ( ( ch >= 128 ||
|
|
|
- ch <= 32 ||
|
|
|
- ch == '<' ||
|
|
|
- ch == '>' ||
|
|
|
- ch == '%' ||
|
|
|
- ch == '?' ||
|
|
|
- ch == '#' ) &&
|
|
|
- !( ch == '\n' || ch == '\r' ) )
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
+ return STRA::CopyWToUTF8Unescaped(cpchStr, static_cast<DWORD>(wcslen(cpchStr)));
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
|
-STRA::Escape(
|
|
|
- VOID
|
|
|
+STRA::CopyWToUTF8Unescaped(
|
|
|
+ __in_ecount(cch)
|
|
|
+ LPCWSTR cpchStr,
|
|
|
+ __in DWORD cch
|
|
|
)
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Escapes a STRA
|
|
|
-
|
|
|
-Arguments:
|
|
|
+{
|
|
|
+ HRESULT hr = S_OK;
|
|
|
|
|
|
- None
|
|
|
+ if (cch == 0)
|
|
|
+ {
|
|
|
+ Reset();
|
|
|
+ return S_OK;
|
|
|
+ }
|
|
|
|
|
|
-Return Value:
|
|
|
+ int iRet = ConvertUnicodeToUTF8(cpchStr,
|
|
|
+ &m_Buff,
|
|
|
+ cch);
|
|
|
+ if (-1 == iRet)
|
|
|
+ {
|
|
|
+ // could not convert
|
|
|
+ hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
+ goto Finished;
|
|
|
+ }
|
|
|
|
|
|
- None
|
|
|
+ m_cchLen = iRet;
|
|
|
|
|
|
---*/
|
|
|
-{
|
|
|
- return EscapeInternal( FShouldEscapeUrl );
|
|
|
+ _ASSERTE(strlen(m_Buff.QueryPtr()) == m_cchLen);
|
|
|
+Finished:
|
|
|
+ return hr;
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
|
-STRA::EscapeUtf8(
|
|
|
+STRA::AuxAppend(
|
|
|
+ __in_ecount(cbLen)
|
|
|
+ LPCSTR pStr,
|
|
|
+ __in DWORD cbLen,
|
|
|
+ __in DWORD cbOffset
|
|
|
)
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
+{
|
|
|
+ _ASSERTE( nullptr != pStr );
|
|
|
+ _ASSERTE( cbOffset <= QueryCB() );
|
|
|
|
|
|
- Escapes the high-bit chars in a STRA. LWS, CR, LF & controls are untouched.
|
|
|
+ ULONGLONG cb64NewSize = static_cast<ULONGLONG>(cbOffset) + cbLen + sizeof( CHAR );
|
|
|
+ if( cb64NewSize > MAXDWORD )
|
|
|
+ {
|
|
|
+ return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
|
|
|
+ }
|
|
|
|
|
|
-Arguments:
|
|
|
+ if( m_Buff.QuerySize() < cb64NewSize )
|
|
|
+ {
|
|
|
+ if( !m_Buff.Resize( static_cast<SIZE_T>(cb64NewSize) ) )
|
|
|
+ {
|
|
|
+ return E_OUTOFMEMORY;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- None
|
|
|
+ memcpy( reinterpret_cast<BYTE*>(m_Buff.QueryPtr()) + cbOffset, pStr, cbLen );
|
|
|
|
|
|
-Return Value:
|
|
|
+ m_cchLen = cbLen + cbOffset;
|
|
|
|
|
|
- None
|
|
|
+ *( QueryStr() + m_cchLen ) = '\0';
|
|
|
|
|
|
---*/
|
|
|
-{
|
|
|
- return EscapeInternal( FShouldEscapeUtf8 );
|
|
|
+ return S_OK;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
HRESULT
|
|
|
-STRA::EscapeInternal(
|
|
|
- PFN_F_SHOULD_ESCAPE pfnFShouldEscape
|
|
|
+STRA::AuxAppendW(
|
|
|
+ __in_ecount(cchAppendW)
|
|
|
+ PCWSTR pszAppendW,
|
|
|
+ __in DWORD cchAppendW,
|
|
|
+ __in DWORD cbOffset,
|
|
|
+ __in UINT CodePage,
|
|
|
+ __in BOOL fFailIfNoTranslation,
|
|
|
+ __in DWORD dwFlags
|
|
|
)
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Escapes a STRA according to the predicate function passed in
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- None
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- None
|
|
|
-
|
|
|
---*/
|
|
|
{
|
|
|
- LPCSTR pch = QueryStr();
|
|
|
- __analysis_assume( pch != nullptr );
|
|
|
- int i = 0;
|
|
|
- BYTE ch;
|
|
|
- HRESULT hr = S_OK;
|
|
|
- ULONG64 NewSize = 0;
|
|
|
+ HRESULT hr = S_OK;
|
|
|
+ DWORD cbRet = 0;
|
|
|
+ DWORD cbAvailable = 0;
|
|
|
+ UNREFERENCED_PARAMETER(fFailIfNoTranslation);
|
|
|
+
|
|
|
+ //
|
|
|
+ // There are only two expect places to append
|
|
|
+ //
|
|
|
+ _ASSERTE( 0 == cbOffset || QueryCB() == cbOffset );
|
|
|
|
|
|
- // Set to true if any % escaping occurs
|
|
|
- BOOL fEscapingDone = FALSE;
|
|
|
+ if ( cchAppendW == 0 )
|
|
|
+ {
|
|
|
+ goto Finished;
|
|
|
+ }
|
|
|
|
|
|
//
|
|
|
- // If there are any characters that need to be escaped we copy the entire string
|
|
|
- // character by character into straTemp, escaping as we go, then at the end
|
|
|
- // copy all of straTemp over. Don't modify InlineBuffer directly.
|
|
|
+ // start by assuming 1 char to 1 char will be enough space
|
|
|
//
|
|
|
- CHAR InlineBuffer[512];
|
|
|
- InlineBuffer[0] = '\0';
|
|
|
- STRA straTemp(InlineBuffer, sizeof(InlineBuffer)/sizeof(*InlineBuffer));
|
|
|
+ if( !m_Buff.Resize( cbOffset + cchAppendW + sizeof( CHAR ) ) )
|
|
|
+ {
|
|
|
+ hr = E_OUTOFMEMORY;
|
|
|
+ goto Finished;
|
|
|
+ }
|
|
|
|
|
|
- _ASSERTE( pch );
|
|
|
+ cbAvailable = m_Buff.QuerySize() - cbOffset;
|
|
|
|
|
|
- while ((DWORD)i < m_cchLen && pch[i] != NULL)
|
|
|
+ cbRet = WideCharToMultiByte(
|
|
|
+ CodePage,
|
|
|
+ dwFlags,
|
|
|
+ pszAppendW,
|
|
|
+ cchAppendW,
|
|
|
+ QueryStr() + cbOffset,
|
|
|
+ cbAvailable,
|
|
|
+ nullptr,
|
|
|
+ nullptr
|
|
|
+ );
|
|
|
+ if( 0 != cbRet )
|
|
|
{
|
|
|
+ if(!m_Buff.Resize(cbOffset + cbRet + 1))
|
|
|
+ {
|
|
|
+ hr = E_OUTOFMEMORY;
|
|
|
+ }
|
|
|
+
|
|
|
//
|
|
|
- // Escape characters that are in the non-printable range
|
|
|
- // but ignore CR and LF
|
|
|
+ // not zero --> success, so we're done
|
|
|
//
|
|
|
-
|
|
|
- ch = pch[i];
|
|
|
- if ( pfnFShouldEscape( ch ) )
|
|
|
- {
|
|
|
- if (FALSE == fEscapingDone)
|
|
|
- {
|
|
|
- // first character in the string that needed escaping
|
|
|
- fEscapingDone = TRUE;
|
|
|
-
|
|
|
- // guess that the size needs to be larger than
|
|
|
- // what we used to have times two
|
|
|
- NewSize = static_cast<ULONG64>(QueryCCH()) * 2;
|
|
|
- if ( NewSize > MAXDWORD )
|
|
|
- {
|
|
|
- hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
|
|
|
- return hr;
|
|
|
- }
|
|
|
-
|
|
|
- hr = straTemp.Resize( static_cast<DWORD>(NewSize) );
|
|
|
-
|
|
|
- if (FAILED(hr))
|
|
|
- {
|
|
|
- return hr;
|
|
|
- }
|
|
|
-
|
|
|
- // Copy all of the previous buffer into buffTemp, only if it is not the first character:
|
|
|
-
|
|
|
- if ( i > 0)
|
|
|
- {
|
|
|
- hr = straTemp.Copy(QueryStr(),
|
|
|
- i * sizeof(CHAR));
|
|
|
- if (FAILED(hr))
|
|
|
- {
|
|
|
- return hr;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // resize the temporary (if needed) with the slop of the entire buffer length
|
|
|
- // this fixes constant reallocation if the entire string needs to be escaped
|
|
|
- NewSize = static_cast<ULONG64>(QueryCCH()) + 2 * sizeof(CHAR) + 1 * sizeof(CHAR);
|
|
|
- if ( NewSize > MAXDWORD )
|
|
|
- {
|
|
|
- hr = HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
|
|
|
- return hr;
|
|
|
- }
|
|
|
-
|
|
|
- BOOL fRet = straTemp.m_Buff.Resize(static_cast<size_t>(NewSize));
|
|
|
- if ( !fRet )
|
|
|
- {
|
|
|
- hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
- return hr;
|
|
|
- }
|
|
|
-
|
|
|
- //
|
|
|
- // Create the string to append for the current character
|
|
|
- //
|
|
|
-
|
|
|
- CHAR chHex[3];
|
|
|
- chHex[0] = '%';
|
|
|
-
|
|
|
- //
|
|
|
- // Convert the low then the high character to hex
|
|
|
- //
|
|
|
-
|
|
|
- UINT nLowDigit = static_cast<UINT>(ch % 16);
|
|
|
- chHex[2] = TODIGIT( nLowDigit );
|
|
|
-
|
|
|
- ch /= 16;
|
|
|
-
|
|
|
- UINT nHighDigit = static_cast<UINT>(ch % 16);
|
|
|
-
|
|
|
- chHex[1] = TODIGIT( nHighDigit );
|
|
|
-
|
|
|
- //
|
|
|
- // Actually append the converted character to the end of the temporary
|
|
|
- //
|
|
|
- hr = straTemp.Append(chHex, 3);
|
|
|
- if (FAILED(hr))
|
|
|
- {
|
|
|
- return hr;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // if no escaping done, no need to copy
|
|
|
- if (fEscapingDone)
|
|
|
- {
|
|
|
- // if ANY escaping done, copy current character into new buffer
|
|
|
- straTemp.Append(&pch[i], 1);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // inspect the next character in the string
|
|
|
- i++;
|
|
|
- }
|
|
|
-
|
|
|
- if (fEscapingDone)
|
|
|
- {
|
|
|
- // the escaped string is now in straTemp
|
|
|
- hr = Copy(straTemp);
|
|
|
- }
|
|
|
-
|
|
|
- return hr;
|
|
|
-
|
|
|
-} // EscapeInternal()
|
|
|
-
|
|
|
-VOID
|
|
|
-STRA::Unescape(
|
|
|
-)
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Unescapes a STRA
|
|
|
-
|
|
|
- Supported escape sequences are:
|
|
|
- %uxxxx unescapes Unicode character xxxx into system codepage
|
|
|
- %xx unescapes character xx
|
|
|
- % without following hex digits is ignored
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- None
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- None
|
|
|
-
|
|
|
---*/
|
|
|
-{
|
|
|
- CHAR *pScan;
|
|
|
- WCHAR wch;
|
|
|
- DWORD dwLen;
|
|
|
- BOOL fChanged = FALSE;
|
|
|
-
|
|
|
- //
|
|
|
- // Now take care of any escape characters
|
|
|
- //
|
|
|
- CHAR* pDest = pScan = strchr(QueryStr(), '%');
|
|
|
-
|
|
|
- while (pScan)
|
|
|
- {
|
|
|
- if ((pScan[1] == 'u' || pScan[1] == 'U') &&
|
|
|
- SAFEIsXDigit(pScan[2]) &&
|
|
|
- SAFEIsXDigit(pScan[3]) &&
|
|
|
- SAFEIsXDigit(pScan[4]) &&
|
|
|
- SAFEIsXDigit(pScan[5]))
|
|
|
- {
|
|
|
- wch = TOHEX(pScan[2]) * 4096 + TOHEX(pScan[3]) * 256
|
|
|
- + TOHEX(pScan[4]) * 16 + TOHEX(pScan[5]);
|
|
|
-
|
|
|
- dwLen = WideCharToMultiByte(CP_ACP,
|
|
|
- WC_NO_BEST_FIT_CHARS,
|
|
|
- &wch,
|
|
|
- 1,
|
|
|
- static_cast<LPSTR>(pDest),
|
|
|
- 6,
|
|
|
- nullptr,
|
|
|
- nullptr);
|
|
|
-
|
|
|
- pDest += dwLen;
|
|
|
- pScan += 6;
|
|
|
- fChanged = TRUE;
|
|
|
- }
|
|
|
- else if (SAFEIsXDigit(pScan[1]) && SAFEIsXDigit(pScan[2]))
|
|
|
- {
|
|
|
- *pDest = TOHEX(pScan[1]) * 16 + TOHEX(pScan[2]);
|
|
|
-
|
|
|
- pDest ++;
|
|
|
- pScan += 3;
|
|
|
- fChanged = TRUE;
|
|
|
- }
|
|
|
- else // Not an escaped char, just a '%'
|
|
|
- {
|
|
|
- if (fChanged)
|
|
|
- {
|
|
|
- *pDest = *pScan;
|
|
|
- }
|
|
|
-
|
|
|
- pDest++;
|
|
|
- pScan++;
|
|
|
- }
|
|
|
-
|
|
|
- //
|
|
|
- // Copy all the information between this and the next escaped char
|
|
|
- //
|
|
|
- CHAR* pNextScan = strchr(pScan, '%');
|
|
|
-
|
|
|
- if (fChanged) // pScan!=pDest, so we have to copy the char's
|
|
|
- {
|
|
|
- if (!pNextScan) // That was the last '%' in the string
|
|
|
- {
|
|
|
- memmove(pDest,
|
|
|
- pScan,
|
|
|
- QueryCCH() - DIFF(pScan - QueryStr()) + 1);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // There is another '%', move intermediate chars
|
|
|
- if ((dwLen = static_cast<DWORD>(DIFF(pNextScan - pScan))) != 0)
|
|
|
- {
|
|
|
- memmove(pDest,
|
|
|
- pScan,
|
|
|
- dwLen);
|
|
|
- pDest += dwLen;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- pScan = pNextScan;
|
|
|
- }
|
|
|
-
|
|
|
- if (fChanged)
|
|
|
- {
|
|
|
- m_cchLen = static_cast<DWORD>(strlen(QueryStr())); // for safety recalc the length
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-HRESULT
|
|
|
-STRA::CopyWToUTF8Unescaped(
|
|
|
- __in LPCWSTR cpchStr
|
|
|
-)
|
|
|
-{
|
|
|
- return STRA::CopyWToUTF8Unescaped(cpchStr, static_cast<DWORD>(wcslen(cpchStr)));
|
|
|
-}
|
|
|
-
|
|
|
-HRESULT
|
|
|
-STRA::CopyWToUTF8Unescaped(
|
|
|
- __in_ecount(cch)
|
|
|
- LPCWSTR cpchStr,
|
|
|
- __in DWORD cch
|
|
|
-)
|
|
|
-{
|
|
|
- HRESULT hr = S_OK;
|
|
|
-
|
|
|
- if (cch == 0)
|
|
|
- {
|
|
|
- Reset();
|
|
|
- return S_OK;
|
|
|
- }
|
|
|
-
|
|
|
- int iRet = ConvertUnicodeToUTF8(cpchStr,
|
|
|
- &m_Buff,
|
|
|
- cch);
|
|
|
- if (-1 == iRet)
|
|
|
- {
|
|
|
- // could not convert
|
|
|
- hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
- goto Finished;
|
|
|
- }
|
|
|
-
|
|
|
- m_cchLen = iRet;
|
|
|
-
|
|
|
- _ASSERTE(strlen(m_Buff.QueryPtr()) == m_cchLen);
|
|
|
-Finished:
|
|
|
- return hr;
|
|
|
-}
|
|
|
-
|
|
|
-HRESULT
|
|
|
-STRA::CopyWToUTF8Escaped(
|
|
|
- __in LPCWSTR cpchStr
|
|
|
-)
|
|
|
-{
|
|
|
- return STRA::CopyWToUTF8Escaped(cpchStr, static_cast<DWORD>(wcslen(cpchStr)));
|
|
|
-}
|
|
|
-
|
|
|
-HRESULT
|
|
|
-STRA::CopyWToUTF8Escaped(
|
|
|
- __in_ecount(cch)
|
|
|
- LPCWSTR cpchStr,
|
|
|
- __in DWORD cch
|
|
|
-)
|
|
|
-{
|
|
|
- HRESULT hr = CopyWToUTF8Unescaped(cpchStr, cch);
|
|
|
- if (FAILED(hr))
|
|
|
- {
|
|
|
- goto Finished;
|
|
|
- }
|
|
|
-
|
|
|
- hr = Escape();
|
|
|
- if (FAILED(hr))
|
|
|
- {
|
|
|
- goto Finished;
|
|
|
- }
|
|
|
-
|
|
|
- hr = S_OK;
|
|
|
-Finished:
|
|
|
- return hr;
|
|
|
-}
|
|
|
-
|
|
|
-HRESULT
|
|
|
-STRA::AuxAppend(
|
|
|
- __in_ecount(cbLen)
|
|
|
- LPCSTR pStr,
|
|
|
- __in DWORD cbLen,
|
|
|
- __in DWORD cbOffset
|
|
|
-)
|
|
|
-{
|
|
|
- _ASSERTE( nullptr != pStr );
|
|
|
- _ASSERTE( cbOffset <= QueryCB() );
|
|
|
-
|
|
|
- ULONGLONG cb64NewSize = static_cast<ULONGLONG>(cbOffset) + cbLen + sizeof( CHAR );
|
|
|
- if( cb64NewSize > MAXDWORD )
|
|
|
- {
|
|
|
- return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
|
|
|
- }
|
|
|
-
|
|
|
- if( m_Buff.QuerySize() < cb64NewSize )
|
|
|
- {
|
|
|
- if( !m_Buff.Resize( static_cast<SIZE_T>(cb64NewSize) ) )
|
|
|
- {
|
|
|
- return E_OUTOFMEMORY;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- memcpy( reinterpret_cast<BYTE*>(m_Buff.QueryPtr()) + cbOffset, pStr, cbLen );
|
|
|
-
|
|
|
- m_cchLen = cbLen + cbOffset;
|
|
|
-
|
|
|
- *( QueryStr() + m_cchLen ) = '\0';
|
|
|
-
|
|
|
- return S_OK;
|
|
|
-}
|
|
|
-
|
|
|
-HRESULT
|
|
|
-STRA::AuxAppendW(
|
|
|
- __in_ecount(cchAppendW)
|
|
|
- PCWSTR pszAppendW,
|
|
|
- __in DWORD cchAppendW,
|
|
|
- __in DWORD cbOffset,
|
|
|
- __in UINT CodePage,
|
|
|
- __in BOOL fFailIfNoTranslation,
|
|
|
- __in DWORD dwFlags
|
|
|
-)
|
|
|
-{
|
|
|
- HRESULT hr = S_OK;
|
|
|
- DWORD cbRet = 0;
|
|
|
- DWORD cbAvailable = 0;
|
|
|
- UNREFERENCED_PARAMETER(fFailIfNoTranslation);
|
|
|
-
|
|
|
- //
|
|
|
- // There are only two expect places to append
|
|
|
- //
|
|
|
- _ASSERTE( 0 == cbOffset || QueryCB() == cbOffset );
|
|
|
-
|
|
|
- if ( cchAppendW == 0 )
|
|
|
- {
|
|
|
- goto Finished;
|
|
|
- }
|
|
|
-
|
|
|
- //
|
|
|
- // start by assuming 1 char to 1 char will be enough space
|
|
|
- //
|
|
|
- if( !m_Buff.Resize( cbOffset + cchAppendW + sizeof( CHAR ) ) )
|
|
|
- {
|
|
|
- hr = E_OUTOFMEMORY;
|
|
|
- goto Finished;
|
|
|
- }
|
|
|
-
|
|
|
- cbAvailable = m_Buff.QuerySize() - cbOffset;
|
|
|
-
|
|
|
- cbRet = WideCharToMultiByte(
|
|
|
- CodePage,
|
|
|
- dwFlags,
|
|
|
- pszAppendW,
|
|
|
- cchAppendW,
|
|
|
- QueryStr() + cbOffset,
|
|
|
- cbAvailable,
|
|
|
- nullptr,
|
|
|
- nullptr
|
|
|
- );
|
|
|
- if( 0 != cbRet )
|
|
|
- {
|
|
|
- if(!m_Buff.Resize(cbOffset + cbRet + 1))
|
|
|
- {
|
|
|
- hr = E_OUTOFMEMORY;
|
|
|
- }
|
|
|
-
|
|
|
- //
|
|
|
- // not zero --> success, so we're done
|
|
|
- //
|
|
|
- goto Finished;
|
|
|
- }
|
|
|
+ goto Finished;
|
|
|
+ }
|
|
|
|
|
|
//
|
|
|
// We only know how to handle ERROR_INSUFFICIENT_BUFFER
|
|
|
@@ -1287,21 +745,6 @@ STRA::ConvertUnicodeToCodePage(
|
|
|
return iStrLen;
|
|
|
}
|
|
|
|
|
|
-// static
|
|
|
-HRESULT
|
|
|
-STRA::ConvertUnicodeToMultiByte(
|
|
|
- __in_ecount(dwStringLen)
|
|
|
- LPCWSTR pszSrcUnicodeString,
|
|
|
- __in BUFFER_T<CHAR,1> * pbufDstAnsiString,
|
|
|
- __in DWORD dwStringLen
|
|
|
-)
|
|
|
-{
|
|
|
- return ConvertUnicodeToCodePage( pszSrcUnicodeString,
|
|
|
- pbufDstAnsiString,
|
|
|
- dwStringLen,
|
|
|
- CP_ACP );
|
|
|
-}
|
|
|
-
|
|
|
// static
|
|
|
HRESULT
|
|
|
STRA::ConvertUnicodeToUTF8(
|
|
|
@@ -1316,403 +759,3 @@ STRA::ConvertUnicodeToUTF8(
|
|
|
dwStringLen,
|
|
|
CP_UTF8 );
|
|
|
}
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Removes leading and trailing whitespace
|
|
|
-
|
|
|
---*/
|
|
|
-
|
|
|
-VOID
|
|
|
-STRA::Trim()
|
|
|
-{
|
|
|
- PSTR pszString = QueryStr();
|
|
|
- DWORD cchNewLength = m_cchLen;
|
|
|
- DWORD cchLeadingWhitespace = 0;
|
|
|
-
|
|
|
- for (LONG ixString = m_cchLen - 1; ixString >= 0; ixString--)
|
|
|
- {
|
|
|
- if (isspace(static_cast<unsigned char>(pszString[ixString])) != 0)
|
|
|
- {
|
|
|
- pszString[ixString] = '\0';
|
|
|
- cchNewLength--;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- DWORD cchTempLength = cchNewLength;
|
|
|
- for (DWORD ixString = 0; ixString < cchTempLength; ixString++)
|
|
|
- {
|
|
|
- if (isspace(static_cast<unsigned char>(pszString[ixString])) != 0)
|
|
|
- {
|
|
|
- cchLeadingWhitespace++;
|
|
|
- cchNewLength--;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (cchNewLength == 0)
|
|
|
- {
|
|
|
-
|
|
|
- Reset();
|
|
|
- }
|
|
|
- else if (cchLeadingWhitespace > 0)
|
|
|
- {
|
|
|
- memmove(pszString, pszString + cchLeadingWhitespace, cchNewLength * sizeof(CHAR));
|
|
|
- pszString[cchNewLength] = '\0';
|
|
|
- }
|
|
|
-
|
|
|
- SyncWithBuffer();
|
|
|
-}
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Compares the string to the provided prefix to check for equality
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- pStraPrefix - string to compare with
|
|
|
- fIgnoreCase - indicates whether the string comparison should be case-sensitive
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- TRUE if prefix string matches with internal string, FALSE otherwise
|
|
|
-
|
|
|
---*/
|
|
|
-BOOL
|
|
|
-STRA::StartsWith(
|
|
|
- __in const STRA * pStraPrefix,
|
|
|
- __in bool fIgnoreCase) const
|
|
|
-{
|
|
|
- _ASSERTE( pStraPrefix != nullptr );
|
|
|
- return StartsWith(pStraPrefix->QueryStr(), fIgnoreCase);
|
|
|
-}
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Compares the string to the provided prefix to check for equality
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- straPrefix - string to compare with
|
|
|
- fIgnoreCase - indicates whether the string comparison should be case-sensitive
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- TRUE if prefix string matches with internal string, FALSE otherwise
|
|
|
-
|
|
|
---*/
|
|
|
-BOOL
|
|
|
-STRA::StartsWith(
|
|
|
- __in const STRA & straPrefix,
|
|
|
- __in bool fIgnoreCase) const
|
|
|
-{
|
|
|
- return StartsWith(straPrefix.QueryStr(), fIgnoreCase);
|
|
|
-}
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Compares the string to the provided prefix to check for equality
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- pszPrefix - string to compare with
|
|
|
- fIgnoreCase - indicates whether the string comparison should be case-sensitive
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- TRUE if prefix string matches with internal string, FALSE otherwise
|
|
|
-
|
|
|
---*/
|
|
|
-BOOL
|
|
|
-STRA::StartsWith(
|
|
|
- __in PCSTR pszPrefix,
|
|
|
- __in bool fIgnoreCase) const
|
|
|
-{
|
|
|
- if (pszPrefix == nullptr)
|
|
|
- {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- size_t cchPrefix = 0;
|
|
|
- HRESULT hr = StringCchLengthA(pszPrefix, STRSAFE_MAX_CCH, &cchPrefix);
|
|
|
- if (FAILED(hr))
|
|
|
- {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- _ASSERTE( cchPrefix <= MAXDWORD );
|
|
|
- if (cchPrefix > m_cchLen)
|
|
|
- {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- BOOL fMatch = FALSE;
|
|
|
- if ( fIgnoreCase )
|
|
|
- {
|
|
|
- fMatch = ( 0 == _strnicmp( QueryStr(), pszPrefix, cchPrefix ) );
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- fMatch = ( 0 == strncmp( QueryStr(), pszPrefix, cchPrefix ) );
|
|
|
- }
|
|
|
-
|
|
|
- return fMatch;
|
|
|
-}
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Compares the string to the provided suffix to check for equality
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- pStraSuffix - string to compare with
|
|
|
- fIgnoreCase - indicates whether the string comparison should be case-sensitive
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- TRUE if suffix string matches with internal string, FALSE otherwise
|
|
|
-
|
|
|
---*/
|
|
|
-BOOL
|
|
|
-STRA::EndsWith(
|
|
|
- __in const STRA * pStraSuffix,
|
|
|
- __in bool fIgnoreCase) const
|
|
|
-{
|
|
|
- _ASSERTE( pStraSuffix != nullptr );
|
|
|
- return EndsWith(pStraSuffix->QueryStr(), fIgnoreCase);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Compares the string to the provided suffix to check for equality
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- straSuffix - string to compare with
|
|
|
- fIgnoreCase - indicates whether the string comparison should be case-sensitive
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- TRUE if suffix string matches with internal string, FALSE otherwise
|
|
|
-
|
|
|
---*/
|
|
|
-BOOL
|
|
|
-STRA::EndsWith(
|
|
|
- __in const STRA & straSuffix,
|
|
|
- __in bool fIgnoreCase) const
|
|
|
-{
|
|
|
- return EndsWith(straSuffix.QueryStr(), fIgnoreCase);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Compares the string to the provided suffix to check for equality
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- pszSuffix - string to compare with
|
|
|
- fIgnoreCase - indicates whether the string comparison should be case-sensitive
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- TRUE if suffix string matches with internal string, FALSE otherwise
|
|
|
-
|
|
|
---*/
|
|
|
-BOOL
|
|
|
-STRA::EndsWith(
|
|
|
- __in PCSTR pszSuffix,
|
|
|
- __in bool fIgnoreCase) const
|
|
|
-{
|
|
|
- PSTR pszString = QueryStr();
|
|
|
-
|
|
|
- if (pszSuffix == nullptr)
|
|
|
- {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- size_t cchSuffix = 0;
|
|
|
- HRESULT hr = StringCchLengthA(pszSuffix, STRSAFE_MAX_CCH, &cchSuffix);
|
|
|
- if (FAILED(hr))
|
|
|
- {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- _ASSERTE( cchSuffix <= MAXDWORD );
|
|
|
- if (cchSuffix > m_cchLen)
|
|
|
- {
|
|
|
- return FALSE;
|
|
|
- }
|
|
|
-
|
|
|
- ptrdiff_t ixOffset = m_cchLen - cchSuffix;
|
|
|
- _ASSERTE(ixOffset >= 0 && ixOffset <= MAXDWORD);
|
|
|
-
|
|
|
- BOOL fMatch = FALSE;
|
|
|
- if ( fIgnoreCase )
|
|
|
- {
|
|
|
- fMatch = ( 0 == _strnicmp( pszString + ixOffset, pszSuffix, cchSuffix ) );
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- fMatch = ( 0 == strncmp( pszString + ixOffset, pszSuffix, cchSuffix ) );
|
|
|
- }
|
|
|
-
|
|
|
- return fMatch;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Searches the string for the first occurrence of the specified character.
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- charValue - character to find
|
|
|
- dwStartIndex - the initial index.
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- The index for the first character occurrence in the string.
|
|
|
-
|
|
|
- -1 if not found.
|
|
|
-
|
|
|
---*/
|
|
|
-INT
|
|
|
-STRA::IndexOf(
|
|
|
- __in CHAR charValue,
|
|
|
- __in DWORD dwStartIndex
|
|
|
- ) const
|
|
|
-{
|
|
|
- INT nIndex = -1;
|
|
|
-
|
|
|
- // Make sure that there are no buffer overruns.
|
|
|
- if ( dwStartIndex >= QueryCCH() )
|
|
|
- {
|
|
|
- return nIndex;
|
|
|
- }
|
|
|
-
|
|
|
- const CHAR* pChar = strchr( QueryStr() + dwStartIndex, charValue );
|
|
|
-
|
|
|
- // Determine the index if found
|
|
|
- if ( pChar )
|
|
|
- {
|
|
|
- // nIndex will be set to -1 on failure.
|
|
|
- (VOID)SizeTToInt( pChar - QueryStr(), &nIndex );
|
|
|
- }
|
|
|
-
|
|
|
- return nIndex;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Searches the string for the first occurrence of the specified substring.
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- pszValue - substring to find
|
|
|
- dwStartIndex - initial index.
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- The index for the first character occurrence in the string.
|
|
|
-
|
|
|
- -1 if not found.
|
|
|
-
|
|
|
---*/
|
|
|
-INT
|
|
|
-STRA::IndexOf(
|
|
|
- __in PCSTR pszValue,
|
|
|
- __in DWORD dwStartIndex
|
|
|
- ) const
|
|
|
-{
|
|
|
- INT nIndex = -1;
|
|
|
-
|
|
|
- // Validate input parameters
|
|
|
- if( dwStartIndex >= QueryCCH() || !pszValue )
|
|
|
- {
|
|
|
- return nIndex;
|
|
|
- }
|
|
|
-
|
|
|
- const CHAR* pChar = strstr( QueryStr() + dwStartIndex, pszValue );
|
|
|
-
|
|
|
- // Determine the index if found
|
|
|
- if( pChar )
|
|
|
- {
|
|
|
- // nIndex will be set to -1 on failure.
|
|
|
- (VOID)SizeTToInt( pChar - QueryStr(), &nIndex );
|
|
|
- }
|
|
|
-
|
|
|
- return nIndex;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*++
|
|
|
-
|
|
|
-Routine Description:
|
|
|
-
|
|
|
- Searches the string for the last occurrence of the specified character.
|
|
|
-
|
|
|
-Arguments:
|
|
|
-
|
|
|
- charValue - character to find
|
|
|
- dwStartIndex - initial index.
|
|
|
-
|
|
|
-Return Value:
|
|
|
-
|
|
|
- The index for the last character occurrence in the string.
|
|
|
-
|
|
|
- -1 if not found.
|
|
|
-
|
|
|
---*/
|
|
|
-INT
|
|
|
-STRA::LastIndexOf(
|
|
|
- __in CHAR charValue,
|
|
|
- __in DWORD dwStartIndex
|
|
|
- ) const
|
|
|
-{
|
|
|
- INT nIndex = -1;
|
|
|
-
|
|
|
- // Make sure that there are no buffer overruns.
|
|
|
- if( dwStartIndex >= QueryCCH() )
|
|
|
- {
|
|
|
- return nIndex;
|
|
|
- }
|
|
|
-
|
|
|
- const CHAR* pChar = strrchr( QueryStr() + dwStartIndex, charValue );
|
|
|
-
|
|
|
- // Determine the index if found
|
|
|
- if( pChar )
|
|
|
- {
|
|
|
- // nIndex will be set to -1 on failure.
|
|
|
- (VOID)SizeTToInt( pChar - QueryStr(), &nIndex );
|
|
|
- }
|
|
|
-
|
|
|
- return nIndex;
|
|
|
-}
|