6 #if defined(TARGET_WINDOWS) && !defined(va_copy)
7 #define va_copy(dst, src) ((dst) = (src))
10 // =============================================================================
12 // AUTHOR: Joe O'Leary (with outside help noted in comments)
14 // If you find any bugs in this code, please let me know:
16 // jmoleary@earthlink.net
17 // http://www.joeo.net/stdstring.htm (a bit outdated)
19 // The latest version of this code should always be available at the
22 // http://www.joeo.net/code/StdString.zip (Dec 6, 2003)
26 // This header file declares the CStdStr template. This template derives
27 // the Standard C++ Library basic_string<> template and add to it the
28 // the following conveniences:
29 // - The full MFC CString set of functions (including implicit cast)
30 // - writing to/reading from COM IStream interfaces
31 // - Functional objects for use in STL algorithms
33 // From this template, we intstantiate two classes: CStdStringA and
34 // CStdStringW. The name "CStdString" is just a #define of one of these,
35 // based upone the UNICODE macro setting
37 // This header also declares our own version of the MFC/ATL UNICODE-MBCS
38 // conversion macros. Our version looks exactly like the Microsoft's to
39 // facilitate portability.
42 // If you you use this in an MFC or ATL build, you should include either
43 // afx.h or atlbase.h first, as appropriate.
45 // PEOPLE WHO HAVE CONTRIBUTED TO THIS CLASS:
47 // Several people have helped me iron out problems and othewise improve
48 // this class. OK, this is a long list but in my own defense, this code
49 // has undergone two major rewrites. Many of the improvements became
50 // necessary after I rewrote the code as a template. Others helped me
51 // improve the CString facade.
53 // Anyway, these people are (in chronological order):
55 // - Pete the Plumber (???)
57 // - Chris (of Melbsys)
70 // - Baptiste Lepilleur
78 // - Aaron (no last name)
79 // - Joldakowski (???)
83 // - Farrokh Nejadlotfi
93 // - Bagira (full name?)
106 // 2005-JAN-10 - Thanks to Don Beusee for pointing out the danger in mapping
107 // length-checked formatting functions to non-length-checked
108 // CRT equivalents. Also thanks to him for motivating me to
109 // optimize my implementation of Replace()
111 // 2004-APR-22 - A big, big thank you to "MKingman" (whoever you are) for
112 // finally spotting a silly little error in StdCodeCvt that
113 // has been causing me (and users of CStdString) problems for
114 // years in some relatively rare conversions. I had reversed
115 // two length arguments.
117 // 2003-NOV-24 - Thanks to a bunch of people for helping me clean up many
118 // compiler warnings (and yes, even a couple of actual compiler
119 // errors). These include Henk Demper for figuring out how
120 // to make the Intellisense work on with CStdString on VC6,
121 // something I was never able to do. Greg Marr pointed out
122 // a compiler warning about an unreferenced symbol and a
123 // problem with my version of Load in MFC builds. Bill
124 // Carducci took a lot of time with me to help me figure out
125 // why some implementations of the Standard C++ Library were
126 // returning error codes for apparently successful conversions
127 // between ASCII and UNICODE. Finally thanks to Brian Groose
128 // for helping me fix compiler signed unsigned warnings in
129 // several functions.
131 // 2003-JUL-10 - Thanks to Charles Godwin for making me realize my 'FmtArg'
132 // fixes had inadvertently broken the DLL-export code (which is
133 // normally commented out. I had to move it up higher. Also
134 // this helped me catch a bug in ssicoll that would prevent
135 // compilation, otherwise.
137 // 2003-MAR-14 - Thanks to Jakko Van Hunen for pointing out a copy-and-paste
138 // bug in one of the overloads of FmtArg.
140 // 2003-MAR-10 - Thanks to Ronny Schulz for (twice!) sending me some changes
141 // to help CStdString build on SGI and for pointing out an
142 // error in placement of my preprocessor macros for ssfmtmsg.
144 // 2002-NOV-26 - Thanks to Bagira for pointing out that my implementation of
145 // SpanExcluding was not properly handling the case in which
146 // the string did NOT contain any of the given characters
148 // 2002-OCT-21 - Many thanks to Paul DeMarco who was invaluable in helping me
149 // get this code working with Borland's free compiler as well
150 // as the Dev-C++ compiler (available free at SourceForge).
152 // 2002-SEP-13 - Thanks to Glen Maynard who helped me get rid of some loud
153 // but harmless warnings that were showing up on g++. Glen
154 // also pointed out that some pre-declarations of FmtArg<>
155 // specializations were unnecessary (and no good on G++)
157 // 2002-JUN-26 - Thanks to Arnt Witteveen for pointing out that I was using
158 // static_cast<> in a place in which I should have been using
159 // reinterpret_cast<> (the ctor for unsigned char strings).
160 // That's what happens when I don't unit-test properly!
161 // Arnt also noticed that CString was silently correcting the
162 // 'nCount' argument to Left() and Right() where CStdString was
163 // not (and crashing if it was bad). That is also now fixed!
165 // 2002-FEB-25 - Thanks to Tim Dowty for pointing out (and giving me the fix
166 // for) a conversion problem with non-ASCII MBCS characters.
167 // CStdString is now used in my favorite commercial MP3 player!
169 // 2001-DEC-06 - Thanks to Wang Haifeng for spotting a problem in one of the
170 // assignment operators (for _bstr_t) that would cause compiler
171 // errors when refcounting protection was turned off.
173 // 2001-NOV-27 - Remove calls to operator!= which involve reverse_iterators
174 // due to a conflict with the rel_ops operator!=. Thanks to
175 // John James for pointing this out.
177 // 2001-OCT-29 - Added a minor range checking fix for the Mid function to
178 // make it as forgiving as CString's version is. Thanks to
179 // Igor Kholodov for noticing this.
180 // - Added a specialization of std::swap for CStdString. Thanks
181 // to Mike Crusader for suggesting this! It's commented out
182 // because you're not supposed to inject your own code into the
183 // 'std' namespace. But if you don't care about that, it's
184 // there if you want it
185 // - Thanks to Jason Mills for catching a case where CString was
186 // more forgiving in the Delete() function than I was.
188 // 2001-JUN-06 - I was violating the Standard name lookup rules stated
189 // in [14.6.2(3)]. None of the compilers I've tried so
190 // far apparently caught this but HP-UX aCC 3.30 did. The
191 // fix was to add 'this->' prefixes in many places.
192 // Thanks to Farrokh Nejadlotfi for this!
194 // 2001-APR-27 - StreamLoad was calculating the number of BYTES in one
195 // case, not characters. Thanks to Pablo Presedo for this.
197 // 2001-FEB-23 - Replace() had a bug which caused infinite loops if the
198 // source string was empty. Fixed thanks to Eric Nitzsche.
200 // 2001-FEB-23 - Scott Hathaway was a huge help in providing me with the
201 // ability to build CStdString on Sun Unix systems. He
202 // sent me detailed build reports about what works and what
203 // does not. If CStdString compiles on your Unix box, you
204 // can thank Scott for it.
206 // 2000-DEC-29 - Joldakowski noticed one overload of Insert failed to do a
207 // range check as CString's does. Now fixed -- thanks!
209 // 2000-NOV-07 - Aaron pointed out that I was calling static member
210 // functions of char_traits via a temporary. This was not
211 // technically wrong, but it was unnecessary and caused
212 // problems for poor old buggy VC5. Thanks Aaron!
214 // 2000-JUL-11 - Joe Woodbury noted that the CString::Find docs don't match
215 // what the CString::Find code really ends up doing. I was
216 // trying to match the docs. Now I match the CString code
217 // - Joe also caught me truncating strings for GetBuffer() calls
218 // when the supplied length was less than the current length.
220 // 2000-MAY-25 - Better support for STLPORT's Standard library distribution
221 // - Got rid of the NSP macro - it interfered with Koenig lookup
222 // - Thanks to Joe Woodbury for catching a TrimLeft() bug that
223 // I introduced in January. Empty strings were not getting
226 // 2000-APR-17 - Thanks to Joe Vitaterna for pointing out that ReverseFind
227 // is supposed to be a const function.
229 // 2000-MAR-07 - Thanks to Ullrich Poll�hne for catching a range bug in one
230 // of the overloads of assign.
232 // 2000-FEB-01 - You can now use CStdString on the Mac with CodeWarrior!
233 // Thanks to Todd Heckel for helping out with this.
235 // 2000-JAN-23 - Thanks to Jim Cline for pointing out how I could make the
236 // Trim() function more efficient.
237 // - Thanks to Jeff Kohn for prompting me to find and fix a typo
238 // in one of the addition operators that takes _bstr_t.
239 // - Got rid of the .CPP file - you only need StdString.h now!
241 // 1999-DEC-22 - Thanks to Greg Pickles for helping me identify a problem
242 // with my implementation of CStdString::FormatV in which
243 // resulting string might not be properly NULL terminated.
245 // 1999-DEC-06 - Chris Conti pointed yet another basic_string<> assignment
246 // bug that MS has not fixed. CStdString did nothing to fix
247 // it either but it does now! The bug was: create a string
248 // longer than 31 characters, get a pointer to it (via c_str())
249 // and then assign that pointer to the original string object.
250 // The resulting string would be empty. Not with CStdString!
252 // 1999-OCT-06 - BufferSet was erasing the string even when it was merely
253 // supposed to shrink it. Fixed. Thanks to Chris Conti.
254 // - Some of the Q172398 fixes were not checking for assignment-
255 // to-self. Fixed. Thanks to Baptiste Lepilleur.
257 // 1999-AUG-20 - Improved Load() function to be more efficient by using
258 // SizeOfResource(). Thanks to Rich Zuris for this.
259 // - Corrected resource ID constructor, again thanks to Rich.
260 // - Fixed a bug that occurred with UNICODE characters above
261 // the first 255 ANSI ones. Thanks to Craig Watson.
262 // - Added missing overloads of TrimLeft() and TrimRight().
263 // Thanks to Karim Ratib for pointing them out
265 // 1999-JUL-21 - Made all calls to GetBuf() with no args check length first.
267 // 1999-JUL-10 - Improved MFC/ATL independence of conversion macros
268 // - Added SS_NO_REFCOUNT macro to allow you to disable any
269 // reference-counting your basic_string<> impl. may do.
270 // - Improved ReleaseBuffer() to be as forgiving as CString.
271 // Thanks for Fan Xia for helping me find this and to
272 // Matthew Williams for pointing it out directly.
274 // 1999-JUL-06 - Thanks to Nigel Nunn for catching a very sneaky bug in
275 // ToLower/ToUpper. They should call GetBuf() instead of
276 // data() in order to ensure the changed string buffer is not
277 // reference-counted (in those implementations that refcount).
279 // 1999-JUL-01 - Added a true CString facade. Now you can use CStdString as
280 // a drop-in replacement for CString. If you find this useful,
281 // you can thank Chris Sells for finally convincing me to give
282 // in and implement it.
283 // - Changed operators << and >> (for MFC CArchive) to serialize
284 // EXACTLY as CString's do. So now you can send a CString out
285 // to a CArchive and later read it in as a CStdString. I have
286 // no idea why you would want to do this but you can.
288 // 1999-JUN-21 - Changed the CStdString class into the CStdStr template.
289 // - Fixed FormatV() to correctly decrement the loop counter.
290 // This was harmless bug but a bug nevertheless. Thanks to
291 // Chris (of Melbsys) for pointing it out
292 // - Changed Format() to try a normal stack-based array before
293 // using to _alloca().
294 // - Updated the text conversion macros to properly use code
295 // pages and to fit in better in MFC/ATL builds. In other
296 // words, I copied Microsoft's conversion stuff again.
297 // - Added equivalents of CString::GetBuffer, GetBufferSetLength
298 // - new sscpy() replacement of CStdString::CopyString()
299 // - a Trim() function that combines TrimRight() and TrimLeft().
301 // 1999-MAR-13 - Corrected the "NotSpace" functional object to use _istpace()
302 // instead of _isspace() Thanks to Dave Plummer for this.
304 // 1999-FEB-26 - Removed errant line (left over from testing) that #defined
305 // _MFC_VER. Thanks to John C Sipos for noticing this.
307 // 1999-FEB-03 - Fixed a bug in a rarely-used overload of operator+() that
308 // caused infinite recursion and stack overflow
309 // - Added member functions to simplify the process of
310 // persisting CStdStrings to/from DCOM IStream interfaces
311 // - Added functional objects (e.g. StdStringLessNoCase) that
312 // allow CStdStrings to be used as keys STL map objects with
313 // case-insensitive comparison
314 // - Added array indexing operators (i.e. operator[]). I
315 // originally assumed that these were unnecessary and would be
316 // inherited from basic_string. However, without them, Visual
317 // C++ complains about ambiguous overloads when you try to use
318 // them. Thanks to Julian Selman to pointing this out.
320 // 1998-FEB-?? - Added overloads of assign() function to completely account
321 // for Q172398 bug. Thanks to "Pete the Plumber" for this
323 // 1998-FEB-?? - Initial submission
326 // 2002 Joseph M. O'Leary. This code is 100% free. Use it anywhere you
327 // want. Rewrite it, restructure it, whatever. If you can write software
328 // that makes money off of it, good for you. I kinda like capitalism.
329 // Please don't blame me if it causes your $30 billion dollar satellite
330 // explode in orbit. If you redistribute it in any form, I'd appreciate it
331 // if you would leave this notice here.
332 // =============================================================================
334 // Avoid multiple inclusion
339 // When using VC, turn off browser references
340 // Turn off unavoidable compiler warnings
342 #if defined(_MSC_VER) && (_MSC_VER > 1100)
343 #pragma component(browser, off, references, "CStdString")
344 #pragma warning (disable : 4290) // C++ Exception Specification ignored
345 #pragma warning (disable : 4127) // Conditional expression is constant
346 #pragma warning (disable : 4097) // typedef name used as synonym for class name
349 // Borland warnings to turn off
352 #pragma option push -w-inl
353 // #pragma warn -inl // Turn off inline function warnings
358 // A copy of IS_INTRESOURCE from VC7. Because old VC6 version of winuser.h
359 // doesn't have this.
361 #define SS_IS_INTRESOURCE(_r) (false)
363 #if !defined (SS_ANSI) && defined(_MSC_VER)
364 #undef SS_IS_INTRESOURCE
366 #define SS_IS_INTRESOURCE(_r) (((uint64_t)(_r) >> 16) == 0)
368 #define SS_IS_INTRESOURCE(_r) (((unsigned long)(_r) >> 16) == 0)
373 // MACRO: SS_UNSIGNED
374 // ------------------
375 // This macro causes the addition of a constructor and assignment operator
376 // which take unsigned characters. CString has such functions and in order
377 // to provide maximum CString-compatability, this code needs them as well.
378 // In practice you will likely never need these functions...
380 //#define SS_UNSIGNED
382 #ifdef SS_ALLOW_UNSIGNED_CHARS
386 // MACRO: SS_SAFE_FORMAT
387 // ---------------------
388 // This macro provides limited compatability with a questionable CString
389 // "feature". You can define it in order to avoid a common problem that
390 // people encounter when switching from CString to CStdString.
392 // To illustrate the problem -- With CString, you can do this:
394 // CString sName("Joe");
396 // sTmp.Format("My name is %s", sName); // WORKS!
398 // However if you were to try this with CStdString, your program would
401 // CStdString sName("Joe");
403 // sTmp.Format("My name is %s", sName); // CRASHES!
405 // You must explicitly call c_str() or cast the object to the proper type
407 // sTmp.Format("My name is %s", sName.c_str()); // WORKS!
408 // sTmp.Format("My name is %s", static_cast<PCSTR>(sName));// WORKS!
409 // sTmp.Format("My name is %s", (PCSTR)sName); // WORKS!
411 // This is because it is illegal to pass anything but a POD type as a
412 // variadic argument to a variadic function (i.e. as one of the "..."
413 // arguments). The type const char* is a POD type. The type CStdString
414 // is not. Of course, neither is the type CString, but CString lets you do
415 // it anyway due to the way they laid out the class in binary. I have no
416 // control over this in CStdString since I derive from whatever
417 // implementation of basic_string is available.
419 // However if you have legacy code (which does this) that you want to take
420 // out of the MFC world and you don't want to rewrite all your calls to
421 // Format(), then you can define this flag and it will no longer crash.
423 // Note however that this ONLY works for Format(), not sprintf, fprintf,
424 // etc. If you pass a CStdString object to one of those functions, your
425 // program will crash. Not much I can do to get around this, short of
426 // writing substitutes for those functions as well.
428 #define SS_SAFE_FORMAT // use new template style Format() function
431 // MACRO: SS_NO_IMPLICIT_CAST
432 // --------------------------
433 // Some people don't like the implicit cast to const char* (or rather to
434 // const CT*) that CStdString (and MFC's CString) provide. That was the
435 // whole reason I created this class in the first place, but hey, whatever
436 // bakes your cake. Just #define this macro to get rid of the the implicit
439 //#define SS_NO_IMPLICIT_CAST // gets rid of operator const CT*()
442 // MACRO: SS_NO_REFCOUNT
443 // ---------------------
444 // turns off reference counting at the assignment level. Only needed
445 // for the version of basic_string<> that comes with Visual C++ versions
446 // 6.0 or earlier, and only then in some heavily multithreaded scenarios.
447 // Uncomment it if you feel you need it.
449 //#define SS_NO_REFCOUNT
453 // When this flag is set, we are building code for the Win32 platform and
454 // may use Win32 specific functions (such as LoadString). This gives us
455 // a couple of nice extras for the code.
457 // Obviously, Microsoft's is not the only compiler available for Win32 out
458 // there. So I can't just check to see if _MSC_VER is defined to detect
459 // if I'm building on Win32. So for now, if you use MS Visual C++ or
460 // Borland's compiler, I turn this on. Otherwise you may turn it on
461 // yourself, if you prefer
463 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WIN32)
469 // When this macro is defined, the code attempts only to use ANSI/ISO
470 // standard library functions to do it's work. It will NOT attempt to use
471 // any Win32 of Visual C++ specific functions -- even if they are
472 // available. You may define this flag yourself to prevent any Win32
473 // of VC++ specific functions from being called.
475 // If we're not on Win32, we MUST use an ANSI build
478 #if !defined(SS_NO_ANSI)
485 // Some implementations of the Standard C Library have a non-standard
486 // function known as alloca(). This functions allows one to allocate a
487 // variable amount of memory on the stack. It is needed to implement
488 // the ASCII/MBCS conversion macros.
490 // I wanted to find some way to determine automatically if alloca() is
491 // available on this platform via compiler flags but that is asking for
492 // trouble. The crude test presented here will likely need fixing on
493 // other platforms. Therefore I'll leave it up to you to fiddle with
494 // this test to determine if it exists. Just make sure SS_ALLOCA is or
495 // is not defined as appropriate and you control this feature.
497 #if defined(_MSC_VER) && !defined(SS_ANSI)
504 // Setting this macro means you are using MBCS characters. In MSVC builds,
505 // this macro gets set automatically by detection of the preprocessor flag
506 // _MBCS. For other platforms you may set it manually if you wish. The
507 // only effect it currently has is to cause the allocation of more space
508 // for wchar_t --> char conversions.
509 // Note that MBCS does not mean UNICODE.
519 // MACRO SS_NO_LOCALE
520 // ------------------
521 // If your implementation of the Standard C++ Library lacks the <locale> header,
522 // you can #define this macro to make your code build properly. Note that this
523 // is some of my newest code and frankly I'm not very sure of it, though it does
524 // pass my unit tests.
526 // #define SS_NO_LOCALE
529 // Compiler Error regarding _UNICODE and UNICODE
530 // -----------------------------------------------
531 // Microsoft header files are screwy. Sometimes they depend on a preprocessor
532 // flag named "_UNICODE". Other times they check "UNICODE" (note the lack of
533 // leading underscore in the second version". In several places, they silently
534 // "synchronize" these two flags this by defining one of the other was defined.
535 // In older version of this header, I used to try to do the same thing.
537 // However experience has taught me that this is a bad idea. You get weird
538 // compiler errors that seem to indicate things like LPWSTR and LPTSTR not being
539 // equivalent in UNICODE builds, stuff like that (when they MUST be in a proper
540 // UNICODE build). You end up scratching your head and saying, "But that HAS
543 // So what should you do if you get this error?
545 // Make sure that both macros (_UNICODE and UNICODE) are defined before this
546 // file is included. You can do that by either
548 // a) defining both yourself before any files get included
549 // b) including the proper MS headers in the proper order
550 // c) including this file before any other file, uncommenting
551 // the #defines below, and commenting out the #errors
553 // Personally I recommend solution a) but it's your call.
556 #if defined (_UNICODE) && !defined (UNICODE)
557 #error UNICODE defined but not UNICODE
558 // #define UNICODE // no longer silently fix this
560 #if defined (UNICODE) && !defined (_UNICODE)
561 #error Warning, UNICODE defined but not _UNICODE
562 // #define _UNICODE // no longer silently fix this
567 // -----------------------------------------------------------------------------
568 // MIN and MAX. The Standard C++ template versions go by so many names (at
569 // at least in the MS implementation) that you never know what's available
570 // -----------------------------------------------------------------------------
572 inline const Type& SSMIN(const Type& arg1, const Type& arg2)
574 return arg2 < arg1 ? arg2 : arg1;
577 inline const Type& SSMAX(const Type& arg1, const Type& arg2)
579 return arg2 > arg1 ? arg2 : arg1;
582 // If they have not #included W32Base.h (part of my W32 utility library) then
583 // we need to define some stuff. Otherwise, this is all defined there.
585 #if !defined(W32BASE_H)
587 // If they want us to use only standard C++ stuff (no Win32 stuff)
591 // On Win32 we have TCHAR.H so just include it. This is NOT violating
592 // the spirit of SS_ANSI as we are not calling any Win32 functions here.
602 // ... but on non-Win32 platforms, we must #define the types we need.
606 typedef const char* PCSTR;
608 typedef const wchar_t* PCWSTR;
609 typedef wchar_t* PWSTR;
611 typedef wchar_t TCHAR;
615 typedef wchar_t OLECHAR;
617 #endif // #ifndef _WIN32
620 // Make sure ASSERT and verify are defined using only ANSI stuff
624 #define ASSERT(f) assert((f))
628 #define VERIFY(x) ASSERT((x))
634 #else // ...else SS_ANSI is NOT defined
642 // Make sure ASSERT and verify are defined
646 #define ASSERT(f) _ASSERTE((f))
650 #define VERIFY(x) ASSERT((x))
656 #endif // #ifdef SS_ANSI
662 #endif // #ifndef W32BASE_H
664 // Standard headers needed
666 #include <string> // basic_string
667 #include <algorithm> // for_each, etc.
668 #include <functional> // for StdStringLessNoCase, et al
670 #include <locale> // for various facets
673 // If this is a recent enough version of VC include comdef.h, so we can write
674 // member functions to deal with COM types & compiler support classes e.g.
677 #if defined (_MSC_VER) && (_MSC_VER >= 1100)
679 #define SS_INC_COMDEF // signal that we #included MS comdef.h file
680 #define STDSTRING_INC_COMDEF
681 #define SS_NOTHROW __declspec(nothrow)
687 #define TRACE_DEFINED_HERE
691 // Microsoft defines PCSTR, PCWSTR, etc, but no PCTSTR. I hate to use the
692 // versions with the "L" in front of them because that's a leftover from Win 16
693 // days, even though it evaluates to the same thing. Therefore, Define a PCSTR
696 #if !defined(PCTSTR) && !defined(PCTSTR_DEFINED)
697 typedef const TCHAR* PCTSTR;
698 #define PCTSTR_DEFINED
701 #if !defined(PCOLESTR) && !defined(PCOLESTR_DEFINED)
702 typedef const OLECHAR* PCOLESTR;
703 #define PCOLESTR_DEFINED
706 #if !defined(POLESTR) && !defined(POLESTR_DEFINED)
707 typedef OLECHAR* POLESTR;
708 #define POLESTR_DEFINED
711 #if !defined(PCUSTR) && !defined(PCUSTR_DEFINED)
712 typedef const unsigned char* PCUSTR;
713 typedef unsigned char* PUSTR;
714 #define PCUSTR_DEFINED
718 // SGI compiler 7.3 doesnt know these types - oh and btw, remember to use
719 // -LANG:std in the CXX Flags
721 typedef unsigned long DWORD;
722 typedef void * LPCVOID;
726 // SS_USE_FACET macro and why we need it:
728 // Since I'm a good little Standard C++ programmer, I use locales. Thus, I
729 // need to make use of the use_facet<> template function here. Unfortunately,
730 // this need is complicated by the fact the MS' implementation of the Standard
731 // C++ Library has a non-standard version of use_facet that takes more
732 // arguments than the standard dictates. Since I'm trying to write CStdString
733 // to work with any version of the Standard library, this presents a problem.
735 // The upshot of this is that I can't do 'use_facet' directly. The MS' docs
736 // tell me that I have to use a macro, _USE() instead. Since _USE obviously
737 // won't be available in other implementations, this means that I have to write
738 // my OWN macro -- SS_USE_FACET -- that evaluates either to _USE or to the
739 // standard, use_facet.
741 // If you are having trouble with the SS_USE_FACET macro, in your implementation
742 // of the Standard C++ Library, you can define your own version of SS_USE_FACET.
746 #define schSTR2(x) schSTR(x)
747 #define schMSG(desc) message(__FILE__ "(" schSTR2(__LINE__) "):" #desc)
752 // STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for
753 // all MSVC builds, erroneously in my opinion. It causes problems for
754 // my SS_ANSI builds. In my code, I always comment out that line. You'll
755 // find it in \stlport\config\stl_msvc.h
757 #if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 )
759 #if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) && defined(_MSC_VER)
761 #pragma schMSG(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS defined!!)
764 #define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)
766 #elif defined(_MSC_VER )
768 #define SS_USE_FACET(loc, fac) std::_USE(loc, fac)
771 #elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)
773 #define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0)
777 #define SS_USE_FACET(loc, fac) std::use_facet<fac >(loc)
783 // =============================================================================
784 // UNICODE/MBCS conversion macros. Made to work just like the MFC/ATL ones.
785 // =============================================================================
787 #include <wchar.h> // Added to Std Library with Amendment #1.
789 // First define the conversion helper functions. We define these regardless of
790 // any preprocessor macro settings since their names won't collide.
792 // Not sure if we need all these headers. I believe ANSI says we do.
806 #if defined(_WIN32) || defined (_WIN32_WCE)
808 inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc,
814 MultiByteToWideChar(acp, 0, pSrcA, nSrc, pDstW, nDst);
817 inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc,
820 return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, acp);
823 inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
829 WideCharToMultiByte(acp, 0, pSrcW, nSrc, pDstA, nDst, 0, 0);
832 inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
835 return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, acp);
842 // StdCodeCvt - made to look like Win32 functions WideCharToMultiByte
843 // and MultiByteToWideChar but uses locales in SS_ANSI
844 // builds. There are a number of overloads.
845 // First argument is the destination buffer.
846 // Second argument is the source buffer
847 //#if defined (SS_ANSI) || !defined (SS_WIN32)
849 // 'SSCodeCvt' - shorthand name for the codecvt facet we use
851 typedef std::codecvt<wchar_t, char, mbstate_t> SSCodeCvt;
853 inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc,
854 const std::locale& loc=std::locale())
863 PCSTR pNextSrcA = pSrcA;
864 PWSTR pNextDstW = pDstW;
865 SSCodeCvt::result res = SSCodeCvt::ok;
866 const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt);
867 #if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD)
868 SSCodeCvt::state_type st= { { 0 } };
870 SSCodeCvt::state_type st= { 0 };
873 pSrcA, pSrcA + nSrc, pNextSrcA,
874 pDstW, pDstW + nDst, pNextDstW);
876 #define ASSERT2(a) if (!(a)) {fprintf(stderr, "StdString: Assertion Failed on line %d\n", __LINE__);}
878 #define ASSERT2 ASSERT
880 ASSERT2(SSCodeCvt::ok == res);
881 ASSERT2(SSCodeCvt::error != res);
882 ASSERT2(pNextDstW >= pDstW);
883 ASSERT2(pNextSrcA >= pSrcA);
885 // Null terminate the converted string
887 if ( pNextDstW - pDstW > nDst )
888 *(pDstW + nDst) = '\0';
894 inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc,
895 const std::locale& loc=std::locale())
897 return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, loc);
900 inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
901 const std::locale& loc=std::locale())
910 PSTR pNextDstA = pDstA;
911 PCWSTR pNextSrcW = pSrcW;
912 SSCodeCvt::result res = SSCodeCvt::ok;
913 const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt);
914 #if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD)
915 SSCodeCvt::state_type st= { { 0 } };
917 SSCodeCvt::state_type st= { 0 };
920 pSrcW, pSrcW + nSrc, pNextSrcW,
921 pDstA, pDstA + nDst, pNextDstA);
923 #define ASSERT2(a) if (!(a)) {fprintf(stderr, "StdString: Assertion Failed on line %d\n", __LINE__);}
925 #define ASSERT2 ASSERT
927 ASSERT2(SSCodeCvt::error != res);
928 ASSERT2(SSCodeCvt::ok == res); // strict, comment out for sanity
929 ASSERT2(pNextDstA >= pDstA);
930 ASSERT2(pNextSrcW >= pSrcW);
933 // Null terminate the converted string
935 if ( pNextDstA - pDstA > nDst )
936 *(pDstA + nDst) = '\0';
943 inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
944 const std::locale& loc=std::locale())
946 return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, loc);
953 // Unicode/MBCS conversion macros are only available on implementations of
954 // the "C" library that have the non-standard _alloca function. As far as I
955 // know that's only Microsoft's though I've heard that the function exists
958 #if defined(SS_ALLOCA) && !defined SS_NO_CONVERSION
960 #include <malloc.h> // needed for _alloca
962 // Define our conversion macros to look exactly like Microsoft's to
963 // facilitate using this stuff both with and without MFC/ATL
965 #ifdef _CONVERSION_USES_THREAD_LOCALE
968 #define SSCVT int _cvt; _cvt; UINT _acp=GetACP(); \
969 _acp; PCWSTR _pw; _pw; PCSTR _pa; _pa
971 #define SSCVT int _cvt = 0; _cvt; UINT _acp=GetACP();\
972 _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa
975 ((_pa = pa) == 0) ? 0 : (\
976 _cvt = (sslen(_pa)),\
977 StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
980 ((_pw = pw) == 0) ? 0 : (\
982 StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
987 #define SSCVT int _cvt; _cvt; UINT _acp=CP_ACP; _acp;\
988 PCWSTR _pw; _pw; PCSTR _pa; _pa
990 #define SSCVT int _cvt = 0; _cvt; UINT _acp=CP_ACP; \
991 _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa
994 ((_pa = pa) == 0) ? 0 : (\
995 _cvt = (sslen(_pa)),\
996 StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
999 ((_pw = pw) == 0) ? 0 : (\
1000 _cvt = (sslen(_pw)),\
1001 StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \
1005 #define SSA2CW(pa) ((PCWSTR)SSA2W((pa)))
1006 #define SSW2CA(pw) ((PCSTR)SSW2A((pw)))
1011 #define SST2CA SSW2CA
1012 #define SSA2CT SSA2CW
1013 // (Did you get a compiler error here about not being able to convert
1014 // PTSTR into PWSTR? Then your _UNICODE and UNICODE flags are messed
1015 // up. Best bet: #define BOTH macros before including any MS headers.)
1016 inline PWSTR SST2W(PTSTR p) { return p; }
1017 inline PTSTR SSW2T(PWSTR p) { return p; }
1018 inline PCWSTR SST2CW(PCTSTR p) { return p; }
1019 inline PCTSTR SSW2CT(PCWSTR p) { return p; }
1023 #define SST2CW SSA2CW
1024 #define SSW2CT SSW2CA
1025 inline PSTR SST2A(PTSTR p) { return p; }
1026 inline PTSTR SSA2T(PSTR p) { return p; }
1027 inline PCSTR SST2CA(PCTSTR p) { return p; }
1028 inline PCTSTR SSA2CT(PCSTR p) { return p; }
1029 #endif // #ifdef UNICODE
1031 #if defined(UNICODE)
1032 // in these cases the default (TCHAR) is the same as OLECHAR
1033 inline PCOLESTR SST2COLE(PCTSTR p) { return p; }
1034 inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; }
1035 inline POLESTR SST2OLE(PTSTR p) { return p; }
1036 inline PTSTR SSOLE2T(POLESTR p) { return p; }
1037 #elif defined(OLE2ANSI)
1038 // in these cases the default (TCHAR) is the same as OLECHAR
1039 inline PCOLESTR SST2COLE(PCTSTR p) { return p; }
1040 inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; }
1041 inline POLESTR SST2OLE(PTSTR p) { return p; }
1042 inline PTSTR SSOLE2T(POLESTR p) { return p; }
1044 //CharNextW doesn't work on Win95 so we use this
1045 #define SST2COLE(pa) SSA2CW((pa))
1046 #define SST2OLE(pa) SSA2W((pa))
1047 #define SSOLE2CT(po) SSW2CA((po))
1048 #define SSOLE2T(po) SSW2A((po))
1052 #define SSW2OLE SSW2A
1053 #define SSOLE2W SSA2W
1054 #define SSW2COLE SSW2CA
1055 #define SSOLE2CW SSA2CW
1056 inline POLESTR SSA2OLE(PSTR p) { return p; }
1057 inline PSTR SSOLE2A(POLESTR p) { return p; }
1058 inline PCOLESTR SSA2COLE(PCSTR p) { return p; }
1059 inline PCSTR SSOLE2CA(PCOLESTR p){ return p; }
1061 #define SSA2OLE SSA2W
1062 #define SSOLE2A SSW2A
1063 #define SSA2COLE SSA2CW
1064 #define SSOLE2CA SSW2CA
1065 inline POLESTR SSW2OLE(PWSTR p) { return p; }
1066 inline PWSTR SSOLE2W(POLESTR p) { return p; }
1067 inline PCOLESTR SSW2COLE(PCWSTR p) { return p; }
1068 inline PCWSTR SSOLE2CW(PCOLESTR p){ return p; }
1071 // Above we've defined macros that look like MS' but all have
1072 // an 'SS' prefix. Now we need the real macros. We'll either
1073 // get them from the macros above or from MFC/ATL.
1075 #if defined (USES_CONVERSION)
1077 #define _NO_STDCONVERSION // just to be consistent
1083 #include <afxconv.h>
1084 #define _NO_STDCONVERSION // just to be consistent
1088 #define USES_CONVERSION SSCVT
1099 #define ocslen sslen
1100 #define ocscpy sscpy
1101 #define T2COLE SST2COLE
1102 #define OLE2CT SSOLE2CT
1103 #define T2OLE SST2COLE
1104 #define OLE2T SSOLE2CT
1105 #define A2OLE SSA2OLE
1106 #define OLE2A SSOLE2A
1107 #define W2OLE SSW2OLE
1108 #define OLE2W SSOLE2W
1109 #define A2COLE SSA2COLE
1110 #define OLE2CA SSOLE2CA
1111 #define W2COLE SSW2COLE
1112 #define OLE2CW SSOLE2CW
1114 #endif // #ifdef _MFC_VER
1115 #endif // #ifndef USES_CONVERSION
1116 #endif // #ifndef SS_NO_CONVERSION
1118 // Define ostring - generic name for std::basic_string<OLECHAR>
1120 #if !defined(ostring) && !defined(OSTRING_DEFINED)
1121 typedef std::basic_string<OLECHAR> ostring;
1122 #define OSTRING_DEFINED
1125 // StdCodeCvt when there's no conversion to be done
1126 template <typename T>
1127 inline T* StdCodeCvt(T* pDst, int nDst, const T* pSrc, int nSrc)
1129 int nChars = SSMIN(nSrc, nDst);
1134 std::basic_string<T>::traits_type::copy(pDst, pSrc, nChars);
1135 // std::char_traits<T>::copy(pDst, pSrc, nChars);
1136 pDst[nChars] = '\0';
1141 inline PSTR StdCodeCvt(PSTR pDst, int nDst, PCUSTR pSrc, int nSrc)
1143 return StdCodeCvt(pDst, nDst, (PCSTR)pSrc, nSrc);
1145 inline PUSTR StdCodeCvt(PUSTR pDst, int nDst, PCSTR pSrc, int nSrc)
1147 return (PUSTR)StdCodeCvt((PSTR)pDst, nDst, pSrc, nSrc);
1150 // Define tstring -- generic name for std::basic_string<TCHAR>
1152 #if !defined(tstring) && !defined(TSTRING_DEFINED)
1153 typedef std::basic_string<TCHAR> tstring;
1154 #define TSTRING_DEFINED
1157 // a very shorthand way of applying the fix for KB problem Q172398
1158 // (basic_string assignment bug)
1160 #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
1161 #define Q172398(x) (x).erase()
1166 // =============================================================================
1167 // INLINE FUNCTIONS ON WHICH CSTDSTRING RELIES
1169 // Usually for generic text mapping, we rely on preprocessor macro definitions
1170 // to map to string functions. However the CStdStr<> template cannot use
1171 // macro-based generic text mappings because its character types do not get
1172 // resolved until template processing which comes AFTER macro processing. In
1173 // other words, the preprocessor macro UNICODE is of little help to us in the
1176 // Therefore, to keep the CStdStr declaration simple, we have these inline
1177 // functions. The template calls them often. Since they are inline (and NOT
1178 // exported when this is built as a DLL), they will probably be resolved away
1181 // Without these functions, the CStdStr<> template would probably have to broken
1182 // out into two, almost identical classes. Either that or it would be a huge,
1183 // convoluted mess, with tons of "if" statements all over the place checking the
1184 // size of template parameter CT.
1185 // =============================================================================
1189 // --------------------------------------------------------------------------
1190 // Win32 GetStringTypeEx wrappers
1191 // --------------------------------------------------------------------------
1192 inline bool wsGetStringType(LCID lc, DWORD dwT, PCSTR pS, int nSize,
1195 return FALSE != GetStringTypeExA(lc, dwT, pS, nSize, pWd);
1197 inline bool wsGetStringType(LCID lc, DWORD dwT, PCWSTR pS, int nSize,
1200 return FALSE != GetStringTypeExW(lc, dwT, pS, nSize, pWd);
1204 template<typename CT>
1205 inline bool ssisspace (CT t)
1208 return wsGetStringType(GetThreadLocale(), CT_CTYPE1, &t, 1, &toYourMother)
1209 && 0 != (C1_BLANK & toYourMother);
1214 // If they defined SS_NO_REFCOUNT, then we must convert all assignments
1216 #if defined (_MSC_VER) && (_MSC_VER < 1300)
1217 #ifdef SS_NO_REFCOUNT
1218 #define SSREF(x) (x).c_str()
1220 #define SSREF(x) (x)
1223 #define SSREF(x) (x)
1226 // -----------------------------------------------------------------------------
1227 // sslen: strlen/wcslen wrappers
1228 // -----------------------------------------------------------------------------
1229 template<typename CT> inline int sslen(const CT* pT)
1231 return 0 == pT ? 0 : (int)std::basic_string<CT>::traits_type::length(pT);
1232 // return 0 == pT ? 0 : std::char_traits<CT>::length(pT);
1234 inline SS_NOTHROW int sslen(const std::string& s)
1236 return static_cast<int>(s.length());
1238 inline SS_NOTHROW int sslen(const std::wstring& s)
1240 return static_cast<int>(s.length());
1243 // -----------------------------------------------------------------------------
1244 // sstolower/sstoupper -- convert characters to upper/lower case
1245 // -----------------------------------------------------------------------------
1248 inline char sstoupper(char ch) { return (char)::toupper(ch); }
1249 inline wchar_t sstoupper(wchar_t ch){ return (wchar_t)::towupper(ch); }
1250 inline char sstolower(char ch) { return (char)::tolower(ch); }
1251 inline wchar_t sstolower(wchar_t ch){ return (wchar_t)::tolower(ch); }
1253 template<typename CT>
1254 inline CT sstolower(const CT& t, const std::locale& loc = std::locale())
1256 return std::tolower<CT>(t, loc);
1258 template<typename CT>
1259 inline CT sstoupper(const CT& t, const std::locale& loc = std::locale())
1261 return std::toupper<CT>(t, loc);
1265 // -----------------------------------------------------------------------------
1266 // ssasn: assignment functions -- assign "sSrc" to "sDst"
1267 // -----------------------------------------------------------------------------
1268 typedef std::string::size_type SS_SIZETYPE; // just for shorthand, really
1269 typedef std::string::pointer SS_PTRTYPE;
1270 typedef std::wstring::size_type SW_SIZETYPE;
1271 typedef std::wstring::pointer SW_PTRTYPE;
1274 template <typename T>
1275 inline void ssasn(std::basic_string<T>& sDst, const std::basic_string<T>& sSrc)
1277 if ( sDst.c_str() != sSrc.c_str() )
1280 sDst.assign(SSREF(sSrc));
1283 template <typename T>
1284 inline void ssasn(std::basic_string<T>& sDst, const T *pA)
1286 // Watch out for NULLs, as always.
1293 // If pA actually points to part of sDst, we must NOT erase(), but
1294 // rather take a substring
1296 else if ( pA >= sDst.c_str() && pA <= sDst.c_str() + sDst.size() )
1298 sDst =sDst.substr(static_cast<typename std::basic_string<T>::size_type>(pA-sDst.c_str()));
1301 // Otherwise (most cases) apply the assignment bug fix, if applicable
1302 // and do the assignment
1310 inline void ssasn(std::string& sDst, const std::wstring& sSrc)
1318 int nDst = static_cast<int>(sSrc.size());
1320 // In MBCS builds, pad the buffer to account for the possibility of
1321 // some 3 byte characters. Not perfect but should get most cases.
1324 // In MBCS builds, we don't know how long the destination string will be.
1325 nDst = static_cast<int>(static_cast<double>(nDst) * 1.3);
1326 sDst.resize(nDst+1);
1327 PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst,
1328 sSrc.c_str(), static_cast<int>(sSrc.size()));
1329 sDst.resize(sslen(szCvt));
1331 sDst.resize(nDst+1);
1332 StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst,
1333 sSrc.c_str(), static_cast<int>(sSrc.size()));
1334 sDst.resize(sSrc.size());
1338 inline void ssasn(std::string& sDst, PCWSTR pW)
1340 int nSrc = sslen(pW);
1343 int nSrc = sslen(pW);
1346 // In MBCS builds, pad the buffer to account for the possibility of
1347 // some 3 byte characters. Not perfect but should get most cases.
1350 nDst = static_cast<int>(static_cast<double>(nDst) * 1.3);
1351 // In MBCS builds, we don't know how long the destination string will be.
1352 sDst.resize(nDst + 1);
1353 PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst,
1355 sDst.resize(sslen(szCvt));
1357 sDst.resize(nDst + 1);
1358 StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()), nDst, pW, nSrc);
1367 inline void ssasn(std::string& sDst, const int nNull)
1374 inline void ssasn(std::wstring& sDst, const std::string& sSrc)
1382 int nSrc = static_cast<int>(sSrc.size());
1385 sDst.resize(nSrc+1);
1386 PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()), nDst,
1387 sSrc.c_str(), nSrc);
1389 sDst.resize(sslen(szCvt));
1392 inline void ssasn(std::wstring& sDst, PCSTR pA)
1394 int nSrc = sslen(pA);
1403 sDst.resize(nDst+1);
1404 PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()), nDst, pA,
1407 sDst.resize(sslen(szCvt));
1410 inline void ssasn(std::wstring& sDst, const int nNull)
1417 // -----------------------------------------------------------------------------
1418 // ssadd: string object concatenation -- add second argument to first
1419 // -----------------------------------------------------------------------------
1420 inline void ssadd(std::string& sDst, const std::wstring& sSrc)
1422 int nSrc = static_cast<int>(sSrc.size());
1426 int nDst = static_cast<int>(sDst.size());
1429 // In MBCS builds, pad the buffer to account for the possibility of
1430 // some 3 byte characters. Not perfect but should get most cases.
1433 nAdd = static_cast<int>(static_cast<double>(nAdd) * 1.3);
1434 sDst.resize(nDst+nAdd+1);
1435 PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst),
1436 nAdd, sSrc.c_str(), nSrc);
1437 sDst.resize(nDst + sslen(szCvt));
1439 sDst.resize(nDst+nAdd+1);
1440 StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst), nAdd, sSrc.c_str(), nSrc);
1441 sDst.resize(nDst + nAdd);
1445 template <typename T>
1446 inline void ssadd(typename std::basic_string<T>& sDst, const typename std::basic_string<T>& sSrc)
1450 inline void ssadd(std::string& sDst, PCWSTR pW)
1452 int nSrc = sslen(pW);
1455 int nDst = static_cast<int>(sDst.size());
1459 nAdd = static_cast<int>(static_cast<double>(nAdd) * 1.3);
1460 sDst.resize(nDst + nAdd + 1);
1461 PCSTR szCvt = StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst),
1463 sDst.resize(nDst + sslen(szCvt));
1465 sDst.resize(nDst + nAdd + 1);
1466 StdCodeCvt(const_cast<SS_PTRTYPE>(sDst.data()+nDst), nAdd, pW, nSrc);
1467 sDst.resize(nDst + nSrc);
1471 template <typename T>
1472 inline void ssadd(typename std::basic_string<T>& sDst, const T *pA)
1476 // If the string being added is our internal string or a part of our
1477 // internal string, then we must NOT do any reallocation without
1478 // first copying that string to another object (since we're using a
1481 if ( pA >= sDst.c_str() && pA <= sDst.c_str()+sDst.length())
1483 if ( sDst.capacity() <= sDst.size()+sslen(pA) )
1484 sDst.append(std::basic_string<T>(pA));
1494 inline void ssadd(std::wstring& sDst, const std::string& sSrc)
1496 if ( !sSrc.empty() )
1498 int nSrc = static_cast<int>(sSrc.size());
1499 int nDst = static_cast<int>(sDst.size());
1501 sDst.resize(nDst + nSrc + 1);
1503 PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst),
1504 nSrc, sSrc.c_str(), nSrc+1);
1505 sDst.resize(nDst + sslen(szCvt));
1507 StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst), nSrc, sSrc.c_str(), nSrc+1);
1508 sDst.resize(nDst + nSrc);
1512 inline void ssadd(std::wstring& sDst, PCSTR pA)
1514 int nSrc = sslen(pA);
1518 int nDst = static_cast<int>(sDst.size());
1520 sDst.resize(nDst + nSrc + 1);
1522 PCWSTR szCvt = StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst),
1524 sDst.resize(nDst + sslen(szCvt));
1526 StdCodeCvt(const_cast<SW_PTRTYPE>(sDst.data()+nDst), nSrc, pA, nSrc+1);
1527 sDst.resize(nDst + nSrc);
1532 // -----------------------------------------------------------------------------
1533 // sscmp: comparison (case sensitive, not affected by locale)
1534 // -----------------------------------------------------------------------------
1535 template<typename CT>
1536 inline int sscmp(const CT* pA1, const CT* pA2)
1545 } while ( (f) && (f == l) );
1547 return (int)(f - l);
1550 // -----------------------------------------------------------------------------
1551 // ssicmp: comparison (case INsensitive, not affected by locale)
1552 // -----------------------------------------------------------------------------
1553 template<typename CT>
1554 inline int ssicmp(const CT* pA1, const CT* pA2)
1556 // Using the "C" locale = "not affected by locale"
1558 std::locale loc = std::locale::classic();
1559 const std::ctype<CT>& ct = SS_USE_FACET(loc, std::ctype<CT>);
1565 f = ct.tolower(*(pA1++));
1566 l = ct.tolower(*(pA2++));
1567 } while ( (f) && (f == l) );
1569 return (int)(f - l);
1572 // -----------------------------------------------------------------------------
1573 // ssupr/sslwr: Uppercase/Lowercase conversion functions
1574 // -----------------------------------------------------------------------------
1576 template<typename CT>
1577 inline void sslwr(CT* pT, size_t nLen, const std::locale& loc=std::locale())
1579 SS_USE_FACET(loc, std::ctype<CT>).tolower(pT, pT+nLen);
1581 template<typename CT>
1582 inline void ssupr(CT* pT, size_t nLen, const std::locale& loc=std::locale())
1584 SS_USE_FACET(loc, std::ctype<CT>).toupper(pT, pT+nLen);
1587 // -----------------------------------------------------------------------------
1588 // vsprintf/vswprintf or _vsnprintf/_vsnwprintf equivalents. In standard
1589 // builds we can't use _vsnprintf/_vsnwsprintf because they're MS extensions.
1591 // -----------------------------------------------------------------------------
1592 // Borland's headers put some ANSI "C" functions in the 'std' namespace.
1593 // Promote them to the global namespace so we can use them here.
1595 #if defined(__BORLANDC__)
1596 using std::vsprintf;
1597 using std::vswprintf;
1600 // GNU is supposed to have vsnprintf and vsnwprintf. But only the newer
1601 // distributions do.
1603 #if defined(__GNUC__)
1605 inline int ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
1607 return vsnprintf(pA, nCount, pFmtA, vl);
1609 inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
1611 return vswprintf(pW, nCount, pFmtW, vl);
1614 // Microsofties can use
1615 #elif defined(_MSC_VER) && !defined(SS_ANSI)
1617 inline int ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
1619 return _vsnprintf(pA, nCount, pFmtA, vl);
1621 inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
1623 return _vsnwprintf(pW, nCount, pFmtW, vl);
1626 #elif defined (SS_DANGEROUS_FORMAT) // ignore buffer size parameter if needed?
1628 inline int ssvsprintf(PSTR pA, size_t /*nCount*/, PCSTR pFmtA, va_list vl)
1630 return vsprintf(pA, pFmtA, vl);
1633 inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
1635 // JMO: Some distributions of the "C" have a version of vswprintf that
1636 // takes 3 arguments (e.g. Microsoft, Borland, GNU). Others have a
1637 // version which takes 4 arguments (an extra "count" argument in the
1638 // second position. The best stab I can take at this so far is that if
1639 // you are NOT running with MS, Borland, or GNU, then I'll assume you
1640 // have the version that takes 4 arguments.
1642 // I'm sure that these checks don't catch every platform correctly so if
1643 // you get compiler errors on one of the lines immediately below, it's
1644 // probably because your implemntation takes a different number of
1645 // arguments. You can comment out the offending line (and use the
1646 // alternate version) or you can figure out what compiler flag to check
1647 // and add that preprocessor check in. Regardless, if you get an error
1648 // on these lines, I'd sure like to hear from you about it.
1650 // Thanks to Ronny Schulz for the SGI-specific checks here.
1652 // #if !defined(__MWERKS__) && !defined(__SUNPRO_CC_COMPAT) && !defined(__SUNPRO_CC)
1653 #if !defined(_MSC_VER) \
1654 && !defined (__BORLANDC__) \
1655 && !defined(__GNUC__) \
1658 return vswprintf(pW, nCount, pFmtW, vl);
1660 // suddenly with the current SGI 7.3 compiler there is no such function as
1661 // vswprintf and the substitute needs explicit casts to compile
1663 #elif defined(__sgi)
1666 return vsprintf( (char *)pW, (char *)pFmtW, vl);
1671 return vswprintf(pW, pFmtW, vl);
1679 // GOT COMPILER PROBLEMS HERE?
1680 // ---------------------------
1681 // Does your compiler choke on one or more of the following 2 functions? It
1682 // probably means that you don't have have either vsnprintf or vsnwprintf in
1683 // your version of the CRT. This is understandable since neither is an ANSI
1684 // "C" function. However it still leaves you in a dilemma. In order to make
1685 // this code build, you're going to have to to use some non-length-checked
1686 // formatting functions that every CRT has: vsprintf and vswprintf.
1688 // This is very dangerous. With the proper erroneous (or malicious) code, it
1689 // can lead to buffer overlows and crashing your PC. Use at your own risk
1690 // In order to use them, just #define SS_DANGEROUS_FORMAT at the top of
1693 // Even THEN you might not be all the way home due to some non-conforming
1694 // distributions. More on this in the comments below.
1696 inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
1699 return _vsnprintf(pA, nCount, pFmtA, vl);
1701 return vsnprintf(pA, nCount, pFmtA, vl);
1704 inline int ssnprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
1707 return _vsnwprintf(pW, nCount, pFmtW, vl);
1709 return vswprintf(pW, nCount, pFmtW, vl);
1716 // -----------------------------------------------------------------------------
1717 // ssload: Type safe, overloaded ::LoadString wrappers
1718 // There is no equivalent of these in non-Win32-specific builds. However, I'm
1719 // thinking that with the message facet, there might eventually be one
1720 // -----------------------------------------------------------------------------
1721 #if defined (SS_WIN32) && !defined(SS_ANSI)
1722 inline int ssload(HMODULE hInst, UINT uId, PSTR pBuf, int nMax)
1724 return ::LoadStringA(hInst, uId, pBuf, nMax);
1726 inline int ssload(HMODULE hInst, UINT uId, PWSTR pBuf, int nMax)
1728 return ::LoadStringW(hInst, uId, pBuf, nMax);
1730 #if defined ( _MSC_VER ) && ( _MSC_VER >= 1500 )
1731 inline int ssload(HMODULE hInst, UINT uId, uint16_t *pBuf, int nMax)
1735 inline int ssload(HMODULE hInst, UINT uId, uint32_t *pBuf, int nMax)
1743 // -----------------------------------------------------------------------------
1744 // sscoll/ssicoll: Collation wrappers
1745 // Note -- with MSVC I have reversed the arguments order here because the
1746 // functions appear to return the opposite of what they should
1747 // -----------------------------------------------------------------------------
1748 #ifndef SS_NO_LOCALE
1749 template <typename CT>
1750 inline int sscoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)
1752 const std::collate<CT>& coll =
1753 SS_USE_FACET(std::locale(), std::collate<CT>);
1755 return coll.compare(sz2, sz2+nLen2, sz1, sz1+nLen1);
1757 template <typename CT>
1758 inline int ssicoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2)
1760 const std::locale loc;
1761 const std::collate<CT>& coll = SS_USE_FACET(loc, std::collate<CT>);
1763 // Some implementations seem to have trouble using the collate<>
1764 // facet typedefs so we'll just default to basic_string and hope
1765 // that's what the collate facet uses (which it generally should)
1767 // std::collate<CT>::string_type s1(sz1);
1768 // std::collate<CT>::string_type s2(sz2);
1769 const std::basic_string<CT> sEmpty;
1770 std::basic_string<CT> s1(sz1 ? sz1 : sEmpty.c_str());
1771 std::basic_string<CT> s2(sz2 ? sz2 : sEmpty.c_str());
1773 sslwr(const_cast<CT*>(s1.c_str()), nLen1, loc);
1774 sslwr(const_cast<CT*>(s2.c_str()), nLen2, loc);
1775 return coll.compare(s2.c_str(), s2.c_str()+nLen2,
1776 s1.c_str(), s1.c_str()+nLen1);
1781 // -----------------------------------------------------------------------------
1782 // ssfmtmsg: FormatMessage equivalents. Needed because I added a CString facade
1783 // Again -- no equivalent of these on non-Win32 builds but their might one day
1784 // be one if the message facet gets implemented
1785 // -----------------------------------------------------------------------------
1786 #if defined (SS_WIN32) && !defined(SS_ANSI)
1787 inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,
1788 DWORD dwLangId, PSTR pBuf, DWORD nSize,
1791 return FormatMessageA(dwFlags, pSrc, dwMsgId, dwLangId,
1792 pBuf, nSize,vlArgs);
1794 inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId,
1795 DWORD dwLangId, PWSTR pBuf, DWORD nSize,
1798 return FormatMessageW(dwFlags, pSrc, dwMsgId, dwLangId,
1799 pBuf, nSize,vlArgs);
1806 // FUNCTION: sscpy. Copies up to 'nMax' characters from pSrc to pDst.
1807 // -----------------------------------------------------------------------------
1809 // inline int sscpy(PSTR pDst, PCSTR pSrc, int nMax=-1);
1810 // inline int sscpy(PUSTR pDst, PCSTR pSrc, int nMax=-1)
1811 // inline int sscpy(PSTR pDst, PCWSTR pSrc, int nMax=-1);
1812 // inline int sscpy(PWSTR pDst, PCWSTR pSrc, int nMax=-1);
1813 // inline int sscpy(PWSTR pDst, PCSTR pSrc, int nMax=-1);
1816 // This function is very much (but not exactly) like strcpy. These
1817 // overloads simplify copying one C-style string into another by allowing
1818 // the caller to specify two different types of strings if necessary.
1820 // The strings must NOT overlap
1822 // "Character" is expressed in terms of the destination string, not
1823 // the source. If no 'nMax' argument is supplied, then the number of
1824 // characters copied will be sslen(pSrc). A NULL terminator will
1825 // also be added so pDst must actually be big enough to hold nMax+1
1826 // characters. The return value is the number of characters copied,
1827 // not including the NULL terminator.
1830 // pSrc - the string to be copied FROM. May be a char based string, an
1831 // MBCS string (in Win32 builds) or a wide string (wchar_t).
1832 // pSrc - the string to be copied TO. Also may be either MBCS or wide
1833 // nMax - the maximum number of characters to be copied into szDest. Note
1834 // that this is expressed in whatever a "character" means to pDst.
1835 // If pDst is a wchar_t type string than this will be the maximum
1836 // number of wchar_ts that my be copied. The pDst string must be
1837 // large enough to hold least nMaxChars+1 characters.
1838 // If the caller supplies no argument for nMax this is a signal to
1839 // the routine to copy all the characters in pSrc, regardless of
1842 // RETURN VALUE: none
1843 // -----------------------------------------------------------------------------
1845 template<typename CT1, typename CT2>
1846 inline int sscpycvt(CT1* pDst, const CT2* pSrc, int nMax)
1848 // Note -- we assume pDst is big enough to hold pSrc. If not, we're in
1849 // big trouble. No bounds checking. Caveat emptor.
1851 int nSrc = sslen(pSrc);
1853 const CT1* szCvt = StdCodeCvt(pDst, nMax, pSrc, nSrc);
1855 // If we're copying the same size characters, then all the "code convert"
1856 // just did was basically memcpy so the #of characters copied is the same
1857 // as the number requested. I should probably specialize this function
1858 // template to achieve this purpose as it is silly to do a runtime check
1859 // of a fact known at compile time. I'll get around to it.
1861 return sslen(szCvt);
1864 template<typename T>
1865 inline int sscpycvt(T* pDst, const T* pSrc, int nMax)
1868 for (; nCount > 0 && *pSrc; ++pSrc, ++pDst, --nCount)
1869 std::basic_string<T>::traits_type::assign(*pDst, *pSrc);
1872 return nMax - nCount;
1875 inline int sscpycvt(PWSTR pDst, PCSTR pSrc, int nMax)
1877 // Note -- we assume pDst is big enough to hold pSrc. If not, we're in
1878 // big trouble. No bounds checking. Caveat emptor.
1880 const PWSTR szCvt = StdCodeCvt(pDst, nMax, pSrc, nMax);
1881 return sslen(szCvt);
1884 template<typename CT1, typename CT2>
1885 inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax, int nLen)
1887 return sscpycvt(pDst, pSrc, SSMIN(nMax, nLen));
1889 template<typename CT1, typename CT2>
1890 inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax)
1892 return sscpycvt(pDst, pSrc, SSMIN(nMax, sslen(pSrc)));
1894 template<typename CT1, typename CT2>
1895 inline int sscpy(CT1* pDst, const CT2* pSrc)
1897 return sscpycvt(pDst, pSrc, sslen(pSrc));
1899 template<typename CT1, typename CT2>
1900 inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc, int nMax)
1902 return sscpycvt(pDst, sSrc.c_str(), SSMIN(nMax, (int)sSrc.length()));
1904 template<typename CT1, typename CT2>
1905 inline int sscpy(CT1* pDst, const std::basic_string<CT2>& sSrc)
1907 return sscpycvt(pDst, sSrc.c_str(), (int)sSrc.length());
1910 #ifdef SS_INC_COMDEF
1911 template<typename CT1>
1912 inline int sscpy(CT1* pDst, const _bstr_t& bs, int nMax)
1914 return sscpycvt(pDst, static_cast<PCOLESTR>(bs),
1915 SSMIN(nMax, static_cast<int>(bs.length())));
1917 template<typename CT1>
1918 inline int sscpy(CT1* pDst, const _bstr_t& bs)
1920 return sscpy(pDst, bs, static_cast<int>(bs.length()));
1925 // -----------------------------------------------------------------------------
1926 // Functional objects for changing case. They also let you pass locales
1927 // -----------------------------------------------------------------------------
1930 template<typename CT>
1931 struct SSToUpper : public std::unary_function<CT, CT>
1933 inline CT operator()(const CT& t) const
1935 return sstoupper(t);
1938 template<typename CT>
1939 struct SSToLower : public std::unary_function<CT, CT>
1941 inline CT operator()(const CT& t) const
1943 return sstolower(t);
1947 template<typename CT>
1948 struct SSToUpper : public std::binary_function<CT, std::locale, CT>
1950 inline CT operator()(const CT& t, const std::locale& loc) const
1952 return sstoupper<CT>(t, loc);
1955 template<typename CT>
1956 struct SSToLower : public std::binary_function<CT, std::locale, CT>
1958 inline CT operator()(const CT& t, const std::locale& loc) const
1960 return sstolower<CT>(t, loc);
1965 // This struct is used for TrimRight() and TrimLeft() function implementations.
1966 //template<typename CT>
1967 //struct NotSpace : public std::unary_function<CT, bool>
1969 // const std::locale& loc;
1970 // inline NotSpace(const std::locale& locArg) : loc(locArg) {}
1971 // inline bool operator() (CT t) { return !std::isspace(t, loc); }
1973 template<typename CT>
1974 struct NotSpace : public std::unary_function<CT, bool>
1977 // Note -- using std::isspace in a COM DLL gives us access violations
1978 // because it causes the dynamic addition of a function to be called
1979 // when the library shuts down. Unfortunately the list is maintained
1980 // in DLL memory but the function is in static memory. So the COM DLL
1981 // goes away along with the function that was supposed to be called,
1982 // and then later when the DLL CRT shuts down it unloads the list and
1983 // tries to call the long-gone function.
1984 // This is DinkumWare's implementation problem. If you encounter this
1985 // problem, you may replace the calls here with good old isspace() and
1986 // iswspace() from the CRT unless they specify SS_ANSI
1990 bool operator() (CT t) const { return !ssisspace(t); }
1993 const std::locale loc;
1994 NotSpace(const std::locale& locArg=std::locale()) : loc(locArg) {}
1995 bool operator() (CT t) const { return !std::isspace(t, loc); }
2002 // Now we can define the template (finally!)
2003 // =============================================================================
2004 // TEMPLATE: CStdStr
2005 // template<typename CT> class CStdStr : public std::basic_string<CT>
2008 // This template derives from basic_string<CT> and adds some MFC CString-
2009 // like functionality
2011 // Basically, this is my attempt to make Standard C++ library strings as
2012 // easy to use as the MFC CString class.
2014 // Note that although this is a template, it makes the assumption that the
2015 // template argument (CT, the character type) is either char or wchar_t.
2016 // =============================================================================
2018 //#define CStdStr _SS // avoid compiler warning 4786
2020 // template<typename ARG> ARG& FmtArg(ARG& arg) { return arg; }
2021 // PCSTR FmtArg(const std::string& arg) { return arg.c_str(); }
2022 // PCWSTR FmtArg(const std::wstring& arg) { return arg.c_str(); }
2024 template<typename ARG>
2027 explicit FmtArg(const ARG& arg) : a_(arg) {}
2028 const ARG& operator()() const { return a_; }
2031 FmtArg& operator=(const FmtArg&) { return *this; }
2034 template<typename CT>
2035 class CStdStr : public std::basic_string<CT>
2037 // Typedefs for shorter names. Using these names also appears to help
2038 // us avoid some ambiguities that otherwise arise on some platforms
2040 #define MYBASE std::basic_string<CT> // my base class
2041 //typedef typename std::basic_string<CT> MYBASE; // my base class
2042 typedef CStdStr<CT> MYTYPE; // myself
2043 typedef typename MYBASE::const_pointer PCMYSTR; // PCSTR or PCWSTR
2044 typedef typename MYBASE::pointer PMYSTR; // PSTR or PWSTR
2045 typedef typename MYBASE::iterator MYITER; // my iterator type
2046 typedef typename MYBASE::const_iterator MYCITER; // you get the idea...
2047 typedef typename MYBASE::reverse_iterator MYRITER;
2048 typedef typename MYBASE::size_type MYSIZE;
2049 typedef typename MYBASE::value_type MYVAL;
2050 typedef typename MYBASE::allocator_type MYALLOC;
2053 // shorthand conversion from PCTSTR to string resource ID
2054 #define SSRES(pctstr) LOWORD(reinterpret_cast<unsigned long>(pctstr))
2056 bool TryLoad(const void* pT)
2058 bool bLoaded = false;
2060 #if defined(SS_WIN32) && !defined(SS_ANSI)
2061 if ( ( pT != NULL ) && SS_IS_INTRESOURCE(pT) )
2063 UINT nId = LOWORD(reinterpret_cast<unsigned long>(pT));
2064 if ( !LoadString(nId) )
2066 TRACE(_T("Can't load string %u\n"), SSRES(pT));
2076 // CStdStr inline constructors
2081 CStdStr(const MYTYPE& str) : MYBASE(SSREF(str))
2085 CStdStr(const std::string& str)
2087 ssasn(*this, SSREF(str));
2090 CStdStr(const std::wstring& str)
2092 ssasn(*this, SSREF(str));
2095 CStdStr(PCMYSTR pT, MYSIZE n) : MYBASE(pT, n)
2102 *this = reinterpret_cast<PCSTR>(pU);
2126 CStdStr(uint16_t* pW)
2136 CStdStr(uint32_t* pW)
2146 CStdStr(MYCITER first, MYCITER last)
2147 : MYBASE(first, last)
2151 CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC& al=MYALLOC())
2152 : MYBASE(nSize, ch, al)
2156 #ifdef SS_INC_COMDEF
2157 CStdStr(const _bstr_t& bstr)
2159 if ( bstr.length() > 0 )
2160 this->append(static_cast<PCMYSTR>(bstr), bstr.length());
2164 // CStdStr inline assignment operators -- the ssasn function now takes care
2165 // of fixing the MSVC assignment bug (see knowledge base article Q172398).
2166 MYTYPE& operator=(const MYTYPE& str)
2172 MYTYPE& operator=(const std::string& str)
2178 MYTYPE& operator=(const std::wstring& str)
2184 MYTYPE& operator=(PCSTR pA)
2190 MYTYPE& operator=(PCWSTR pW)
2197 MYTYPE& operator=(PCUSTR pU)
2199 ssasn(*this, reinterpret_cast<PCSTR>(pU));
2204 MYTYPE& operator=(uint16_t* pA)
2210 MYTYPE& operator=(uint32_t* pA)
2216 MYTYPE& operator=(CT t)
2223 #ifdef SS_INC_COMDEF
2224 MYTYPE& operator=(const _bstr_t& bstr)
2226 if ( bstr.length() > 0 )
2228 this->assign(static_cast<PCMYSTR>(bstr), bstr.length());
2240 // Overloads also needed to fix the MSVC assignment bug (KB: Q172398)
2241 // *** Thanks to Pete The Plumber for catching this one ***
2242 // They also are compiled if you have explicitly turned off refcounting
2243 #if ( defined(_MSC_VER) && ( _MSC_VER < 1200 ) ) || defined(SS_NO_REFCOUNT)
2245 MYTYPE& assign(const MYTYPE& str)
2248 sscpy(GetBuffer(str.size()+1), SSREF(str));
2249 this->ReleaseBuffer(str.size());
2253 MYTYPE& assign(const MYTYPE& str, MYSIZE nStart, MYSIZE nChars)
2255 // This overload of basic_string::assign is supposed to assign up to
2256 // <nChars> or the NULL terminator, whichever comes first. Since we
2257 // are about to call a less forgiving overload (in which <nChars>
2258 // must be a valid length), we must adjust the length here to a safe
2259 // value. Thanks to Ullrich Poll�hne for catching this bug
2261 nChars = SSMIN(nChars, str.length() - nStart);
2262 MYTYPE strTemp(str.c_str()+nStart, nChars);
2264 this->assign(strTemp);
2268 MYTYPE& assign(const MYBASE& str)
2274 MYTYPE& assign(const MYBASE& str, MYSIZE nStart, MYSIZE nChars)
2276 // This overload of basic_string::assign is supposed to assign up to
2277 // <nChars> or the NULL terminator, whichever comes first. Since we
2278 // are about to call a less forgiving overload (in which <nChars>
2279 // must be a valid length), we must adjust the length here to a safe
2280 // value. Thanks to Ullrich Poll�hne for catching this bug
2282 nChars = SSMIN(nChars, str.length() - nStart);
2284 // Watch out for assignment to self
2288 MYTYPE strTemp(str.c_str() + nStart, nChars);
2289 static_cast<MYBASE*>(this)->assign(strTemp);
2294 static_cast<MYBASE*>(this)->assign(str.c_str()+nStart, nChars);
2299 MYTYPE& assign(const CT* pC, MYSIZE nChars)
2301 // Q172398 only fix -- erase before assigning, but not if we're
2302 // assigning from our own buffer
2304 #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
2305 if ( !this->empty() &&
2306 ( pC < this->data() || pC > this->data() + this->capacity() ) )
2312 static_cast<MYBASE*>(this)->assign(pC, nChars);
2316 MYTYPE& assign(MYSIZE nChars, MYVAL val)
2319 static_cast<MYBASE*>(this)->assign(nChars, val);
2323 MYTYPE& assign(const CT* pT)
2325 return this->assign(pT, MYBASE::traits_type::length(pT));
2328 MYTYPE& assign(MYCITER iterFirst, MYCITER iterLast)
2330 #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
2331 // Q172398 fix. don't call erase() if we're assigning from ourself
2332 if ( iterFirst < this->begin() ||
2333 iterFirst > this->begin() + this->size() )
2338 this->replace(this->begin(), this->end(), iterFirst, iterLast);
2344 // -------------------------------------------------------------------------
2345 // CStdStr inline concatenation.
2346 // -------------------------------------------------------------------------
2347 MYTYPE& operator+=(const MYTYPE& str)
2353 MYTYPE& operator+=(const std::string& str)
2359 MYTYPE& operator+=(const std::wstring& str)
2365 MYTYPE& operator+=(PCSTR pA)
2371 MYTYPE& operator+=(PCWSTR pW)
2377 MYTYPE& operator+=(uint16_t* pW)
2383 MYTYPE& operator+=(uint32_t* pW)
2389 MYTYPE& operator+=(CT t)
2394 #ifdef SS_INC_COMDEF // if we have _bstr_t, define a += for it too.
2395 MYTYPE& operator+=(const _bstr_t& bstr)
2397 return this->operator+=(static_cast<PCMYSTR>(bstr));
2401 // -------------------------------------------------------------------------
2402 // CStdStr -- Direct access to character buffer. In the MS' implementation,
2403 // the at() function that we use here also calls _Freeze() providing us some
2404 // protection from multithreading problems associated with ref-counting.
2405 // In VC 7 and later, of course, the ref-counting stuff is gone.
2406 // -------------------------------------------------------------------------
2408 CT* GetBuf(int nMinLen=-1)
2410 if ( static_cast<int>(this->size()) < nMinLen )
2411 this->resize(static_cast<MYSIZE>(nMinLen));
2413 return this->empty() ? const_cast<CT*>(this->data()) : &(this->at(0));
2416 CT* SetBuf(int nLen)
2418 nLen = ( nLen > 0 ? nLen : 0 );
2419 if ( this->capacity() < 1 && nLen == 0 )
2422 this->resize(static_cast<MYSIZE>(nLen));
2423 return const_cast<CT*>(this->data());
2425 void RelBuf(int nNewLen=-1)
2427 this->resize(static_cast<MYSIZE>(nNewLen > -1 ? nNewLen :
2428 sslen(this->c_str())));
2431 void BufferRel() { RelBuf(); } // backwards compatability
2432 CT* Buffer() { return GetBuf(); } // backwards compatability
2433 CT* BufferSet(int nLen) { return SetBuf(nLen);}// backwards compatability
2435 bool Equals(const CT* pT, bool bUseCase=false) const
2437 return 0 == (bUseCase ? this->compare(pT) : ssicmp(this->c_str(), pT));
2440 // -------------------------------------------------------------------------
2441 // FUNCTION: CStdStr::Load
2443 // Loads string from resource specified by nID
2446 // nID - resource Identifier. Purely a Win32 thing in this case
2449 // true if successful, false otherwise
2450 // -------------------------------------------------------------------------
2454 bool Load(UINT nId, HMODULE hModule=NULL)
2456 bool bLoaded = false; // set to true of we succeed.
2458 #ifdef _MFC_VER // When in Rome (or MFC land)...
2460 // If they gave a resource handle, use it. Note - this is archaic
2461 // and not really what I would recommend. But then again, in MFC
2462 // land, you ought to be using CString for resources anyway since
2463 // it walks the resource chain for you.
2465 HMODULE hModuleOld = NULL;
2467 if ( NULL != hModule )
2469 hModuleOld = AfxGetResourceHandle();
2470 AfxSetResourceHandle(hModule);
2473 // ...load the string
2476 bLoaded = FALSE != strRes.LoadString(nId);
2478 // ...and if we set the resource handle, restore it.
2480 if ( NULL != hModuleOld )
2481 AfxSetResourceHandle(hModule);
2486 #else // otherwise make our own hackneyed version of CString's Load
2488 // Get the resource name and module handle
2490 if ( NULL == hModule )
2491 hModule = GetResourceHandle();
2493 PCTSTR szName = MAKEINTRESOURCE((nId>>4)+1); // lifted
2496 // No sense continuing if we can't find the resource
2498 HRSRC hrsrc = ::FindResource(hModule, szName, RT_STRING);
2500 if ( NULL == hrsrc )
2502 TRACE(_T("Cannot find resource %d: 0x%X"), nId, ::GetLastError());
2504 else if ( 0 == (dwSize = ::SizeofResource(hModule, hrsrc) / sizeof(CT)))
2506 TRACE(_T("Cant get size of resource %d 0x%X\n"),nId,GetLastError());
2510 bLoaded = 0 != ssload(hModule, nId, GetBuf(dwSize), dwSize);
2514 #endif // #ifdef _MFC_VER
2517 TRACE(_T("String not loaded 0x%X\n"), ::GetLastError());
2522 #endif // #ifdef SS_ANSI
2524 // -------------------------------------------------------------------------
2525 // CString Facade Functions:
2527 // The following methods are intended to allow you to use this class as a
2528 // near drop-in replacement for CString.
2529 // -------------------------------------------------------------------------
2531 BSTR AllocSysString() const
2535 return ::SysAllocString(os.c_str());
2539 #ifndef SS_NO_LOCALE
2540 int Collate(PCMYSTR szThat) const
2542 return sscoll(this->c_str(), this->length(), szThat, sslen(szThat));
2545 int CollateNoCase(PCMYSTR szThat) const
2547 return ssicoll(this->c_str(), this->length(), szThat, sslen(szThat));
2550 int FindOneOf(PCMYSTR szCharSet) const
2552 MYSIZE nIdx = this->find_first_of(szCharSet);
2553 return static_cast<int>(MYBASE::npos == nIdx ? -1 : nIdx);
2557 void FormatMessage(PCMYSTR szFormat, ...) throw(std::exception)
2560 va_start(argList, szFormat);
2562 if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
2564 reinterpret_cast<PMYSTR>(&szTemp), 0, &argList) == 0 ||
2567 throw std::runtime_error("out of memory");
2574 void FormatMessage(UINT nFormatId, ...) throw(std::exception)
2577 VERIFY(sFormat.LoadString(nFormatId));
2579 va_start(argList, nFormatId);
2581 if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
2583 reinterpret_cast<PMYSTR>(&szTemp), 0, &argList) == 0 ||
2586 throw std::runtime_error("out of memory");
2594 // GetAllocLength -- an MSVC7 function but it costs us nothing to add it.
2596 int GetAllocLength()
2598 return static_cast<int>(this->capacity());
2601 // -------------------------------------------------------------------------
2602 // GetXXXX -- Direct access to character buffer
2603 // -------------------------------------------------------------------------
2604 CT* GetBuffer(int nMinLen=-1)
2606 return GetBuf(nMinLen);
2609 CT* GetBufferSetLength(int nLen)
2611 return BufferSet(nLen);
2615 bool LoadString(UINT nId)
2617 return this->Load(nId);
2623 std::reverse(this->begin(), this->end());
2626 void ReleaseBuffer(int nNewLen=-1)
2632 BSTR SetSysString(BSTR* pbstr) const
2636 if ( !::SysReAllocStringLen(pbstr, os.c_str(), os.length()) )
2637 throw std::runtime_error("out of memory");
2639 ASSERT(*pbstr != 0);
2644 MYTYPE SpanExcluding(PCMYSTR szCharSet) const
2646 MYSIZE pos = this->find_first_of(szCharSet);
2647 return pos == MYBASE::npos ? *this : Left(pos);
2650 MYTYPE SpanIncluding(PCMYSTR szCharSet) const
2652 MYSIZE pos = this->find_first_not_of(szCharSet);
2653 return pos == MYBASE::npos ? *this : Left(pos);
2656 #if defined SS_WIN32 && !defined(UNICODE) && !defined(SS_ANSI)
2658 // CString's OemToAnsi and AnsiToOem functions are available only in
2659 // Unicode builds. However since we're a template we also need a
2660 // runtime check of CT and a reinterpret_cast to account for the fact
2661 // that CStdStringW gets instantiated even in non-Unicode builds.
2665 if ( sizeof(CT) == sizeof(char) && !empty() )
2667 ::CharToOem(reinterpret_cast<PCSTR>(this->c_str()),
2668 reinterpret_cast<PSTR>(GetBuf()));
2678 if ( sizeof(CT) == sizeof(char) && !empty() )
2680 ::OemToChar(reinterpret_cast<PCSTR>(this->c_str()),
2681 reinterpret_cast<PSTR>(GetBuf()));
2696 this->assign(mt.c_str(), mt.size());
2699 // I have intentionally not implemented the following CString
2700 // functions. You cannot make them work without taking advantage
2701 // of implementation specific behavior. However if you absolutely
2702 // MUST have them, uncomment out these lines for "sort-of-like"
2703 // their behavior. You're on your own.
2705 // CT* LockBuffer() { return GetBuf(); }// won't really lock
2706 // void UnlockBuffer(); { } // why have UnlockBuffer w/o LockBuffer?
2708 // Array-indexing operators. Required because we defined an implicit cast
2709 // to operator const CT* (Thanks to Julian Selman for pointing this out)
2711 CT& operator[](int nIdx)
2713 return static_cast<MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
2716 const CT& operator[](int nIdx) const
2718 return static_cast<const MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
2721 CT& operator[](unsigned int nIdx)
2723 return static_cast<MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
2726 const CT& operator[](unsigned int nIdx) const
2728 return static_cast<const MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
2731 CT& operator[](unsigned long nIdx)
2733 return static_cast<MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
2736 const CT& operator[](unsigned long nIdx) const
2738 return static_cast<const MYBASE*>(this)->operator[](static_cast<MYSIZE>(nIdx));
2741 #ifndef SS_NO_IMPLICIT_CAST
2742 operator const CT*() const
2744 return this->c_str();
2748 // IStream related functions. Useful in IPersistStream implementations
2750 #ifdef SS_INC_COMDEF
2752 // struct SSSHDR - useful for non Std C++ persistence schemes.
2753 typedef struct SSSHDR
2757 } SSSHDR; // as in "Standard String Stream Header"
2759 #define SSSO_UNICODE 0x01 // the string is a wide string
2760 #define SSSO_COMPRESS 0x02 // the string is compressed
2762 // -------------------------------------------------------------------------
2763 // FUNCTION: StreamSize
2765 // Returns how many bytes it will take to StreamSave() this CStdString
2766 // object to an IStream.
2767 // -------------------------------------------------------------------------
2768 ULONG StreamSize() const
2770 // Control header plus string
2771 ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));
2772 return (this->size() * sizeof(CT)) + sizeof(SSSHDR);
2775 // -------------------------------------------------------------------------
2776 // FUNCTION: StreamSave
2778 // Saves this CStdString object to a COM IStream.
2779 // -------------------------------------------------------------------------
2780 HRESULT StreamSave(IStream* pStream) const
2782 ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));
2783 HRESULT hr = E_FAIL;
2784 ASSERT(pStream != 0);
2786 hdr.byCtrl = sizeof(CT) == 2 ? SSSO_UNICODE : 0;
2787 hdr.nChars = this->size();
2790 if ( FAILED(hr=pStream->Write(&hdr, sizeof(SSSHDR), 0)) )
2792 TRACE(_T("StreamSave: Cannot write control header, ERR=0x%X\n"),hr);
2796 ; // nothing to write
2798 else if ( FAILED(hr=pStream->Write(this->c_str(),
2799 this->size()*sizeof(CT), 0)) )
2801 TRACE(_T("StreamSave: Cannot write string to stream 0x%X\n"), hr);
2808 // -------------------------------------------------------------------------
2809 // FUNCTION: StreamLoad
2811 // This method loads the object from an IStream.
2812 // -------------------------------------------------------------------------
2813 HRESULT StreamLoad(IStream* pStream)
2815 ASSERT(pStream != 0);
2817 HRESULT hr = E_FAIL;
2819 if ( FAILED(hr=pStream->Read(&hdr, sizeof(SSSHDR), 0)) )
2821 TRACE(_T("StreamLoad: Cant read control header, ERR=0x%X\n"), hr);
2823 else if ( hdr.nChars > 0 )
2826 PMYSTR pMyBuf = BufferSet(hdr.nChars);
2828 // If our character size matches the character size of the string
2829 // we're trying to read, then we can read it directly into our
2830 // buffer. Otherwise, we have to read into an intermediate buffer
2833 if ( (hdr.byCtrl & SSSO_UNICODE) != 0 )
2835 ULONG nBytes = hdr.nChars * sizeof(wchar_t);
2836 if ( sizeof(CT) == sizeof(wchar_t) )
2838 if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) )
2839 TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
2843 PWSTR pBufW = reinterpret_cast<PWSTR>(_alloca((nBytes)+1));
2844 if ( FAILED(hr=pStream->Read(pBufW, nBytes, &nRead)) )
2845 TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
2847 sscpy(pMyBuf, pBufW, hdr.nChars);
2852 ULONG nBytes = hdr.nChars * sizeof(char);
2853 if ( sizeof(CT) == sizeof(char) )
2855 if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) )
2856 TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
2860 PSTR pBufA = reinterpret_cast<PSTR>(_alloca(nBytes));
2861 if ( FAILED(hr=pStream->Read(pBufA, hdr.nChars, &nRead)) )
2862 TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr);
2864 sscpy(pMyBuf, pBufA, hdr.nChars);
2874 #endif // #ifdef SS_INC_COMDEF
2878 // SetResourceHandle/GetResourceHandle. In MFC builds, these map directly
2879 // to AfxSetResourceHandle and AfxGetResourceHandle. In non-MFC builds they
2880 // point to a single static HINST so that those who call the member
2881 // functions that take resource IDs can provide an alternate HINST of a DLL
2882 // to search. This is not exactly the list of HMODULES that MFC provides
2883 // but it's better than nothing.
2886 static void SetResourceHandle(HMODULE hNew)
2888 AfxSetResourceHandle(hNew);
2890 static HMODULE GetResourceHandle()
2892 return AfxGetResourceHandle();
2895 static void SetResourceHandle(HMODULE hNew)
2897 SSResourceHandle() = hNew;
2899 static HMODULE GetResourceHandle()
2901 return SSResourceHandle();
2908 // -----------------------------------------------------------------------------
2909 // MSVC USERS: HOW TO EXPORT CSTDSTRING FROM A DLL
2911 // If you are using MS Visual C++ and you want to export CStdStringA and
2912 // CStdStringW from a DLL, then all you need to
2914 // 1. make sure that all components link to the same DLL version
2915 // of the CRT (not the static one).
2916 // 2. Uncomment the 3 lines of code below
2917 // 3. #define 2 macros per the instructions in MS KnowledgeBase
2918 // article Q168958. The macros are:
2920 // MACRO DEFINTION WHEN EXPORTING DEFINITION WHEN IMPORTING
2921 // ----- ------------------------ -------------------------
2922 // SSDLLEXP (nothing, just #define it) extern
2923 // SSDLLSPEC __declspec(dllexport) __declspec(dllimport)
2925 // Note that these macros must be available to ALL clients who want to
2926 // link to the DLL and use the class. If they
2928 // A word of advice: Don't bother.
2930 // Really, it is not necessary to export CStdString functions from a DLL. I
2931 // never do. In my projects, I do generally link to the DLL version of the
2932 // Standard C++ Library, but I do NOT attempt to export CStdString functions.
2933 // I simply include the header where it is needed and allow for the code
2936 // That redundancy is a lot less than you think. This class does most of its
2937 // work via the Standard C++ Library, particularly the base_class basic_string<>
2938 // member functions. Most of the functions here are small enough to be inlined
2939 // anyway. Besides, you'll find that in actual practice you use less than 1/2
2940 // of the code here, even in big projects and different modules will use as
2941 // little as 10% of it. That means a lot less functions actually get linked
2942 // your binaries. If you export this code from a DLL, it ALL gets linked in.
2944 // I've compared the size of the binaries from exporting vs NOT exporting. Take
2945 // my word for it -- exporting this code is not worth the hassle.
2947 // -----------------------------------------------------------------------------
2948 //#pragma warning(disable:4231) // non-standard extension ("extern template")
2949 // SSDLLEXP template class SSDLLSPEC CStdStr<char>;
2950 // SSDLLEXP template class SSDLLSPEC CStdStr<wchar_t>;
2953 // =============================================================================
2954 // END OF CStdStr INLINE FUNCTION DEFINITIONS
2955 // =============================================================================
2957 // Now typedef our class names based upon this humongous template
2959 typedef CStdStr<char> CStdStringA; // a better std::string
2960 typedef CStdStr<wchar_t> CStdStringW; // a better std::wstring
2961 typedef CStdStr<uint16_t> CStdString16; // a 16bit char string
2962 typedef CStdStr<uint32_t> CStdString32; // a 32bit char string
2963 typedef CStdStr<OLECHAR> CStdStringO; // almost always CStdStringW
2965 // -----------------------------------------------------------------------------
2966 // CStdStr addition functions defined as inline
2967 // -----------------------------------------------------------------------------
2970 inline CStdStringA operator+(const CStdStringA& s1, const CStdStringA& s2)
2972 CStdStringA sRet(SSREF(s1));
2976 inline CStdStringA operator+(const CStdStringA& s1, CStdStringA::value_type t)
2978 CStdStringA sRet(SSREF(s1));
2982 inline CStdStringA operator+(const CStdStringA& s1, PCSTR pA)
2984 CStdStringA sRet(SSREF(s1));
2988 inline CStdStringA operator+(PCSTR pA, const CStdStringA& sA)
2991 CStdStringA::size_type nObjSize = sA.size();
2992 CStdStringA::size_type nLitSize =
2993 static_cast<CStdStringA::size_type>(sslen(pA));
2995 sRet.reserve(nLitSize + nObjSize);
3002 inline CStdStringA operator+(const CStdStringA& s1, const CStdStringW& s2)
3004 return s1 + CStdStringA(s2);
3006 inline CStdStringW operator+(const CStdStringW& s1, const CStdStringW& s2)
3008 CStdStringW sRet(SSREF(s1));
3012 inline CStdStringA operator+(const CStdStringA& s1, PCWSTR pW)
3014 return s1 + CStdStringA(pW);
3018 inline CStdStringW operator+(PCWSTR pW, const CStdStringA& sA)
3020 return CStdStringW(pW) + CStdStringW(SSREF(sA));
3022 inline CStdStringW operator+(PCSTR pA, const CStdStringW& sW)
3024 return CStdStringW(pA) + sW;
3027 inline CStdStringA operator+(PCWSTR pW, const CStdStringA& sA)
3029 return CStdStringA(pW) + sA;
3031 inline CStdStringA operator+(PCSTR pA, const CStdStringW& sW)
3033 return pA + CStdStringA(sW);
3037 // ...Now the wide string versions.
3038 inline CStdStringW operator+(const CStdStringW& s1, CStdStringW::value_type t)
3040 CStdStringW sRet(SSREF(s1));
3044 inline CStdStringW operator+(const CStdStringW& s1, PCWSTR pW)
3046 CStdStringW sRet(SSREF(s1));
3050 inline CStdStringW operator+(PCWSTR pW, const CStdStringW& sW)
3053 CStdStringW::size_type nObjSize = sW.size();
3054 CStdStringA::size_type nLitSize =
3055 static_cast<CStdStringW::size_type>(sslen(pW));
3057 sRet.reserve(nLitSize + nObjSize);
3063 inline CStdStringW operator+(const CStdStringW& s1, const CStdStringA& s2)
3065 return s1 + CStdStringW(s2);
3067 inline CStdStringW operator+(const CStdStringW& s1, PCSTR pA)
3069 return s1 + CStdStringW(pA);
3073 // New-style format function is a template
3075 #ifdef SS_SAFE_FORMAT
3078 struct FmtArg<CStdStringA>
3080 explicit FmtArg(const CStdStringA& arg) : a_(arg) {}
3081 PCSTR operator()() const { return a_.c_str(); }
3082 const CStdStringA& a_;
3084 FmtArg<CStdStringA>& operator=(const FmtArg<CStdStringA>&) { return *this; }
3087 struct FmtArg<CStdStringW>
3089 explicit FmtArg(const CStdStringW& arg) : a_(arg) {}
3090 PCWSTR operator()() const { return a_.c_str(); }
3091 const CStdStringW& a_;
3093 FmtArg<CStdStringW>& operator=(const FmtArg<CStdStringW>&) { return *this; }
3097 struct FmtArg<std::string>
3099 explicit FmtArg(const std::string& arg) : a_(arg) {}
3100 PCSTR operator()() const { return a_.c_str(); }
3101 const std::string& a_;
3103 FmtArg<std::string>& operator=(const FmtArg<std::string>&) { return *this; }
3106 struct FmtArg<std::wstring>
3108 explicit FmtArg(const std::wstring& arg) : a_(arg) {}
3109 PCWSTR operator()() const { return a_.c_str(); }
3110 const std::wstring& a_;
3112 FmtArg<std::wstring>& operator=(const FmtArg<std::wstring>&) {return *this;}
3114 #endif // #ifdef SS_SAFEFORMAT
3117 // SSResourceHandle: our MFC-like resource handle
3118 inline HMODULE& SSResourceHandle()
3120 static HMODULE hModuleSS = GetModuleHandle(0);
3126 // In MFC builds, define some global serialization operators
3127 // Special operators that allow us to serialize CStdStrings to CArchives.
3128 // Note that we use an intermediate CString object in order to ensure that
3129 // we use the exact same format.
3132 inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringA& strA)
3134 CString strTemp = strA;
3135 return ar << strTemp;
3137 inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringW& strW)
3139 CString strTemp = strW;
3140 return ar << strTemp;
3143 inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringA& strA)
3150 inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringW& strW)
3157 #endif // #ifdef _MFC_VER -- (i.e. is this MFC?)
3160 // Define TCHAR based friendly names for some of these functions
3163 //#define CStdString CStdStringW
3164 typedef CStdStringW CStdString;
3166 //#define CStdString CStdStringA
3167 typedef CStdStringA CStdString;
3170 // ...and some shorter names for the space-efficient
3172 // -----------------------------------------------------------------------------
3173 // FUNCTIONAL COMPARATORS:
3175 // These structs are derived from the std::binary_function template. They
3176 // give us functional classes (which may be used in Standard C++ Library
3177 // collections and algorithms) that perform case-insensitive comparisons of
3178 // CStdString objects. This is useful for maps in which the key may be the
3179 // proper string but in the wrong case.
3180 // -----------------------------------------------------------------------------
3181 #define StdStringLessNoCaseW SSLNCW // avoid VC compiler warning 4786
3182 #define StdStringEqualsNoCaseW SSENCW
3183 #define StdStringLessNoCaseA SSLNCA
3184 #define StdStringEqualsNoCaseA SSENCA
3187 #define StdStringLessNoCase SSLNCW
3188 #define StdStringEqualsNoCase SSENCW
3190 #define StdStringLessNoCase SSLNCA
3191 #define StdStringEqualsNoCase SSENCA
3194 struct StdStringLessNoCaseW
3195 : std::binary_function<CStdStringW, CStdStringW, bool>
3198 bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const
3199 { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; }
3201 struct StdStringEqualsNoCaseW
3202 : std::binary_function<CStdStringW, CStdStringW, bool>
3205 bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const
3206 { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; }
3208 struct StdStringLessNoCaseA
3209 : std::binary_function<CStdStringA, CStdStringA, bool>
3212 bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const
3213 { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; }
3215 struct StdStringEqualsNoCaseA
3216 : std::binary_function<CStdStringA, CStdStringA, bool>
3219 bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const
3220 { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; }
3223 // If we had to define our own version of TRACE above, get rid of it now
3225 #ifdef TRACE_DEFINED_HERE
3227 #undef TRACE_DEFINED_HERE
3231 // These std::swap specializations come courtesy of Mike Crusader.
3235 // inline void swap(CStdStringA& s1, CStdStringA& s2) throw()
3240 // inline void swap(CStdStringW& s1, CStdStringW& s2) throw()
3246 // Turn back on any Borland warnings we turned off.
3249 #pragma option pop // Turn back on inline function warnings
3250 // #pragma warn +inl // Turn back on inline function warnings
3253 typedef std::vector<CStdString> CStdStringArray;
3255 #endif // #ifndef STDSTRING_H