📄 stdstring.h
字号:
//
// CString sName("Joe");
// CString sTmp;
// sTmp.Format("My name is %s", sName); // WORKS!
//
// However if you were to try this with CStdString, your program would
// crash.
//
// CStdString sName("Joe");
// CStdString sTmp;
// sTmp.Format("My name is %s", sName); // CRASHES!
//
// You must explicitly call c_str() or cast the object to the proper type
//
// sTmp.Format("My name is %s", sName.c_str()); // WORKS!
// sTmp.Format("My name is %s", static_cast<PCSTR>(sName));// WORKS!
// sTmp.Format("My name is %s", (PCSTR)sName);// WORKS!
//
// This is because it is illegal to pass anything but a POD type as a
// variadic argument to a variadic function (i.e. as one of the "..."
// arguments). The type const char* is a POD type. The type CStdString
// is not. Of course, neither is the type CString, but CString lets you do
// it anyway due to the way they laid out the class in binary. I have no
// control over this in CStdString since I derive from whatever
// implementation of basic_string is available.
//
// However if you have legacy code (which does this) that you want to take
// out of the MFC world and you don't want to rewrite all your calls to
// Format(), then you can define this flag and it will no longer crash.
//
// Note however that this ONLY works for Format(), not sprintf, fprintf,
// etc. If you pass a CStdString object to one of those functions, your
// program will crash. Not much I can do to get around this, short of
// writing substitutes for those functions as well.
#define SS_SAFE_FORMAT // use new template style Format() function
// MACRO: SS_NO_IMPLICIT_CAST
// --------------------------
// Some people don't like the implicit cast to const char* (or rather to
// const CT*) that CStdString (and MFC's CString) provide. That was the
// whole reason I created this class in the first place, but hey, whatever
// bakes your cake. Just #define this macro to get rid of the the implicit
// cast.
//#define SS_NO_IMPLICIT_CAST // gets rid of operator const CT*()
// MACRO: SS_NO_REFCOUNT
// ---------------------
// turns off reference counting at the assignment level. Only needed
// for the version of basic_string<> that comes with Visual C++ versions
// 6.0 or earlier, and only then in some heavily multithreaded scenarios.
// Uncomment it if you feel you need it.
//#define SS_NO_REFCOUNT
// MACRO: SS_WIN32
// ---------------
// When this flag is set, we are building code for the Win32 platform and
// may use Win32 specific functions (such as LoadString). This gives us
// a couple of nice extras for the code.
//
// Obviously, Microsoft's is not the only compiler available for Win32 out
// there. So I can't just check to see if _MSC_VER is defined to detect
// if I'm building on Win32. So for now, if you use MS Visual C++ or
// Borland's compiler, I turn this on. Otherwise you may turn it on
// yourself, if you prefer
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WIN32)
#define SS_WIN32
#endif
// MACRO: SS_ANSI
// --------------
// When this macro is defined, the code attempts only to use ANSI/ISO
// standard library functions to do it's work. It will NOT attempt to use
// any Win32 of Visual C++ specific functions -- even if they are
// available. You may define this flag yourself to prevent any Win32
// of VC++ specific functions from being called.
// If we're not on Win32, we MUST use an ANSI build
#ifndef SS_WIN32
#if !defined(SS_NO_ANSI)
#define SS_ANSI
#endif
#endif
// MACRO: SS_ALLOCA
// ----------------
// Some implementations of the Standard C Library have a non-standard
// function known as alloca(). This functions allows one to allocate a
// variable amount of memory on the stack. It is needed to implement
// the ASCII/MBCS conversion macros.
//
// I wanted to find some way to determine automatically if alloca() is
// available on this platform via compiler flags but that is asking for
// trouble. The crude test presented here will likely need fixing on
// other platforms. Therefore I'll leave it up to you to fiddle with
// this test to determine if it exists. Just make sure SS_ALLOCA is or
// is not defined as appropriate and you control this feature.
#if defined(_MSC_VER) && !defined(SS_ANSI)
#define SS_ALLOCA
#endif
// MACRO: SS_MBCS
// --------------
// Setting this macro means you are using MBCS characters. In MSVC
// builds, this macro gets set automatically by detection of the
// preprocessor flag _MBCS. For other platforms you may set it manually
// if you wish. The only effect it currently has is to cause the
// allocation of more space for wchar_t --> char conversions.
// Note that MBCS does not mean UNICODE.
//
// #define SS_MBCS
//
#ifdef _MBCS
#define SS_MBCS
#endif
// Compiler Error regarding _UNICODE and UNICODE
// -----------------------------------------------
// Microsoft header files are screwy. Sometimes they depend on a preprocessor
// flag named "_UNICODE". Other times they check "UNICODE" (note the lack of
// leading underscore in the second version". In several places, they silently
// "synchronize" these two flags this by defining one of the other was defined.
// In older version of this header , I used to try to do the same thing.
//
// However experience has taught me that this is a bad idea. You get weird
// compiler errors that seem to indicate things like LPWSTR and LPTSTR not being
// equivalent in UNICODE builds, stuff like that (when they MUST be in a proper
// UNICODE build). You end up scratching your head and saying, "But that HAS
// to compile!".
//
// So what should you do if you get this error?
//
// Make sure that both macros (_UNICODE and UNICODE) are defined before this
// file is included. You can do that by either
//
// a) defining both yourself before any files get included
// b) including the proper MS headers in the proper order
// c) including this file before any other file, uncommenting
// the #defines below, and commenting out the #errors
//
// Personally I recommend solution a) but it's your call.
#ifdef _MSC_VER
#if defined (_UNICODE) && !defined (UNICODE)
#error UNICODE defined but not UNICODE
// #define UNICODE // no longer silently fix this
#endif
#if defined (UNICODE) && !defined (_UNICODE)
#error Warning, UNICODE defined but not _UNICODE
// #define _UNICODE // no longer silently fix this
#endif
#endif
// -----------------------------------------------------------------------------
// MIN and MAX. The Standard C++ template versions go by so many names (at
// at least in the MS implementation) that you never know what's available
// -----------------------------------------------------------------------------
template<class Type>
inline const Type& SSMIN(const Type& arg1, const Type& arg2)
{
return arg2 < arg1 ? arg2 : arg1;
}
template<class Type>
inline const Type& SSMAX(const Type& arg1, const Type& arg2)
{
return arg2 > arg1 ? arg2 : arg1;
}
// If they have not #included W32Base.h (part of my W32 utility library) then
// we need to define some stuff. Otherwise, this is all defined there.
#if !defined(W32BASE_H)
// If they want us to use only standard C++ stuff (no Win32 stuff)
#ifdef SS_ANSI
// On Win32 we have TCHAR.H so just include it. This is NOT violating
// the spirit of SS_ANSI as we are not calling any Win32 functions here.
#ifdef SS_WIN32
#include <TCHAR.H>
#include <WTYPES.H>
#ifndef STRICT
#define STRICT
#endif
// ... but on non-Win32 platforms, we must #define the types we need.
#else
typedef const char* PCSTR;
typedef char* PSTR;
typedef const wchar_t* PCWSTR;
typedef wchar_t* PWSTR;
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif
typedef wchar_t OLECHAR;
#endif // #ifndef _WIN32
// Make sure ASSERT and verify are defined using only ANSI stuff
#ifndef ASSERT
#include <assert.h>
#define ASSERT(f) assert((f))
#endif
#ifndef VERIFY
#ifdef _DEBUG
#define VERIFY(x) ASSERT((x))
#else
#define VERIFY(x) x
#endif
#endif
#else // ...else SS_ANSI is NOT defined
#include <TCHAR.H>
#include <WTYPES.H>
#ifndef STRICT
#define STRICT
#endif
// Make sure ASSERT and verify are defined
#ifndef ASSERT
#include <crtdbg.h>
#define ASSERT(f) _ASSERTE((f))
#endif
#ifndef VERIFY
#ifdef _DEBUG
#define VERIFY(x) ASSERT((x))
#else
#define VERIFY(x) x
#endif
#endif
#endif // #ifdef SS_ANSI
#ifndef UNUSED
#define UNUSED(x) x
#endif
#endif // #ifndef W32BASE_H
// Standard headers needed
#include <string> // basic_string
#include <algorithm> // for_each, etc.
#include <functional> // for StdStringLessNoCase, et al
#include <locale> // for various facets
// If this is a recent enough version of VC include comdef.h, so we can write
// member functions to deal with COM types & compiler support classes e.g.
// _bstr_t
#if defined (_MSC_VER) && (_MSC_VER >= 1100)
#include <comdef.h>
#define SS_INC_COMDEF // signal that we #included MS comdef.h file
#define STDSTRING_INC_COMDEF
#define SS_NOTHROW __declspec(nothrow)
#else
#define SS_NOTHROW
#endif
#ifndef TRACE
#define TRACE_DEFINED_HERE
#define TRACE
#endif
// Microsoft defines PCSTR, PCWSTR, etc, but no PCTSTR. I hate to use the
// versions with the "L" in front of them because that's a leftover from Win 16
// days, even though it evaluates to the same thing. Therefore, Define a PCSTR
// as an LPCTSTR.
#if !defined(PCTSTR) && !defined(PCTSTR_DEFINED)
typedef const TCHAR* PCTSTR;
#define PCTSTR_DEFINED
#endif
#if !defined(PCOLESTR) && !defined(PCOLESTR_DEFINED)
typedef const OLECHAR* PCOLESTR;
#define PCOLESTR_DEFINED
#endif
#if !defined(POLESTR) && !defined(POLESTR_DEFINED)
typedef OLECHAR* POLESTR;
#define POLESTR_DEFINED
#endif
#if !defined(PCUSTR) && !defined(PCUSTR_DEFINED)
typedef const unsigned char* PCUSTR;
typedef unsigned char* PUSTR;
#define PCUSTR_DEFINED
#endif
// SGI compiler 7.3 doesnt know these types - oh and btw, remember to use
// -LANG:std in the CXX Flags
#if defined(__sgi)
typedef unsigned long DWORD;
typedef void * LPCVOID;
#endif
// SS_USE_FACET macro and why we need it:
//
// Since I'm a good little Standard C++ programmer, I use locales. Thus, I
// need to make use of the use_facet<> template function here. Unfortunately,
// this need is complicated by the fact the MS' implementation of the Standard
// C++ Library has a non-standard version of use_facet that takes more
// arguments than the standard dictates. Since I'm trying to write CStdString
// to work with any version of the Standard library, this presents a problem.
//
// The upshot of this is that I can't do 'use_facet' directly. The MS' docs
// tell me that I have to use a macro, _USE() instead. Since _USE obviously
// won't be available in other implementations, this means that I have to write
// my OWN macro -- SS_USE_FACET -- that evaluates either to _USE or to the
// standard, use_facet.
//
// If you are having trouble with the SS_USE_FACET macro, in your implementation
// of the Standard C++ Library, you can define your own version of SS_USE_FACET.
#ifndef schMSG
#define schSTR(x) #x
#define schSTR2(x) schSTR(x)
#define schMSG(desc) message(__FILE__ "(" schSTR2(__LINE__) "):" #desc)
#endif
#ifndef SS_USE_FACET
// STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for
// all MSVC builds, erroneously in my opinion. It causes problems for
// my SS_ANSI builds. In my code, I always comment out that line. You'll
// find it in \stlport\config\stl_msvc.h
#if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 )
#if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) && defined(_MSC_VER)
#ifdef SS_ANSI
#pragma schMSG(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS defined!!)
#endif
#endif
#define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)
#elif defined(_MSC_VER )
#define SS_USE_FACET(loc, fac) std::_USE(loc, fac)
// ...and
#elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)
#define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0)
#else
#define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)
#endif
#endif
// =============================================================================
// UNICODE/MBCS conversion macros. Made to work just like the MFC/ATL ones.
// =============================================================================
#include <wchar.h> // Added to Std Library with Amendment #1.
// First define the conversion helper functions. We define these regardless of
// any preprocessor macro settings since their names won't collide.
// Not sure if we need all these headers. I believe ANSI says we do.
#include <stdio.h>
#include <stdarg.h>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -