|
|
/**********************************************************************/ /** Microsoft Windows NT **/ /** Copyright(c) Microsoft Corp., 1999 **/ /**********************************************************************/
/*
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 MCourage 12-Feb-1999 Another rewrite. All unicode of course. */
#ifndef _STRING_HXX_
#define _STRING_HXX_
# include <irtlmisc.h>
# include <buffer.hxx>
LONG CompareStringNoCase( IN const WCHAR * String1, IN const WCHAR * String2, IN DWORD cchString1 = 0, IN DWORD cchString2 = 0 );
class IRTL_DLLEXP STRU;
/*++
class STRU:
Intention: A light-weight string class supporting encapsulated string class.
This object is derived from BUFFER class. It maintains following state:
m_cchLen - string length cached when we update the string.
--*/ class STRU { public:
STRU() : m_Buff(), m_cchLen( 0) { *QueryStr() = L'\0'; }
//
// creates a stack version of the STR object - uses passed in stack buffer
// STR does not free this pbInit on its own.
//
STRU( WCHAR * pbInit, DWORD cbInit ) : m_Buff( (BYTE *) pbInit, cbInit), m_cchLen(0) { DBG_ASSERT(cbInit > 0);
*pbInit = L'\0'; }
//
// Checks and returns TRUE if this string has no valid data else FALSE
//
BOOL IsEmpty( VOID ) const { return ( m_cchLen == 0 ); }
//
// Returns TRUE if str has the same value as this string.
//
BOOL Equals( const STRU & str ) const { return (str.QueryCCH() == QueryCCH()) && (wcscmp(str.QueryStr(), QueryStr()) == 0); }
//
// Returns TRUE if str has the same value as this string.
//
BOOL Equals( const WCHAR * pchInit ) const { if (pchInit == NULL || pchInit[0] == '\0') { return (IsEmpty()); } return (wcscmp(pchInit, QueryStr()) == 0); }
//
// Returns TRUE if str has the same value as this string.
//
BOOL EqualsNoCase( const STRU & str ) const { return (str.QueryCCH() == QueryCCH()) && ( CompareStringNoCase(str.QueryStr(), QueryStr(), str.QueryCCH(), QueryCCH()) == 0 ); }
//
// Returns TRUE if str has the same value as this string.
//
BOOL EqualsNoCase( const WCHAR * pchInit ) const { if (pchInit == NULL || pchInit[0] == '\0') { return (IsEmpty()); } return ( CompareStringNoCase( pchInit, QueryStr(), 0, // the function will calculate the length
QueryCCH()) == 0 ); }
//
// Returns the number of bytes in the string excluding the terminating
// NUL
//
UINT QueryCB( VOID ) const { return ( m_cchLen * sizeof(WCHAR)); }
//
// Returns # of characters in the string excluding the terminating NUL
//
UINT QueryCCH( VOID ) const { return (m_cchLen); }
//
// Return the string buffer
//
WCHAR * QueryStr( VOID ) { return ((WCHAR *) m_Buff.QueryPtr()); }
const WCHAR * QueryStr( VOID ) const { return ((const WCHAR *) m_Buff.QueryPtr()); }
//
// Resets the internal string to be NULL string. Buffer remains cached.
//
VOID Reset( VOID ) { DBG_ASSERT( QueryStr() ); *(QueryStr()) = L'\0'; m_cchLen = 0; }
//
// Resize the internal buffer
//
HRESULT Resize( DWORD cbSize ) { if (!m_Buff.Resize( cbSize ) ) { return HRESULT_FROM_WIN32( GetLastError() ); }
return S_OK; }
//
// Append something to the end of the string
//
HRESULT Append( const WCHAR * pchInit ) { if (pchInit) { return AuxAppend( (const BYTE *) pchInit, (ULONG) ::wcslen(pchInit) * sizeof(WCHAR), QueryCB() ); } else { return S_OK; } }
HRESULT Append( const WCHAR * pchInit, DWORD cchLen ) { if (pchInit && cchLen) { return AuxAppend( (const BYTE *) pchInit, cchLen * sizeof(WCHAR), QueryCB() ); } else { return S_OK; } }
HRESULT Append( const STRU & str ) { if (str.QueryCCH()) { return AuxAppend( (const BYTE *) str.QueryStr(), str.QueryCCH() * sizeof(WCHAR), QueryCB() ); } else { return S_OK; } } HRESULT AppendA( const CHAR * pchInit ) { return AuxAppendA( (const BYTE*) pchInit, (ULONG) strlen( pchInit ), QueryCB() ); }
//
// Copy the contents of another string to this one
//
HRESULT Copy( const WCHAR * pchInit ) { if (pchInit) { return AuxAppend( (const BYTE *) pchInit, (ULONG) ::wcslen(pchInit) * sizeof(WCHAR), 0 ); } else { return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); } }
HRESULT Copy( const WCHAR * pchInit, DWORD cchLen ) { if (pchInit) { return AuxAppend( (const BYTE *) pchInit, cchLen * sizeof(WCHAR), 0 ); } else { return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); } }
HRESULT Copy( const STRU & str ) { return AuxAppend( (const BYTE *) str.QueryStr(), str.QueryCCH() * sizeof(WCHAR), 0 ); } HRESULT CopyA( const CHAR * pchInit ) { return AuxAppendA( (const BYTE*) pchInit, (ULONG) strlen( pchInit ), 0 ); } HRESULT CopyA( const CHAR * pchInit, DWORD cchLen ) { return AuxAppendA( (const BYTE*) pchInit, cchLen, 0 ); }
//
// Allow access to the internal buffer, for direct manipulation.
//
BUFFER * QueryBuffer( VOID ) { return &m_Buff; }
//
// Recalculate the length of the string, etc. because we've modified
// the buffer directly.
//
VOID SyncWithBuffer( VOID ) { m_cchLen = (LONG) wcslen( QueryStr() ); }
//
// Makes a copy of the stored string into the given buffer
// NYI
//
HRESULT CopyToBuffer( WCHAR * lpszBuffer, LPDWORD lpcb ) const;
//
//
BOOL 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. NOTE: The actual wcslen may be less than cchLen if you are expanding the string. If this is the case SyncWithBuffer should be called to ensure consistency. The real use of this method is to truncate.
Arguments:
cchLen - The number of characters in the new string. Return Value:
TRUE - if the buffer size is sufficient to hold the string. FALSE - insufficient buffer.
--*/ { if( cchLen >= m_Buff.QuerySize() / sizeof(WCHAR) ) { return FALSE; }
*((WCHAR *) m_Buff.QueryPtr() + cchLen) = L'\0'; m_cchLen = cchLen; return TRUE; }
//
// Useful for unescaping URL, QueryString etc
//
HRESULT Unescape(); HRESULT Escape();
private:
//
// Avoid C++ errors. This object should never go through a copy
// constructor, unintended cast or assignment.
//
STRU( const STRU & ) {} STRU( const WCHAR * ) {} STRU( WCHAR * ) {} STRU & operator = ( const STRU & ) { return *this; }
HRESULT STRU::AuxAppend( const BYTE * pStr, ULONG cbStr, ULONG cbOffset, BOOL fAddSlop = TRUE );
HRESULT STRU::AuxAppendA( const BYTE * pStr, ULONG cbStr, ULONG cbOffset, BOOL fAddSlop = TRUE );
BUFFER m_Buff; LONG m_cchLen; };
//
// 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_STRU( name, size ) WCHAR __ach##name[size]; \
STRU name( __ach##name, sizeof( __ach##name ))
//
// Macros for declaring and initializing a STRU that will use inline memory
// of <size> bytes as a member of an object.
//
#define INLINE_STRU(name, size) WCHAR __ach##name[size]; \
STRU name;
#define INLINE_STRU_INIT(name) name( __ach##name, sizeof( __ach##name ) )
//
// General string utilities
//
#define ISWHITEW( wch ) ((wch) == L' ' || (wch) == L'\t' || (wch) == L'\r')
WCHAR * SkipWhite( WCHAR * pwch );
WCHAR * SkipTo( WCHAR * pwch, WCHAR wch );
WCHAR * FlipSlashes( WCHAR * pszPath );
HRESULT MakePathCanonicalizationProof( IN LPWSTR pszName, OUT STRU * pstrPath );
#endif // !_STRING_HXX_
|