|
|
/**********************************************************************/ /** 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_
|