windows-nt/Source/XPSP1/NT/base/win32/fusion/inc/fusionstring.h
2020-09-26 16:20:57 +08:00

428 lines
10 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
FusionString.h
Abstract:
Stuff to futz with everybody's favorite type, generally templatized
to work on char, wchar_t, or anything else; occasionally
templatized to work on arbitrary STL style [begin, end)
sequences.
Also stuff particularly for NT's UNICODE_STRING.
To be merged with CFusionBuffer.h.
Author:
Jay M. Krell (a-JayK) May 2000
Revision History:
--*/
#pragma once
#include <stdio.h>
#include "fusionntdll.h"
//#include "fusionalgorithm.h"
class CUnicodeCharTraits;
template <typename T> class CGenericBaseStringBuffer;
int
FusionpCompareStrings(
PCWSTR sz1,
SIZE_T cch1,
PCWSTR sz2,
SIZE_T cch2,
bool fCaseInsensitive
);
inline bool
FusionpEqualStrings(
PCWSTR sz1,
SIZE_T cch1,
PCWSTR sz2,
SIZE_T cch2,
bool fCaseInsensitive
)
{
return ((cch1 == cch2) && (FusionpCompareStrings(sz1, cch1, sz2, cch2, fCaseInsensitive) == 0));
}
int
FusionpCompareStrings(
const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
PCWSTR psz2,
SIZE_T cch2,
bool fCaseInsensitive
);
int
FusionpCompareStrings(
PCWSTR psz1,
SIZE_T cch1,
const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2,
bool fCaseInsensitive
);
int
FusionpCompareStrings(
const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff1,
const CGenericBaseStringBuffer<CUnicodeCharTraits> &rbuff2,
bool fCaseInsensitive
);
int
FusionpCompareStrings(
PCSTR sz1,
SIZE_T cch1,
PCSTR sz2,
SIZE_T cch2,
bool fCaseInsensitive
);
#if !defined(FUSION_CANONICAL_CASE_IS_UPPER)
#define FUSION_CANONICAL_CASE_IS_UPPER 1
#endif // !defined(FUSION_CANONICAL_CASE_IS_UPPER)
#if FUSION_CANONICAL_CASE_IS_UPPER
inline WCHAR FusionpCanonicalizeUnicodeChar(WCHAR wch) { return ::FusionpRtlUpcaseUnicodeChar(wch); }
#else
inline WCHAR FusionpCanonicalizeUnicodeChar(WCHAR wch) { return ::FusionpRtlDowncaseUnicodeChar(wch); }
#endif
inline int
FusionpStrCmpI(
PCWSTR psz1,
PCWSTR psz2
)
{
return ::FusionpCompareStrings(
psz1,
(psz1 != NULL) ? ::wcslen(psz1) : 0,
psz2,
(psz2 != NULL) ? ::wcslen(psz2) : 0,
true);
}
/*-----------------------------------------------------------------------------
StringLength is a generic name for getting the length, in count of
characters, of various kinds of strings
-----------------------------------------------------------------------------*/
inline SIZE_T StringLength(LPCSTR psz)
{
return ::strlen(psz);
}
inline SIZE_T StringLength(LPCWSTR psz)
{
return ::wcslen(psz);
}
#if defined(NT_INCLUDED) // { {
inline SIZE_T StringLength(const UNICODE_STRING* s)
{
return s->Length / sizeof(*s->Buffer);
}
inline SIZE_T StringLength(const ANSI_STRING* s)
{
return s->Length / sizeof(*s->Buffer);
}
/*
perhaps half backed, like UNICODE_STRING itself, should probably call
these CContantUnicodeString or CUnicodeStringNoFree, to indicate
they do no allocation or deallocation
..
..
darn, really just need to merge this with existing FusionBuffer...
*/
#define CONSTANT_UNICODE_STRING(x) \
{ \
/* the subtraction is to not count the terminal nul */ \
static_cast<unsigned short>(sizeof(x) - sizeof((x)[0])), \
static_cast<unsigned short>(sizeof(x) - sizeof((x)[0])), \
const_cast<PWSTR>(x) \
}
extern const UNICODE_STRING g_strEmptyUnicodeString;
class CUnicodeString : public UNICODE_STRING
{
public:
~CUnicodeString() { }
CUnicodeString(PCWSTR buffer, SIZE_T length)
{
this->Buffer = const_cast<PWSTR>(buffer); // Careful!
this->Length = static_cast<USHORT>(length * sizeof(*Buffer));
this->MaximumLength = this->Length;
}
CUnicodeString(PCWSTR buffer)
{
this->Buffer = const_cast<PWSTR>(buffer);
this->Length = static_cast<USHORT>(::wcslen(buffer) * sizeof(*Buffer));
this->MaximumLength = this->Length;
}
operator const UNICODE_STRING *() const { return this; }
void operator=(PCWSTR buffer)
{
this->Buffer = const_cast<PWSTR>(buffer); // Careful!
this->Length = static_cast<USHORT>(::wcslen(buffer) * sizeof(*Buffer));
this->MaximumLength = this->Length;
}
void Sync()
{
this->Length = static_cast<USHORT>(::wcslen(Buffer) * sizeof(*Buffer));
}
int FormatV(PCWSTR pszFormat, va_list args)
{
// note that vsnprintf doesn't nul terminate if there isn't room,
// it squeezes the nul out in favor of an additional character,
// we work around this by telling it one char less, and by always
// putting a nul at the end
int cchMaximumLength = this->MaximumLength / sizeof(*Buffer);
this->Buffer[cchMaximumLength - 1] = 0;
int i = _vsnwprintf(this->Buffer, cchMaximumLength - 1, pszFormat, args);
if (i >= 0)
{
this->Buffer[i] = 0;
this->Length = static_cast<USHORT>(i * sizeof(*Buffer));
}
return i;
}
int Format(PCWSTR pszFormat, ...)
{
va_list args;
va_start(args, pszFormat);
int i = FormatV(pszFormat, args);
va_end(args);
return i;
}
//protected:
CUnicodeString()
{
this->Buffer = L"";
this->Length = sizeof(*Buffer);
this->MaximumLength = this->Length;
}
private: // deliberately not implemented
CUnicodeString(const CUnicodeString&);
void operator=(const CUnicodeString&);
};
template <int N>
class CUnicodeStringN : public CUnicodeString
{
public:
~CUnicodeStringN() { }
CUnicodeStringN()
{
this->Buffer = m_rgchBuffer;
this->Length = 0;
this->MaximumLength = sizeof(m_rgchBuffer);
m_rgchBuffer[0] = 0;
m_rgchBuffer[N-1] = 0;
}
WCHAR m_rgchBuffer[N];
private: // deliberately not implemented
CUnicodeStringN(const CUnicodeStringN&);
void operator=(const CUnicodeStringN&);
};
#endif // } }
/*-----------------------------------------------------------------------------
genericized name for strchr and wcschr
-----------------------------------------------------------------------------*/
//template <typename Char> const Char* StringFindChar(const Char* s, Char ch)
// Automatically provide non const, but looser type binding between s
// and ch. Still requires nul termination, so doesn't really support more than
// char*, const char*, wchar_t*, and const wchar_t*.
//
// StdFind is the obvious generalization that doesn't require a particular
// terminal value, but the ability to pass a terminal pointer or iterator.
template <typename String, typename Char>
inline String
StringFindChar(String s, Char ch)
{
String end = s + StringLength(s);
String found = StdFind(s, end, ch);
if (found == end)
{
found = NULL;
}
return found;
}
/*-----------------------------------------------------------------------------
specialize StringFindChar for char to use strchr provided
in msvcrt.dll or ntdll.dll.
-----------------------------------------------------------------------------*/
// strchr is getting defined to be StrChrW, which does not work.
#if !defined(strchr) // { {
template <>
inline const char* StringFindChar<const char*>(const char* s, char ch)
{
s = strchr(s, ch);
return s;
}
template <>
inline char* StringFindChar<char*>(char* s, char ch)
{
s = strchr(s, ch);
return s;
}
#endif // } }
/*-----------------------------------------------------------------------------
specialize StringFindChar for wchar_t to use wcschr provided
in msvcrt.dll or ntdll.dll.
-----------------------------------------------------------------------------*/
template <>
inline const wchar_t* StringFindChar<const wchar_t*>(const wchar_t* s, wchar_t ch)
{
s = wcschr(s, ch);
return s;
}
template <>
inline wchar_t* StringFindChar<wchar_t*>(wchar_t* s, wchar_t ch)
{
s = wcschr(s, ch);
return s;
}
/*-----------------------------------------------------------------------------
common code for StringReverseSpan and StringReverseComplementSpan
-----------------------------------------------------------------------------*/
template <typename Char>
INT
PrivateStringReverseSpanCommon(
const Char* begin,
const Char* end,
const Char* set, // nul terminated
bool breakVal
)
{
const Char* t = end;
while (t != begin)
{
if (breakVal == !!StringFindChar(set, *--t))
{
++t; // don't count the last checked one
break;
}
}
return static_cast<INT>(end - t);
}
/*-----------------------------------------------------------------------------
Find the length of the run of characters in set from the end of [begin, end).
"wcsrspn"
variants of this can be seen at
\vsee\lib\xfcstr\strexw.cpp
and \\jayk1\g\temp\rspn.cpp
-----------------------------------------------------------------------------*/
template <typename Char>
inline INT
StringReverseSpan(
const Char* begin,
const Char* end,
const Char* set
)
{
// break when not found
return ::PrivateStringReverseSpanCommon(begin, end, set, false);
}
/*-----------------------------------------------------------------------------
Find the length of the run of characters not in set from the end of [begin, end).
"wcsrcspn"
variants of this can be seen at
\vsee\lib\xfcstr\strexw.cpp
and \\jayk1\g\temp\rspn.cpp
-----------------------------------------------------------------------------*/
template <typename Char>
inline INT
StringReverseComplementSpan(
const Char* begin,
const Char* end,
const Char* set
)
{
// break when found
return ::PrivateStringReverseSpanCommon(begin, end, set, true);
}
template <typename Char>
inline INT
PrivateStringSpanCommon(
const Char* begin,
const Char* end,
const Char* set,
bool breakVal
)
{
const Char* t = begin;
while ( t != end )
{
if (breakVal == !!StringFindChar(set, *t++))
{
--t;
break;
}
}
return static_cast<INT>(t - begin);
}
template <typename Char>
inline INT
StringSpan(
const Char* begin,
const Char* end,
const Char* set
)
{
return ::PrivateStringSpanCommon( begin, end, set, false );
}
template <typename Char>
inline INT
StringComplimentSpan(
const Char* begin,
const Char* end,
const Char* set
)
{
return ::PrivateStringSpanCommon( begin, end, set, true );
}