在实际工作中,std的string功能相对于MFC的CString来说,实在是相形见绌。
CStdString类实现了CString的功能,支持跨平台。
1 // ============================================================================= 2 // FILE: StdString.h 3 // AUTHOR: Joe O'Leary (with outside help noted in comments) 4 // 5 // If you find any bugs in this code, please let me know: 6 // 7 // jmoleary@earthlink.net 8 // http://www.joeo.net/stdstring.htm (a bit outdated) 9 // 10 // The latest version of this code should always be available at the 11 // following link: 12 // 13 // http://www.joeo.net/code/StdString.zip (Dec 6, 2003) 14 // 15 // 16 // REMARKS: 17 // This header file declares the CStdStr template. This template derives 18 // the Standard C++ Library basic_string<> template and add to it the 19 // the following conveniences: 20 // - The full MFC CString set of functions (including implicit cast) 21 // - writing to/reading from COM IStream interfaces 22 // - Functional objects for use in STL algorithms 23 // 24 // From this template, we intstantiate two classes: CStdStringA and 25 // CStdStringW. The name "CStdString" is just a #define of one of these, 26 // based upone the UNICODE macro setting 27 // 28 // This header also declares our own version of the MFC/ATL UNICODE-MBCS 29 // conversion macros. Our version looks exactly like the Microsoft's to 30 // facilitate portability. 31 // 32 // NOTE: 33 // If you you use this in an MFC or ATL build, you should include either 34 // afx.h or atlbase.h first, as appropriate. 35 // 36 // PEOPLE WHO HAVE CONTRIBUTED TO THIS CLASS: 37 // 38 // Several people have helped me iron out problems and othewise improve 39 // this class. OK, this is a long list but in my own defense, this code 40 // has undergone two major rewrites. Many of the improvements became 41 // necessary after I rewrote the code as a template. Others helped me 42 // improve the CString facade. 43 // 44 // Anyway, these people are (in chronological order): 45 // 46 // - Pete the Plumber (???) 47 // - Julian Selman 48 // - Chris (of Melbsys) 49 // - Dave Plummer 50 // - John C Sipos 51 // - Chris Sells 52 // - Nigel Nunn 53 // - Fan Xia 54 // - Matthew Williams 55 // - Carl Engman 56 // - Mark Zeren 57 // - Craig Watson 58 // - Rich Zuris 59 // - Karim Ratib 60 // - Chris Conti 61 // - Baptiste Lepilleur 62 // - Greg Pickles 63 // - Jim Cline 64 // - Jeff Kohn 65 // - Todd Heckel 66 // - Ullrich Poll鋒ne 67 // - Joe Vitaterna 68 // - Joe Woodbury 69 // - Aaron (no last name) 70 // - Joldakowski (???) 71 // - Scott Hathaway 72 // - Eric Nitzche 73 // - Pablo Presedo 74 // - Farrokh Nejadlotfi 75 // - Jason Mills 76 // - Igor Kholodov 77 // - Mike Crusader 78 // - John James 79 // - Wang Haifeng 80 // - Tim Dowty 81 // - Arnt Witteveen 82 // - Glen Maynard 83 // - Paul DeMarco 84 // - Bagira (full name?) 85 // - Ronny Schulz 86 // - Jakko Van Hunen 87 // - Charles Godwin 88 // - Henk Demper 89 // - Greg Marr 90 // - Bill Carducci 91 // - Brian Groose 92 // - MKingman 93 // - Don Beusee 94 // 95 // REVISION HISTORY 96 // 97 // 2005-JAN-10 - Thanks to Don Beusee for pointing out the danger in mapping 98 // length-checked formatting functions to non-length-checked 99 // CRT equivalents. Also thanks to him for motivating me to 100 // optimize my implementation of Replace() 101 // 102 // 2004-APR-22 - A big, big thank you to "MKingman" (whoever you are) for 103 // finally spotting a silly little error in StdCodeCvt that 104 // has been causing me (and users of CStdString) problems for 105 // years in some relatively rare conversions. I had reversed 106 // two length arguments. 107 // 108 // 2003-NOV-24 - Thanks to a bunch of people for helping me clean up many 109 // compiler warnings (and yes, even a couple of actual compiler 110 // errors). These include Henk Demper for figuring out how 111 // to make the Intellisense work on with CStdString on VC6, 112 // something I was never able to do. Greg Marr pointed out 113 // a compiler warning about an unreferenced symbol and a 114 // problem with my version of Load in MFC builds. Bill 115 // Carducci took a lot of time with me to help me figure out 116 // why some implementations of the Standard C++ Library were 117 // returning error codes for apparently successful conversions 118 // between ASCII and UNICODE. Finally thanks to Brian Groose 119 // for helping me fix compiler signed unsigned warnings in 120 // several functions. 121 // 122 // 2003-JUL-10 - Thanks to Charles Godwin for making me realize my 'FmtArg' 123 // fixes had inadvertently broken the DLL-export code (which is 124 // normally commented out. I had to move it up higher. Also 125 // this helped me catch a bug in ssicoll that would prevent 126 // compilation, otherwise. 127 // 128 // 2003-MAR-14 - Thanks to Jakko Van Hunen for pointing out a copy-and-paste 129 // bug in one of the overloads of FmtArg. 130 // 131 // 2003-MAR-10 - Thanks to Ronny Schulz for (twice!) sending me some changes 132 // to help CStdString build on SGI and for pointing out an 133 // error in placement of my preprocessor macros for ssfmtmsg. 134 // 135 // 2002-NOV-26 - Thanks to Bagira for pointing out that my implementation of 136 // SpanExcluding was not properly handling the case in which 137 // the string did NOT contain any of the given characters 138 // 139 // 2002-OCT-21 - Many thanks to Paul DeMarco who was invaluable in helping me 140 // get this code working with Borland's free compiler as well 141 // as the Dev-C++ compiler (available free at SourceForge). 142 // 143 // 2002-SEP-13 - Thanks to Glen Maynard who helped me get rid of some loud 144 // but harmless warnings that were showing up on g++. Glen 145 // also pointed out that some pre-declarations of FmtArg<> 146 // specializations were unnecessary (and no good on G++) 147 // 148 // 2002-JUN-26 - Thanks to Arnt Witteveen for pointing out that I was using 149 // static_cast<> in a place in which I should have been using 150 // reinterpret_cast<> (the ctor for unsigned char strings). 151 // That's what happens when I don't unit-test properly! 152 // Arnt also noticed that CString was silently correcting the 153 // 'nCount' argument to Left() and Right() where CStdString was 154 // not (and crashing if it was bad). That is also now fixed! 155 // 156 // 2002-FEB-25 - Thanks to Tim Dowty for pointing out (and giving me the fix 157 // for) a conversion problem with non-ASCII MBCS characters. 158 // CStdString is now used in my favorite commercial MP3 player! 159 // 160 // 2001-DEC-06 - Thanks to Wang Haifeng for spotting a problem in one of the 161 // assignment operators (for _bstr_t) that would cause compiler 162 // errors when refcounting protection was turned off. 163 // 164 // 2001-NOV-27 - Remove calls to operator!= which involve reverse_iterators 165 // due to a conflict with the rel_ops operator!=. Thanks to 166 // John James for pointing this out. 167 // 168 // 2001-OCT-29 - Added a minor range checking fix for the Mid function to 169 // make it as forgiving as CString's version is. Thanks to 170 // Igor Kholodov for noticing this. 171 // - Added a specialization of std::swap for CStdString. Thanks 172 // to Mike Crusader for suggesting this! It's commented out 173 // because you're not supposed to inject your own code into the 174 // 'std' namespace. But if you don't care about that, it's 175 // there if you want it 176 // - Thanks to Jason Mills for catching a case where CString was 177 // more forgiving in the Delete() function than I was. 178 // 179 // 2001-JUN-06 - I was violating the Standard name lookup rules stated 180 // in [14.6.2(3)]. None of the compilers I've tried so 181 // far apparently caught this but HP-UX aCC 3.30 did. The 182 // fix was to add 'this->' prefixes in many places. 183 // Thanks to Farrokh Nejadlotfi for this! 184 // 185 // 2001-APR-27 - StreamLoad was calculating the number of BYTES in one 186 // case, not characters. Thanks to Pablo Presedo for this. 187 // 188 // 2001-FEB-23 - Replace() had a bug which caused infinite loops if the 189 // source string was empty. Fixed thanks to Eric Nitzsche. 190 // 191 // 2001-FEB-23 - Scott Hathaway was a huge help in providing me with the 192 // ability to build CStdString on Sun Unix systems. He 193 // sent me detailed build reports about what works and what 194 // does not. If CStdString compiles on your Unix box, you 195 // can thank Scott for it. 196 // 197 // 2000-DEC-29 - Joldakowski noticed one overload of Insert failed to do a 198 // range check as CString's does. Now fixed -- thanks! 199 // 200 // 2000-NOV-07 - Aaron pointed out that I was calling static member 201 // functions of char_traits via a temporary. This was not 202 // technically wrong, but it was unnecessary and caused 203 // problems for poor old buggy VC5. Thanks Aaron! 204 // 205 // 2000-JUL-11 - Joe Woodbury noted that the CString::Find docs don't match 206 // what the CString::Find code really ends up doing. I was 207 // trying to match the docs. Now I match the CString code 208 // - Joe also caught me truncating strings for GetBuffer() calls 209 // when the supplied length was less than the current length. 210 // 211 // 2000-MAY-25 - Better support for STLPORT's Standard library distribution 212 // - Got rid of the NSP macro - it interfered with Koenig lookup 213 // - Thanks to Joe Woodbury for catching a TrimLeft() bug that 214 // I introduced in January. Empty strings were not getting 215 // trimmed 216 // 217 // 2000-APR-17 - Thanks to Joe Vitaterna for pointing out that ReverseFind 218 // is supposed to be a const function. 219 // 220 // 2000-MAR-07 - Thanks to Ullrich Poll鋒ne for catching a range bug in one 221 // of the overloads of assign. 222 // 223 // 2000-FEB-01 - You can now use CStdString on the Mac with CodeWarrior! 224 // Thanks to Todd Heckel for helping out with this. 225 // 226 // 2000-JAN-23 - Thanks to Jim Cline for pointing out how I could make the 227 // Trim() function more efficient. 228 // - Thanks to Jeff Kohn for prompting me to find and fix a typo 229 // in one of the addition operators that takes _bstr_t. 230 // - Got rid of the .CPP file - you only need StdString.h now! 231 // 232 // 1999-DEC-22 - Thanks to Greg Pickles for helping me identify a problem 233 // with my implementation of CStdString::FormatV in which 234 // resulting string might not be properly NULL terminated. 235 // 236 // 1999-DEC-06 - Chris Conti pointed yet another basic_string<> assignment 237 // bug that MS has not fixed. CStdString did nothing to fix 238 // it either but it does now! The bug was: create a string 239 // longer than 31 characters, get a pointer to it (via c_str()) 240 // and then assign that pointer to the original string object. 241 // The resulting string would be empty. Not with CStdString! 242 // 243 // 1999-OCT-06 - BufferSet was erasing the string even when it was merely 244 // supposed to shrink it. Fixed. Thanks to Chris Conti. 245 // - Some of the Q172398 fixes were not checking for assignment- 246 // to-self. Fixed. Thanks to Baptiste Lepilleur. 247 // 248 // 1999-AUG-20 - Improved Load() function to be more efficient by using 249 // SizeOfResource(). Thanks to Rich Zuris for this. 250 // - Corrected resource ID constructor, again thanks to Rich. 251 // - Fixed a bug that occurred with UNICODE characters above 252 // the first 255 ANSI ones. Thanks to Craig Watson. 253 // - Added missing overloads of TrimLeft() and TrimRight(). 254 // Thanks to Karim Ratib for pointing them out 255 // 256 // 1999-JUL-21 - Made all calls to GetBuf() with no args check length first. 257 // 258 // 1999-JUL-10 - Improved MFC/ATL independence of conversion macros 259 // - Added SS_NO_REFCOUNT macro to allow you to disable any 260 // reference-counting your basic_string<> impl. may do. 261 // - Improved ReleaseBuffer() to be as forgiving as CString. 262 // Thanks for Fan Xia for helping me find this and to 263 // Matthew Williams for pointing it out directly. 264 // 265 // 1999-JUL-06 - Thanks to Nigel Nunn for catching a very sneaky bug in 266 // ToLower/ToUpper. They should call GetBuf() instead of 267 // data() in order to ensure the changed string buffer is not 268 // reference-counted (in those implementations that refcount). 269 // 270 // 1999-JUL-01 - Added a true CString facade. Now you can use CStdString as 271 // a drop-in replacement for CString. If you find this useful, 272 // you can thank Chris Sells for finally convincing me to give 273 // in and implement it. 274 // - Changed operators << and >> (for MFC CArchive) to serialize 275 // EXACTLY as CString's do. So now you can send a CString out 276 // to a CArchive and later read it in as a CStdString. I have 277 // no idea why you would want to do this but you can. 278 // 279 // 1999-JUN-21 - Changed the CStdString class into the CStdStr template. 280 // - Fixed FormatV() to correctly decrement the loop counter. 281 // This was harmless bug but a bug nevertheless. Thanks to 282 // Chris (of Melbsys) for pointing it out 283 // - Changed Format() to try a normal stack-based array before 284 // using to _alloca(). 285 // - Updated the text conversion macros to properly use code 286 // pages and to fit in better in MFC/ATL builds. In other 287 // words, I copied Microsoft's conversion stuff again. 288 // - Added equivalents of CString::GetBuffer, GetBufferSetLength 289 // - new sscpy() replacement of CStdString::CopyString() 290 // - a Trim() function that combines TrimRight() and TrimLeft(). 291 // 292 // 1999-MAR-13 - Corrected the "NotSpace" functional object to use _istpace() 293 // instead of _isspace() Thanks to Dave Plummer for this. 294 // 295 // 1999-FEB-26 - Removed errant line (left over from testing) that #defined 296 // _MFC_VER. Thanks to John C Sipos for noticing this. 297 // 298 // 1999-FEB-03 - Fixed a bug in a rarely-used overload of operator+() that 299 // caused infinite recursion and stack overflow 300 // - Added member functions to simplify the process of 301 // persisting CStdStrings to/from DCOM IStream interfaces 302 // - Added functional objects (e.g. StdStringLessNoCase) that 303 // allow CStdStrings to be used as keys STL map objects with 304 // case-insensitive comparison 305 // - Added array indexing operators (i.e. operator[]). I 306 // originally assumed that these were unnecessary and would be 307 // inherited from basic_string. However, without them, Visual 308 // C++ complains about ambiguous overloads when you try to use 309 // them. Thanks to Julian Selman to pointing this out. 310 // 311 // 1998-FEB-?? - Added overloads of assign() function to completely account 312 // for Q172398 bug. Thanks to "Pete the Plumber" for this 313 // 314 // 1998-FEB-?? - Initial submission 315 // 316 // COPYRIGHT: 317 // 2002 Joseph M. O'Leary. This code is 100% free. Use it anywhere you 318 // want. Rewrite it, restructure it, whatever. If you can write software 319 // that makes money off of it, good for you. I kinda like capitalism. 320 // Please don't blame me if it causes your $30 billion dollar satellite 321 // explode in orbit. If you redistribute it in any form, I'd appreciate it 322 // if you would leave this notice here. 323 // ============================================================================= 324 325 // Avoid multiple inclusion 326 327 #ifndef STDSTRING_H 328 #define STDSTRING_H 329 330 // When using VC, turn off browser references 331 // Turn off unavoidable compiler warnings 332 333 #if defined(_MSC_VER) && (_MSC_VER > 1100) 334 #pragma component(browser, off, references, "CStdString") 335 #pragma warning (disable : 4290) // C++ Exception Specification ignored 336 #pragma warning (disable : 4127) // Conditional expression is constant 337 #pragma warning (disable : 4097) // typedef name used as synonym for class name 338 #endif 339 340 #ifndef _UNICODE 341 #define SS_ANSI 342 #endif 343 344 // Borland warnings to turn off 345 346 #ifdef __BORLANDC__ 347 #pragma option push -w-inl 348 // #pragma warn -inl // Turn off inline function warnings 349 #endif 350 351 // SS_IS_INTRESOURCE 352 // ----------------- 353 // A copy of IS_INTRESOURCE from VC7. Because old VC6 version of winuser.h 354 // doesn't have this. 355 356 #define SS_IS_INTRESOURCE(_r) (false) 357 358 #if !defined (SS_ANSI) && defined(_MSC_VER) 359 #undef SS_IS_INTRESOURCE 360 #if defined(_WIN64) 361 #define SS_IS_INTRESOURCE(_r) (((unsigned __int64)(_r) >> 16) == 0) 362 #else 363 #define SS_IS_INTRESOURCE(_r) (((unsigned long)(_r) >> 16) == 0) 364 #endif 365 #endif 366 367 368 // MACRO: SS_UNSIGNED 369 // ------------------ 370 // This macro causes the addition of a constructor and assignment operator 371 // which take unsigned characters. CString has such functions and in order 372 // to provide maximum CString-compatability, this code needs them as well. 373 // In practice you will likely never need these functions... 374 375 //#define SS_UNSIGNED 376 377 #ifdef SS_ALLOW_UNSIGNED_CHARS 378 #define SS_UNSIGNED 379 #endif 380 381 // MACRO: SS_SAFE_FORMAT 382 // --------------------- 383 // This macro provides limited compatability with a questionable CString 384 // "feature". You can define it in order to avoid a common problem that 385 // people encounter when switching from CString to CStdString. 386 // 387 // To illustrate the problem -- With CString, you can do this: 388 // 389 // CString sName("Joe"); 390 // CString sTmp; 391 // sTmp.Format("My name is %s", sName); // WORKS! 392 // 393 // However if you were to try this with CStdString, your program would 394 // crash. 395 // 396 // CStdString sName("Joe"); 397 // CStdString sTmp; 398 // sTmp.Format("My name is %s", sName); // CRASHES! 399 // 400 // You must explicitly call c_str() or cast the object to the proper type 401 // 402 // sTmp.Format("My name is %s", sName.c_str()); // WORKS! 403 // sTmp.Format("My name is %s", static_cast<PCSTR>(sName));// WORKS! 404 // sTmp.Format("My name is %s", (PCSTR)sName); // WORKS! 405 // 406 // This is because it is illegal to pass anything but a POD type as a 407 // variadic argument to a variadic function (i.e. as one of the "..." 408 // arguments). The type const char* is a POD type. The type CStdString 409 // is not. Of course, neither is the type CString, but CString lets you do 410 // it anyway due to the way they laid out the class in binary. I have no 411 // control over this in CStdString since I derive from whatever 412 // implementation of basic_string is available. 413 // 414 // However if you have legacy code (which does this) that you want to take 415 // out of the MFC world and you don't want to rewrite all your calls to 416 // Format(), then you can define this flag and it will no longer crash. 417 // 418 // Note however that this ONLY works for Format(), not sprintf, fprintf, 419 // etc. If you pass a CStdString object to one of those functions, your 420 // program will crash. Not much I can do to get around this, short of 421 // writing substitutes for those functions as well. 422 423 #define SS_SAFE_FORMAT // use new template style Format() function 424 425 426 // MACRO: SS_NO_IMPLICIT_CAST 427 // -------------------------- 428 // Some people don't like the implicit cast to const char* (or rather to 429 // const CT*) that CStdString (and MFC's CString) provide. That was the 430 // whole reason I created this class in the first place, but hey, whatever 431 // bakes your cake. Just #define this macro to get rid of the the implicit 432 // cast. 433 434 //#define SS_NO_IMPLICIT_CAST // gets rid of operator const CT*() 435 436 437 // MACRO: SS_NO_REFCOUNT 438 // --------------------- 439 // turns off reference counting at the assignment level. Only needed 440 // for the version of basic_string<> that comes with Visual C++ versions 441 // 6.0 or earlier, and only then in some heavily multithreaded scenarios. 442 // Uncomment it if you feel you need it. 443 444 //#define SS_NO_REFCOUNT 445 446 // MACRO: SS_WIN32 447 // --------------- 448 // When this flag is set, we are building code for the Win32 platform and 449 // may use Win32 specific functions (such as LoadString). This gives us 450 // a couple of nice extras for the code. 451 // 452 // Obviously, Microsoft's is not the only compiler available for Win32 out 453 // there. So I can't just check to see if _MSC_VER is defined to detect 454 // if I'm building on Win32. So for now, if you use MS Visual C++ or 455 // Borland's compiler, I turn this on. Otherwise you may turn it on 456 // yourself, if you prefer 457 458 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WIN32) 459 #define SS_WIN32 460 #endif 461 462 // MACRO: SS_ANSI 463 // -------------- 464 // When this macro is defined, the code attempts only to use ANSI/ISO 465 // standard library functions to do it's work. It will NOT attempt to use 466 // any Win32 of Visual C++ specific functions -- even if they are 467 // available. You may define this flag yourself to prevent any Win32 468 // of VC++ specific functions from being called. 469 470 // If we're not on Win32, we MUST use an ANSI build 471 472 #ifndef SS_WIN32 473 #if !defined(SS_NO_ANSI) 474 #define SS_ANSI 475 #endif 476 #endif 477 478 // MACRO: SS_ALLOCA 479 // ---------------- 480 // Some implementations of the Standard C Library have a non-standard 481 // function known as alloca(). This functions allows one to allocate a 482 // variable amount of memory on the stack. It is needed to implement 483 // the ASCII/MBCS conversion macros. 484 // 485 // I wanted to find some way to determine automatically if alloca() is 486 // available on this platform via compiler flags but that is asking for 487 // trouble. The crude test presented here will likely need fixing on 488 // other platforms. Therefore I'll leave it up to you to fiddle with 489 // this test to determine if it exists. Just make sure SS_ALLOCA is or 490 // is not defined as appropriate and you control this feature. 491 492 #if defined(_MSC_VER) && !defined(SS_ANSI) 493 #define SS_ALLOCA 494 #endif 495 496 497 // MACRO: SS_MBCS 498 // -------------- 499 // Setting this macro means you are using MBCS characters. In MSVC builds, 500 // this macro gets set automatically by detection of the preprocessor flag 501 // _MBCS. For other platforms you may set it manually if you wish. The 502 // only effect it currently has is to cause the allocation of more space 503 // for wchar_t --> char conversions. 504 // Note that MBCS does not mean UNICODE. 505 // 506 // #define SS_MBCS 507 // 508 509 #ifdef _MBCS 510 #define SS_MBCS 511 #endif 512 513 514 // MACRO SS_NO_LOCALE 515 // ------------------ 516 // If your implementation of the Standard C++ Library lacks the <locale> header, 517 // you can #define this macro to make your code build properly. Note that this 518 // is some of my newest code and frankly I'm not very sure of it, though it does 519 // pass my unit tests. 520 521 // #define SS_NO_LOCALE 522 523 524 // Compiler Error regarding _UNICODE and UNICODE 525 // ----------------------------------------------- 526 // Microsoft header files are screwy. Sometimes they depend on a preprocessor 527 // flag named "_UNICODE". Other times they check "UNICODE" (note the lack of 528 // leading underscore in the second version". In several places, they silently 529 // "synchronize" these two flags this by defining one of the other was defined. 530 // In older version of this header, I used to try to do the same thing. 531 // 532 // However experience has taught me that this is a bad idea. You get weird 533 // compiler errors that seem to indicate things like LPWSTR and LPTSTR not being 534 // equivalent in UNICODE builds, stuff like that (when they MUST be in a proper 535 // UNICODE build). You end up scratching your head and saying, "But that HAS 536 // to compile!". 537 // 538 // So what should you do if you get this error? 539 // 540 // Make sure that both macros (_UNICODE and UNICODE) are defined before this 541 // file is included. You can do that by either 542 // 543 // a) defining both yourself before any files get included 544 // b) including the proper MS headers in the proper order 545 // c) including this file before any other file, uncommenting 546 // the #defines below, and commenting out the #errors 547 // 548 // Personally I recommend solution a) but it's your call. 549 550 #ifdef _MSC_VER 551 #if defined (_UNICODE) && !defined (UNICODE) 552 #error UNICODE defined but not UNICODE 553 // #define UNICODE // no longer silently fix this 554 #endif 555 #if defined (UNICODE) && !defined (_UNICODE) 556 #error Warning, UNICODE defined but not _UNICODE 557 // #define _UNICODE // no longer silently fix this 558 #endif 559 #endif 560 561 562 // ----------------------------------------------------------------------------- 563 // MIN and MAX. The Standard C++ template versions go by so many names (at 564 // at least in the MS implementation) that you never know what's available 565 // ----------------------------------------------------------------------------- 566 template<class Type> 567 inline const Type& SSMIN(const Type& arg1, const Type& arg2) 568 { 569 return arg2 < arg1 ? arg2 : arg1; 570 } 571 template<class Type> 572 inline const Type& SSMAX(const Type& arg1, const Type& arg2) 573 { 574 return arg2 > arg1 ? arg2 : arg1; 575 } 576 577 // If they have not #included W32Base.h (part of my W32 utility library) then 578 // we need to define some stuff. Otherwise, this is all defined there. 579 580 #if !defined(W32BASE_H) 581 582 // If they want us to use only standard C++ stuff (no Win32 stuff) 583 584 #ifdef SS_ANSI 585 586 // On Win32 we have TCHAR.H so just include it. This is NOT violating 587 // the spirit of SS_ANSI as we are not calling any Win32 functions here. 588 589 #ifdef SS_WIN32 590 591 #include <TCHAR.H> 592 #include <WTYPES.H> 593 #ifndef STRICT 594 #define STRICT 595 #endif 596 597 // ... but on non-Win32 platforms, we must #define the types we need. 598 599 #else 600 601 typedef const char* PCSTR; 602 typedef char* PSTR; 603 typedef const wchar_t* PCWSTR; 604 typedef wchar_t* PWSTR; 605 #ifdef UNICODE 606 typedef wchar_t TCHAR; 607 #else 608 typedef char TCHAR; 609 #endif 610 typedef wchar_t OLECHAR; 611 612 #endif // #ifndef _WIN32 613 614 615 // Make sure ASSERT and verify are defined using only ANSI stuff 616 617 #ifndef ASSERT 618 #include <assert.h> 619 #define ASSERT(f) assert((f)) 620 #endif 621 #ifndef VERIFY 622 #ifdef _DEBUG 623 #define VERIFY(x) ASSERT((x)) 624 #else 625 #define VERIFY(x) x 626 #endif 627 #endif 628 629 #else // ...else SS_ANSI is NOT defined 630 631 #include <TCHAR.H> 632 #include <WTYPES.H> 633 #ifndef STRICT 634 #define STRICT 635 #endif 636 637 // Make sure ASSERT and verify are defined 638 639 #ifndef ASSERT 640 #include <crtdbg.h> 641 #define ASSERT(f) _ASSERTE((f)) 642 #endif 643 #ifndef VERIFY 644 #ifdef _DEBUG 645 #define VERIFY(x) ASSERT((x)) 646 #else 647 #define VERIFY(x) x 648 #endif 649 #endif 650 651 #endif // #ifdef SS_ANSI 652 653 #ifndef UNUSED 654 #define UNUSED(x) x 655 #endif 656 657 #endif // #ifndef W32BASE_H 658 659 // Standard headers needed 660 661 #include <string> // basic_string 662 #include <algorithm> // for_each, etc. 663 #include <functional> // for StdStringLessNoCase, et al 664 #ifndef SS_NO_LOCALE 665 #include <locale> // for various facets 666 #endif 667 668 // If this is a recent enough version of VC include comdef.h, so we can write 669 // member functions to deal with COM types & compiler support classes e.g. 670 // _bstr_t 671 672 #if defined (_MSC_VER) && (_MSC_VER >= 1100) 673 #include <comdef.h> 674 #define SS_INC_COMDEF // signal that we #included MS comdef.h file 675 #define STDSTRING_INC_COMDEF 676 #define SS_NOTHROW __declspec(nothrow) 677 #else 678 #define SS_NOTHROW 679 #endif 680 681 #ifndef TRACE 682 #define TRACE_DEFINED_HERE 683 #define TRACE 684 #endif 685 686 // Microsoft defines PCSTR, PCWSTR, etc, but no PCTSTR. I hate to use the 687 // versions with the "L" in front of them because that's a leftover from Win 16 688 // days, even though it evaluates to the same thing. Therefore, Define a PCSTR 689 // as an LPCTSTR. 690 691 #if !defined(PCTSTR) && !defined(PCTSTR_DEFINED) 692 typedef const TCHAR* PCTSTR; 693 #define PCTSTR_DEFINED 694 #endif 695 696 #if !defined(PCOLESTR) && !defined(PCOLESTR_DEFINED) 697 typedef const OLECHAR* PCOLESTR; 698 #define PCOLESTR_DEFINED 699 #endif 700 701 #if !defined(POLESTR) && !defined(POLESTR_DEFINED) 702 typedef OLECHAR* POLESTR; 703 #define POLESTR_DEFINED 704 #endif 705 706 #if !defined(PCUSTR) && !defined(PCUSTR_DEFINED) 707 typedef const unsigned char* PCUSTR; 708 typedef unsigned char* PUSTR; 709 #define PCUSTR_DEFINED 710 #endif 711 712 713 // SGI compiler 7.3 doesnt know these types - oh and btw, remember to use 714 // -LANG:std in the CXX Flags 715 #if defined(__sgi) 716 typedef unsigned long DWORD; 717 typedef void * LPCVOID; 718 #endif 719 720 721 // SS_USE_FACET macro and why we need it: 722 // 723 // Since I'm a good little Standard C++ programmer, I use locales. Thus, I 724 // need to make use of the use_facet<> template function here. Unfortunately, 725 // this need is complicated by the fact the MS' implementation of the Standard 726 // C++ Library has a non-standard version of use_facet that takes more 727 // arguments than the standard dictates. Since I'm trying to write CStdString 728 // to work with any version of the Standard library, this presents a problem. 729 // 730 // The upshot of this is that I can't do 'use_facet' directly. The MS' docs 731 // tell me that I have to use a macro, _USE() instead. Since _USE obviously 732 // won't be available in other implementations, this means that I have to write 733 // my OWN macro -- SS_USE_FACET -- that evaluates either to _USE or to the 734 // standard, use_facet. 735 // 736 // If you are having trouble with the SS_USE_FACET macro, in your implementation 737 // of the Standard C++ Library, you can define your own version of SS_USE_FACET. 738 739 #ifndef schMSG 740 #define schSTR(x) #x 741 #define schSTR2(x) schSTR(x) 742 #define schMSG(desc) message(__FILE__ "(" schSTR2(__LINE__) "):" #desc) 743 #endif 744 745 #ifndef SS_USE_FACET 746 747 // STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for 748 // all MSVC builds, erroneously in my opinion. It causes problems for 749 // my SS_ANSI builds. In my code, I always comment out that line. You'll 750 // find it in stlportconfigstl_msvc.h 751 752 #if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 ) 753 754 #if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) && defined(_MSC_VER) 755 #ifdef SS_ANSI 756 #pragma schMSG(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS defined!!) 757 #endif 758 #endif 759 #define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc) 760 761 #elif defined(_MSC_VER ) 762 763 #define SS_USE_FACET(loc, fac) std::_USE(loc, fac) 764 765 // ...and 766 #elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE) 767 768 #define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0) 769 770 #else 771 772 #define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc) 773 774 #endif 775 776 #endif 777 778 // ============================================================================= 779 // UNICODE/MBCS conversion macros. Made to work just like the MFC/ATL ones. 780 // ============================================================================= 781 782 #include <wchar.h> // Added to Std Library with Amendment #1. 783 784 // First define the conversion helper functions. We define these regardless of 785 // any preprocessor macro settings since their names won't collide. 786 787 // Not sure if we need all these headers. I believe ANSI says we do. 788 789 #include <stdio.h> 790 #include <stdarg.h> 791 #include <wctype.h> 792 #include <ctype.h> 793 #include <stdlib.h> 794 #ifndef va_start 795 #include <varargs.h> 796 #endif 797 798 799 #ifdef SS_NO_LOCALE 800 801 #if defined(_WIN32) || defined (_WIN32_WCE) 802 803 inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc, 804 UINT acp=CP_ACP) 805 { 806 ASSERT(0 != pSrcA); 807 ASSERT(0 != pDstW); 808 pDstW[0] = '