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