Windows2003-3790/inetsrv/iis/inc/string.hxx
2020-09-30 16:53:55 +02:00

369 lines
11 KiB
C++

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1994 **/
/**********************************************************************/
/*
string.hxx
This module contains a light weight string class
FILE HISTORY:
Johnl 15-Aug-1994 Created
MuraliK 09-July-1996 Rewrote for efficiency with no unicode support
*/
#ifndef _STRING_HXX_
#define _STRING_HXX_
# include <buffer.hxx>
//
// Maximum number of characters a loadable string resource can be
//
# define STR_MAX_RES_SIZE ( 320)
class IRTL_DLLEXP STR;
//
// If an application defines STR_MODULE_NAME, it will be used
// as the default module name on string loads
//
#ifndef STR_MODULE_NAME
#define STR_MODULE_NAME NULL
#endif
//
// These are the characters that are considered to be white space
//
#define ISWHITE( ch ) ((ch) == L'\t' || (ch) == L' ' || (ch) == L'\r')
#define ISWHITEA( ch ) ((ch) == '\t' || (ch) == ' ' || (ch) == '\r')
//
// Removes useless segments from the URL and makes sure it doesn't go
// past the root of the tree (i.e., "/foo/../..")
//
INT CanonURL( CHAR * pszPath, BOOL fIsDBCS = FALSE );
//
// Map these string functions to appropriate RT call depending on the code
// page of the system. Thus we only use DBCS operations when necessary.
//
DWORD InitializeStringFunctions( VOID );
UCHAR * IISstrupr( UCHAR * pszString );
UCHAR * IISstrlwr( UCHAR * pszString );
INT IISstrnicmp( UCHAR * pszString1, UCHAR * pszString2, size_t iSize );
size_t IISstrlen( UCHAR * pszString1 );
char * IISstrncpy (char * dest, const char * source, size_t count);
INT IISstricmp( UCHAR * pszString1, UCHAR * pszString2);
UCHAR *IISstrrchr(const UCHAR * pszString, UINT c);
/*++
class STR:
Intention:
A light-weight string class supporting encapsulated string class.
This object is derived from BUFFER class.
It maintains following state:
m_fValid - whether this object is valid -
used only by STR() init functions
* NYI: I need to kill this someday *
m_cchLen - string length cached when we update the string.
m_fNoRealloc - does not allow resize of the buffer. if overflow - return error / truncate
Member Functions:
There are two categories of functions:
1) Safe Functions - which do integrity checking of state
2) UnSafe Functions - which do not do integrity checking, but
enable writing to the data stream freely.
(someday this will be enabled as Safe versions without
problem for users)
--*/
class IRTL_DLLEXP STR : public BUFFER
{
public:
STR()
: BUFFER (),
m_cchLen ( 0),
m_fNoRealloc (FALSE)
{}
// creates a stack version of the STR object - uses passed in stack buffer
// STR does not free this pbInit on its own.
STR( CHAR * pbInit, DWORD cbInit, BOOL fNoRealloc = FALSE)
: BUFFER( (BYTE *) pbInit, cbInit),
m_cchLen (0),
m_fNoRealloc (fNoRealloc)
{}
STR( DWORD cbInit)
: BUFFER( cbInit),
m_cchLen (0),
m_fNoRealloc (FALSE)
{}
STR( const CHAR * pchInit )
: BUFFER (),
m_cchLen ( 0),
m_fNoRealloc (FALSE)
{ AuxInit( (const BYTE * ) pchInit); }
STR( const STR & str )
: BUFFER (),
m_cchLen ( 0),
m_fNoRealloc (FALSE)
{ AuxInit( (const BYTE * ) str.QueryStr()); }
BOOL SetLen( IN DWORD cchLen)
{
return ( ( cchLen >= QuerySize())? FALSE :
( *((CHAR *) QueryPtr() + cchLen) = '\0', // null terminate
m_cchLen = cchLen, // set the length
TRUE
)
);
}
BOOL IsValid(VOID) const { return ( BUFFER::IsValid()) ; }
//
// Checks and returns TRUE if this string has no valid data else FALSE
//
BOOL IsEmpty( VOID) const { return ( *QueryStr() == '\0'); }
BOOL Append( const CHAR * pchInit ) {
return ((pchInit != NULL) ? (AuxAppend( (const BYTE * ) pchInit,
(UINT) ::strlen(pchInit))) :
TRUE);
}
BOOL Append( const CHAR * pchInit, DWORD cchLen ) {
return ((pchInit != NULL) ? (AuxAppend( (const BYTE * ) pchInit,
cchLen)) :
TRUE);
}
BOOL Append( const STR & str )
{ return AuxAppend( (const BYTE * ) str.QueryStr(), str.QueryCCH()); }
// Resets the internal string to be NULL string. Buffer remains cached.
VOID Reset( VOID)
{ DBG_ASSERT( QueryPtr() != NULL);
*(QueryStr()) = '\0'; m_cchLen = 0;
}
// erase the internal string. Buffer remains cached.
VOID Clear( VOID)
{ DBG_ASSERT( QueryPtr() != NULL);
ZeroMemory( QueryPtr(), QueryCB());
Reset();
}
BOOL Copy( const CHAR * pchInit ) {
if ( QueryPtr() ) { *(QueryStr()) = '\0'; m_cchLen = 0; }
return ( (pchInit != NULL) ?
AuxAppend( (const BYTE *) pchInit, (UINT) ::strlen( pchInit ), FALSE ):
TRUE);
}
BOOL SafeCopy( const CHAR * pchInit );
BOOL Copy( const CHAR * pchInit, IN DWORD cchLen ) {
if ( QueryPtr() ) { *(QueryStr()) = '\0'; m_cchLen = 0; }
return ( (pchInit != NULL) ?
AuxAppend( (const BYTE *) pchInit, cchLen, FALSE ):
TRUE);
}
BOOL Copy( const STR & str )
{ return ( Copy(str.QueryStr(), str.QueryCCH())); }
//
// Loads a string from this module's string resource table
//
BOOL LoadString( IN DWORD dwResID,
IN LPCTSTR lpszModuleName = STR_MODULE_NAME,
IN DWORD dwLangID = 0);
BOOL LoadString( IN DWORD dwResID,
IN HMODULE hModule);
//
// Loads a string with insert params from this module's .mc resource
// table. Pass zero for the resource ID to use *this.
//
BOOL
FormatString( IN DWORD dwResID,
IN LPCTSTR apszInsertParams[],
IN LPCTSTR lpszModuleName = STR_MODULE_NAME OPTIONAL,
IN DWORD cbMaxMsg = 1024 OPTIONAL );
//
// Inserts and removes any odd ranged Latin-1 characters with the
// escaped hexadecimal equivalent (%xx)
//
BOOL Escape();
BOOL EscapeSpaces();
BOOL Unescape();
//
// support for hashing the string for privacy purposes
//
VOID Hash();
VOID Unhash();
//
// Returns the number of bytes in the string excluding the terminating
// NULL
//
UINT QueryCB( VOID ) const
{ return ( m_cchLen * sizeof(CHAR)); }
//
// Returns # of characters in the string excluding the terminating NULL
//
UINT QueryCCH( VOID ) const { return (m_cchLen); }
//
// Makes a copy of the stored string in given buffer
//
BOOL CopyToBuffer( WCHAR * lpszBuffer, LPDWORD lpcch) const;
BOOL CopyToBuffer( CHAR * lpszBuffer, LPDWORD lpcch) const;
//
// Return the string buffer
//
CHAR * QueryStrA( VOID ) const { return ( QueryStr()); }
CHAR * QueryStr( VOID ) const { return ((CHAR *) QueryPtr()); }
CHAR QueryFirstChar( VOID ) const
{ return (m_cchLen > 0) ? *QueryStr() : '\0'; }
CHAR QueryLastChar( VOID ) const
{ return (m_cchLen > 0) ? *(QueryStr() + m_cchLen - 1) : '\0'; }
//
// Makes a clone of the current string in the string pointer passed in.
//
BOOL Clone( OUT STR * pstrClone) const
{
return ((pstrClone == NULL) ?
(SetLastError(ERROR_INVALID_PARAMETER), FALSE) :
(pstrClone->Copy( *this))
);
} // STR::Clone()
BOOL Equ( const STR & strA) const {
return (QueryCB() != strA.QueryCB()) ? FALSE :
( QueryCB() ? !IISstricmp((UCHAR *)QueryStr(), (UCHAR *)strA.QueryStr()) : TRUE );
}
BOOL Equ( CHAR *pszA) const {
return QueryCB() ? !IISstricmp((UCHAR *)QueryStr(), (UCHAR *)pszA) : *pszA == '\0';
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// UNSAFE FUNCTIONS - make sure you have enough space here
// Use these only if you have been dumping bytes to string
// object by considering it as a buffer object
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Append a single character
VOID Append( CHAR ch)
{
register CHAR * pch = ((CHAR *) QueryPtr()) + (m_cchLen++);
*pch = ch; *(pch+1) = '\0';
}
// Append two characters
VOID Append( CHAR ch1, CHAR ch2)
{
register CHAR * pch = ((CHAR *) QueryPtr()) + (m_cchLen += 2);
*(pch-2) = ch1; *(pch-1) = ch2; *pch = '\0';
}
// Append CRLF pattern \r\n --> use two character append function
VOID AppendCRLF(VOID) { Append( '\r', '\n'); }
private:
DWORD m_cchLen;
BOOL m_fNoRealloc;
VOID AuxInit( const BYTE * pInit );
BOOL AuxAppend( const BYTE * pInit,
UINT cbStr, BOOL fAddSlop = TRUE );
};
//
// Quick macro for declaring a STR that will use stack memory of <size>
// bytes. If the buffer overflows then a heap buffer will be allocated
//
#define STACK_STR( name, size ) \
CHAR __ach##name[size]; \
STR name( __ach##name, sizeof( __ach##name ))
//
// Similar to STACK_STR, but suing the static buffer constructor, so no
// realloc can occur
//
#define STACK_STATSTR( name, size ) \
CHAR __ach##name[size]; \
STR name( __ach##name, sizeof( __ach##name ), TRUE)
//
// Unlike the STACK_STR macro, this template can be used for member
// variables in classes.
//
template <size_t N>
class IRTL_DLLEXP Str : public STR
{
private:
CHAR m_achData[N]; // Actual data
public:
Str()
: STR(m_achData, N)
{}
}; // class Str<N>
//
// this template is similar to Str, but initializes STR to static buffer usage (no realloc)
//
template <size_t N>
class StatStr : public STR
{
private:
CHAR m_achData[N]; // Actual data
public:
StatStr()
: STR(m_achData, N, TRUE)
{}
}; // class Str<N>
#endif // !_STRING_HXX_