// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. #ifndef _MULTISZA_H_ #define _MULTISZA_H_ #include #include "stringa.h" /*++ class MULTISZ: Intention: A light-weight multi-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 MULTISZ() init functions * NYI: I need to kill this someday * m_cchLen - string length cached when we update the string. m_cStrings - number of strings. 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 MULTISZA : public BUFFER { public: MULTISZA() : BUFFER (), m_cchLen ( 0), m_cStrings(0) { Reset(); } // creates a stack version of the MULTISZA object - uses passed in stack buffer // MULTISZA does not free this pbInit on its own. MULTISZA( __in_bcount(cbInit) CHAR * pbInit, DWORD cbInit) : BUFFER( (BYTE *) pbInit, cbInit), m_cchLen (0), m_cStrings(0) {} MULTISZA( const CHAR * pchInit ) : BUFFER (), m_cchLen ( 0), m_cStrings(0) { AuxInit(pchInit); } MULTISZA( const MULTISZA & str ) : BUFFER (), m_cchLen ( 0), m_cStrings(0) { AuxInit( str.QueryStr()); } // 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() == L'\0'); } BOOL Append( const CHAR * pchInit ) { return ((pchInit != NULL) ? (AuxAppend( pchInit, (DWORD) (::strlen(pchInit)) * sizeof(CHAR) )) : TRUE); } BOOL Append( const CHAR * pchInit, DWORD cchLen ) { return ((pchInit != NULL) ? (AuxAppend( pchInit, cchLen * sizeof(CHAR))) : TRUE); } BOOL Append( STRA & str ) { return AuxAppend( str.QueryStr(), (str.QueryCCH()) * sizeof(CHAR)); } // Resets the internal string to be NULL string. Buffer remains cached. VOID Reset( VOID) { DBG_ASSERT( QueryPtr() != NULL); QueryStr()[0] = L'\0'; QueryStr()[1] = L'\0'; m_cchLen = 2; m_cStrings = 0; } BOOL Copy( const CHAR * pchInit, IN DWORD cbLen ) { if ( QueryPtr() ) { Reset(); } return ( (pchInit != NULL) ? AuxAppend( pchInit, cbLen, FALSE ): TRUE); } BOOL Copy( const MULTISZA & str ) { return ( Copy(str.QueryStr(), str.QueryCB())); } // // Returns the number of bytes in the string including the terminating // NULLs // UINT QueryCB( VOID ) const { return ( m_cchLen * sizeof(CHAR)); } // // Returns # of characters in the string including the terminating NULLs // UINT QueryCCH( VOID ) const { return (m_cchLen); } // // Returns # of strings in the MULTISZA. // DWORD QueryStringCount( VOID ) const { return m_cStrings; } // // Makes a copy of the stored string in given buffer // BOOL CopyToBuffer( __out_ecount_opt(*lpcch) CHAR * lpszBuffer, LPDWORD lpcch) const; // // Return the string buffer // CHAR * QueryStrA( VOID ) const { return ( QueryStr()); } CHAR * QueryStr( VOID ) const { return ((CHAR *) QueryPtr()); } // // Makes a clone of the current string in the string pointer passed in. // BOOL Clone( OUT MULTISZA * pstrClone) const { return ((pstrClone == NULL) ? (SetLastError(ERROR_INVALID_PARAMETER), FALSE) : (pstrClone->Copy( *this)) ); } // MULTISZA::Clone() // // Recalculates the length of *this because we've modified the buffers // directly // VOID RecalcLen( VOID ) { m_cchLen = MULTISZA::CalcLength( QueryStr(), &m_cStrings ); } // // Calculate total character length of a MULTI_SZ, including the // terminating NULLs. // static DWORD CalcLength( const CHAR * str, LPDWORD pcStrings = NULL ); // // Determine if the MULTISZA contains a specific string. // BOOL FindString( const CHAR * str ); BOOL FindString( STRA & str ) { return FindString( str.QueryStr() ); } // // Determine if the MULTISZA contains a specific string - case-insensitive // BOOL FindStringNoCase( const CHAR * str ); BOOL FindStringNoCase( STRA & str ) { return FindStringNoCase( str.QueryStr() ); } // // Used for scanning a MULTISZA. // const CHAR * First( VOID ) const { return *QueryStr() == L'\0' ? NULL : QueryStr(); } const CHAR * Next( const CHAR * Current ) const { Current += ::strlen( Current ) + 1; return *Current == L'\0' ? NULL : Current; } BOOL Equals( MULTISZA* pmszRhs ); private: DWORD m_cchLen; DWORD m_cStrings; VOID AuxInit( const CHAR * pInit ); BOOL AuxAppend( const CHAR * pInit, UINT cbStr, BOOL fAddSlop = TRUE ); }; // // Quick macro for declaring a MULTISZA that will use stack memory of // bytes. If the buffer overflows then a heap buffer will be allocated // #define STACK_MULTISZA( name, size ) CHAR __ach##name[size]; \ MULTISZA name( __ach##name, sizeof( __ach##name )) HRESULT SplitCommaDelimitedString( PCSTR pszList, BOOL fTrimEntries, BOOL fRemoveEmptyEntries, MULTISZA * pmszList ); #endif // !_MULTISZA_HXX_