📄 stdstring.h
字号:
}
// -----------------------------------------------------------------------------
// sscmp: comparison (case sensitive, not affected by locale)
// -----------------------------------------------------------------------------
template<typename CT>
inline int sscmp(const CT* pA1, const CT* pA2)
{
CT f;
CT l;
do
{
f = *(pA1++);
l = *(pA2++);
} while ( (f) && (f == l) );
return (int)(f - l);
}
// -----------------------------------------------------------------------------
// ssicmp: comparison (case INsensitive, not affected by locale)
// -----------------------------------------------------------------------------
template<typename CT>
inline int ssicmp(const CT* pA1, const CT* pA2)
{
// Using the "C" locale = "not affected by locale"
std::locale loc = std::locale::classic();
const std::ctype<CT>& ct = SS_USE_FACET(loc, std::ctype<CT>);
CT f;
CT l;
do
{
f = ct.tolower(*(pA1++));
l = ct.tolower(*(pA2++));
} while ( (f) && (f == l) );
return (int)(f - l);
}
// -----------------------------------------------------------------------------
// ssupr/sslwr: Uppercase/Lowercase conversion functions
// -----------------------------------------------------------------------------
template<typename CT>
inline void sslwr(CT* pT, size_t nLen, const std::locale& loc=std::locale())
{
SS_USE_FACET(loc, std::ctype<CT>).tolower(pT, pT+nLen);
}
template<typename CT>
inline void ssupr(CT* pT, size_t nLen, const std::locale& loc=std::locale())
{
SS_USE_FACET(loc, std::ctype<CT>).toupper(pT, pT+nLen);
}
// -----------------------------------------------------------------------------
// vsprintf/vswprintf or _vsnprintf/_vsnwprintf equivalents. In standard
// builds we can't use _vsnprintf/_vsnwsprintf because they're MS extensions.
// -----------------------------------------------------------------------------
#if defined(SS_ANSI) || !defined(_MSC_VER)
// Borland's headers put some ANSI "C" functions in the 'std' namespace.
// Promote them to the global namespace so we can use them here.
#if defined(__BORLANDC__)
using std::vsprintf;
using std::vswprintf;
#endif
inline int ssvsprintf(PSTR pA, size_t /*nCount*/, PCSTR pFmtA, va_list vl)
{
return vsprintf(pA, pFmtA, vl);
}
inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
{
// JMO: Some distributions of the "C" have a version of vswprintf that
// takes 3 arguments (e.g. Microsoft, Borland, GNU). Others have a
// version which takes 4 arguments (an extra "count" argument in the
// second position. The best stab I can take at this so far is that if
// you are NOT running with MS, Borland, or GNU, then I'll assume you
// have the version that takes 4 arguments.
//
// I'm sure that these checks don't catch every platform correctly so if
// you get compiler errors on one of the lines immediately below, it's
// probably because your implemntation takes a different number of
// arguments. You can comment out the offending line (and use the
// alternate version) or you can figure out what compiler flag to check
// and add that preprocessor check in. Regardless, if you get an error
// on these lines, I'd sure like to hear from you about it.
//
// Thanks to Ronny Schulz for the SGI-specific checks here.
// #if !defined(__MWERKS__) && !defined(__SUNPRO_CC_COMPAT) && !defined(__SUNPRO_CC)
#if !defined(_MSC_VER) \
&& !defined (__BORLANDC__) \
&& !defined(__GNUC__) \
&& !defined(__sgi)
return vswprintf(pW, nCount, pFmtW, vl);
// suddenly with the current SGI 7.3 compiler there is no such function as
// vswprintf and the substitute needs explicit casts to compile
#elif defined(__sgi)
nCount;
return vsprintf( (char *)pW, (char *)pFmtW, vl);
#else
nCount;
return vswprintf(pW, pFmtW, vl);
#endif
}
#else
inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
{
return _vsnprintf(pA, nCount, pFmtA, vl);
}
inline int ssnprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
{
return _vsnwprintf(pW, nCount, pFmtW, vl);
}
#endif
// -----------------------------------------------------------------------------
// ssload: Type safe, overloaded ::LoadString wrappers
// There is no equivalent of these in non-Win32-specific builds. However, I'm
// thinking that with the message facet, there might eventually be one
// -----------------------------------------------------------------------------
#if defined (SS_WIN32) && !defined(SS_ANSI)
inline int ssload(HMODULE hInst, UINT uId, PSTR pBuf, int nMax)
{
return ::LoadStringA(hInst, uId, pBuf, nMax);
}
inline int ssload(HMODULE hInst, UINT uId, PWSTR pBuf, int nMax)
{
return ::LoadStringW(hInst, uId, pBuf, nMax);
}
#endif
// -----------------------------------------------------------------------------
// sscoll/ssicoll: Collation wrappers
// Note -- with MSVC I have reversed the arguments order here because the
// functions appear to return the opposite of what they should
// -----------------------------------------------------------------------------
template <typename CT>
inline int sscoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)
{
const std::collate<CT>& coll =
SS_USE_FACET(std::locale(), std::collate<CT>);
return coll.compare(sz2, sz2+nLen2, sz1, sz1+nLen1);
}
template <typename CT>
inline int ssicoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)
{
const std::locale loc;
const std::collate<CT>& coll = SS_USE_FACET(loc, std::collate<CT>);
// Some implementations seem to have trouble using the collate<>
// facet typedefs so we'll just default to basic_string and hope
// that's what the collate facet uses (which it generally should)
// std::collate<CT>::string_type s1(sz1);
// std::collate<CT>::string_type s2(sz2);
const std::basic_string<CT> sEmpty;
std::basic_string<CT> s1(sz1 ? sz1 : sEmpty.c_str());
std::basic_string<CT> s2(sz2 ? sz2 : sEmpty.c_str());
sslwr(const_cast<CT*>(s1.c_str()), nLen1, loc);
sslwr(const_cast<CT*>(s2.c_str()), nLen2, loc);
return coll.compare(s2.c_str(), s2.c_str()+nLen2,
s1.c_str(), s1.c_str()+nLen1);
}
// -----------------------------------------------------------------------------
// ssfmtmsg: FormatMessage equivalents. Needed because I added a CString facade
// Again -- no equivalent of these on non-Win32 builds but their might one day
// be one if the message facet gets implemented
// -----------------------------------------------------------------------------
#if defined (SS_WIN32) && !defined(SS_ANSI)
inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,
DWORD dwLangId, PSTR pBuf, DWORD nSize,
va_list* vlArgs)
{
return FormatMessageA(dwFlags, pSrc, dwMsgId, dwLangId,
pBuf, nSize,vlArgs);
}
inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,
DWORD dwLangId, PWSTR pBuf, DWORD nSize,
va_list* vlArgs)
{
return FormatMessageW(dwFlags, pSrc, dwMsgId, dwLangId,
pBuf, nSize,vlArgs);
}
#else
#endif
// FUNCTION: sscpy. Copies up to 'nMax' characters from pSrc to pDst.
// -----------------------------------------------------------------------------
// FUNCTION: sscpy
// inline int sscpy(PSTR pDst, PCSTR pSrc, int nMax=-1);
// inline int sscpy(PUSTR pDst, PCSTR pSrc, int nMax=-1)
// inline int sscpy(PSTR pDst, PCWSTR pSrc, int nMax=-1);
// inline int sscpy(PWSTR pDst, PCWSTR pSrc, int nMax=-1);
// inline int sscpy(PWSTR pDst, PCSTR pSrc, int nMax=-1);
//
// DESCRIPTION:
// This function is very much (but not exactly) like strcpy. These
// overloads simplify copying one C-style string into another by allowing
// the caller to specify two different types of strings if necessary.
//
// The strings must NOT overlap
//
// "Character" is expressed in terms of the destination string, not
// the source. If no 'nMax' argument is supplied, then the number of
// characters copied will be sslen(pSrc). A NULL terminator will
// also be added so pDst must actually be big enough to hold nMax+1
// characters. The return value is the number of characters copied,
// not including the NULL terminator.
//
// PARAMETERS:
// pSrc - the string to be copied FROM. May be a char based string, an
// MBCS string (in Win32 builds) or a wide string (wchar_t).
// pSrc - the string to be copied TO. Also may be either MBCS or wide
// nMax - the maximum number of characters to be copied into szDest. Note
// that this is expressed in whatever a "character" means to pDst.
// If pDst is a wchar_t type string than this will be the maximum
// number of wchar_ts that my be copied. The pDst string must be
// large enough to hold least nMaxChars+1 characters.
// If the caller supplies no argument for nMax this is a signal to
// the routine to copy all the characters in pSrc, regardless of
// how long it is.
//
// RETURN VALUE: none
// -----------------------------------------------------------------------------
template<typename CT1, typename CT2>
inline int sscpycvt(CT1* pDst, const CT2* pSrc, int nMax)
{
// Note -- we assume pDst is big enough to hold pSrc. If not, we're in
// big trouble. No bounds checking. Caveat emptor.
int nSrc = sslen(pSrc);
const CT1* szCvt = StdCodeCvt(pDst, nMax, pSrc, nSrc);
// If we're copying the same size characters, then all the "code convert"
// just did was basically memcpy so the #of characters copied is the same
// as the number requested. I should probably specialize this function
// template to achieve this purpose as it is silly to do a runtime check
// of a fact known at compile time. I'll get around to it.
return sslen(szCvt);
}
inline int sscpycvt(PSTR pDst, PCSTR pSrc, int nMax)
{
int nCount = nMax;
for (; nCount > 0 && *pSrc; ++pSrc, ++pDst, --nCount)
std::basic_string<char>::traits_type::assign(*pDst, *pSrc);
*pDst = '\0';
return nMax - nCount;
}
inline int sscpycvt(PWSTR pDst, PCWSTR pSrc, int nMax)
{
int nCount = nMax;
for (; nCount > 0 && *pSrc; ++pSrc, ++pDst, --nCount)
std::basic_string<wchar_t>::traits_type::assign(*pDst, *pSrc);
*pDst = L'\0';
return nMax - nCount;
}
inline int sscpycvt(PWSTR pDst, PCSTR pSrc, int nMax)
{
// Note -- we assume pDst is big enough to hold pSrc. If not, we're in
// big trouble. No bounds checking. Caveat emptor.
const PWSTR szCvt = StdCodeCvt(pDst, nMax, pSrc, nMax);
return sslen(szCvt);
}
template<typename CT1, typename CT2>
inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax, int nLen)
{
return sscpycvt(pDst, pSrc, SSMIN(nMax, nLen));
}
template<typename CT1, typename CT2>
inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax)
{
return sscpycvt(pDst, pSrc, SSMIN(nMax, sslen(pSrc)));
}
template<typename CT1, typename CT2>
inline int sscpy(CT1* pDst, const CT2* pSrc)
{
return sscpycvt(pDst, pSrc, sslen(pSrc));
}
template<typename CT1, typename CT2>
inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc, int nMax)
{
return sscpycvt(pDst, sSrc.c_str(), SSMIN(nMax, (int)sSrc.length()));
}
template<typename CT1, typename CT2>
inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc)
{
return sscpycvt(pDst, sSrc.c_str(), (int)sSrc.length());
}
#ifdef SS_INC_COMDEF
template<typename CT1>
inline int sscpy(CT1* pDst, const _bstr_t& bs, int nMax)
{
return sscpycvt(pDst, static_cast<PCOLESTR>(bs),
SSMIN(nMax, static_cast<int>(bs.length())));
}
template<typename CT1>
inline int sscpy(CT1* pDst, const _bstr_t& bs)
{
return sscpy(pDst, bs, static_cast<int>(bs.length()));
}
#endif
// -----------------------------------------------------------------------------
// Functional objects for changing case. They also let you pass locales
// -----------------------------------------------------------------------------
template<typename CT>
struct SSToUpper : public std::binary_function<CT, std::locale, CT>
{
inline CT operator()(const CT& t, const std::locale& loc) const
{
return sstoupper<CT>(t, loc);
}
};
template<typename CT>
struct SSToLower : public std::binary_function<CT, std::locale, CT>
{
inline CT operator()(const CT& t, const std::locale& loc) const
{
return sstolower<CT>(t, loc);
}
};
// This struct is used for TrimRight() and TrimLeft() function implementations.
//template<typename CT>
//struct NotSpace : public std::unary_function<CT, bool>
//{
// const std::locale& loc;
// inline NotSpace(const std::locale& locArg) : loc(locArg) {}
// inline bool operator() (CT t) { return !std::isspace(t, loc); }
//};
template<typename CT>
struct NotSpace : public std::unary_function<CT, bool>
{
// DINKUMWARE BUG:
// Note -- using std::isspace in a COM DLL gives us access violations
// because it causes the dynamic addition of a function to be called
// when the library shuts down. Unfortunately the list is maintained
// in DLL memory but the function is in static memory. So the COM DLL
// goes away along with the function that was supposed to be called,
// and then later when the DLL CRT shuts down it unloads the list and
// tries to call the long-gone function.
// This is DinkumWare's implementation problem.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -