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.
368 lines
11 KiB
368 lines
11 KiB
/**********************************************************************/
|
|
/** 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_
|