📄 stdstring.h
字号:
// 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 nChars)
{
StdCodeCvt(pDst, pSrc, nChars);
pDst[SSMAX(nChars, 0)] = '\0';
return nChars;
}
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
// -----------------------------------------------------------------------------
#ifdef SS_ANSI
#ifdef SS_NO_LOCALE
template<typename CT>
struct SSToUpper : public std::unary_function<CT, CT>
{
inline CT operator()(const CT& t) const
{
return sstoupper(t);
}
};
template<typename CT>
struct SSToLower : public std::unary_function<CT, CT>
{
inline CT operator()(const CT& t) const
{
return sstolower(t);
}
};
#else
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);
}
};
#endif
#endif
// 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. Until then, we will
// use good old isspace and iswspace from the CRT unless they
// specify SS_ANSI
#if defined(SS_ANSI) && !defined(SS_NO_LOCALE)
const std::locale loc;
NotSpace(const std::locale& locArg=std::locale()) : loc(locArg) {}
bool operator() (CT t) const { return !std::isspace(t, loc); }
#else
bool ssisp(char c) const { return FALSE != ::isspace((int) c); }
bool ssisp(wchar_t c) const { return FALSE != ::iswspace((wint_t) c); }
bool operator()(CT t) const { return !ssisp(t); }
#endif
};
// Now we can define the template (finally!)
// =============================================================================
// TEMPLATE: CStdStr
// template<typename CT> class CStdStr : public std::basic_string<CT>
//
// REMARKS:
// This template derives from basic_string<CT> and adds some MFC CString-
// like functionality
//
// Basically, this is my attempt to make Standard C++ library strings as
// easy to use as the MFC CString class.
//
// Note that although this is a template, it makes the assumption that the
// template argument (CT, the character type) is either char or wchar_t.
// =============================================================================
//#define CStdStr _SS // avoid compiler warning 4786
// template<typename ARG> ARG& FmtArg(ARG& arg) { return arg; }
// PCSTR FmtArg(const std::string& arg) { return arg.c_str(); }
// PCWSTR FmtArg(const std::wstring& arg) { return arg.c_str(); }
template<typename ARG>
struct FmtArg
{
explicit FmtArg(const ARG& arg) : a_(arg) {}
const ARG& Val() const { return a_; }
const ARG& a_;
private:
FmtArg& operator=(const FmtArg&) { return *this; }
};
template<typename CT>
class CStdStr : public std::basic_string<CT>
{
// Typedefs for shorter names. Using these names also appears to help
// us avoid some ambiguities that otherwise arise on some platforms
typedef typename std::basic_string<CT> MYBASE; // my base class
typedef CStdStr<CT> MYTYPE; // myself
typedef typename MYBASE::const_pointer PCMYSTR; // PCSTR or PCWSTR
typedef typename MYBASE::pointer PMYSTR; // PSTR or PWSTR
typedef typename MYBASE::iterator MYITER; // my iterator type
typedef typename MYBASE::const_iterator MYCITER; // you get the idea...
typedef typename MYBASE::reverse_iterator MYRITER;
typedef typename MYBASE::size_type MYSIZE;
typedef typename MYBASE::value_type MYVAL;
typedef typename MYBASE::allocator_type MYALLOC;
public:
// shorthand conversion from PCTSTR to string resource ID
#define _TRES(pctstr) (LOWORD((DWORD)(pctstr)))
// CStdStr inline constructors
CStdStr()
{
}
CStdStr(const MYTYPE& str) : MYBASE(SSREF(str))
{
}
CStdStr(const std::string& str)
{
ssasn(*this, SSREF(str));
}
CStdStr(const std::wstring& str)
{
ssasn(*this, SSREF(str));
}
CStdStr(PCMYSTR pT, MYSIZE n) : MYBASE(pT, n)
{
}
#ifdef SS_ALLOW_UNSIGNED_CHARS
CStdStr(PCUSTR pU)
{
*this = reinterpret_cast<PCSTR>(pU);
}
#endif
CStdStr(PCSTR pA)
{
#ifdef SS_ANSI
*this = pA;
#else
if ( 0 != HIWORD(pA) )
*this = pA;
else if ( 0 != pA && !Load(_TRES(pA)) )
TRACE(_T("Can't load string %u\n"), _TRES(pA));
#endif
}
CStdStr(PCWSTR pW)
{
#ifdef SS_ANSI
*this = pW;
#else
if ( 0 != HIWORD(pW) )
*this = pW;
else if ( 0 != pW && !Load(_TRES(pW)) )
TRACE(_T("Can't load string %u\n"), _TRES(pW));
#endif
}
CStdStr(MYCITER first, MYCITER last)
: MYBASE(first, last)
{
}
CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC& al=MYALLOC())
: MYBASE(nSize, ch, al)
{
}
#ifdef SS_INC_COMDEF
CStdStr(const _bstr_t& bstr)
{
if ( bstr.length() > 0 )
this->append(static_cast<PCMYSTR>(bstr), bstr.length());
}
#endif
// CStdStr inline assignment operators -- the ssasn function now takes care
// of fixing the MSVC assignment bug (see knowledge base article Q172398).
MYTYPE& operator=(const MYTYPE& str)
{
ssasn(*this, str);
return *this;
}
MYTYPE& operator=(const std::string& str)
{
ssasn(*this, str);
return *this;
}
MYTYPE& operator=(const std::wstring& str)
{
ssasn(*this, str);
return *this;
}
MYTYPE& operator=(PCSTR pA)
{
ssasn(*this, pA);
return *this;
}
MYTYPE& operator=(PCWSTR pW)
{
ssasn(*this, pW);
return *this;
}
#ifdef SS_ALLOW_UNSIGNED_CHARS
MYTYPE& operator=(PCUSTR pU)
{
ssasn(*this, reinterpret_cast<PCSTR>(pU)):
return *this;
}
#endif
MYTYPE& operator=(CT t)
{
Q172398(*this);
this->assign(1, t);
return *this;
}
#ifdef SS_INC_COMDEF
MYTYPE& operator=(const _bstr_t& bstr)
{
if ( bstr.length() > 0 )
{
this->assign(static_cast<PCMYSTR>(bstr), bstr.length());
return *this;
}
else
{
this->erase();
return *this;
}
}
#endif
// Overloads also needed to fix the MSVC assignment bug (KB: Q172398)
// *** Thanks to Pete The Plumber for catching this one ***
// They also are compiled if you have explicitly turned off refcounting
#if ( defined(_MSC_VER) && ( _MSC_VER < 1200 ) ) || defined(SS_NO_REFCOUNT)
MYTYPE& assign(const MYTYPE& str)
{
ssasn(*this, str);
return *this;
}
MYTYPE& assign(const MYTYPE& str, MYSIZE nStart, MYSIZE nChars)
{
// This overload of basic_string::assign is supposed to assign up to
// <nChars> or the NULL terminator, whichever comes first. Since we
// are about to call a less forgiving overload (in which <nChars>
// must be a valid length), we must adjust the length here to a safe
// value. Thanks to Ullrich Poll鋒ne for catching this bug
nChars = SSMIN(nChars, str.length() - nStart);
// Watch out for assignment to self
if ( this == &str )
{
MYTYPE strTemp(str.c_str()+nStart, nChars);
MYBASE::assign(strTemp);
}
else
{
Q172398(*this);
MYBASE::assign(str.c_str()+nStart, nChars);
}
return *this;
}
MYTYPE& assign(const MYBASE& str)
{
ssasn(*this, str);
return *this;
}
MYTYPE& assign(const MYBASE& str, MYSIZE nStart, MYSIZE n
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -