You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
417 lines
11 KiB
417 lines
11 KiB
/**********************************************************************/
|
|
/** Microsoft Windows NT **/
|
|
/** Copyright(c) Microsoft Corp., 1997 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Module:
|
|
string.hxx
|
|
|
|
Abstract:
|
|
|
|
This module contains a light weight string class for ANSI/UNICODE
|
|
operations.
|
|
|
|
|
|
|
|
FILE HISTORY:
|
|
4/8/97 michth created
|
|
11/9/98 MuraliK Imported from IIS5 project
|
|
*/
|
|
|
|
|
|
#ifndef _STRINGAU_HXX_
|
|
#define _STRINGAU_HXX_
|
|
|
|
# include <buffer.hxx>
|
|
# include "dbgutil.h"
|
|
|
|
class IRTL_DLLEXP STRAU;
|
|
|
|
#ifdef UNICODE
|
|
# define STRAU_DEFAULT_UNICODE TRUE
|
|
|
|
#else
|
|
# define STRAU_DEFAULT_UNICODE FALSE
|
|
|
|
#endif // UNICODE
|
|
|
|
|
|
/*
|
|
Class STRAU
|
|
String Ascii-Unicode
|
|
|
|
This class transparently converts between ANSI and Unicode.
|
|
All members can take/return string in either ANSI or Unicode.
|
|
For members which have a parameter of bUnicode, the actual string
|
|
type must match the flag, even though it gets passed in as the
|
|
declared type.
|
|
|
|
Strings are sync'd on an as needed basis. If a string is set in
|
|
ANSI, then a UNICODE version will only be created if a get for
|
|
UNICODE is done, or if a UNICODE string is appended.
|
|
|
|
All conversions are done using Latin-1. This is because the intended
|
|
use of this class is for converting HTML pages, which are defined to
|
|
be Latin-1.
|
|
*/
|
|
|
|
class IRTL_DLLEXP STRAU
|
|
{
|
|
public:
|
|
|
|
STRAU()
|
|
: m_bufAnsi (0),
|
|
m_bufUnicode(0),
|
|
m_cchUnicodeLen ( 0),
|
|
m_cbMultiByteLen ( 0),
|
|
m_bInSync (TRUE),
|
|
m_bUnicode (STRAU_DEFAULT_UNICODE),
|
|
m_bIsValid (TRUE)
|
|
{}
|
|
|
|
STRAU( LPCSTR pchInit )
|
|
: m_bufAnsi (0),
|
|
m_bufUnicode(0),
|
|
m_cchUnicodeLen ( 0),
|
|
m_cbMultiByteLen ( 0),
|
|
m_bInSync (TRUE),
|
|
m_bUnicode (FALSE),
|
|
m_bIsValid (TRUE)
|
|
{ AuxInit(pchInit); }
|
|
|
|
STRAU( LPCSTR pchInit,
|
|
BOOL bUnicode )
|
|
: m_bufAnsi (0),
|
|
m_bufUnicode(0),
|
|
m_cchUnicodeLen ( 0),
|
|
m_cbMultiByteLen ( 0),
|
|
m_bInSync (TRUE),
|
|
m_bUnicode (FALSE),
|
|
m_bIsValid (TRUE)
|
|
{
|
|
if (bUnicode) {
|
|
AuxInit((LPWSTR)pchInit);
|
|
}
|
|
else {
|
|
AuxInit((LPSTR)pchInit);
|
|
}
|
|
}
|
|
|
|
STRAU( LPCWSTR pchInit )
|
|
: m_bufAnsi (0),
|
|
m_bufUnicode(0),
|
|
m_cchUnicodeLen ( 0),
|
|
m_cbMultiByteLen ( 0),
|
|
m_bInSync (TRUE),
|
|
m_bUnicode (FALSE),
|
|
m_bIsValid (TRUE)
|
|
{ AuxInit(pchInit); }
|
|
|
|
STRAU( STRAU & str )
|
|
: m_bufAnsi(0),
|
|
m_bufUnicode(0),
|
|
m_cchUnicodeLen ( 0),
|
|
m_cbMultiByteLen ( 0),
|
|
m_bInSync (TRUE),
|
|
m_bUnicode (FALSE),
|
|
m_bIsValid (TRUE)
|
|
{
|
|
if (str.IsCurrentUnicode()) {
|
|
AuxInit((LPCWSTR)str.QueryStr(TRUE));
|
|
}
|
|
else {
|
|
AuxInit((LPCSTR)str.QueryStr(FALSE));
|
|
}
|
|
}
|
|
|
|
BOOL IsValid(VOID) { return m_bIsValid; }
|
|
|
|
//
|
|
// Checks and returns TRUE if this string has no valid data else FALSE
|
|
//
|
|
BOOL IsEmpty( VOID)
|
|
{
|
|
return ( (m_bUnicode) ?
|
|
*(LPWSTR)(QueryStr(m_bUnicode)) == (WCHAR)'\0' :
|
|
*(LPSTR)(QueryStr(m_bUnicode)) == '\0'); }
|
|
|
|
BOOL Append( LPCSTR pchInit ) {
|
|
return ((pchInit != NULL) ? (AuxAppend( (LPCSTR ) pchInit,
|
|
(DWORD)strlen(pchInit))) :
|
|
TRUE);
|
|
}
|
|
|
|
BOOL Append( LPCWSTR pchInit ) {
|
|
return ((pchInit != NULL) ? (AuxAppend( (LPCWSTR ) pchInit,
|
|
(DWORD)wcslen(pchInit))) :
|
|
TRUE);
|
|
}
|
|
|
|
BOOL Append( LPCSTR pchInit, DWORD cbLen ) {
|
|
return ((pchInit != NULL) ? (AuxAppend( (LPCSTR ) pchInit,
|
|
cbLen)) :
|
|
TRUE);
|
|
}
|
|
|
|
BOOL Append( LPCWSTR pchInit, DWORD cchLen ) {
|
|
return ((pchInit != NULL) ? (AuxAppend( (LPCWSTR ) pchInit,
|
|
cchLen)) :
|
|
TRUE);
|
|
}
|
|
|
|
BOOL Append( STRAU & str )
|
|
{
|
|
if (m_bUnicode || str.IsCurrentUnicode()) {
|
|
return AuxAppend( str.QueryStrW(), str.QueryCCH());
|
|
}
|
|
else {
|
|
return AuxAppend( str.QueryStrA(), str.QueryCCH());
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// SaveState and RestoreState are used to undo the
|
|
// effects of Reset on error conditions. They are put here
|
|
// to be with Reset. They must be macros since SaveState declares
|
|
// variables which RestoreState uses.
|
|
//
|
|
#define SaveState() \
|
|
DBG_ASSERT( m_bufAnsi.QueryPtr() != NULL); \
|
|
DBG_ASSERT( m_bufUnicode.QueryPtr() != NULL); \
|
|
CHAR cFirstChar = *(LPSTR)(m_bufAnsi.QueryPtr()); \
|
|
WCHAR wFirstChar = *(LPWSTR)(m_bufUnicode.QueryPtr()); \
|
|
DWORD cchUnicodeLen = m_cchUnicodeLen; \
|
|
DWORD cbMultiByteLen = m_cbMultiByteLen; \
|
|
BOOL bUnicode = m_bUnicode; \
|
|
BOOL bInSync = m_bInSync; \
|
|
|
|
#define RestoreState() \
|
|
*(LPSTR)(m_bufAnsi.QueryPtr()) = cFirstChar; \
|
|
*(LPWSTR)(m_bufUnicode.QueryPtr()) = wFirstChar; \
|
|
m_cchUnicodeLen = cchUnicodeLen; \
|
|
m_cbMultiByteLen = cbMultiByteLen; \
|
|
m_bUnicode = bUnicode; \
|
|
m_bInSync = bInSync; \
|
|
//
|
|
// Resets the internal string to be NULL string. Buffer remains cached.
|
|
//
|
|
VOID Reset( VOID)
|
|
{
|
|
DBG_ASSERT( m_bufAnsi.QueryPtr() != NULL);
|
|
DBG_ASSERT( m_bufUnicode.QueryPtr() != NULL);
|
|
*(LPSTR)(m_bufAnsi.QueryPtr()) = '\0';
|
|
*(LPWSTR)(m_bufUnicode.QueryPtr()) = (WCHAR)'\0';
|
|
m_bUnicode = STRAU_DEFAULT_UNICODE;
|
|
m_bInSync = TRUE;
|
|
m_cchUnicodeLen = 0;
|
|
m_cbMultiByteLen = 0;
|
|
}
|
|
|
|
|
|
BOOL SetLen( IN DWORD cchLen);
|
|
|
|
BOOL Copy( LPCSTR pchInit )
|
|
{
|
|
return Copy( pchInit, (DWORD)strlen(pchInit));
|
|
}
|
|
|
|
BOOL Copy( LPCWSTR pchInit ) {
|
|
return Copy( pchInit, (DWORD)wcslen(pchInit));
|
|
}
|
|
|
|
|
|
BOOL SafeCopy( LPCSTR pchInit );
|
|
BOOL SafeCopy( LPCWSTR pchInit );
|
|
|
|
BOOL Copy( LPCSTR pchInit, IN DWORD cbLen ) {
|
|
Reset();
|
|
return ( (pchInit != NULL) ?
|
|
AuxAppend( (LPSTR) pchInit, cbLen, FALSE ):
|
|
TRUE);
|
|
}
|
|
|
|
BOOL Copy( LPCWSTR pchInit, IN DWORD cchLen ) {
|
|
Reset();
|
|
return ( (pchInit != NULL) ?
|
|
AuxAppend( (LPWSTR) pchInit, cchLen, FALSE ):
|
|
TRUE);
|
|
}
|
|
|
|
BOOL Copy( STRAU & str )
|
|
{
|
|
BOOL bReturn;
|
|
if (str.IsCurrentUnicode()) {
|
|
bReturn = Copy((LPWSTR)str.QueryStr(TRUE), str.QueryCCH());
|
|
}
|
|
else {
|
|
bReturn = Copy((LPSTR)str.QueryStr(FALSE), str.QueryCB(FALSE));
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
//
|
|
// Returns the number of bytes in the string excluding the terminating
|
|
// NULL
|
|
//
|
|
|
|
#ifdef UNICODE
|
|
UINT QueryCB(BOOL bUnicode = TRUE)
|
|
#else
|
|
UINT QueryCB(BOOL bUnicode = FALSE)
|
|
#endif
|
|
{
|
|
if (bUnicode) {
|
|
return QueryCBW();
|
|
}
|
|
else {
|
|
return QueryCBA();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return # of bytes in the string excluding the teminating NULL
|
|
//
|
|
|
|
UINT QueryCBA()
|
|
{
|
|
if (m_bUnicode && !m_bInSync) {
|
|
|
|
//
|
|
// Force sync to set m_cbMultiByteLen
|
|
//
|
|
|
|
QueryStrA();
|
|
}
|
|
return (m_cbMultiByteLen * sizeof(CHAR));
|
|
}
|
|
|
|
//
|
|
// Return # of bytes in the string excluding the teminating NULL
|
|
//
|
|
|
|
UINT QueryCBW()
|
|
{
|
|
if (!m_bUnicode && !m_bInSync) {
|
|
|
|
//
|
|
// Force sync to set m_cchUnicodeLen
|
|
//
|
|
|
|
QueryStrW();
|
|
}
|
|
return (m_cchUnicodeLen * sizeof(WCHAR));
|
|
}
|
|
|
|
//
|
|
// Returns # of characters in the string excluding the terminating NULL
|
|
//
|
|
|
|
UINT QueryCCH( VOID )
|
|
{
|
|
|
|
//
|
|
// Unicode Len is same as # characters,
|
|
// but Multibyte Len is not, so use
|
|
// Unicode Len
|
|
//
|
|
|
|
if (!m_bUnicode && !m_bInSync) {
|
|
|
|
//
|
|
// Force sync to set m_cchUnicodeLen
|
|
//
|
|
|
|
QueryStrW();
|
|
}
|
|
return (m_cchUnicodeLen);
|
|
}
|
|
|
|
//
|
|
// Return the string buffer
|
|
//
|
|
|
|
#ifdef UNICODE
|
|
LPWSTR QueryStr(BOOL bUnicode = TRUE) { if (bUnicode) return QueryStrW(); else return (LPWSTR) QueryStrA(); }
|
|
#else
|
|
LPSTR QueryStr(BOOL bUnicode = FALSE) { if (bUnicode) return (LPSTR) QueryStrW(); else return QueryStrA(); }
|
|
#endif
|
|
|
|
LPSTR QueryStrA( VOID );
|
|
|
|
LPWSTR QueryStrW( VOID );
|
|
|
|
BOOL IsCurrentUnicode(void)
|
|
{
|
|
return m_bUnicode;
|
|
}
|
|
|
|
// resize just the unicode buffer
|
|
BOOL ResizeW(IN DWORD cbSize)
|
|
{
|
|
return (m_bufUnicode.Resize(cbSize));
|
|
}
|
|
|
|
private:
|
|
|
|
DWORD m_cchUnicodeLen;
|
|
DWORD m_cbMultiByteLen;
|
|
|
|
VOID AuxInit( LPCSTR pInit );
|
|
|
|
VOID AuxInit( LPCWSTR pInit );
|
|
|
|
BOOL AuxAppend( LPCSTR pInit,
|
|
UINT cchStr,
|
|
BOOL fAddSlop = TRUE );
|
|
|
|
BOOL AuxAppend( LPCWSTR pInit,
|
|
UINT cchStr,
|
|
BOOL fAddSlop = TRUE );
|
|
|
|
BUFFER m_bufAnsi;
|
|
BUFFER m_bufUnicode;
|
|
BOOL m_bInSync;
|
|
BOOL m_bUnicode;
|
|
BOOL m_bIsValid;
|
|
|
|
LPWSTR PrivateQueryStr(BOOL bUnicode);
|
|
|
|
};
|
|
|
|
|
|
/********************************************************************++
|
|
Declarations of functions and helper values for handling
|
|
ANSI/UNICODE conversions
|
|
--********************************************************************/
|
|
|
|
|
|
//
|
|
// When appending data, this is the extra amount we request to avoid
|
|
// reallocations
|
|
//
|
|
|
|
#define STR_SLOP 128
|
|
|
|
#define CODEPAGE_LATIN1 1252
|
|
|
|
#define STR_CONVERSION_SUCCEEDED(x) (((x) < 0) ? FALSE : TRUE)
|
|
|
|
int
|
|
ConvertMultiByteToUnicode(LPCSTR pszSrcAnsiString,
|
|
BUFFER *pbufDstUnicodeString,
|
|
DWORD dwStringLen);
|
|
|
|
int
|
|
ConvertUnicodeToMultiByte(LPCWSTR pszSrcUnicodeString,
|
|
BUFFER *pbufDstAnsiString,
|
|
DWORD dwStringLen);
|
|
|
|
int
|
|
ConvertUnicodeToUTF8(LPCWSTR pszSrcUnicodeString,
|
|
BUFFER * pbufDstAnsiString,
|
|
DWORD dwStringLen);
|
|
|
|
|
|
#endif // !_STRINGAU_HXX_
|