/[rdesktop]/sourceforge.net/trunk/seamlessrdp/ClientDLL/stdstring.h
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/seamlessrdp/ClientDLL/stdstring.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 936 by astrand, Thu Jun 30 14:46:14 2005 UTC revision 937 by astrand, Fri Jul 1 06:50:52 2005 UTC
# Line 103  Line 103 
103  //                                      finally spotting a silly little error in StdCodeCvt that  //                                      finally spotting a silly little error in StdCodeCvt that
104  //                                      has been causing me (and users of CStdString) problems for  //                                      has been causing me (and users of CStdString) problems for
105  //                                      years in some relatively rare conversions.  I had reversed  //                                      years in some relatively rare conversions.  I had reversed
106  //                                      two length arguments.  //                                      two length arguments.
107  //  //
108  //    2003-NOV-24 - Thanks to a bunch of people for helping me clean up many  //    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  //                                      compiler warnings (and yes, even a couple of actual compiler
# Line 167  Line 167 
167  //  //
168  //    2001-OCT-29 - Added a minor range checking fix for the Mid function to  //    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  //                                      make it as forgiving as CString's version is.  Thanks to
170  //                                      Igor Kholodov for noticing this.    //                                      Igor Kholodov for noticing this.
171  //                                - Added a specialization of std::swap for CStdString.  Thanks  //                                - Added a specialization of std::swap for CStdString.  Thanks
172  //                                      to Mike Crusader for suggesting this!  It's commented out  //                                      to Mike Crusader for suggesting this!  It's commented out
173  //                                      because you're not supposed to inject your own code into the  //                                      because you're not supposed to inject your own code into the
# Line 245  Line 245 
245  //                                - Some of the Q172398 fixes were not checking for assignment-  //                                - Some of the Q172398 fixes were not checking for assignment-
246  //                                      to-self.  Fixed.  Thanks to Baptiste Lepilleur.  //                                      to-self.  Fixed.  Thanks to Baptiste Lepilleur.
247  //  //
248  //        1999-AUG-20 - Improved Load() function to be more efficient by using  //        1999-AUG-20 - Improved Load() function to be more efficient by using
249  //                                      SizeOfResource().  Thanks to Rich Zuris for this.  //                                      SizeOfResource().  Thanks to Rich Zuris for this.
250  //                                - Corrected resource ID constructor, again thanks to Rich.  //                                - Corrected resource ID constructor, again thanks to Rich.
251  //                                - Fixed a bug that occurred with UNICODE characters above  //                                - Fixed a bug that occurred with UNICODE characters above
252  //                                      the first 255 ANSI ones.  Thanks to Craig Watson.  //                                      the first 255 ANSI ones.  Thanks to Craig Watson.
253  //                                - Added missing overloads of TrimLeft() and TrimRight().  //                                - Added missing overloads of TrimLeft() and TrimRight().
254  //                                      Thanks to Karim Ratib for pointing them out  //                                      Thanks to Karim Ratib for pointing them out
255  //  //
# Line 274  Line 274 
274  //                                - Changed operators << and >> (for MFC CArchive) to serialize  //                                - Changed operators << and >> (for MFC CArchive) to serialize
275  //                                      EXACTLY as CString's do.  So now you can send a CString out  //                                      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  //                                      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.  //                                      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.  //        1999-JUN-21 - Changed the CStdString class into the CStdStr template.
280  //                                - Fixed FormatV() to correctly decrement the loop counter.  //                                - Fixed FormatV() to correctly decrement the loop counter.
# Line 284  Line 284 
284  //                                      using to _alloca().  //                                      using to _alloca().
285  //                                - Updated the text conversion macros to properly use code  //                                - Updated the text conversion macros to properly use code
286  //                                      pages and to fit in better in MFC/ATL builds.  In other  //                                      pages and to fit in better in MFC/ATL builds.  In other
287  //                                      words, I copied Microsoft's conversion stuff again.  //                                      words, I copied Microsoft's conversion stuff again.
288  //                                - Added equivalents of CString::GetBuffer, GetBufferSetLength  //                                - Added equivalents of CString::GetBuffer, GetBufferSetLength
289  //                                - new sscpy() replacement of CStdString::CopyString()  //                                - new sscpy() replacement of CStdString::CopyString()
290  //                                - a Trim() function that combines TrimRight() and TrimLeft().  //                                - a Trim() function that combines TrimRight() and TrimLeft().
# Line 298  Line 298 
298  //        1999-FEB-03 - Fixed a bug in a rarely-used overload of operator+() that  //        1999-FEB-03 - Fixed a bug in a rarely-used overload of operator+() that
299  //                                      caused infinite recursion and stack overflow  //                                      caused infinite recursion and stack overflow
300  //                                - Added member functions to simplify the process of  //                                - Added member functions to simplify the process of
301  //                                      persisting CStdStrings to/from DCOM IStream interfaces  //                                      persisting CStdStrings to/from DCOM IStream interfaces
302  //                                - Added functional objects (e.g. StdStringLessNoCase) that  //                                - Added functional objects (e.g. StdStringLessNoCase) that
303  //                                      allow CStdStrings to be used as keys STL map objects with  //                                      allow CStdStrings to be used as keys STL map objects with
304  //                                      case-insensitive comparison  //                                      case-insensitive comparison
305  //                                - Added array indexing operators (i.e. operator[]).  I  //                                - Added array indexing operators (i.e. operator[]).  I
306  //                                      originally assumed that these were unnecessary and would be  //                                      originally assumed that these were unnecessary and would be
307  //                                      inherited from basic_string.  However, without them, Visual  //                                      inherited from basic_string.  However, without them, Visual
308  //                                      C++ complains about ambiguous overloads when you try to use  //                                      C++ complains about ambiguous overloads when you try to use
309  //                                      them.  Thanks to Julian Selman to pointing this out.  //                                      them.  Thanks to Julian Selman to pointing this out.
310  //  //
311  //        1998-FEB-?? - Added overloads of assign() function to completely account  //        1998-FEB-?? - Added overloads of assign() function to completely account
312  //                                      for Q172398 bug.  Thanks to "Pete the Plumber" for this  //                                      for Q172398 bug.  Thanks to "Pete the Plumber" for this
# Line 316  Line 316 
316  // COPYRIGHT:  // COPYRIGHT:
317  //              2002 Joseph M. O'Leary.  This code is 100% free.  Use it anywhere you  //              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  //      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.  //      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  //      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  //      explode in orbit.  If you redistribute it in any form, I'd appreciate it
322  //      if you would leave this notice here.  //      if you would leave this notice here.
# Line 411  Line 411 
411  //      out of the MFC world and you don't want to rewrite all your calls to  //      out of the MFC world and you don't want to rewrite all your calls to
412  //      Format(), then you can define this flag and it will no longer crash.  //      Format(), then you can define this flag and it will no longer crash.
413  //  //
414  //      Note however that this ONLY works for Format(), not sprintf, fprintf,  //      Note however that this ONLY works for Format(), not sprintf, fprintf,
415  //      etc.  If you pass a CStdString object to one of those functions, your  //      etc.  If you pass a CStdString object to one of those functions, your
416  //      program will crash.  Not much I can do to get around this, short of  //      program will crash.  Not much I can do to get around this, short of
417  //      writing substitutes for those functions as well.  //      writing substitutes for those functions as well.
# Line 461  Line 461 
461  //      standard library functions to do it's work.  It will NOT attempt to use  //      standard library functions to do it's work.  It will NOT attempt to use
462  //      any Win32 of Visual C++ specific functions -- even if they are  //      any Win32 of Visual C++ specific functions -- even if they are
463  //      available.  You may define this flag yourself to prevent any Win32  //      available.  You may define this flag yourself to prevent any Win32
464  //      of VC++ specific functions from being called.  //      of VC++ specific functions from being called.
465    
466  // If we're not on Win32, we MUST use an ANSI build  // If we're not on Win32, we MUST use an ANSI build
467    
# Line 508  Line 508 
508    
509  // Compiler Error regarding _UNICODE and UNICODE  // Compiler Error regarding _UNICODE and UNICODE
510  // -----------------------------------------------  // -----------------------------------------------
511  // Microsoft header files are screwy.  Sometimes they depend on a preprocessor  // Microsoft header files are screwy.  Sometimes they depend on a preprocessor
512  // flag named "_UNICODE".  Other times they check "UNICODE" (note the lack of  // flag named "_UNICODE".  Other times they check "UNICODE" (note the lack of
513  // leading underscore in the second version".  In several places, they silently  // leading underscore in the second version".  In several places, they silently
514  // "synchronize" these two flags this by defining one of the other was defined.  // "synchronize" these two flags this by defining one of the other was defined.
515  // In older version of this header, I used to try to do the same thing.  // In older version of this header, I used to try to do the same thing.
516  //  //
517  // However experience has taught me that this is a bad idea.  You get weird  // However experience has taught me that this is a bad idea.  You get weird
518  // compiler errors that seem to indicate things like LPWSTR and LPTSTR not being  // compiler errors that seem to indicate things like LPWSTR and LPTSTR not being
# Line 535  Line 535 
535  #ifdef _MSC_VER  #ifdef _MSC_VER
536  #if defined (_UNICODE) && !defined (UNICODE)  #if defined (_UNICODE) && !defined (UNICODE)
537  #error UNICODE defined  but not UNICODE  #error UNICODE defined  but not UNICODE
538          //      #define UNICODE  // no longer silently fix this  //      #define UNICODE  // no longer silently fix this
539  #endif  #endif
540  #if defined (UNICODE) && !defined (_UNICODE)  #if defined (UNICODE) && !defined (_UNICODE)
541  #error Warning, UNICODE defined  but not _UNICODE  #error Warning, UNICODE defined  but not _UNICODE
542          //      #define _UNICODE  // no longer silently fix this  //      #define _UNICODE  // no longer silently fix this
543  #endif  #endif
544  #endif  #endif
545    
546    
547  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
548  // MIN and MAX.  The Standard C++ template versions go by so many names (at  // MIN and MAX.  The Standard C++ template versions go by so many names (at
549  // at least in the MS implementation) that you never know what's available  // at least in the MS implementation) that you never know what's available
550  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
551  template < class Type >  template < class Type >
552      inline const Type & SSMIN(const Type & arg1, const Type & arg2)  inline const Type & SSMIN(const Type & arg1, const Type & arg2)
553  {  {
554      return arg2 < arg1 ? arg2 : arg1;      return arg2 < arg1 ? arg2 : arg1;
555  }  }
556  template < class Type >  template < class Type >
557      inline const Type & SSMAX(const Type & arg1, const Type & arg2)  inline const Type & SSMAX(const Type & arg1, const Type & arg2)
558  {  {
559      return arg2 > arg1 ? arg2 : arg1;      return arg2 > arg1 ? arg2 : arg1;
560  }  }
# Line 564  template < class Type > Line 564  template < class Type >
564    
565  #if !defined(W32BASE_H)  #if !defined(W32BASE_H)
566    
567          // If they want us to use only standard C++ stuff (no Win32 stuff)  // If they want us to use only standard C++ stuff (no Win32 stuff)
568    
569  #ifdef SS_ANSI  #ifdef SS_ANSI
570    
571                  // On Win32 we have TCHAR.H so just include it.  This is NOT violating  // On Win32 we have TCHAR.H so just include it.  This is NOT violating
572          // the spirit of SS_ANSI as we are not calling any Win32 functions here.  // the spirit of SS_ANSI as we are not calling any Win32 functions here.
573    
574  #ifdef SS_WIN32  #ifdef SS_WIN32
575    
# Line 579  template < class Type > Line 579  template < class Type >
579  #define STRICT  #define STRICT
580  #endif  #endif
581    
582          // ... but on non-Win32 platforms, we must #define the types we need.  // ... but on non-Win32 platforms, we must #define the types we need.
583    
584  #else  #else
585    
# Line 597  typedef wchar_t OLECHAR; Line 597  typedef wchar_t OLECHAR;
597  #endif // #ifndef _WIN32  #endif // #ifndef _WIN32
598    
599    
600                  // Make sure ASSERT and verify are defined using only ANSI stuff  // Make sure ASSERT and verify are defined using only ANSI stuff
601    
602  #ifndef ASSERT  #ifndef ASSERT
603  #include <assert.h>  #include <assert.h>
# Line 619  typedef wchar_t OLECHAR; Line 619  typedef wchar_t OLECHAR;
619  #define STRICT  #define STRICT
620  #endif  #endif
621    
622                  // Make sure ASSERT and verify are defined  // Make sure ASSERT and verify are defined
623    
624  #ifndef ASSERT  #ifndef ASSERT
625  #include <crtdbg.h>  #include <crtdbg.h>
# Line 727  typedef void *LPCVOID; Line 727  typedef void *LPCVOID;
727    
728  #ifndef SS_USE_FACET  #ifndef SS_USE_FACET
729    
730          // STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for  // STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for
731          // all MSVC builds, erroneously in my opinion.  It causes problems for  // all MSVC builds, erroneously in my opinion.  It causes problems for
732          // my SS_ANSI builds.  In my code, I always comment out that line.  You'll  // my SS_ANSI builds.  In my code, I always comment out that line.  You'll
733          // find it in   \stlport\config\stl_msvc.h  // find it in   \stlport\config\stl_msvc.h
734    
735  #if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 )  #if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 )
736    
# Line 745  typedef void *LPCVOID; Line 745  typedef void *LPCVOID;
745    
746  #define SS_USE_FACET(loc, fac) std::_USE(loc, fac)  #define SS_USE_FACET(loc, fac) std::_USE(loc, fac)
747    
748          // ...and  // ...and
749  #elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)  #elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)
750    
751  #define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0)  #define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0)
# Line 765  typedef void *LPCVOID; Line 765  typedef void *LPCVOID;
765  #include <wchar.h>              // Added to Std Library with Amendment #1.  #include <wchar.h>              // Added to Std Library with Amendment #1.
766    
767  // First define the conversion helper functions.  We define these regardless of  // First define the conversion helper functions.  We define these regardless of
768  // any preprocessor macro settings since their names won't collide.  // any preprocessor macro settings since their names won't collide.
769    
770  // Not sure if we need all these headers.   I believe ANSI says we do.  // Not sure if we need all these headers.   I believe ANSI says we do.
771    
# Line 803  inline PWSTR StdCodeCvt(PWSTR pDstW, int Line 803  inline PWSTR StdCodeCvt(PWSTR pDstW, int
803          SSCodeCvt::result res = SSCodeCvt::ok;          SSCodeCvt::result res = SSCodeCvt::ok;
804          const SSCodeCvt & conv = SS_USE_FACET(loc, SSCodeCvt);          const SSCodeCvt & conv = SS_USE_FACET(loc, SSCodeCvt);
805          SSCodeCvt::state_type st = {          SSCodeCvt::state_type st = {
806          0};                                         0};
807          res = conv.in(st,          res = conv.in(st,
808                        pSrcA, pSrcA + nSrc, pNextSrcA,                        pSrcA, pSrcA + nSrc, pNextSrcA,
809                        pDstW, pDstW + nDst, pNextDstW);                        pDstW, pDstW + nDst, pNextDstW);
# Line 842  inline PSTR StdCodeCvt(PSTR pDstA, int n Line 842  inline PSTR StdCodeCvt(PSTR pDstA, int n
842          SSCodeCvt::result res = SSCodeCvt::ok;          SSCodeCvt::result res = SSCodeCvt::ok;
843          const SSCodeCvt & conv = SS_USE_FACET(loc, SSCodeCvt);          const SSCodeCvt & conv = SS_USE_FACET(loc, SSCodeCvt);
844          SSCodeCvt::state_type st = {          SSCodeCvt::state_type st = {
845          0};                                         0};
846          res = conv.out(st,          res = conv.out(st,
847                         pSrcW, pSrcW + nSrc, pNextSrcW,                         pSrcW, pSrcW + nSrc, pNextSrcW,
848                         pDstA, pDstA + nDst, pNextDstA);                         pDstA, pDstA + nDst, pNextDstA);
# Line 869  inline PUSTR StdCodeCvt(PUSTR pDstA, int Line 869  inline PUSTR StdCodeCvt(PUSTR pDstA, int
869    
870  /*  /*
871  #else   // ...or are we doing things assuming win32 and Visual C++?  #else   // ...or are we doing things assuming win32 and Visual C++?
872    
873          inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc, UINT acp=CP_ACP)          inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc, UINT acp=CP_ACP)
874          {          {
875                  ASSERT(0 != pSrcA);                  ASSERT(0 != pSrcA);
# Line 882  inline PUSTR StdCodeCvt(PUSTR pDstA, int Line 882  inline PUSTR StdCodeCvt(PUSTR pDstA, int
882          {          {
883                  return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, acp);                  return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, acp);
884          }          }
885    
886          inline PSTR StdCodeCvt(PSTR pDstA, nDst PCWSTR pSrcW, int nSrc, UINT acp=CP_ACP)          inline PSTR StdCodeCvt(PSTR pDstA, nDst PCWSTR pSrcW, int nSrc, UINT acp=CP_ACP)
887          {          {
888                  ASSERT(0 != pDstA);                  ASSERT(0 != pDstA);
# Line 895  inline PUSTR StdCodeCvt(PUSTR pDstA, int Line 895  inline PUSTR StdCodeCvt(PUSTR pDstA, int
895          {          {
896                  return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, acp);                  return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, acp);
897          }          }
898    
899  #endif  #endif
900  */  */
901    
902  // Unicode/MBCS conversion macros are only available on implementations of  // Unicode/MBCS conversion macros are only available on implementations of
903  // the "C" library that have the non-standard _alloca function.  As far as I  // the "C" library that have the non-standard _alloca function.  As far as I
904  // know that's only Microsoft's though I've heard that the function exists  // know that's only Microsoft's though I've heard that the function exists
905  // elsewhere.    // elsewhere.
906    
907  #if defined(SS_ALLOCA) && !defined SS_NO_CONVERSION  #if defined(SS_ALLOCA) && !defined SS_NO_CONVERSION
908    
909  #include <malloc.h>             // needed for _alloca  #include <malloc.h>             // needed for _alloca
910    
911      // Define our conversion macros to look exactly like Microsoft's to  // Define our conversion macros to look exactly like Microsoft's to
912      // facilitate using this stuff both with and without MFC/ATL  // facilitate using this stuff both with and without MFC/ATL
913    
914  #ifdef _CONVERSION_USES_THREAD_LOCALE  #ifdef _CONVERSION_USES_THREAD_LOCALE
915    
# Line 959  inline PUSTR StdCodeCvt(PUSTR pDstA, int Line 959  inline PUSTR StdCodeCvt(PUSTR pDstA, int
959  #define SSA2T   SSA2W  #define SSA2T   SSA2W
960  #define SST2CA  SSW2CA  #define SST2CA  SSW2CA
961  #define SSA2CT  SSA2CW  #define SSA2CT  SSA2CW
962                  // (Did you get a compiler error here about not being able to convert  // (Did you get a compiler error here about not being able to convert
963                  // PTSTR into PWSTR?  Then your _UNICODE and UNICODE flags are messed  // PTSTR into PWSTR?  Then your _UNICODE and UNICODE flags are messed
964                  // up.  Best bet: #define BOTH macros before including any MS headers.)  // up.  Best bet: #define BOTH macros before including any MS headers.)
965  inline PWSTR SST2W(PTSTR p)  inline PWSTR SST2W(PTSTR p)
966  {  {
967      return p;      return p;
# Line 1002  inline PCTSTR SSA2CT(PCSTR p) Line 1002  inline PCTSTR SSA2CT(PCSTR p)
1002  #endif // #ifdef UNICODE  #endif // #ifdef UNICODE
1003    
1004  #if defined(UNICODE)  #if defined(UNICODE)
1005      // in these cases the default (TCHAR) is the same as OLECHAR  // in these cases the default (TCHAR) is the same as OLECHAR
1006  inline PCOLESTR SST2COLE(PCTSTR p)  inline PCOLESTR SST2COLE(PCTSTR p)
1007  {  {
1008      return p;      return p;
# Line 1020  inline PTSTR SSOLE2T(POLESTR p) Line 1020  inline PTSTR SSOLE2T(POLESTR p)
1020      return p;      return p;
1021  }  }
1022  #elif defined(OLE2ANSI)  #elif defined(OLE2ANSI)
1023      // in these cases the default (TCHAR) is the same as OLECHAR  // in these cases the default (TCHAR) is the same as OLECHAR
1024  inline PCOLESTR SST2COLE(PCTSTR p)  inline PCOLESTR SST2COLE(PCTSTR p)
1025  {  {
1026      return p;      return p;
# Line 1038  inline PTSTR SSOLE2T(POLESTR p) Line 1038  inline PTSTR SSOLE2T(POLESTR p)
1038      return p;      return p;
1039  }  }
1040  #else  #else
1041              //CharNextW doesn't work on Win95 so we use this  //CharNextW doesn't work on Win95 so we use this
1042  #define SST2COLE(pa)    SSA2CW((pa))  #define SST2COLE(pa)    SSA2CW((pa))
1043  #define SST2OLE(pa)             SSA2W((pa))  #define SST2OLE(pa)             SSA2W((pa))
1044  #define SSOLE2CT(po)    SSW2CA((po))  #define SSOLE2CT(po)    SSW2CA((po))
# Line 1089  inline PCWSTR SSOLE2CW(PCOLESTR p) Line 1089  inline PCWSTR SSOLE2CW(PCOLESTR p)
1089  }  }
1090  #endif  #endif
1091    
1092      // Above we've defined macros that look like MS' but all have  // Above we've defined macros that look like MS' but all have
1093      // an 'SS' prefix.  Now we need the real macros.  We'll either  // an 'SS' prefix.  Now we need the real macros.  We'll either
1094      // get them from the macros above or from MFC/ATL.  // get them from the macros above or from MFC/ATL.
1095    
1096  #if defined (USES_CONVERSION)  #if defined (USES_CONVERSION)
1097    
# Line 1151  inline PSTR StdCodeCvt(PSTR pDst, int nD Line 1151  inline PSTR StdCodeCvt(PSTR pDst, int nD
1151      if (nChars > 0) {      if (nChars > 0) {
1152          pDst[0] = '\0';          pDst[0] = '\0';
1153          std::basic_string < char >::traits_type::copy(pDst, pSrc, nChars);          std::basic_string < char >::traits_type::copy(pDst, pSrc, nChars);
1154  //              std::char_traits<char>::copy(pDst, pSrc, nChars);          //              std::char_traits<char>::copy(pDst, pSrc, nChars);
1155          pDst[nChars] = '\0';          pDst[nChars] = '\0';
1156      }      }
1157    
# Line 1173  inline PWSTR StdCodeCvt(PWSTR pDst, int Line 1173  inline PWSTR StdCodeCvt(PWSTR pDst, int
1173      if (nChars > 0) {      if (nChars > 0) {
1174          pDst[0] = '\0';          pDst[0] = '\0';
1175          std::basic_string < wchar_t >::traits_type::copy(pDst, pSrc, nChars);          std::basic_string < wchar_t >::traits_type::copy(pDst, pSrc, nChars);
1176  //              std::char_traits<wchar_t>::copy(pDst, pSrc, nChars);          //              std::char_traits<wchar_t>::copy(pDst, pSrc, nChars);
1177          pDst[nChars] = '\0';          pDst[nChars] = '\0';
1178      }      }
1179    
# Line 1210  typedef std::basic_string < TCHAR > tstr Line 1210  typedef std::basic_string < TCHAR > tstr
1210  // Therefore, to keep the CStdStr declaration simple, we have these inline  // Therefore, to keep the CStdStr declaration simple, we have these inline
1211  // functions.  The template calls them often.  Since they are inline (and NOT  // functions.  The template calls them often.  Since they are inline (and NOT
1212  // exported when this is built as a DLL), they will probably be resolved away  // exported when this is built as a DLL), they will probably be resolved away
1213  // to nothing.  // to nothing.
1214  //  //
1215  // Without these functions, the CStdStr<> template would probably have to broken  // Without these functions, the CStdStr<> template would probably have to broken
1216  // out into two, almost identical classes.  Either that or it would be a huge,  // out into two, almost identical classes.  Either that or it would be a huge,
1217  // convoluted mess, with tons of "if" statements all over the place checking the  // convoluted mess, with tons of "if" statements all over the place checking the
1218  // size of template parameter CT.  // size of template parameter CT.
1219  //  //
1220  // In several cases, you will see two versions of each function.  One version is  // In several cases, you will see two versions of each function.  One version is
1221  // the more portable, standard way of doing things, while the other is the  // the more portable, standard way of doing things, while the other is the
1222  // non-standard, but often significantly faster Visual C++ way.  // non-standard, but often significantly faster Visual C++ way.
# Line 1233  typedef std::basic_string < TCHAR > tstr Line 1233  typedef std::basic_string < TCHAR > tstr
1233  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1234  // sslen: strlen/wcslen wrappers  // sslen: strlen/wcslen wrappers
1235  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1236  template < typename CT > inline int sslen(const CT * pT)  template < typename CT >
1237    inline int sslen(const CT * pT)
1238  {  {
1239      return 0 == pT ? 0 : (int) std::basic_string <      return 0 == pT ? 0 : (int) std::basic_string <
1240          CT >::traits_type::length(pT);             CT >::traits_type::length(pT);
1241  //      return 0 == pT ? 0 : std::char_traits<CT>::length(pT);      //      return 0 == pT ? 0 : std::char_traits<CT>::length(pT);
1242  }  }
1243  inline SS_NOTHROW int sslen(const std::string & s)  inline SS_NOTHROW int sslen(const std::string & s)
1244  {  {
# Line 1252  inline SS_NOTHROW int sslen(const std::w Line 1253  inline SS_NOTHROW int sslen(const std::w
1253  // sstolower/sstoupper -- convert characters to upper/lower case  // sstolower/sstoupper -- convert characters to upper/lower case
1254  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1255  template < typename CT >  template < typename CT >
1256      inline CT sstolower(const CT & t, const std::locale & loc = std::locale())  inline CT sstolower(const CT & t, const std::locale & loc = std::locale())
1257  {  {
1258      return std::tolower < CT > (t, loc);      return std::tolower < CT > (t, loc);
1259  }  }
1260    
1261  template < typename CT >  template < typename CT >
1262      inline CT sstoupper(const CT & t, const std::locale & loc = std::locale())  inline CT sstoupper(const CT & t, const std::locale & loc = std::locale())
1263  {  {
1264      return std::toupper < CT > (t, loc);      return std::toupper < CT > (t, loc);
1265  }  }
# Line 1305  inline void ssasn(std::string & sDst, co Line 1306  inline void ssasn(std::string & sDst, co
1306  {  {
1307      if (sSrc.empty()) {      if (sSrc.empty()) {
1308          sDst.erase();          sDst.erase();
1309      }      } else {
     else {  
1310          int nDst = static_cast < int >(sSrc.size());          int nDst = static_cast < int >(sSrc.size());
1311    
1312          // In MBCS builds, pad the buffer to account for the possibility of          // In MBCS builds, pad the buffer to account for the possibility of
1313          // some 3 byte characters.  Not perfect but should get most cases.          // some 3 byte characters.  Not perfect but should get most cases.
1314    
1315  #ifdef SS_MBCS  #ifdef SS_MBCS
1316    
1317          nDst = static_cast < int >(static_cast < double >(nDst) * 1.3);          nDst = static_cast < int >(static_cast < double >(nDst) * 1.3);
1318  #endif  #endif
1319    
# Line 1324  inline void ssasn(std::string & sDst, co Line 1325  inline void ssasn(std::string & sDst, co
1325          // In MBCS builds, we don't know how long the destination string will be.          // In MBCS builds, we don't know how long the destination string will be.
1326    
1327  #ifdef SS_MBCS  #ifdef SS_MBCS
1328    
1329          sDst.resize(sslen(szCvt));          sDst.resize(sslen(szCvt));
1330  #else  #else
1331    
1332          szCvt;          szCvt;
1333          sDst.resize(sSrc.size());          sDst.resize(sSrc.size());
1334  #endif  #endif
1335    
1336      }      }
1337  }  }
1338  inline void ssasn(std::string & sDst, PCWSTR pW)  inline void ssasn(std::string & sDst, PCWSTR pW)
# Line 1342  inline void ssasn(std::string & sDst, PC Line 1346  inline void ssasn(std::string & sDst, PC
1346          // some 3 byte characters.  Not perfect but should get most cases.          // some 3 byte characters.  Not perfect but should get most cases.
1347    
1348  #ifdef SS_MBCS  #ifdef SS_MBCS
1349    
1350          nDst = static_cast < int >(static_cast < double >(nDst) * 1.3);          nDst = static_cast < int >(static_cast < double >(nDst) * 1.3);
1351  #endif  #endif
1352    
# Line 1353  inline void ssasn(std::string & sDst, PC Line 1358  inline void ssasn(std::string & sDst, PC
1358          // In MBCS builds, we don't know how long the destination string will be.          // In MBCS builds, we don't know how long the destination string will be.
1359    
1360  #ifdef SS_MBCS  #ifdef SS_MBCS
1361    
1362          sDst.resize(sslen(szCvt));          sDst.resize(sslen(szCvt));
1363  #else  #else
1364    
1365          sDst.resize(nDst);          sDst.resize(nDst);
1366          szCvt;          szCvt;
1367  #endif  #endif
1368      }  
1369      else {      } else {
1370          sDst.erase();          sDst.erase();
1371      }      }
1372  }  }
# Line 1405  inline void ssasn(std::wstring & sDst, c Line 1412  inline void ssasn(std::wstring & sDst, c
1412  {  {
1413      if (sSrc.empty()) {      if (sSrc.empty()) {
1414          sDst.erase();          sDst.erase();
1415      }      } else {
     else {  
1416          int nSrc = static_cast < int >(sSrc.size());          int nSrc = static_cast < int >(sSrc.size());
1417          int nDst = nSrc;          int nDst = nSrc;
1418    
# Line 1424  inline void ssasn(std::wstring & sDst, P Line 1430  inline void ssasn(std::wstring & sDst, P
1430    
1431      if (0 == nSrc) {      if (0 == nSrc) {
1432          sDst.erase();          sDst.erase();
1433      }      } else {
     else {  
1434          int nDst = nSrc;          int nDst = nSrc;
1435          sDst.resize(nDst + 1);          sDst.resize(nDst + 1);
1436          PCWSTR szCvt =          PCWSTR szCvt =
# Line 1458  inline void ssadd(std::string & sDst, co Line 1463  inline void ssadd(std::string & sDst, co
1463          // some 3 byte characters.  Not perfect but should get most cases.          // some 3 byte characters.  Not perfect but should get most cases.
1464    
1465  #ifdef SS_MBCS  #ifdef SS_MBCS
1466    
1467          nAdd = static_cast < int >(static_cast < double >(nAdd) * 1.3);          nAdd = static_cast < int >(static_cast < double >(nAdd) * 1.3);
1468  #endif  #endif
1469    
# Line 1467  inline void ssadd(std::string & sDst, co Line 1473  inline void ssadd(std::string & sDst, co
1473                         nAdd, sSrc.c_str(), nSrc);                         nAdd, sSrc.c_str(), nSrc);
1474    
1475  #ifdef SS_MBCS  #ifdef SS_MBCS
1476    
1477          sDst.resize(nDst + sslen(szCvt));          sDst.resize(nDst + sslen(szCvt));
1478  #else  #else
1479    
1480          sDst.resize(nDst + nAdd);          sDst.resize(nDst + nAdd);
1481          szCvt;          szCvt;
1482  #endif  #endif
1483    
1484      }      }
1485  }  }
1486  inline void ssadd(std::string & sDst, const std::string & sSrc)  inline void ssadd(std::string & sDst, const std::string & sSrc)
# Line 1486  inline void ssadd(std::string & sDst, PC Line 1495  inline void ssadd(std::string & sDst, PC
1495          int nAdd = nSrc;          int nAdd = nSrc;
1496    
1497  #ifdef SS_MBCS  #ifdef SS_MBCS
1498    
1499          nAdd = static_cast < int >(static_cast < double >(nAdd) * 1.3);          nAdd = static_cast < int >(static_cast < double >(nAdd) * 1.3);
1500  #endif  #endif
1501    
# Line 1495  inline void ssadd(std::string & sDst, PC Line 1505  inline void ssadd(std::string & sDst, PC
1505                         nAdd, pW, nSrc);                         nAdd, pW, nSrc);
1506    
1507  #ifdef SS_MBCS  #ifdef SS_MBCS
1508    
1509          sDst.resize(nDst + sslen(szCvt));          sDst.resize(nDst + sslen(szCvt));
1510  #else  #else
1511    
1512          sDst.resize(nDst + nSrc);          sDst.resize(nDst + nSrc);
1513          szCvt;          szCvt;
1514  #endif  #endif
1515    
1516      }      }
1517  }  }
1518  inline void ssadd(std::string & sDst, PCSTR pA)  inline void ssadd(std::string & sDst, PCSTR pA)
# Line 1515  inline void ssadd(std::string & sDst, PC Line 1528  inline void ssadd(std::string & sDst, PC
1528                  sDst.append(std::string(pA));                  sDst.append(std::string(pA));
1529              else              else
1530                  sDst.append(pA);                  sDst.append(pA);
1531          }          } else {
         else {  
1532              sDst.append(pA);              sDst.append(pA);
1533          }          }
1534      }      }
# Line 1537  inline void ssadd(std::wstring & sDst, c Line 1549  inline void ssadd(std::wstring & sDst, c
1549                         nSrc, sSrc.c_str(), nSrc + 1);                         nSrc, sSrc.c_str(), nSrc + 1);
1550    
1551  #ifdef SS_MBCS  #ifdef SS_MBCS
1552    
1553          sDst.resize(nDst + sslen(szCvt));          sDst.resize(nDst + sslen(szCvt));
1554  #else  #else
1555    
1556          sDst.resize(nDst + nSrc);          sDst.resize(nDst + nSrc);
1557          szCvt;          szCvt;
1558  #endif  #endif
1559    
1560      }      }
1561  }  }
1562  inline void ssadd(std::wstring & sDst, PCSTR pA)  inline void ssadd(std::wstring & sDst, PCSTR pA)
# Line 1557  inline void ssadd(std::wstring & sDst, P Line 1572  inline void ssadd(std::wstring & sDst, P
1572                         nSrc, pA, nSrc + 1);                         nSrc, pA, nSrc + 1);
1573    
1574  #ifdef SS_MBCS  #ifdef SS_MBCS
1575    
1576          sDst.resize(nDst + sslen(szCvt));          sDst.resize(nDst + sslen(szCvt));
1577  #else  #else
1578    
1579          sDst.resize(nDst + nSrc);          sDst.resize(nDst + nSrc);
1580          szCvt;          szCvt;
1581  #endif  #endif
1582    
1583      }      }
1584  }  }
1585  inline void ssadd(std::wstring & sDst, PCWSTR pW)  inline void ssadd(std::wstring & sDst, PCWSTR pW)
# Line 1577  inline void ssadd(std::wstring & sDst, P Line 1595  inline void ssadd(std::wstring & sDst, P
1595                  sDst.append(std::wstring(pW));                  sDst.append(std::wstring(pW));
1596              else              else
1597                  sDst.append(pW);                  sDst.append(pW);
1598          }          } else {
         else {  
1599              sDst.append(pW);              sDst.append(pW);
1600          }          }
1601      }      }
# Line 1588  inline void ssadd(std::wstring & sDst, P Line 1605  inline void ssadd(std::wstring & sDst, P
1605  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1606  // sscmp: comparison (case sensitive, not affected by locale)  // sscmp: comparison (case sensitive, not affected by locale)
1607  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1608  template < typename CT > inline int sscmp(const CT * pA1, const CT * pA2)  template < typename CT >
1609    inline int sscmp(const CT * pA1, const CT * pA2)
1610  {  {
1611      CT f;      CT f;
1612      CT l;      CT l;
# Line 1604  template < typename CT > inline int sscm Line 1622  template < typename CT > inline int sscm
1622  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1623  // ssicmp: comparison (case INsensitive, not affected by locale)  // ssicmp: comparison (case INsensitive, not affected by locale)
1624  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1625  template < typename CT > inline int ssicmp(const CT * pA1, const CT * pA2)  template < typename CT >
1626    inline int ssicmp(const CT * pA1, const CT * pA2)
1627  {  {
1628      // Using the "C" locale = "not affected by locale"      // Using the "C" locale = "not affected by locale"
1629    
# Line 1626  template < typename CT > inline int ssic Line 1645  template < typename CT > inline int ssic
1645  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1646    
1647  template < typename CT >  template < typename CT >
1648      inline void sslwr(CT * pT, size_t nLen, const std::locale & loc =  inline void sslwr(CT * pT, size_t nLen, const std::locale & loc =
1649                        std::locale())                        std::locale())
1650  {  {
1651      SS_USE_FACET(loc, std::ctype < CT >).tolower(pT, pT + nLen);      SS_USE_FACET(loc, std::ctype < CT >).tolower(pT, pT + nLen);
1652  }  }
1653  template < typename CT >  template < typename CT >
1654      inline void ssupr(CT * pT, size_t nLen, const std::locale & loc =  inline void ssupr(CT * pT, size_t nLen, const std::locale & loc =
1655                        std::locale())                        std::locale())
1656  {  {
1657      SS_USE_FACET(loc, std::ctype < CT >).toupper(pT, pT + nLen);      SS_USE_FACET(loc, std::ctype < CT >).toupper(pT, pT + nLen);
# Line 1643  template < typename CT > Line 1662  template < typename CT >
1662  // builds we can't use _vsnprintf/_vsnwsprintf because they're MS extensions.  // builds we can't use _vsnprintf/_vsnwsprintf because they're MS extensions.
1663  //  //
1664  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1665  // Borland's headers put some ANSI "C" functions in the 'std' namespace.  // Borland's headers put some ANSI "C" functions in the 'std' namespace.
1666  // Promote them to the global namespace so we can use them here.  // Promote them to the global namespace so we can use them here.
1667    
1668  #if defined(__BORLANDC__)  #if defined(__BORLANDC__)
# Line 1651  using std::vsprintf; Line 1670  using std::vsprintf;
1670  using std::vswprintf;  using std::vswprintf;
1671  #endif  #endif
1672    
1673          // GNU is supposed to have vsnprintf and vsnwprintf.  But only the newer  // GNU is supposed to have vsnprintf and vsnwprintf.  But only the newer
1674          // distributions do.  // distributions do.
1675    
1676  #if defined(__GNUC__)  #if defined(__GNUC__)
1677    
# Line 1665  inline int ssvsprintf(PWSTR pW, size_t n Line 1684  inline int ssvsprintf(PWSTR pW, size_t n
1684      return vswprintf(pW, nCount, pFmtW, vl);      return vswprintf(pW, nCount, pFmtW, vl);
1685  }  }
1686    
1687          // Microsofties can use  // Microsofties can use
1688  #elif defined(_MSC_VER) && !defined(SS_ANSI)  #elif defined(_MSC_VER) && !defined(SS_ANSI)
1689    
1690  inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)  inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
# Line 1679  inline int ssnprintf(PWSTR pW, size_t nC Line 1698  inline int ssnprintf(PWSTR pW, size_t nC
1698    
1699  #elif !defined (SS_DANGEROUS_FORMAT)  #elif !defined (SS_DANGEROUS_FORMAT)
1700    
1701          // GOT COMPILER PROBLEMS HERE?  // GOT COMPILER PROBLEMS HERE?
1702          // ---------------------------  // ---------------------------
1703          // Does your compiler choke on one or more of the following 2 functions?  It  // Does your compiler choke on one or more of the following 2 functions?  It
1704          // probably means that you don't have have either vsnprintf or vsnwprintf in  // probably means that you don't have have either vsnprintf or vsnwprintf in
1705          // your version of the CRT.  This is understandable since neither is an ANSI  // your version of the CRT.  This is understandable since neither is an ANSI
1706          // "C" function.  However it still leaves you in a dilemma.  In order to make  // "C" function.  However it still leaves you in a dilemma.  In order to make
1707          // this code build, you're going to have to to use some non-length-checked  // this code build, you're going to have to to use some non-length-checked
1708          // formatting functions that every CRT has:  vsprintf and vswprintf.    // formatting functions that every CRT has:  vsprintf and vswprintf.
1709          //  //
1710          // This is very dangerous.  With the proper erroneous (or malicious) code, it  // This is very dangerous.  With the proper erroneous (or malicious) code, it
1711          // can lead to buffer overlows and crashing your PC.  Use at your own risk  // can lead to buffer overlows and crashing your PC.  Use at your own risk
1712          // In order to use them, just #define SS_DANGEROUS_FORMAT at the top of  // In order to use them, just #define SS_DANGEROUS_FORMAT at the top of
1713          // this file.  // this file.
1714          //  //
1715          // Even THEN you might not be all the way home due to some non-conforming  // Even THEN you might not be all the way home due to some non-conforming
1716          // distributions.  More on this in the comments below.  // distributions.  More on this in the comments below.
1717    
1718  inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)  inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl)
1719  {  {
# Line 1715  inline int ssvsprintf(PSTR pA, size_t /* Line 1734  inline int ssvsprintf(PSTR pA, size_t /*
1734  inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)  inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl)
1735  {  {
1736      // JMO: Some distributions of the "C" have a version of vswprintf that      // JMO: Some distributions of the "C" have a version of vswprintf that
1737      // takes 3 arguments (e.g. Microsoft, Borland, GNU).  Others have a      // takes 3 arguments (e.g. Microsoft, Borland, GNU).  Others have a
1738      // version which takes 4 arguments (an extra "count" argument in the      // version which takes 4 arguments (an extra "count" argument in the
1739      // second position.  The best stab I can take at this so far is that if      // second position.  The best stab I can take at this so far is that if
1740      // you are NOT running with MS, Borland, or GNU, then I'll assume you      // you are NOT running with MS, Borland, or GNU, then I'll assume you
# Line 1731  inline int ssvsprintf(PWSTR pW, size_t n Line 1750  inline int ssvsprintf(PWSTR pW, size_t n
1750      //      //
1751      // Thanks to Ronny Schulz for the SGI-specific checks here.      // Thanks to Ronny Schulz for the SGI-specific checks here.
1752    
1753  //      #if !defined(__MWERKS__) && !defined(__SUNPRO_CC_COMPAT) && !defined(__SUNPRO_CC)      //      #if !defined(__MWERKS__) && !defined(__SUNPRO_CC_COMPAT) && !defined(__SUNPRO_CC)
1754  #if    !defined(_MSC_VER) \  #if    !defined(_MSC_VER) \
1755          && !defined (__BORLANDC__) \          && !defined (__BORLANDC__) \
1756          && !defined(__GNUC__) \          && !defined(__GNUC__) \
# Line 1744  inline int ssvsprintf(PWSTR pW, size_t n Line 1763  inline int ssvsprintf(PWSTR pW, size_t n
1763    
1764  #elif defined(__sgi)  #elif defined(__sgi)
1765    
1766      nCount;  nCount;
1767      return vsprintf((char *) pW, (char *) pFmtW, vl);  return vsprintf((char *) pW, (char *) pFmtW, vl);
1768    
1769  #else  #else
1770    
1771      nCount;  nCount;
1772      return vswprintf(pW, pFmtW, vl);  return vswprintf(pW, pFmtW, vl);
1773    
1774  #endif  #endif
1775    
# Line 1783  inline int ssload(HMODULE hInst, UINT uI Line 1802  inline int ssload(HMODULE hInst, UINT uI
1802  //              functions appear to return the opposite of what they should  //              functions appear to return the opposite of what they should
1803  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1804  template < typename CT >  template < typename CT >
1805      inline int sscoll(const CT * sz1, int nLen1, const CT * sz2, int nLen2)  inline int sscoll(const CT * sz1, int nLen1, const CT * sz2, int nLen2)
1806  {  {
1807      const std::collate < CT > &coll =      const std::collate < CT > &coll =
1808          SS_USE_FACET(std::locale(), std::collate < CT >);          SS_USE_FACET(std::locale(), std::collate < CT >);
# Line 1791  template < typename CT > Line 1810  template < typename CT >
1810      return coll.compare(sz2, sz2 + nLen2, sz1, sz1 + nLen1);      return coll.compare(sz2, sz2 + nLen2, sz1, sz1 + nLen1);
1811  }  }
1812  template < typename CT >  template < typename CT >
1813      inline int ssicoll(const CT * sz1, int nLen1, const CT * sz2, int nLen2)  inline int ssicoll(const CT * sz1, int nLen1, const CT * sz2, int nLen2)
1814  {  {
1815      const std::locale loc;      const std::locale loc;
1816      const std::collate < CT > &coll = SS_USE_FACET(loc, std::collate < CT >);      const std::collate < CT > &coll = SS_USE_FACET(loc, std::collate < CT >);
# Line 1800  template < typename CT > Line 1819  template < typename CT >
1819      // facet typedefs so we'll just default to basic_string and hope      // facet typedefs so we'll just default to basic_string and hope
1820      // that's what the collate facet uses (which it generally should)      // that's what the collate facet uses (which it generally should)
1821    
1822  //      std::collate<CT>::string_type s1(sz1);      //      std::collate<CT>::string_type s1(sz1);
1823  //      std::collate<CT>::string_type s2(sz2);      //      std::collate<CT>::string_type s2(sz2);
1824      const std::basic_string < CT > sEmpty;      const std::basic_string < CT > sEmpty;
1825      std::basic_string < CT > s1(sz1 ? sz1 : sEmpty.c_str());      std::basic_string < CT > s1(sz1 ? sz1 : sEmpty.c_str());
1826      std::basic_string < CT > s2(sz2 ? sz2 : sEmpty.c_str());      std::basic_string < CT > s2(sz2 ? sz2 : sEmpty.c_str());
# Line 1862  inline DWORD ssfmtmsg(DWORD dwFlags, LPC Line 1881  inline DWORD ssfmtmsg(DWORD dwFlags, LPC
1881  //              characters.  The return value is the number of characters copied,  //              characters.  The return value is the number of characters copied,
1882  //              not including the NULL terminator.  //              not including the NULL terminator.
1883  //  //
1884  // PARAMETERS:  // PARAMETERS:
1885  //              pSrc - the string to be copied FROM.  May be a char based string, an  //              pSrc - the string to be copied FROM.  May be a char based string, an
1886  //                         MBCS string (in Win32 builds) or a wide string (wchar_t).  //                         MBCS string (in Win32 builds) or a wide string (wchar_t).
1887  //              pSrc - the string to be copied TO.  Also may be either MBCS or wide  //              pSrc - the string to be copied TO.  Also may be either MBCS or wide
# Line 1878  inline DWORD ssfmtmsg(DWORD dwFlags, LPC Line 1897  inline DWORD ssfmtmsg(DWORD dwFlags, LPC
1897  // RETURN VALUE: none  // RETURN VALUE: none
1898  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1899  template < typename CT1, typename CT2 >  template < typename CT1, typename CT2 >
1900      inline int sscpycvt(CT1 * pDst, const CT2 * pSrc, int nMax)  inline int sscpycvt(CT1 * pDst, const CT2 * pSrc, int nMax)
1901  {  {
1902      // Note -- we assume pDst is big enough to hold pSrc.  If not, we're in      // Note -- we assume pDst is big enough to hold pSrc.  If not, we're in
1903      // big trouble.  No bounds checking.  Caveat emptor.      // big trouble.  No bounds checking.  Caveat emptor.
# Line 1924  inline int sscpycvt(PWSTR pDst, PCSTR pS Line 1943  inline int sscpycvt(PWSTR pDst, PCSTR pS
1943  }  }
1944    
1945  template < typename CT1, typename CT2 >  template < typename CT1, typename CT2 >
1946      inline int sscpy(CT1 * pDst, const CT2 * pSrc, int nMax, int nLen)  inline int sscpy(CT1 * pDst, const CT2 * pSrc, int nMax, int nLen)
1947  {  {
1948      return sscpycvt(pDst, pSrc, SSMIN(nMax, nLen));      return sscpycvt(pDst, pSrc, SSMIN(nMax, nLen));
1949  }  }
1950  template < typename CT1, typename CT2 >  template < typename CT1, typename CT2 >
1951      inline int sscpy(CT1 * pDst, const CT2 * pSrc, int nMax)  inline int sscpy(CT1 * pDst, const CT2 * pSrc, int nMax)
1952  {  {
1953      return sscpycvt(pDst, pSrc, SSMIN(nMax, sslen(pSrc)));      return sscpycvt(pDst, pSrc, SSMIN(nMax, sslen(pSrc)));
1954  }  }
1955  template < typename CT1, typename CT2 >  template < typename CT1, typename CT2 >
1956      inline int sscpy(CT1 * pDst, const CT2 * pSrc)  inline int sscpy(CT1 * pDst, const CT2 * pSrc)
1957  {  {
1958      return sscpycvt(pDst, pSrc, sslen(pSrc));      return sscpycvt(pDst, pSrc, sslen(pSrc));
1959  }  }
1960  template < typename CT1, typename CT2 >  template < typename CT1, typename CT2 >
1961      inline int sscpy(CT1 * pDst, const std::basic_string < CT2 > &sSrc,  inline int sscpy(CT1 * pDst, const std::basic_string < CT2 > &sSrc,
1962                       int nMax)                   int nMax)
1963  {  {
1964      return sscpycvt(pDst, sSrc.c_str(), SSMIN(nMax, (int) sSrc.length()));      return sscpycvt(pDst, sSrc.c_str(), SSMIN(nMax, (int) sSrc.length()));
1965  }  }
1966  template < typename CT1, typename CT2 >  template < typename CT1, typename CT2 >
1967      inline int sscpy(CT1 * pDst, const std::basic_string < CT2 > &sSrc)  inline int sscpy(CT1 * pDst, const std::basic_string < CT2 > &sSrc)
1968  {  {
1969      return sscpycvt(pDst, sSrc.c_str(), (int) sSrc.length());      return sscpycvt(pDst, sSrc.c_str(), (int) sSrc.length());
1970  }  }
1971    
1972  #ifdef SS_INC_COMDEF  #ifdef SS_INC_COMDEF
1973  template < typename CT1 >  template < typename CT1 >
1974      inline int sscpy(CT1 * pDst, const _bstr_t & bs, int nMax)  inline int sscpy(CT1 * pDst, const _bstr_t & bs, int nMax)
1975  {  {
1976      return sscpycvt(pDst, static_cast < PCOLESTR > (bs),      return sscpycvt(pDst, static_cast < PCOLESTR > (bs),
1977                      SSMIN(nMax, static_cast < int >(bs.length())));                      SSMIN(nMax, static_cast < int >(bs.length())));
1978  }  }
1979  template < typename CT1 > inline int sscpy(CT1 * pDst, const _bstr_t & bs)  template < typename CT1 >
1980    inline int sscpy(CT1 * pDst, const _bstr_t & bs)
1981  {  {
1982      return sscpy(pDst, bs, static_cast < int >(bs.length()));      return sscpy(pDst, bs, static_cast < int >(bs.length()));
1983  }  }
# Line 1969  template < typename CT1 > inline int ssc Line 1989  template < typename CT1 > inline int ssc
1989  // -----------------------------------------------------------------------------  // -----------------------------------------------------------------------------
1990    
1991  template < typename CT >  template < typename CT >
1992      struct SSToUpper:public std::binary_function < CT, std::locale, CT >  struct SSToUpper:public std::binary_function < CT, std::locale, CT >
1993  {  {
1994      inline CT operator() (const CT & t, const std::locale & loc) const      inline CT operator() (const CT & t, const std::locale & loc) const
1995      {      {
# Line 1977  template < typename CT > Line 1997  template < typename CT >
1997      }      }
1998  };  };
1999  template < typename CT >  template < typename CT >
2000      struct SSToLower:public std::binary_function < CT, std::locale, CT >  struct SSToLower:public std::binary_function < CT, std::locale, CT >
2001  {  {
2002      inline CT operator() (const CT & t, const std::locale & loc) const      inline CT operator() (const CT & t, const std::locale & loc) const
2003      {      {
# Line 1994  template < typename CT > Line 2014  template < typename CT >
2014  //      inline bool operator() (CT t) { return !std::isspace(t, loc); }  //      inline bool operator() (CT t) { return !std::isspace(t, loc); }
2015  //};  //};
2016  template < typename CT >  template < typename CT >
2017      struct NotSpace:public std::unary_function < CT, bool >  struct NotSpace:public std::unary_function < CT, bool >
2018  {  {
2019      // DINKUMWARE BUG:      // DINKUMWARE BUG:
2020      // Note -- using std::isspace in a COM DLL gives us access violations      // Note -- using std::isspace in a COM DLL gives us access violations
# Line 2009  template < typename CT > Line 2029  template < typename CT >
2029      // iswspace() from the CRT unless they specify SS_ANSI      // iswspace() from the CRT unless they specify SS_ANSI
2030    
2031      const std::locale loc;      const std::locale loc;
2032    NotSpace(const std::locale & locArg = std::locale()):loc(locArg) {      NotSpace(const std::locale & locArg = std::locale()):loc(locArg)
2033      }      {}
2034      bool operator() (CT t) const      bool operator() (CT t) const
2035      {      {
2036          return !std::isspace(t, loc);          return !std::isspace(t, loc);
# Line 2033  template < typename CT > Line 2053  template < typename CT >
2053  //              easy to use as the MFC CString class.  //              easy to use as the MFC CString class.
2054  //  //
2055  //              Note that although this is a template, it makes the assumption that the  //              Note that although this is a template, it makes the assumption that the
2056  //              template argument (CT, the character type) is either char or wchar_t.    //              template argument (CT, the character type) is either char or wchar_t.
2057  // =============================================================================  // =============================================================================
2058    
2059  //#define CStdStr _SS   // avoid compiler warning 4786  //#define CStdStr _SS   // avoid compiler warning 4786
# Line 2042  template < typename CT > Line 2062  template < typename CT >
2062  //    PCSTR  FmtArg(const std::string& arg)  { return arg.c_str(); }  //    PCSTR  FmtArg(const std::string& arg)  { return arg.c_str(); }
2063  //    PCWSTR FmtArg(const std::wstring& arg) { return arg.c_str(); }  //    PCWSTR FmtArg(const std::wstring& arg) { return arg.c_str(); }
2064    
2065  template < typename ARG > struct FmtArg  template < typename ARG >
2066    struct FmtArg
2067  {  {
2068      explicit FmtArg(const ARG & arg):a_(arg)      explicit FmtArg(const ARG & arg):a_(arg)
2069      {      {}
     }  
2070      const ARG & operator() () const      const ARG & operator() () const
2071      {      {
2072          return a_;          return a_;
2073      }      }
2074      const ARG & a_;      const ARG & a_;
2075    private:  private:
2076      FmtArg & operator=(const FmtArg &)      FmtArg & operator=(const FmtArg &)
2077      {      {
2078          return *this;          return *this;
2079      }      }
2080  };  };
2081    
2082  template < typename CT > class CStdStr:public std::basic_string < CT > {  template < typename CT >
2083      // Typedefs for shorter names.  Using these names also appears to help  class CStdStr:public std::basic_string < CT >
2084      // us avoid some ambiguities that otherwise arise on some platforms  {
2085            // Typedefs for shorter names.  Using these names also appears to help
2086            // us avoid some ambiguities that otherwise arise on some platforms
2087    
2088  #define MYBASE std::basic_string<CT>    // my base class  #define MYBASE std::basic_string<CT>    // my base class
2089      //typedef typename std::basic_string<CT>                MYBASE;  // my base class          //typedef typename std::basic_string<CT>                MYBASE;  // my base class
2090      typedef CStdStr < CT > MYTYPE;      // myself          typedef CStdStr < CT > MYTYPE;      // myself
2091      typedef typename MYBASE::const_pointer PCMYSTR;     // PCSTR or PCWSTR          typedef typename MYBASE::const_pointer PCMYSTR;     // PCSTR or PCWSTR
2092      typedef typename MYBASE::pointer PMYSTR;    // PSTR or PWSTR          typedef typename MYBASE::pointer PMYSTR;    // PSTR or PWSTR
2093      typedef typename MYBASE::iterator MYITER;   // my iterator type          typedef typename MYBASE::iterator MYITER;   // my iterator type
2094      typedef typename MYBASE::const_iterator MYCITER;    // you get the idea...          typedef typename MYBASE::const_iterator MYCITER;    // you get the idea...
2095      typedef typename MYBASE::reverse_iterator MYRITER;          typedef typename MYBASE::reverse_iterator MYRITER;
2096      typedef typename MYBASE::size_type MYSIZE;          typedef typename MYBASE::size_type MYSIZE;
2097      typedef typename MYBASE::value_type MYVAL;          typedef typename MYBASE::value_type MYVAL;
2098      typedef typename MYBASE::allocator_type MYALLOC;          typedef typename MYBASE::allocator_type MYALLOC;
2099    
2100    public:      public:
2101      // shorthand conversion from PCTSTR to string resource ID          // shorthand conversion from PCTSTR to string resource ID
2102  #define SSRES(pctstr)  LOWORD(reinterpret_cast<unsigned long>(pctstr))  #define SSRES(pctstr)  LOWORD(reinterpret_cast<unsigned long>(pctstr))
2103    
2104      bool TryLoad(const void *pT)          bool TryLoad(const void *pT)
2105      {          {
2106          bool bLoaded = false;              bool bLoaded = false;
2107    
2108  #if defined(SS_WIN32) && !defined(SS_ANSI)  #if defined(SS_WIN32) && !defined(SS_ANSI)
2109          if ((pT != NULL) && SS_IS_INTRESOURCE(pT)) {  
2110              UINT nId = LOWORD(reinterpret_cast < unsigned long >(pT));              if ((pT != NULL) && SS_IS_INTRESOURCE(pT)) {
2111              if (!LoadString(nId)) {                  UINT nId = LOWORD(reinterpret_cast < unsigned long >(pT));
2112                  TRACE(_T("Can't load string %u\n"), SSRES(pT));                  if (!LoadString(nId)) {
2113                        TRACE(_T("Can't load string %u\n"), SSRES(pT));
2114                    }
2115                    bLoaded = true;
2116              }              }
             bLoaded = true;  
         }  
2117  #endif  #endif
2118    
2119          return bLoaded;              return bLoaded;
2120      }          }
2121    
2122    
2123      // CStdStr inline constructors          // CStdStr inline constructors
2124      CStdStr() {          CStdStr()
2125      }          {}
2126    
2127    CStdStr(const MYTYPE & str):MYBASE(SSREF(str)) {          CStdStr(const MYTYPE & str):MYBASE(SSREF(str))
2128      }          {}
2129    
2130      CStdStr(const std::string & str)          CStdStr(const std::string & str)
2131      {          {
2132          ssasn(*this, SSREF(str));              ssasn(*this, SSREF(str));
2133      }          }
2134    
2135      CStdStr(const std::wstring & str)          CStdStr(const std::wstring & str)
2136      {          {
2137          ssasn(*this, SSREF(str));              ssasn(*this, SSREF(str));
2138      }          }
2139    
2140    CStdStr(PCMYSTR pT, MYSIZE n):MYBASE(pT, n) {          CStdStr(PCMYSTR pT, MYSIZE n):MYBASE(pT, n)
2141      }          {}
2142    
2143  #ifdef SS_UNSIGNED  #ifdef SS_UNSIGNED
2144      CStdStr(PCUSTR pU) {  
2145          *this = reinterpret_cast < PCSTR > (pU);          CStdStr(PCUSTR pU)
2146      }          {
2147                *this = reinterpret_cast < PCSTR > (pU);
2148            }
2149  #endif  #endif
2150    
2151      CStdStr(PCSTR pA) {          CStdStr(PCSTR pA)
2152            {
2153  #ifdef SS_ANSI  #ifdef SS_ANSI
         *this = pA;  
 #else  
         if (!TryLoad(pA))  
2154              *this = pA;              *this = pA;
2155    #else
2156    
2157                if (!TryLoad(pA))
2158                    *this = pA;
2159  #endif  #endif
     }  
2160    
2161      CStdStr(PCWSTR pW) {          }
2162    
2163            CStdStr(PCWSTR pW)
2164            {
2165  #ifdef SS_ANSI  #ifdef SS_ANSI
         *this = pW;  
 #else  
         if (!TryLoad(pW))  
2166              *this = pW;              *this = pW;
2167    #else
2168    
2169                if (!TryLoad(pW))
2170                    *this = pW;
2171  #endif  #endif
     }  
2172    
2173      CStdStr(MYCITER first, MYCITER last)          }
   :    MYBASE(first, last) {  
     }  
2174    
2175      CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC & al = MYALLOC())          CStdStr(MYCITER first, MYCITER last)
2176    :    MYBASE(nSize, ch, al) {                  :    MYBASE(first, last)
2177      }          {}
2178    
2179            CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC & al = MYALLOC())
2180                    :    MYBASE(nSize, ch, al)
2181            {}
2182    
2183  #ifdef SS_INC_COMDEF  #ifdef SS_INC_COMDEF
2184      CStdStr(const _bstr_t & bstr)  
2185      {          CStdStr(const _bstr_t & bstr)
2186          if (bstr.length() > 0)          {
2187              this->append(static_cast < PCMYSTR > (bstr), bstr.length());              if (bstr.length() > 0)
2188      }                  this->append(static_cast < PCMYSTR > (bstr), bstr.length());
2189            }
2190  #endif  #endif
2191    
2192      // CStdStr inline assignment operators -- the ssasn function now takes care          // CStdStr inline assignment operators -- the ssasn function now takes care
2193      // of fixing  the MSVC assignment bug (see knowledge base article Q172398).          // of fixing  the MSVC assignment bug (see knowledge base article Q172398).
2194      MYTYPE & operator=(const MYTYPE & str)          MYTYPE & operator=(const MYTYPE & str)
2195      {          {
2196          ssasn(*this, str);              ssasn(*this, str);
2197          return *this;              return *this;
2198      }          }
2199    
2200      MYTYPE & operator=(const std::string & str) {          MYTYPE & operator=(const std::string & str)
2201          ssasn(*this, str);          {
2202          return *this;              ssasn(*this, str);
2203      }              return *this;
2204            }
2205    
2206      MYTYPE & operator=(const std::wstring & str) {          MYTYPE & operator=(const std::wstring & str)
2207          ssasn(*this, str);          {
2208          return *this;              ssasn(*this, str);
2209      }              return *this;
2210            }
2211    
2212      MYTYPE & operator=(PCSTR pA) {          MYTYPE & operator=(PCSTR pA)
2213          ssasn(*this, pA);          {
2214          return *this;              ssasn(*this, pA);
2215      }              return *this;
2216            }
2217    
2218      MYTYPE & operator=(PCWSTR pW) {          MYTYPE & operator=(PCWSTR pW)
2219          ssasn(*this, pW);          {
2220          return *this;              ssasn(*this, pW);
2221      }              return *this;
2222            }
2223    
2224  #ifdef SS_UNSIGNED  #ifdef SS_UNSIGNED
2225      MYTYPE & operator=(PCUSTR pU) {          MYTYPE & operator=(PCUSTR pU)
2226          ssasn(*this, reinterpret_cast < PCSTR > (pU));          {
2227          return *this;              ssasn(*this, reinterpret_cast < PCSTR > (pU));
2228      }              return *this;
2229            }
2230  #endif  #endif
2231    
2232      MYTYPE & operator=(CT t) {          MYTYPE & operator=(CT t)
2233          Q172398(*this);          {
2234          this->assign(1, t);              Q172398(*this);
2235          return *this;              this->assign(1, t);
     }  
   
 #ifdef SS_INC_COMDEF  
     MYTYPE & operator=(const _bstr_t & bstr) {  
         if (bstr.length() > 0) {  
             this->assign(static_cast < PCMYSTR > (bstr), bstr.length());  
2236              return *this;              return *this;
2237          }          }
2238          else {  
2239              this->erase();  #ifdef SS_INC_COMDEF
2240              return *this;          MYTYPE & operator=(const _bstr_t & bstr)
2241            {
2242                if (bstr.length() > 0) {
2243                    this->assign(static_cast < PCMYSTR > (bstr), bstr.length());
2244                    return *this;
2245                } else {
2246                    this->erase();
2247                    return *this;
2248                }
2249          }          }
     }  
2250  #endif  #endif
2251    
2252    
2253      // Overloads  also needed to fix the MSVC assignment bug (KB: Q172398)          // Overloads  also needed to fix the MSVC assignment bug (KB: Q172398)
2254      //  *** Thanks to Pete The Plumber for catching this one ***          //  *** Thanks to Pete The Plumber for catching this one ***
2255      // They also are compiled if you have explicitly turned off refcounting          // They also are compiled if you have explicitly turned off refcounting
2256  #if ( defined(_MSC_VER) && ( _MSC_VER < 1200 ) ) || defined(SS_NO_REFCOUNT)  #if ( defined(_MSC_VER) && ( _MSC_VER < 1200 ) ) || defined(SS_NO_REFCOUNT)
2257    
2258      MYTYPE & assign(const MYTYPE & str) {          MYTYPE & assign(const MYTYPE & str)
2259          Q172398(*this);          {
2260          sscpy(GetBuffer(str.size() + 1), SSREF(str));              Q172398(*this);
2261          this->ReleaseBuffer(str.size());              sscpy(GetBuffer(str.size() + 1), SSREF(str));
2262          return *this;              this->ReleaseBuffer(str.size());
2263      }              return *this;
2264            }
     MYTYPE & assign(const MYTYPE & str, MYSIZE nStart, MYSIZE nChars) {  
         // This overload of basic_string::assign is supposed to assign up to  
         // <nChars> or the NULL terminator, whichever comes first.  Since we  
         // are about to call a less forgiving overload (in which <nChars>  
         // must be a valid length), we must adjust the length here to a safe  
         // value.  Thanks to Ullrich Pollähne for catching this bug  
   
         nChars = SSMIN(nChars, str.length() - nStart);  
         MYTYPE strTemp(str.c_str() + nStart, nChars);  
         Q172398(*this);  
         this->assign(strTemp);  
         return *this;  
     }  
   
     MYTYPE & assign(const MYBASE & str) {  
         ssasn(*this, str);  
         return *this;  
     }  
   
     MYTYPE & assign(const MYBASE & str, MYSIZE nStart, MYSIZE nChars) {  
         // This overload of basic_string::assign is supposed to assign up to  
         // <nChars> or the NULL terminator, whichever comes first.  Since we  
         // are about to call a less forgiving overload (in which <nChars>  
         // must be a valid length), we must adjust the length here to a safe  
         // value. Thanks to Ullrich Pollähne for catching this bug  
   
         nChars = SSMIN(nChars, str.length() - nStart);  
2265    
2266          // Watch out for assignment to self          MYTYPE & assign(const MYTYPE & str, MYSIZE nStart, MYSIZE nChars)
2267            {
2268                // This overload of basic_string::assign is supposed to assign up to
2269                // <nChars> or the NULL terminator, whichever comes first.  Since we
2270                // are about to call a less forgiving overload (in which <nChars>
2271                // must be a valid length), we must adjust the length here to a safe
2272                // value.  Thanks to Ullrich Pollähne for catching this bug
2273    
2274          if (this == &str) {              nChars = SSMIN(nChars, str.length() - nStart);
2275              MYTYPE strTemp(str.c_str() + nStart, nChars);              MYTYPE strTemp(str.c_str() + nStart, nChars);
             static_cast < MYBASE * >(this)->assign(strTemp);  
         }  
         else {  
2276              Q172398(*this);              Q172398(*this);
2277              static_cast < MYBASE * >(this)->assign(str.c_str() + nStart,              this->assign(strTemp);
2278                                                     nChars);              return *this;
2279          }          }
         return *this;  
     }  
2280    
2281      MYTYPE & assign(const CT * pC, MYSIZE nChars) {          MYTYPE & assign(const MYBASE & str)
2282          // Q172398 only fix -- erase before assigning, but not if we're          {
2283          // assigning from our own buffer              ssasn(*this, str);
2284                return *this;
2285            }
2286    
2287  #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )          MYTYPE & assign(const MYBASE & str, MYSIZE nStart, MYSIZE nChars)
2288          if (!this->empty() &&          {
2289              (pC < this->data() || pC > this->data() + this->capacity())) {              // This overload of basic_string::assign is supposed to assign up to
2290              this->erase();              // <nChars> or the NULL terminator, whichever comes first.  Since we
2291                // are about to call a less forgiving overload (in which <nChars>
2292                // must be a valid length), we must adjust the length here to a safe
2293                // value. Thanks to Ullrich Pollähne for catching this bug
2294    
2295                nChars = SSMIN(nChars, str.length() - nStart);
2296    
2297                // Watch out for assignment to self
2298    
2299                if (this == &str) {
2300                    MYTYPE strTemp(str.c_str() + nStart, nChars);
2301                    static_cast < MYBASE * >(this)->assign(strTemp);
2302                } else {
2303                    Q172398(*this);
2304                    static_cast < MYBASE * >(this)->assign(str.c_str() + nStart,
2305                                                           nChars);
2306                }
2307                return *this;
2308          }          }
2309    
2310            MYTYPE & assign(const CT * pC, MYSIZE nChars)
2311            {
2312                // Q172398 only fix -- erase before assigning, but not if we're
2313                // assigning from our own buffer
2314    
2315    #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
2316                if (!this->empty() &&
2317                        (pC < this->data() || pC > this->data() + this->capacity())) {
2318                    this->erase();
2319                }
2320  #endif  #endif
2321          Q172398(*this);              Q172398(*this);
2322          static_cast < MYBASE * >(this)->assign(pC, nChars);              static_cast < MYBASE * >(this)->assign(pC, nChars);
2323          return *this;              return *this;
2324      }          }
2325    
2326      MYTYPE & assign(MYSIZE nChars, MYVAL val) {          MYTYPE & assign(MYSIZE nChars, MYVAL val)
2327          Q172398(*this);          {
2328          static_cast < MYBASE * >(this)->assign(nChars, val);              Q172398(*this);
2329          return *this;              static_cast < MYBASE * >(this)->assign(nChars, val);
2330      }              return *this;
2331            }
2332    
2333      MYTYPE & assign(const CT * pT) {          MYTYPE & assign(const CT * pT)
2334          return this->assign(pT, MYBASE::traits_type::length(pT));          {
2335      }              return this->assign(pT, MYBASE::traits_type::length(pT));
2336            }
2337    
2338      MYTYPE & assign(MYCITER iterFirst, MYCITER iterLast) {          MYTYPE & assign(MYCITER iterFirst, MYCITER iterLast)
2339            {
2340  #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )  #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 )
2341          // Q172398 fix.  don't call erase() if we're assigning from ourself              // Q172398 fix.  don't call erase() if we're assigning from ourself
2342          if (iterFirst < this->begin() ||              if (iterFirst < this->begin() ||
2343              iterFirst > this->begin() + this->size()) {                      iterFirst > this->begin() + this->size()) {
2344              this->erase()                  this->erase()
2345          }              }
2346  #endif  #endif
2347          this->replace(this->begin(), this->end(), iterFirst, iterLast);              this->replace(this->begin(), this->end(), iterFirst, iterLast);
2348          return *this;              return *this;
2349      }          }
2350  #endif  #endif
2351    
2352    
2353      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
2354      // CStdStr inline concatenation.          // CStdStr inline concatenation.
2355      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
2356      MYTYPE & operator+=(const MYTYPE & str) {          MYTYPE & operator+=(const MYTYPE & str)
2357          ssadd(*this, str);          {
2358          return *this;              ssadd(*this, str);
2359      }              return *this;
2360            }
2361    
2362      MYTYPE & operator+=(const std::string & str) {          MYTYPE & operator+=(const std::string & str)
2363          ssadd(*this, str);          {
2364          return *this;              ssadd(*this, str);
2365      }              return *this;
2366            }
2367    
2368      MYTYPE & operator+=(const std::wstring & str) {          MYTYPE & operator+=(const std::wstring & str)
2369          ssadd(*this, str);          {
2370          return *this;              ssadd(*this, str);
2371      }              return *this;
2372            }
2373    
2374      MYTYPE & operator+=(PCSTR pA) {          MYTYPE & operator+=(PCSTR pA)
2375          ssadd(*this, pA);          {
2376          return *this;              ssadd(*this, pA);
2377      }              return *this;
2378            }
2379    
2380      MYTYPE & operator+=(PCWSTR pW) {          MYTYPE & operator+=(PCWSTR pW)
2381          ssadd(*this, pW);          {
2382          return *this;              ssadd(*this, pW);
2383      }              return *this;
2384            }
2385    
2386      MYTYPE & operator+=(CT t) {          MYTYPE & operator+=(CT t)
2387          this->append(1, t);          {
2388          return *this;              this->append(1, t);
2389      }              return *this;
2390            }
2391  #ifdef SS_INC_COMDEF            // if we have _bstr_t, define a += for it too.  #ifdef SS_INC_COMDEF            // if we have _bstr_t, define a += for it too.
2392      MYTYPE & operator+=(const _bstr_t & bstr) {          MYTYPE & operator+=(const _bstr_t & bstr)
2393          return this->operator+=(static_cast < PCMYSTR > (bstr));          {
2394      }              return this->operator+=(static_cast < PCMYSTR > (bstr));
2395            }
2396  #endif  #endif
2397    
2398    
2399      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
2400      // Case changing functions          // Case changing functions
2401      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
   
     MYTYPE & ToUpper(const std::locale & loc = std::locale()) {  
         // Note -- if there are any MBCS character sets in which the lowercase  
         // form a character takes up a different number of bytes than the  
         // uppercase form, this would probably not work...  
   
         std::transform(this->begin(),  
                        this->end(),  
                        this->begin(), std::bind2nd(SSToUpper < CT > (), loc));  
   
         // ...but if it were, this would probably work better.  Also, this way  
         // seems to be a bit faster when anything other then the "C" locale is  
         // used...  
   
 //              if ( !empty() )  
 //              {  
 //                      ssupr(this->GetBuf(), this->size(), loc);  
 //                      this->RelBuf();  
 //              }  
2402    
2403          return *this;          MYTYPE & ToUpper(const std::locale & loc = std::locale())
2404      }          {
2405                // Note -- if there are any MBCS character sets in which the lowercase
2406                // form a character takes up a different number of bytes than the
2407                // uppercase form, this would probably not work...
2408    
2409                std::transform(this->begin(),
2410                               this->end(),
2411                               this->begin(), std::bind2nd(SSToUpper < CT > (), loc));
2412    
2413                // ...but if it were, this would probably work better.  Also, this way
2414                // seems to be a bit faster when anything other then the "C" locale is
2415                // used...
2416    
2417                //              if ( !empty() )
2418                //              {
2419                //                      ssupr(this->GetBuf(), this->size(), loc);
2420                //                      this->RelBuf();
2421                //              }
2422    
2423      MYTYPE & ToLower(const std::locale & loc = std::locale()) {              return *this;
2424          // Note -- if there are any MBCS character sets in which the lowercase          }
         // form a character takes up a different number of bytes than the  
         // uppercase form, this would probably not work...  
   
         std::transform(this->begin(),  
                        this->end(),  
                        this->begin(), std::bind2nd(SSToLower < CT > (), loc));  
   
         // ...but if it were, this would probably work better.  Also, this way  
         // seems to be a bit faster when anything other then the "C" locale is  
         // used...  
   
 //              if ( !empty() )  
 //              {  
 //                      sslwr(this->GetBuf(), this->size(), loc);  
 //                      this->RelBuf();  
 //              }  
         return *this;  
     }  
2425    
2426            MYTYPE & ToLower(const std::locale & loc = std::locale())
2427            {
2428                // Note -- if there are any MBCS character sets in which the lowercase
2429                // form a character takes up a different number of bytes than the
2430                // uppercase form, this would probably not work...
2431    
2432                std::transform(this->begin(),
2433                               this->end(),
2434                               this->begin(), std::bind2nd(SSToLower < CT > (), loc));
2435    
2436                // ...but if it were, this would probably work better.  Also, this way
2437                // seems to be a bit faster when anything other then the "C" locale is
2438                // used...
2439    
2440                //              if ( !empty() )
2441                //              {
2442                //                      sslwr(this->GetBuf(), this->size(), loc);
2443                //                      this->RelBuf();
2444                //              }
2445                return *this;
2446            }
2447    
     MYTYPE & Normalize() {  
         return Trim().ToLower();  
     }  
2448    
2449            MYTYPE & Normalize()
2450            {
2451                return Trim().ToLower();
2452            }
2453    
     // -------------------------------------------------------------------------  
     // CStdStr -- Direct access to character buffer.  In the MS' implementation,  
     // the at() function that we use here also calls _Freeze() providing us some  
     // protection from multithreading problems associated with ref-counting.  
     // In VC 7 and later, of course, the ref-counting stuff is gone.  
     // -------------------------------------------------------------------------  
   
     CT *GetBuf(int nMinLen = -1) {  
         if (static_cast < int >(this->size()) < nMinLen)  
             this->resize(static_cast < MYSIZE > (nMinLen));  
2454    
2455          return this->empty()? const_cast <          // -------------------------------------------------------------------------
2456              CT * >(this->data()) : &(this->at(0));          // CStdStr -- Direct access to character buffer.  In the MS' implementation,
2457      }          // the at() function that we use here also calls _Freeze() providing us some
2458            // protection from multithreading problems associated with ref-counting.
2459            // In VC 7 and later, of course, the ref-counting stuff is gone.
2460            // -------------------------------------------------------------------------
2461    
2462      CT *SetBuf(int nLen)          CT *GetBuf(int nMinLen = -1)
2463      {          {
2464          nLen = (nLen > 0 ? nLen : 0);              if (static_cast < int >(this->size())
2465          if (this->capacity() < 1 && nLen == 0)                      < nMinLen)
2466              this->resize(1);                  this->resize(static_cast < MYSIZE > (nMinLen));
2467    
2468          this->resize(static_cast < MYSIZE > (nLen));              return this->empty()? const_cast <
2469          return const_cast < CT * >(this->data());                     CT * >(this->data()) : &(this->at(0));
2470      }          }
     void RelBuf(int nNewLen = -1) {  
         this->resize(static_cast < MYSIZE > (nNewLen > -1 ? nNewLen :  
                                              sslen(this->c_str())));  
     }  
2471    
2472      void BufferRel()          CT *SetBuf(int nLen)
2473      {          {
2474          RelBuf();              nLen = (nLen > 0 ? nLen : 0);
2475      }                           // backwards compatability              if (this->capacity() < 1 && nLen == 0)
2476      CT *Buffer()                  this->resize(1);
     {  
         return GetBuf();  
     }                           // backwards compatability  
     CT *BufferSet(int nLen)  
     {  
         return SetBuf(nLen);  
     }                           // backwards compatability  
2477    
2478      bool Equals(const CT * pT, bool bUseCase = false) const              this->resize(static_cast < MYSIZE > (nLen));
2479      {              return const_cast < CT * >(this->data());
2480          return 0 ==          }
2481              (bUseCase ? this->compare(pT) : ssicmp(this->c_str(), pT));          void RelBuf(int nNewLen = -1)
2482      }          {
2483                this->resize(static_cast < MYSIZE > (nNewLen > -1 ? nNewLen :
2484                                                     sslen(this->c_str())));
2485            }
2486    
2487      // -------------------------------------------------------------------------          void BufferRel()
2488      // FUNCTION:  CStdStr::Load          {
2489      // REMARKS:              RelBuf();
2490      //              Loads string from resource specified by nID          }                           // backwards compatability
2491      //          CT *Buffer()
2492      // PARAMETERS:          {
2493      //              nID - resource Identifier.  Purely a Win32 thing in this case              return GetBuf();
2494      //          }                           // backwards compatability
2495      // RETURN VALUE:          CT *BufferSet(int nLen)
2496      //              true if successful, false otherwise          {
2497      // -------------------------------------------------------------------------              return SetBuf(nLen);
2498            }                           // backwards compatability
2499    
2500  #ifndef SS_ANSI          bool Equals(const CT * pT, bool bUseCase = false) const
2501            {
2502                return 0 ==
2503                       (bUseCase ? this->compare(pT) : ssicmp(this->c_str(), pT));
2504            }
2505    
2506      bool Load(UINT nId, HMODULE hModule = NULL) {          // -------------------------------------------------------------------------
2507          bool bLoaded = false;   // set to true of we succeed.          // FUNCTION:  CStdStr::Load
2508            // REMARKS:
2509            //              Loads string from resource specified by nID
2510            //
2511            // PARAMETERS:
2512            //              nID - resource Identifier.  Purely a Win32 thing in this case
2513            //
2514            // RETURN VALUE:
2515            //              true if successful, false otherwise
2516            // -------------------------------------------------------------------------
2517    
2518  #ifdef _MFC_VER                 // When in Rome (or MFC land)...  #ifndef SS_ANSI
2519    
2520          // If they gave a resource handle, use it.  Note - this is archaic          bool Load(UINT nId, HMODULE hModule = NULL)
2521          // and not really what I would recommend.  But then again, in MFC          {
2522          // land, you ought to be using CString for resources anyway since              bool bLoaded = false;   // set to true of we succeed.
         // it walks the resource chain for you.  
2523    
2524          HMODULE hModuleOld = NULL;  #ifdef _MFC_VER                 // When in Rome (or MFC land)...
2525    
2526          if (NULL != hModule) {              // If they gave a resource handle, use it.  Note - this is archaic
2527              hModuleOld = AfxGetResourceHandle();              // and not really what I would recommend.  But then again, in MFC
2528              AfxSetResourceHandle(hModule);              // land, you ought to be using CString for resources anyway since
2529          }              // it walks the resource chain for you.
2530    
2531                HMODULE hModuleOld = NULL;
2532    
2533                if (NULL != hModule) {
2534                    hModuleOld = AfxGetResourceHandle();
2535                    AfxSetResourceHandle(hModule);
2536                }
2537    
2538          // ...load the string              // ...load the string
2539    
2540          CString strRes;              CString strRes;
2541          bLoaded = FALSE != strRes.LoadString(nId);              bLoaded = FALSE != strRes.LoadString(nId);
2542    
2543          // ...and if we set the resource handle, restore it.              // ...and if we set the resource handle, restore it.
2544    
2545          if (NULL != hModuleOld)              if (NULL != hModuleOld)
2546              AfxSetResourceHandle(hModule);                  AfxSetResourceHandle(hModule);
2547    
2548          if (bLoaded)              if (bLoaded)
2549              *this = strRes;                  *this = strRes;
2550    
2551  #else // otherwise make our own hackneyed version of CString's Load  #else // otherwise make our own hackneyed version of CString's Load
2552    
2553          // Get the resource name and module handle              // Get the resource name and module handle
2554    
2555          if (NULL == hModule)              if (NULL == hModule)
2556              hModule = GetResourceHandle();                  hModule = GetResourceHandle();
2557    
2558          PCTSTR szName = MAKEINTRESOURCE((nId >> 4) + 1);        // lifted              PCTSTR szName = MAKEINTRESOURCE((nId >> 4) + 1);        // lifted
2559          DWORD dwSize = 0;              DWORD dwSize = 0;
2560    
2561          // No sense continuing if we can't find the resource              // No sense continuing if we can't find the resource
2562    
2563          HRSRC hrsrc =::FindResource(hModule, szName, RT_STRING);              HRSRC hrsrc =::FindResource(hModule, szName, RT_STRING);
2564    
2565          if (NULL == hrsrc) {              if (NULL == hrsrc) {
2566              TRACE(_T("Cannot find resource %d: 0x%X"), nId,::GetLastError());                  TRACE(_T("Cannot find resource %d: 0x%X"), nId,::GetLastError());
2567          }              } else if (0 == (dwSize =::SizeofResource(hModule, hrsrc) / sizeof(CT))) {
2568          else if (0 == (dwSize =::SizeofResource(hModule, hrsrc) / sizeof(CT))) {                  TRACE(_T("Cant get size of resource %d 0x%X\n"), nId,
2569              TRACE(_T("Cant get size of resource %d 0x%X\n"), nId,                        GetLastError());
2570                    GetLastError());              } else {
2571          }                  bLoaded = 0 != ssload(hModule, nId, GetBuf(dwSize), dwSize);
2572          else {                  ReleaseBuffer();
2573              bLoaded = 0 != ssload(hModule, nId, GetBuf(dwSize), dwSize);              }
             ReleaseBuffer();  
         }  
2574    
2575  #endif // #ifdef _MFC_VER  #endif // #ifdef _MFC_VER
2576    
2577          if (!bLoaded)              if (!bLoaded)
2578              TRACE(_T("String not loaded 0x%X\n"),::GetLastError());                  TRACE(_T("String not loaded 0x%X\n"),::GetLastError());
2579    
2580          return bLoaded;              return bLoaded;
2581      }          }
2582    
2583  #endif // #ifdef SS_ANSI  #endif // #ifdef SS_ANSI
2584    
2585      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
2586      // FUNCTION:  CStdStr::Format          // FUNCTION:  CStdStr::Format
2587      //              void _cdecl Formst(CStdStringA& PCSTR szFormat, ...)          //              void _cdecl Formst(CStdStringA& PCSTR szFormat, ...)
2588      //              void _cdecl Format(PCSTR szFormat);          //              void _cdecl Format(PCSTR szFormat);
2589      //                    //
2590      // DESCRIPTION:          // DESCRIPTION:
2591      //              This function does sprintf/wsprintf style formatting on CStdStringA          //              This function does sprintf/wsprintf style formatting on CStdStringA
2592      //              objects.  It looks a lot like MFC's CString::Format.  Some people          //              objects.  It looks a lot like MFC's CString::Format.  Some people
2593      //              might even call this identical.  Fortunately, these people are now          //              might even call this identical.  Fortunately, these people are now
2594      //              dead... heh heh.          //              dead... heh heh.
2595      //          //
2596      // PARAMETERS:          // PARAMETERS:
2597      //              nId - ID of string resource holding the format string          //              nId - ID of string resource holding the format string
2598      //              szFormat - a PCSTR holding the format specifiers          //              szFormat - a PCSTR holding the format specifiers
2599      //              argList - a va_list holding the arguments for the format specifiers.          //              argList - a va_list holding the arguments for the format specifiers.
2600      //          //
2601      // RETURN VALUE:  None.          // RETURN VALUE:  None.
2602      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
2603      // formatting (using wsprintf style formatting)          // formatting (using wsprintf style formatting)
2604    
2605      // If they want a Format() function that safely handles string objects          // If they want a Format() function that safely handles string objects
2606      // without casting          // without casting
2607    
2608  #ifdef SS_SAFE_FORMAT  #ifdef SS_SAFE_FORMAT
2609    
2610      // Question:  Joe, you wacky coder you, why do you have so many overloads          // Question:  Joe, you wacky coder you, why do you have so many overloads
2611      //      of the Format() function          //      of the Format() function
2612      // Answer:  One reason only - CString compatability.  In short, by making          // Answer:  One reason only - CString compatability.  In short, by making
2613      //      the Format() function a template this way, I can do strong typing          //      the Format() function a template this way, I can do strong typing
2614      //      and allow people to pass CStdString arguments as fillers for          //      and allow people to pass CStdString arguments as fillers for
2615      //      "%s" format specifiers without crashing their program!  The downside          //      "%s" format specifiers without crashing their program!  The downside
2616      //      is that I need to overload on the number of arguments.   If you are          //      is that I need to overload on the number of arguments.   If you are
2617      //      passing more arguments than I have listed below in any of my          //      passing more arguments than I have listed below in any of my
2618      //      overloads, just add another one.          //      overloads, just add another one.
2619      //          //
2620      //      Yes, yes, this is really ugly.  In essence what I am doing here is          //      Yes, yes, this is really ugly.  In essence what I am doing here is
2621      //      protecting people from a bad (and incorrect) programming practice          //      protecting people from a bad (and incorrect) programming practice
2622      //      that they should not be doing anyway.  I am protecting them from          //      that they should not be doing anyway.  I am protecting them from
2623      //      themselves.  Why am I doing this?  Well, if you had any idea the          //      themselves.  Why am I doing this?  Well, if you had any idea the
2624      //      number of times I've been emailed by people about this          //      number of times I've been emailed by people about this
2625      //      "incompatability" in my code, you wouldn't ask.          //      "incompatability" in my code, you wouldn't ask.
2626    
2627      void Fmt(const CT * szFmt, ...)          void Fmt(const CT * szFmt, ...)
2628      {          {
2629          va_list argList;              va_list argList;
2630          va_start(argList, szFmt);              va_start(argList, szFmt);
2631          FormatV(szFmt, argList);              FormatV(szFmt, argList);
2632          va_end(argList);              va_end(argList);
2633      }          }
2634    
2635  #ifndef SS_ANSI  #ifndef SS_ANSI
2636    
2637      void Format(UINT nId)          void Format(UINT nId)
2638      {          {
2639          MYTYPE strFmt;              MYTYPE strFmt;
2640          if (strFmt.Load(nId))              if (strFmt.Load(nId))
2641              this->swap(strFmt);                  this->swap(strFmt);
2642      }          }
2643      template < class A1 > void Format(UINT nId, const A1 & v)          template < class A1 >
2644      {          void Format(UINT nId, const A1 & v)
2645          MYTYPE strFmt;          {
2646          if (strFmt.Load(nId))              MYTYPE strFmt;
2647              Fmt(strFmt, FmtArg < A1 > (v) ());              if (strFmt.Load(nId))
2648      }                  Fmt(strFmt, FmtArg < A1 > (v) ());
2649      template < class A1, class A2 >          }
2650            template < class A1, class A2 >
2651          void Format(UINT nId, const A1 & v1, const A2 & v2)          void Format(UINT nId, const A1 & v1, const A2 & v2)
2652      {          {
2653          MYTYPE strFmt;              MYTYPE strFmt;
2654          if (strFmt.Load(nId))              if (strFmt.Load(nId))
2655              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) ());                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) ());
2656      }          }
2657      template < class A1, class A2, class A3 >          template < class A1, class A2, class A3 >
2658          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3)          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3)
2659      {          {
2660          MYTYPE strFmt;              MYTYPE strFmt;
2661          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2662              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2663                  FmtArg < A3 > (v3) ());                      FmtArg < A3 > (v3) ());
2664                }
2665          }          }
2666      }          template < class A1, class A2, class A3, class A4 >
     template < class A1, class A2, class A3, class A4 >  
2667          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
2668                      const A4 & v4)                      const A4 & v4)
2669      {          {
2670          MYTYPE strFmt;              MYTYPE strFmt;
2671          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2672              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2673                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) ());                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) ());
2674                }
2675          }          }
2676      }          template < class A1, class A2, class A3, class A4, class A5 >
     template < class A1, class A2, class A3, class A4, class A5 >  
2677          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
2678                      const A4 & v4, const A5 & v5)                      const A4 & v4, const A5 & v5)
2679      {          {
2680          MYTYPE strFmt;              MYTYPE strFmt;
2681          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2682              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2683                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2684                  FmtArg < A5 > (v5) ());                      FmtArg < A5 > (v5) ());
2685                }
2686          }          }
2687      }          template < class A1, class A2, class A3, class A4, class A5, class A6 >
     template < class A1, class A2, class A3, class A4, class A5, class A6 >  
2688          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
2689                      const A4 & v4, const A5 & v5, const A6 & v6)                      const A4 & v4, const A5 & v5, const A6 & v6)
2690      {          {
2691          MYTYPE strFmt;              MYTYPE strFmt;
2692          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2693              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2694                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2695                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) ());                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) ());
2696                }
2697          }          }
2698      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2699          class A7 >          class A7 >
2700          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
2701                      const A4 & v4, const A5 & v5, const A6 & v6,                      const A4 & v4, const A5 & v5, const A6 & v6,
2702                      const A7 & v7)                      const A7 & v7)
2703      {          {
2704          MYTYPE strFmt;              MYTYPE strFmt;
2705          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2706              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2707                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2708                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2709                  FmtArg < A7 > (v7) ());                      FmtArg < A7 > (v7) ());
2710                }
2711          }          }
2712      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2713          class A7, class A8 >          class A7, class A8 >
2714          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
2715                      const A4 & v4, const A5 & v5, const A6 & v6,                      const A4 & v4, const A5 & v5, const A6 & v6,
2716                      const A7 & v7, const A8 & v8)                      const A7 & v7, const A8 & v8)
2717      {          {
2718          MYTYPE strFmt;              MYTYPE strFmt;
2719          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2720              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2721                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2722                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2723                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) ());                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) ());
2724                }
2725          }          }
2726      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2727          class A7, class A8, class A9 >          class A7, class A8, class A9 >
2728          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
2729                      const A4 & v4, const A5 & v5, const A6 & v6,                      const A4 & v4, const A5 & v5, const A6 & v6,
2730                      const A7 & v7, const A8 & v8, const A9 & v9)                      const A7 & v7, const A8 & v8, const A9 & v9)
2731      {          {
2732          MYTYPE strFmt;              MYTYPE strFmt;
2733          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2734              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2735                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2736                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2737                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2738                  FmtArg < A9 > (v9) ());                      FmtArg < A9 > (v9) ());
2739                }
2740          }          }
2741      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2742          class A7, class A8, class A9, class A10 >          class A7, class A8, class A9, class A10 >
2743          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
2744                      const A4 & v4, const A5 & v5, const A6 & v6,                      const A4 & v4, const A5 & v5, const A6 & v6,
2745                      const A7 & v7, const A8 & v8, const A9 & v9,                      const A7 & v7, const A8 & v8, const A9 & v9,
2746                      const A10 & v10)                      const A10 & v10)
2747      {          {
2748          MYTYPE strFmt;              MYTYPE strFmt;
2749          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2750              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2751                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2752                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2753                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2754                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) ());                      FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) ());
2755                }
2756          }          }
2757      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2758          class A7, class A8, class A9, class A10, class A11 >          class A7, class A8, class A9, class A10, class A11 >
2759          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
2760                      const A4 & v4, const A5 & v5, const A6 & v6,                      const A4 & v4, const A5 & v5, const A6 & v6,
2761                      const A7 & v7, const A8 & v8, const A9 & v9,                      const A7 & v7, const A8 & v8, const A9 & v9,
2762                      const A10 & v10, const A11 & v11)                      const A10 & v10, const A11 & v11)
2763      {          {
2764          MYTYPE strFmt;              MYTYPE strFmt;
2765          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2766              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2767                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2768                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2769                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2770                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                      FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
2771                  FmtArg < A11 > (v11) ());                      FmtArg < A11 > (v11) ());
2772                }
2773          }          }
2774      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2775          class A7, class A8, class A9, class A10, class A11, class A12 >          class A7, class A8, class A9, class A10, class A11, class A12 >
2776          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
2777                      const A4 & v4, const A5 & v5, const A6 & v6,                      const A4 & v4, const A5 & v5, const A6 & v6,
2778                      const A7 & v7, const A8 & v8, const A9 & v9,                      const A7 & v7, const A8 & v8, const A9 & v9,
2779                      const A10 & v10, const A11 & v11, const A12 & v12)                      const A10 & v10, const A11 & v11, const A12 & v12)
2780      {          {
2781          MYTYPE strFmt;              MYTYPE strFmt;
2782          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2783              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2784                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2785                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2786                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2787                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                      FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
2788                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) ());                      FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) ());
2789                }
2790          }          }
2791      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2792          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
2793          class A13 >          class A13 >
2794          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
# Line 2738  template < typename CT > class CStdStr:p Line 2796  template < typename CT > class CStdStr:p
2796                      const A7 & v7, const A8 & v8, const A9 & v9,                      const A7 & v7, const A8 & v8, const A9 & v9,
2797                      const A10 & v10, const A11 & v11, const A12 & v12,                      const A10 & v10, const A11 & v11, const A12 & v12,
2798                      const A13 & v13)                      const A13 & v13)
2799      {          {
2800          MYTYPE strFmt;              MYTYPE strFmt;
2801          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2802              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2803                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2804                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2805                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2806                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                      FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
2807                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                      FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
2808                  FmtArg < A13 > (v13) ());                      FmtArg < A13 > (v13) ());
2809                }
2810          }          }
2811      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2812          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
2813          class A13, class A14 >          class A13, class A14 >
2814          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
# Line 2758  template < typename CT > class CStdStr:p Line 2816  template < typename CT > class CStdStr:p
2816                      const A7 & v7, const A8 & v8, const A9 & v9,                      const A7 & v7, const A8 & v8, const A9 & v9,
2817                      const A10 & v10, const A11 & v11, const A12 & v12,                      const A10 & v10, const A11 & v11, const A12 & v12,
2818                      const A13 & v13, const A14 & v14)                      const A13 & v13, const A14 & v14)
2819      {          {
2820          MYTYPE strFmt;              MYTYPE strFmt;
2821          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2822              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2823                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2824                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2825                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2826                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                      FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
2827                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                      FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
2828                  FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) ());                      FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) ());
2829                }
2830          }          }
2831      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2832          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
2833          class A13, class A14, class A15 >          class A13, class A14, class A15 >
2834          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
# Line 2778  template < typename CT > class CStdStr:p Line 2836  template < typename CT > class CStdStr:p
2836                      const A7 & v7, const A8 & v8, const A9 & v9,                      const A7 & v7, const A8 & v8, const A9 & v9,
2837                      const A10 & v10, const A11 & v11, const A12 & v12,                      const A10 & v10, const A11 & v11, const A12 & v12,
2838                      const A13 & v13, const A14 & v14, const A15 & v15)                      const A13 & v13, const A14 & v14, const A15 & v15)
2839      {          {
2840          MYTYPE strFmt;              MYTYPE strFmt;
2841          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2842              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2843                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2844                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2845                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2846                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                      FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
2847                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                      FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
2848                  FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),                      FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),
2849                  FmtArg < A15 > (v15) ());                      FmtArg < A15 > (v15) ());
2850                }
2851          }          }
2852      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2853          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
2854          class A13, class A14, class A15, class A16 >          class A13, class A14, class A15, class A16 >
2855          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
# Line 2800  template < typename CT > class CStdStr:p Line 2858  template < typename CT > class CStdStr:p
2858                      const A10 & v10, const A11 & v11, const A12 & v12,                      const A10 & v10, const A11 & v11, const A12 & v12,
2859                      const A13 & v13, const A14 & v14, const A15 & v15,                      const A13 & v13, const A14 & v14, const A15 & v15,
2860                      const A16 & v16)                      const A16 & v16)
2861      {          {
2862          MYTYPE strFmt;              MYTYPE strFmt;
2863          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2864              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2865                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2866                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2867                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2868                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                      FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
2869                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                      FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
2870                  FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),                      FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),
2871                  FmtArg < A15 > (v15) (), FmtArg < A16 > (v16) ());                      FmtArg < A15 > (v15) (), FmtArg < A16 > (v16) ());
2872                }
2873          }          }
2874      }          template < class A1, class A2, class A3, class A4, class A5, class A6,
     template < class A1, class A2, class A3, class A4, class A5, class A6,  
2875          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
2876          class A13, class A14, class A15, class A16, class A17 >          class A13, class A14, class A15, class A16, class A17 >
2877          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,          void Format(UINT nId, const A1 & v1, const A2 & v2, const A3 & v3,
# Line 2822  template < typename CT > class CStdStr:p Line 2880  template < typename CT > class CStdStr:p
2880                      const A10 & v10, const A11 & v11, const A12 & v12,                      const A10 & v10, const A11 & v11, const A12 & v12,
2881                      const A13 & v13, const A14 & v14, const A15 & v15,                      const A13 & v13, const A14 & v14, const A15 & v15,
2882                      const A16 & v16, const A17 & v17)                      const A16 & v16, const A17 & v17)
2883      {          {
2884          MYTYPE strFmt;              MYTYPE strFmt;
2885          if (strFmt.Load(nId)) {              if (strFmt.Load(nId)) {
2886              Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),                  Fmt(strFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2887                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                      FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2888                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                      FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2889                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                      FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2890                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                      FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
2891                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                      FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
2892                  FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),                      FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),
2893                  FmtArg < A15 > (v15) (), FmtArg < A16 > (v16) (),                      FmtArg < A15 > (v15) (), FmtArg < A16 > (v16) (),
2894                  FmtArg < A17 > (v17) ());                      FmtArg < A17 > (v17) ());
2895                }
2896          }          }
     }  
2897    
2898  #endif // #ifndef SS_ANSI  #endif // #ifndef SS_ANSI
2899    
2900      // ...now the other overload of Format: the one that takes a string literal          // ...now the other overload of Format: the one that takes a string literal
2901    
2902      void Format(const CT * szFmt)          void Format(const CT * szFmt)
2903      {          {
2904          *this = szFmt;              *this = szFmt;
2905      }          }
2906      template < class A1 > void Format(const CT * szFmt, const A1 & v)          template < class A1 >
2907      {          void Format(const CT * szFmt, const A1 & v)
2908          Fmt(szFmt, FmtArg < A1 > (v) ());          {
2909      }              Fmt(szFmt, FmtArg < A1 > (v) ());
2910      template < class A1, class A2 >          }
2911            template < class A1, class A2 >
2912          void Format(const CT * szFmt, const A1 & v1, const A2 & v2)          void Format(const CT * szFmt, const A1 & v1, const A2 & v2)
2913      {          {
2914          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) ());              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) ());
2915      }          }
2916      template < class A1, class A2, class A3 >          template < class A1, class A2, class A3 >
2917          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
2918                      const A3 & v3)                      const A3 & v3)
2919      {          {
2920          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2921              FmtArg < A3 > (v3) ());                  FmtArg < A3 > (v3) ());
2922      }          }
2923      template < class A1, class A2, class A3, class A4 >          template < class A1, class A2, class A3, class A4 >
2924          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
2925                      const A3 & v3, const A4 & v4)                      const A3 & v3, const A4 & v4)
2926      {          {
2927          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2928              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) ());                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) ());
2929      }          }
2930      template < class A1, class A2, class A3, class A4, class A5 >          template < class A1, class A2, class A3, class A4, class A5 >
2931          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
2932                      const A3 & v3, const A4 & v4, const A5 & v5)                      const A3 & v3, const A4 & v4, const A5 & v5)
2933      {          {
2934          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2935              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2936              FmtArg < A5 > (v5) ());                  FmtArg < A5 > (v5) ());
2937      }          }
2938      template < class A1, class A2, class A3, class A4, class A5, class A6 >          template < class A1, class A2, class A3, class A4, class A5, class A6 >
2939          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
2940                      const A3 & v3, const A4 & v4, const A5 & v5,                      const A3 & v3, const A4 & v4, const A5 & v5,
2941                      const A6 & v6)                      const A6 & v6)
2942      {          {
2943          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2944              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2945              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) ());                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) ());
2946      }          }
2947      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
2948          class A7 >          class A7 >
2949          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
2950                      const A3 & v3, const A4 & v4, const A5 & v5,                      const A3 & v3, const A4 & v4, const A5 & v5,
2951                      const A6 & v6, const A7 & v7)                      const A6 & v6, const A7 & v7)
2952      {          {
2953          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2954              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2955              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2956              FmtArg < A7 > (v7) ());                  FmtArg < A7 > (v7) ());
2957      }          }
2958      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
2959          class A7, class A8 >          class A7, class A8 >
2960          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
2961                      const A3 & v3, const A4 & v4, const A5 & v5,                      const A3 & v3, const A4 & v4, const A5 & v5,
2962                      const A6 & v6, const A7 & v7, const A8 & v8)                      const A6 & v6, const A7 & v7, const A8 & v8)
2963      {          {
2964          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2965              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2966              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2967              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) ());                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) ());
2968      }          }
2969      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
2970          class A7, class A8, class A9 >          class A7, class A8, class A9 >
2971          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
2972                      const A3 & v3, const A4 & v4, const A5 & v5,                      const A3 & v3, const A4 & v4, const A5 & v5,
2973                      const A6 & v6, const A7 & v7, const A8 & v8,                      const A6 & v6, const A7 & v7, const A8 & v8,
2974                      const A9 & v9)                      const A9 & v9)
2975      {          {
2976          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2977              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2978              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2979              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2980              FmtArg < A9 > (v9) ());                  FmtArg < A9 > (v9) ());
2981      }          }
2982      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
2983          class A7, class A8, class A9, class A10 >          class A7, class A8, class A9, class A10 >
2984          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
2985                      const A3 & v3, const A4 & v4, const A5 & v5,                      const A3 & v3, const A4 & v4, const A5 & v5,
2986                      const A6 & v6, const A7 & v7, const A8 & v8,                      const A6 & v6, const A7 & v7, const A8 & v8,
2987                      const A9 & v9, const A10 & v10)                      const A9 & v9, const A10 & v10)
2988      {          {
2989          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
2990              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
2991              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
2992              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
2993              FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) ());                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) ());
2994      }          }
2995      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
2996          class A7, class A8, class A9, class A10, class A11 >          class A7, class A8, class A9, class A10, class A11 >
2997          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
2998                      const A3 & v3, const A4 & v4, const A5 & v5,                      const A3 & v3, const A4 & v4, const A5 & v5,
2999                      const A6 & v6, const A7 & v7, const A8 & v8,                      const A6 & v6, const A7 & v7, const A8 & v8,
3000                      const A9 & v9, const A10 & v10, const A11 & v11)                      const A9 & v9, const A10 & v10, const A11 & v11)
3001      {          {
3002          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
3003              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
3004              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
3005              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
3006              FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
3007              FmtArg < A11 > (v11) ());                  FmtArg < A11 > (v11) ());
3008      }          }
3009      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
3010          class A7, class A8, class A9, class A10, class A11, class A12 >          class A7, class A8, class A9, class A10, class A11, class A12 >
3011          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
3012                      const A3 & v3, const A4 & v4, const A5 & v5,                      const A3 & v3, const A4 & v4, const A5 & v5,
3013                      const A6 & v6, const A7 & v7, const A8 & v8,                      const A6 & v6, const A7 & v7, const A8 & v8,
3014                      const A9 & v9, const A10 & v10, const A11 & v11,                      const A9 & v9, const A10 & v10, const A11 & v11,
3015                      const A12 & v12)                      const A12 & v12)
3016      {          {
3017          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
3018              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
3019              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
3020              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
3021              FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
3022              FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) ());                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) ());
3023      }          }
3024      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
3025          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
3026          class A13 >          class A13 >
3027          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
# Line 2970  template < typename CT > class CStdStr:p Line 3029  template < typename CT > class CStdStr:p
3029                      const A6 & v6, const A7 & v7, const A8 & v8,                      const A6 & v6, const A7 & v7, const A8 & v8,
3030                      const A9 & v9, const A10 & v10, const A11 & v11,                      const A9 & v9, const A10 & v10, const A11 & v11,
3031                      const A12 & v12, const A13 & v13)                      const A12 & v12, const A13 & v13)
3032      {          {
3033          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
3034              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
3035              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
3036              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
3037              FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
3038              FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
3039              FmtArg < A13 > (v13) ());                  FmtArg < A13 > (v13) ());
3040      }          }
3041      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
3042          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
3043          class A13, class A14 >          class A13, class A14 >
3044          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
# Line 2987  template < typename CT > class CStdStr:p Line 3046  template < typename CT > class CStdStr:p
3046                      const A6 & v6, const A7 & v7, const A8 & v8,                      const A6 & v6, const A7 & v7, const A8 & v8,
3047                      const A9 & v9, const A10 & v10, const A11 & v11,                      const A9 & v9, const A10 & v10, const A11 & v11,
3048                      const A12 & v12, const A13 & v13, const A14 & v14)                      const A12 & v12, const A13 & v13, const A14 & v14)
3049      {          {
3050          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
3051              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
3052              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
3053              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
3054              FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
3055              FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
3056              FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) ());                  FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) ());
3057      }          }
3058      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
3059          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
3060          class A13, class A14, class A15 >          class A13, class A14, class A15 >
3061          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
# Line 3005  template < typename CT > class CStdStr:p Line 3064  template < typename CT > class CStdStr:p
3064                      const A9 & v9, const A10 & v10, const A11 & v11,                      const A9 & v9, const A10 & v10, const A11 & v11,
3065                      const A12 & v12, const A13 & v13, const A14 & v14,                      const A12 & v12, const A13 & v13, const A14 & v14,
3066                      const A15 & v15)                      const A15 & v15)
3067      {          {
3068          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
3069              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
3070              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
3071              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
3072              FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
3073              FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
3074              FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),                  FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),
3075              FmtArg < A15 > (v15) ());                  FmtArg < A15 > (v15) ());
3076      }          }
3077      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
3078          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
3079          class A13, class A14, class A15, class A16 >          class A13, class A14, class A15, class A16 >
3080          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
# Line 3024  template < typename CT > class CStdStr:p Line 3083  template < typename CT > class CStdStr:p
3083                      const A9 & v9, const A10 & v10, const A11 & v11,                      const A9 & v9, const A10 & v10, const A11 & v11,
3084                      const A12 & v12, const A13 & v13, const A14 & v14,                      const A12 & v12, const A13 & v13, const A14 & v14,
3085                      const A15 & v15, const A16 & v16)                      const A15 & v15, const A16 & v16)
3086      {          {
3087          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
3088              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
3089              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
3090              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
3091              FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
3092              FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
3093              FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),                  FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),
3094              FmtArg < A15 > (v15) (), FmtArg < A16 > (v16) ());                  FmtArg < A15 > (v15) (), FmtArg < A16 > (v16) ());
3095      }          }
3096      template < class A1, class A2, class A3, class A4, class A5, class A6,          template < class A1, class A2, class A3, class A4, class A5, class A6,
3097          class A7, class A8, class A9, class A10, class A11, class A12,          class A7, class A8, class A9, class A10, class A11, class A12,
3098          class A13, class A14, class A15, class A16, class A17 >          class A13, class A14, class A15, class A16, class A17 >
3099          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,          void Format(const CT * szFmt, const A1 & v1, const A2 & v2,
# Line 3043  template < typename CT > class CStdStr:p Line 3102  template < typename CT > class CStdStr:p
3102                      const A9 & v9, const A10 & v10, const A11 & v11,                      const A9 & v9, const A10 & v10, const A11 & v11,
3103                      const A12 & v12, const A13 & v13, const A14 & v14,                      const A12 & v12, const A13 & v13, const A14 & v14,
3104                      const A15 & v15, const A16 & v16, const A17 & v17)                      const A15 & v15, const A16 & v16, const A17 & v17)
3105      {          {
3106          Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),              Fmt(szFmt, FmtArg < A1 > (v1) (), FmtArg < A2 > (v2) (),
3107              FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),                  FmtArg < A3 > (v3) (), FmtArg < A4 > (v4) (),
3108              FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),                  FmtArg < A5 > (v5) (), FmtArg < A6 > (v6) (),
3109              FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),                  FmtArg < A7 > (v7) (), FmtArg < A8 > (v8) (),
3110              FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),                  FmtArg < A9 > (v9) (), FmtArg < A10 > (v10) (),
3111              FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),                  FmtArg < A11 > (v11) (), FmtArg < A12 > (v12) (),
3112              FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),                  FmtArg < A13 > (v13) (), FmtArg < A14 > (v14) (),
3113              FmtArg < A15 > (v15) (), FmtArg < A16 > (v16) (),                  FmtArg < A15 > (v15) (), FmtArg < A16 > (v16) (),
3114              FmtArg < A17 > (v17) ());                  FmtArg < A17 > (v17) ());
3115      }          }
3116    
3117  #else // #ifdef SS_SAFE_FORMAT  #else // #ifdef SS_SAFE_FORMAT
3118    
3119    
3120  #ifndef SS_ANSI  #ifndef SS_ANSI
3121    
3122      void Format(UINT nId, ...)          void Format(UINT nId, ...)
3123      {          {
3124          va_list argList;              va_list argList;
3125          va_start(argList, nId);              va_start(argList, nId);
3126    
3127          MYTYPE strFmt;              MYTYPE strFmt;
3128          if (strFmt.Load(nId))              if (strFmt.Load(nId))
3129              FormatV(strFmt, argList);                  FormatV(strFmt, argList);
3130    
3131          va_end(argList);              va_end(argList);
3132      }          }
3133    
3134  #endif // #ifdef SS_ANSI  #endif // #ifdef SS_ANSI
3135    
3136      void Format(const CT * szFmt, ...)          void Format(const CT * szFmt, ...)
3137      {          {
3138          va_list argList;              va_list argList;
3139          va_start(argList, szFmt);              va_start(argList, szFmt);
3140          FormatV(szFmt, argList);              FormatV(szFmt, argList);
3141          va_end(argList);              va_end(argList);
3142      }          }
3143    
3144  #endif // #ifdef SS_SAFE_FORMAT  #endif // #ifdef SS_SAFE_FORMAT
3145    
3146      void AppendFormat(const CT * szFmt, ...)          void AppendFormat(const CT * szFmt, ...)
3147      {          {
3148          va_list argList;              va_list argList;
3149          va_start(argList, szFmt);              va_start(argList, szFmt);
3150          AppendFormatV(szFmt, argList);              AppendFormatV(szFmt, argList);
3151          va_end(argList);              va_end(argList);
3152      }          }
3153    
3154  #define MAX_FMT_TRIES           5       // #of times we try  #define MAX_FMT_TRIES           5       // #of times we try
3155  #define FMT_BLOCK_SIZE          2048    // # of bytes to increment per try  #define FMT_BLOCK_SIZE          2048    // # of bytes to increment per try
# Line 3098  template < typename CT > class CStdStr:p Line 3157  template < typename CT > class CStdStr:p
3157  #define BUFSIZE_2ND 512  #define BUFSIZE_2ND 512
3158  #define STD_BUF_SIZE            1024  #define STD_BUF_SIZE            1024
3159    
3160      // an efficient way to add formatted characters to the string.  You may only          // an efficient way to add formatted characters to the string.  You may only
3161      // add up to STD_BUF_SIZE characters at a time, though          // add up to STD_BUF_SIZE characters at a time, though
3162      void AppendFormatV(const CT * szFmt, va_list argList)          void AppendFormatV(const CT * szFmt, va_list argList)
3163      {          {
3164          CT szBuf[STD_BUF_SIZE];              CT szBuf[STD_BUF_SIZE];
3165  #ifdef SS_ANSI  #ifdef SS_ANSI
3166          int nLen = ssvsprintf(szBuf, STD_BUF_SIZE - 1, szFmt, argList);  
3167                int nLen = ssvsprintf(szBuf, STD_BUF_SIZE - 1, szFmt, argList);
3168  #else  #else
3169          int nLen = ssnprintf(szBuf, STD_BUF_SIZE - 1, szFmt, argList);  
3170                int nLen = ssnprintf(szBuf, STD_BUF_SIZE - 1, szFmt, argList);
3171  #endif  #endif
         if (0 < nLen)  
             this->append(szBuf, nLen);  
     }  
3172    
3173      // -------------------------------------------------------------------------              if (0 < nLen)
3174      // FUNCTION:  FormatV                  this->append(szBuf, nLen);
3175      //              void FormatV(PCSTR szFormat, va_list, argList);          }
     //            
     // DESCRIPTION:  
     //              This function formats the string with sprintf style format-specs.  
     //              It makes a general guess at required buffer size and then tries  
     //              successively larger buffers until it finds one big enough or a  
     //              threshold (MAX_FMT_TRIES) is exceeded.  
     //  
     // PARAMETERS:  
     //              szFormat - a PCSTR holding the format of the output  
     //              argList - a Microsoft specific va_list for variable argument lists  
     //  
     // RETURN VALUE:  
     // -------------------------------------------------------------------------  
3176    
3177      void FormatV(const CT * szFormat, va_list argList)          // -------------------------------------------------------------------------
3178      {          // FUNCTION:  FormatV
3179            //              void FormatV(PCSTR szFormat, va_list, argList);
3180            //
3181            // DESCRIPTION:
3182            //              This function formats the string with sprintf style format-specs.
3183            //              It makes a general guess at required buffer size and then tries
3184            //              successively larger buffers until it finds one big enough or a
3185            //              threshold (MAX_FMT_TRIES) is exceeded.
3186            //
3187            // PARAMETERS:
3188            //              szFormat - a PCSTR holding the format of the output
3189            //              argList - a Microsoft specific va_list for variable argument lists
3190            //
3191            // RETURN VALUE:
3192            // -------------------------------------------------------------------------
3193    
3194            void FormatV(const CT * szFormat, va_list argList)
3195            {
3196  #ifdef SS_ANSI  #ifdef SS_ANSI
3197    
3198          int nLen = sslen(szFormat) + STD_BUF_SIZE;              int nLen = sslen(szFormat) + STD_BUF_SIZE;
3199          ssvsprintf(GetBuffer(nLen), nLen - 1, szFormat, argList);              ssvsprintf(GetBuffer(nLen), nLen - 1, szFormat, argList);
3200          ReleaseBuffer();              ReleaseBuffer();
3201    
3202  #else  #else
3203    
3204          CT *pBuf = NULL;              CT *pBuf = NULL;
3205          int nChars = 1;              int nChars = 1;
3206          int nUsed = 0;              int nUsed = 0;
3207          size_type nActual = 0;              size_type nActual = 0;
3208          int nTry = 0;              int nTry = 0;
3209    
3210          do {              do {
3211              // Grow more than linearly (e.g. 512, 1536, 3072, etc)                  // Grow more than linearly (e.g. 512, 1536, 3072, etc)
3212    
3213              nChars += ((nTry + 1) * FMT_BLOCK_SIZE);                  nChars += ((nTry + 1) * FMT_BLOCK_SIZE);
3214              pBuf = reinterpret_cast < CT * >(_alloca(sizeof(CT) * nChars));                  pBuf = reinterpret_cast < CT * >(_alloca(sizeof(CT) * nChars));
3215              nUsed = ssnprintf(pBuf, nChars - 1, szFormat, argList);                  nUsed = ssnprintf(pBuf, nChars - 1, szFormat, argList);
3216    
3217              // Ensure proper NULL termination.                  // Ensure proper NULL termination.
3218    
3219              nActual = nUsed == -1 ? nChars - 1 : SSMIN(nUsed, nChars - 1);                  nActual = nUsed == -1 ? nChars - 1 : SSMIN(nUsed, nChars - 1);
3220              pBuf[nActual] = '\0';                  pBuf[nActual] = '\0';
3221    
3222    
3223          } while (nUsed < 0 && nTry++ < MAX_FMT_TRIES);              } while (nUsed < 0 && nTry++ < MAX_FMT_TRIES);
3224    
3225          // assign whatever we managed to format              // assign whatever we managed to format
3226    
3227          this->assign(pBuf, nActual);              this->assign(pBuf, nActual);
3228    
3229  #endif  #endif
     }  
3230    
3231      // -------------------------------------------------------------------------          }
3232      // CString Facade Functions:  
3233      //          // -------------------------------------------------------------------------
3234      // The following methods are intended to allow you to use this class as a          // CString Facade Functions:
3235      // near drop-in replacement for CString.          //
3236      // -------------------------------------------------------------------------          // The following methods are intended to allow you to use this class as a
3237            // near drop-in replacement for CString.
3238            // -------------------------------------------------------------------------
3239  #ifdef SS_WIN32  #ifdef SS_WIN32
3240      BSTR AllocSysString() const          BSTR AllocSysString() const
3241      {          {
3242          ostring os;              ostring os;
3243          ssasn(os, *this);              ssasn(os, *this);
3244          return::SysAllocString(os.c_str());              return::SysAllocString(os.c_str());
3245      }          }
3246  #endif  #endif
3247    
3248      int Collate(PCMYSTR szThat) const          int Collate(PCMYSTR szThat) const
3249      {          {
3250          return sscoll(this->c_str(), this->length(), szThat, sslen(szThat));              return sscoll(this->c_str(), this->length(), szThat, sslen(szThat));
3251      }          }
3252    
3253      int CollateNoCase(PCMYSTR szThat) const          int CollateNoCase(PCMYSTR szThat) const
3254      {          {
3255          return ssicoll(this->c_str(), this->length(), szThat, sslen(szThat));              return ssicoll(this->c_str(), this->length(), szThat, sslen(szThat));
3256      }          }
3257    
3258      int Compare(PCMYSTR szThat) const          int Compare(PCMYSTR szThat) const
3259      {          {
3260          return this->compare(szThat);              return this->compare(szThat);
3261      }          }
3262    
3263      int CompareNoCase(PCMYSTR szThat) const          int CompareNoCase(PCMYSTR szThat) const
3264      {          {
3265          return ssicmp(this->c_str(), szThat);              return ssicmp(this->c_str(), szThat);
3266      }          }
3267    
3268      int Delete(int nIdx, int nCount = 1) {          int Delete(int nIdx, int nCount = 1)
3269          if (nIdx < 0)          {
3270              nIdx = 0;              if (nIdx < 0)
3271                    nIdx = 0;
         if (nIdx < this->GetLength())  
             this->erase(static_cast < MYSIZE > (nIdx),  
                         static_cast < MYSIZE > (nCount));  
3272    
3273          return GetLength();              if (nIdx < this->GetLength())
3274      }                  this->erase(static_cast < MYSIZE > (nIdx),
3275                                static_cast < MYSIZE > (nCount));
3276    
3277      void Empty()              return GetLength();
3278      {          }
         this->erase();  
     }  
3279    
3280      int Find(CT ch) const          void Empty()
3281      {          {
3282          MYSIZE nIdx = this->find_first_of(ch);              this->erase();
3283          return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);          }
     }  
3284    
3285      int Find(PCMYSTR szSub) const          int Find(CT ch) const
3286      {          {
3287          MYSIZE nIdx = this->find(szSub);              MYSIZE nIdx = this->find_first_of(ch);
3288          return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);              return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);
3289      }          }
3290    
3291      int Find(CT ch, int nStart) const          int Find(PCMYSTR szSub) const
3292      {          {
3293          // CString::Find docs say add 1 to nStart when it's not zero              MYSIZE nIdx = this->find(szSub);
3294          // CString::Find code doesn't do that however.  We'll stick              return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);
3295          // with what the code does          }
   
         MYSIZE nIdx =  
             this->find_first_of(ch, static_cast < MYSIZE > (nStart));  
         return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);  
     }  
3296    
3297      int Find(PCMYSTR szSub, int nStart) const          int Find(CT ch, int nStart) const
3298      {          {
3299          // CString::Find docs say add 1 to nStart when it's not zero              // CString::Find docs say add 1 to nStart when it's not zero
3300          // CString::Find code doesn't do that however.  We'll stick              // CString::Find code doesn't do that however.  We'll stick
3301          // with what the code does              // with what the code does
3302    
3303          MYSIZE nIdx = this->find(szSub, static_cast < MYSIZE > (nStart));              MYSIZE nIdx =
3304          return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);                  this->find_first_of(ch, static_cast < MYSIZE > (nStart));
3305      }              return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);
3306            }
3307    
3308      int FindOneOf(PCMYSTR szCharSet) const          int Find(PCMYSTR szSub, int nStart) const
3309      {          {
3310          MYSIZE nIdx = this->find_first_of(szCharSet);              // CString::Find docs say add 1 to nStart when it's not zero
3311          return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);              // CString::Find code doesn't do that however.  We'll stick
3312      }              // with what the code does
3313    
3314                MYSIZE nIdx = this->find(szSub, static_cast < MYSIZE > (nStart));
3315                return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);
3316            }
3317    
3318            int FindOneOf(PCMYSTR szCharSet) const
3319            {
3320                MYSIZE nIdx = this->find_first_of(szCharSet);
3321                return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);
3322            }
3323    
3324  #ifndef SS_ANSI  #ifndef SS_ANSI
3325      void FormatMessage(PCMYSTR szFormat, ...) throw(std::exception)          void FormatMessage(PCMYSTR szFormat, ...) throw(std::exception)
3326      {          {
3327          va_list argList;              va_list argList;
3328          va_start(argList, szFormat);              va_start(argList, szFormat);
3329          PMYSTR szTemp;              PMYSTR szTemp;
3330          if (ssfmtmsg              if (ssfmtmsg
3331              (FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,                      (FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
3332               szFormat, 0, 0, reinterpret_cast < PMYSTR > (&szTemp), 0,                       szFormat, 0, 0, reinterpret_cast < PMYSTR > (&szTemp), 0,
3333               &argList) == 0 || szTemp == 0) {                       &argList) == 0 || szTemp == 0) {
3334              throw std::runtime_error("out of memory");                  throw std::runtime_error("out of memory");
3335          }              }
3336          *this = szTemp;              *this = szTemp;
3337          LocalFree(szTemp);              LocalFree(szTemp);
3338          va_end(argList);              va_end(argList);
3339      }          }
3340    
3341      void FormatMessage(UINT nFormatId, ...) throw(std::exception)          void FormatMessage(UINT nFormatId, ...) throw(std::exception)
3342      {          {
3343          MYTYPE sFormat;              MYTYPE sFormat;
3344          VERIFY(sFormat.LoadString(nFormatId));              VERIFY(sFormat.LoadString(nFormatId));
3345          va_list argList;              va_list argList;
3346          va_start(argList, nFormatId);              va_start(argList, nFormatId);
3347          PMYSTR szTemp;              PMYSTR szTemp;
3348          if (ssfmtmsg              if (ssfmtmsg
3349              (FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,                      (FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
3350               sFormat, 0, 0, reinterpret_cast < PMYSTR > (&szTemp), 0,                       sFormat, 0, 0, reinterpret_cast < PMYSTR > (&szTemp), 0,
3351               &argList) == 0 || szTemp == 0) {                       &argList) == 0 || szTemp == 0) {
3352              throw std::runtime_error("out of memory");                  throw std::runtime_error("out of memory");
3353          }              }
3354          *this = szTemp;              *this = szTemp;
3355          LocalFree(szTemp);              LocalFree(szTemp);
3356          va_end(argList);              va_end(argList);
3357      }          }
3358  #endif  #endif
3359    
3360      // GetAllocLength -- an MSVC7 function but it costs us nothing to add it.          // GetAllocLength -- an MSVC7 function but it costs us nothing to add it.
3361    
3362      int GetAllocLength()          int GetAllocLength()
3363      {          {
3364          return static_cast < int >(this->capacity());              return static_cast < int >(this->capacity());
3365      }          }
3366    
3367      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
3368      // GetXXXX -- Direct access to character buffer          // GetXXXX -- Direct access to character buffer
3369      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
3370      CT GetAt(int nIdx) const          CT GetAt(int nIdx) const
3371      {          {
3372          return this->at(static_cast < MYSIZE > (nIdx));              return this->at(static_cast < MYSIZE > (nIdx));
3373      }          }
3374    
3375      CT *GetBuffer(int nMinLen = -1) {          CT *GetBuffer(int nMinLen = -1)
3376          return GetBuf(nMinLen);          {
3377      }              return GetBuf(nMinLen);
3378            }
3379    
3380      CT *GetBufferSetLength(int nLen)          CT *GetBufferSetLength(int nLen)
3381      {          {
3382          return BufferSet(nLen);              return BufferSet(nLen);
3383      }          }
3384    
3385      // GetLength() -- MFC docs say this is the # of BYTES but          // GetLength() -- MFC docs say this is the # of BYTES but
3386      // in truth it is the number of CHARACTERs (chars or wchar_ts)          // in truth it is the number of CHARACTERs (chars or wchar_ts)
3387      int GetLength() const          int GetLength() const
3388      {          {
3389          return static_cast < int >(this->length());              return static_cast < int >(this->length());
3390      }          }
3391    
3392      int Insert(int nIdx, CT ch)          int Insert(int nIdx, CT ch)
3393      {          {
3394          if (static_cast < MYSIZE > (nIdx) > this->size() - 1)              if (static_cast < MYSIZE > (nIdx) >
3395              this->append(1, ch);                      this->size() - 1)
3396          else                  this->append(1, ch);
3397              this->insert(static_cast < MYSIZE > (nIdx), 1, ch);              else
3398                    this->insert(static_cast < MYSIZE > (nIdx), 1, ch);
3399    
3400          return GetLength();              return GetLength();
3401      }          }
3402      int Insert(int nIdx, PCMYSTR sz)          int Insert(int nIdx, PCMYSTR sz)
3403      {          {
3404          if (static_cast < MYSIZE > (nIdx) >= this->size())              if (static_cast < MYSIZE > (nIdx) >
3405              this->append(sz, static_cast < MYSIZE > (sslen(sz)));                      = this->size())
3406          else                  this->append(sz, static_cast < MYSIZE > (sslen(sz)));
3407              this->insert(static_cast < MYSIZE > (nIdx), sz);              else
3408                    this->insert(static_cast < MYSIZE > (nIdx), sz);
3409    
3410          return GetLength();              return GetLength();
3411      }          }
3412    
3413      bool IsEmpty() const          bool IsEmpty() const
3414      {          {
3415          return this->empty();              return this->empty();
3416      }          }
3417    
3418      MYTYPE Left(int nCount) const          MYTYPE Left(int nCount) const
3419      {          {
3420          // Range check the count.              // Range check the count.
3421    
3422          nCount = SSMAX(0, SSMIN(nCount, static_cast < int >(this->size())));              nCount = SSMAX(0, SSMIN(nCount, static_cast < int >(this->size())));
3423          return this->substr(0, static_cast < MYSIZE > (nCount));              return this->substr(0, static_cast < MYSIZE > (nCount));
3424      }          }
3425    
3426  #ifndef SS_ANSI  #ifndef SS_ANSI
3427      bool LoadString(UINT nId)          bool LoadString(UINT nId)
3428      {          {
3429          return this->Load(nId);              return this->Load(nId);
3430      }          }
3431  #endif  #endif
3432    
3433      void MakeLower()          void MakeLower()
3434      {          {
3435          ToLower();              ToLower();
3436      }          }
   
     void MakeReverse()  
     {  
         std::reverse(this->begin(), this->end());  
     }  
   
     void MakeUpper()  
     {  
         ToUpper();  
     }  
3437    
3438      MYTYPE Mid(int nFirst) const          void MakeReverse()
3439      {          {
3440          return Mid(nFirst, this->GetLength() - nFirst);              std::reverse(this->begin(), this->end());
3441      }          }
3442    
3443      MYTYPE Mid(int nFirst, int nCount) const          void MakeUpper()
3444      {          {
3445          // CString does range checking here.  Since we're trying to emulate it,              ToUpper();
3446          // we must check too.          }
3447    
3448          if (nFirst < 0)          MYTYPE Mid(int nFirst) const
3449              nFirst = 0;          {
3450          if (nCount < 0)              return Mid(nFirst, this->GetLength() - nFirst);
3451              nCount = 0;          }
3452    
3453          int nSize = static_cast < int >(this->size());          MYTYPE Mid(int nFirst, int nCount) const
3454            {
3455                // CString does range checking here.  Since we're trying to emulate it,
3456                // we must check too.
3457    
3458          if (nFirst + nCount > nSize)              if (nFirst < 0)
3459                nCount = nSize - nFirst;                  nFirst = 0;
3460                if (nCount < 0)
3461                    nCount = 0;
3462    
3463          if (nFirst > nSize)              int nSize = static_cast < int >(this->size());
               return MYTYPE();  
3464    
3465          ASSERT(nFirst >= 0);              if (nFirst + nCount > nSize)
3466          ASSERT(nFirst + nCount <= nSize);                  nCount = nSize - nFirst;
3467    
3468          return this->substr(static_cast < MYSIZE > (nFirst),              if (nFirst > nSize)
3469                              static_cast < MYSIZE > (nCount));                  return MYTYPE();
     }  
3470    
3471      void ReleaseBuffer(int nNewLen = -1) {              ASSERT(nFirst >= 0);
3472          RelBuf(nNewLen);              ASSERT(nFirst + nCount <= nSize);
     }  
3473    
3474      int Remove(CT ch)              return this->substr(static_cast < MYSIZE > (nFirst),
3475      {                                  static_cast < MYSIZE > (nCount));
         MYSIZE nIdx = 0;  
         int nRemoved = 0;  
         while ((nIdx = this->find_first_of(ch)) != MYBASE::npos) {  
             this->erase(nIdx, 1);  
             nRemoved++;  
3476          }          }
         return nRemoved;  
     }  
3477    
3478      int Replace(CT chOld, CT chNew)          void ReleaseBuffer(int nNewLen = -1)
3479      {          {
3480          int nReplaced = 0;              RelBuf(nNewLen);
3481            }
3482    
3483          for (MYITER iter = this->begin(); iter != this->end(); iter++) {          int Remove(CT ch)
3484              if (*iter == chOld) {          {
3485                  *iter = chNew;              MYSIZE nIdx = 0;
3486                  nReplaced++;              int nRemoved = 0;
3487                while ((nIdx = this->find_first_of(ch)) != MYBASE::npos) {
3488                    this->erase(nIdx, 1);
3489                    nRemoved++;
3490              }              }
3491                return nRemoved;
3492          }          }
3493    
3494          return nReplaced;          int Replace(CT chOld, CT chNew)
3495      }          {
3496                int nReplaced = 0;
3497    
3498      int Replace(PCMYSTR szOld, PCMYSTR szNew)              for (MYITER iter = this->begin(); iter != this->end(); iter++) {
3499      {                  if (*iter == chOld) {
3500          int nReplaced = 0;                      *iter = chNew;
3501          MYSIZE nIdx = 0;                      nReplaced++;
         MYSIZE nOldLen = sslen(szOld);  
   
         if (0 != nOldLen) {  
             // If the replacement string is longer than the one it replaces, this  
             // string is going to have to grow in size,  Figure out how much  
             // and grow it all the way now, rather than incrementally  
   
             MYSIZE nNewLen = sslen(szNew);  
             if (nNewLen > nOldLen) {  
                 int nFound = 0;  
                 while (nIdx < this->length() &&  
                        (nIdx = this->find(szOld, nIdx)) != MYBASE::npos) {  
                     nFound++;  
                     nIdx += nOldLen;  
3502                  }                  }
                 this->reserve(this->size() + nFound * (nNewLen - nOldLen));  
3503              }              }
3504    
3505                return nReplaced;
3506            }
3507    
3508              static const CT ch = CT(0);          int Replace(PCMYSTR szOld, PCMYSTR szNew)
3509              PCMYSTR szRealNew = szNew == 0 ? &ch : szNew;          {
3510              nIdx = 0;              int nReplaced = 0;
3511                MYSIZE nIdx = 0;
3512              while (nIdx < this->length() &&              MYSIZE nOldLen = sslen(szOld);
3513                     (nIdx = this->find(szOld, nIdx)) != MYBASE::npos) {  
3514                  this->replace(this->begin() + nIdx,              if (0 != nOldLen) {
3515                                this->begin() + nIdx + nOldLen, szRealNew);                  // If the replacement string is longer than the one it replaces, this
3516                    // string is going to have to grow in size,  Figure out how much
3517                    // and grow it all the way now, rather than incrementally
3518    
3519                    MYSIZE nNewLen = sslen(szNew);
3520                    if (nNewLen > nOldLen) {
3521                        int nFound = 0;
3522                        while (nIdx < this->length() &&
3523                                (nIdx = this->find(szOld, nIdx)) != MYBASE::npos) {
3524                            nFound++;
3525                            nIdx += nOldLen;
3526                        }
3527                        this->reserve(this->size() + nFound * (nNewLen - nOldLen));
3528                    }
3529    
3530    
3531                    static const CT ch = CT(0);
3532                    PCMYSTR szRealNew = szNew == 0 ? &ch : szNew;
3533                    nIdx = 0;
3534    
3535                  nReplaced++;                  while (nIdx < this->length() &&
3536                  nIdx += nNewLen;                          (nIdx = this->find(szOld, nIdx)) != MYBASE::npos) {
3537                        this->replace(this->begin() + nIdx,
3538                                      this->begin() + nIdx + nOldLen, szRealNew);
3539    
3540                        nReplaced++;
3541                        nIdx += nNewLen;
3542                    }
3543              }              }
         }  
3544    
3545          return nReplaced;              return nReplaced;
3546      }          }
3547    
3548      int ReverseFind(CT ch) const          int ReverseFind(CT ch) const
3549      {          {
3550          MYSIZE nIdx = this->find_last_of(ch);              MYSIZE nIdx = this->find_last_of(ch);
3551          return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);              return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);
3552      }          }
3553    
3554      // ReverseFind overload that's not in CString but might be useful          // ReverseFind overload that's not in CString but might be useful
3555      int ReverseFind(PCMYSTR szFind, MYSIZE pos = MYBASE::npos) const          int ReverseFind(PCMYSTR szFind, MYSIZE pos = MYBASE::npos) const
3556      {          {
3557          MYSIZE nIdx = this->rfind(0 == szFind ? MYTYPE() : szFind, pos);              MYSIZE nIdx = this->rfind(0 == szFind ? MYTYPE() : szFind, pos);
3558          return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);              return static_cast < int >(MYBASE::npos == nIdx ? -1 : nIdx);
3559      }          }
3560    
3561      MYTYPE Right(int nCount) const          MYTYPE Right(int nCount) const
3562      {          {
3563          // Range check the count.              // Range check the count.
3564    
3565          nCount = SSMAX(0, SSMIN(nCount, static_cast < int >(this->size())));              nCount = SSMAX(0, SSMIN(nCount, static_cast < int >(this->size())));
3566          return this->substr(this->size() - static_cast < MYSIZE > (nCount));              return this->substr(this->size() - static_cast < MYSIZE > (nCount));
3567      }          }
3568    
3569      void SetAt(int nIndex, CT ch)          void SetAt(int nIndex, CT ch)
3570      {          {
3571          ASSERT(this->size() > static_cast < MYSIZE > (nIndex));              ASSERT(this->size() > static_cast < MYSIZE > (nIndex));
3572          this->at(static_cast < MYSIZE > (nIndex)) = ch;              this->at(static_cast < MYSIZE > (nIndex)) = ch;
3573      }          }
3574    
3575  #ifndef SS_ANSI  #ifndef SS_ANSI
3576      BSTR SetSysString(BSTR * pbstr) const          BSTR SetSysString(BSTR * pbstr) const
3577      {          {
3578          ostring os;              ostring os;
3579          ssasn(os, *this);              ssasn(os, *this);
3580          if (!::SysReAllocStringLen(pbstr, os.c_str(), os.length()))              if (!::SysReAllocStringLen(pbstr, os.c_str(), os.length()))
3581              throw std::runtime_error("out of memory");                  throw std::runtime_error("out of memory");
3582    
3583          ASSERT(*pbstr != 0);              ASSERT(*pbstr != 0);
3584          return *pbstr;              return *pbstr;
3585      }          }
3586  #endif  #endif
3587    
3588      MYTYPE SpanExcluding(PCMYSTR szCharSet) const          MYTYPE SpanExcluding(PCMYSTR szCharSet) const
3589      {          {
3590          MYSIZE pos = this->find_first_of(szCharSet);              MYSIZE pos = this->find_first_of(szCharSet);
3591          return pos == MYBASE::npos ? *this : Left(pos);              return pos == MYBASE::npos ? *this : Left(pos);
3592      }          }
3593    
3594      MYTYPE SpanIncluding(PCMYSTR szCharSet) const          MYTYPE SpanIncluding(PCMYSTR szCharSet) const
3595      {          {
3596          MYSIZE pos = this->find_first_not_of(szCharSet);              MYSIZE pos = this->find_first_not_of(szCharSet);
3597          return pos == MYBASE::npos ? *this : Left(pos);              return pos == MYBASE::npos ? *this : Left(pos);
3598      }          }
3599    
3600  #if defined SS_WIN32 && !defined(UNICODE) && !defined(SS_ANSI)  #if defined SS_WIN32 && !defined(UNICODE) && !defined(SS_ANSI)
3601    
3602      // CString's OemToAnsi and AnsiToOem functions are available only in          // CString's OemToAnsi and AnsiToOem functions are available only in
3603      // Unicode builds.  However since we're a template we also need a          // Unicode builds.  However since we're a template we also need a
3604      // runtime check of CT and a reinterpret_cast to account for the fact          // runtime check of CT and a reinterpret_cast to account for the fact
3605      // that CStdStringW gets instantiated even in non-Unicode builds.          // that CStdStringW gets instantiated even in non-Unicode builds.
3606    
3607      void AnsiToOem()          void AnsiToOem()
3608      {          {
3609          if (sizeof(CT) == sizeof(char) && !empty()) {              if (sizeof(CT) == sizeof(char) && !empty()) {
3610              ::CharToOem(reinterpret_cast < PCSTR > (this->c_str()),                  ::CharToOem(reinterpret_cast < PCSTR > (this->c_str()),
3611                          reinterpret_cast < PSTR > (GetBuf()));                              reinterpret_cast < PSTR > (GetBuf()));
3612          }              } else {
3613          else {                  ASSERT(false);
3614              ASSERT(false);              }
3615          }          }
     }  
3616    
3617      void OemToAnsi()          void OemToAnsi()
3618      {          {
3619          if (sizeof(CT) == sizeof(char) && !empty()) {              if (sizeof(CT) == sizeof(char) && !empty()) {
3620              ::OemToChar(reinterpret_cast < PCSTR > (this->c_str()),                  ::OemToChar(reinterpret_cast < PCSTR > (this->c_str()),
3621                          reinterpret_cast < PSTR > (GetBuf()));                              reinterpret_cast < PSTR > (GetBuf()));
3622          }              } else {
3623          else {                  ASSERT(false);
3624              ASSERT(false);              }
3625          }          }
     }  
3626    
3627  #endif  #endif
3628    
3629    
3630      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
3631      // Trim and its variants          // Trim and its variants
3632      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
3633      MYTYPE & Trim() {          MYTYPE & Trim()
3634          return TrimLeft().TrimRight();          {
3635      }              return TrimLeft().TrimRight();
3636            }
3637    
3638      MYTYPE & TrimLeft() {          MYTYPE & TrimLeft()
3639          this->erase(this->begin(),          {
3640                      std::find_if(this->begin(), this->end(),              this->erase(this->begin(),
3641                                   NotSpace < CT > ()));                          std::find_if(this->begin(), this->end(),
3642                                         NotSpace < CT > ()));
3643    
3644          return *this;              return *this;
3645      }          }
3646    
3647      MYTYPE & TrimLeft(CT tTrim) {          MYTYPE & TrimLeft(CT tTrim)
3648          this->erase(0, this->find_first_not_of(tTrim));          {
3649          return *this;              this->erase(0, this->find_first_not_of(tTrim));
3650      }              return *this;
3651            }
3652    
3653      MYTYPE & TrimLeft(PCMYSTR szTrimChars) {          MYTYPE & TrimLeft(PCMYSTR szTrimChars)
3654          this->erase(0, this->find_first_not_of(szTrimChars));          {
3655          return *this;              this->erase(0, this->find_first_not_of(szTrimChars));
3656      }              return *this;
3657            }
3658    
3659      MYTYPE & TrimRight() {          MYTYPE & TrimRight()
3660          // NOTE:  When comparing reverse_iterators here (MYRITER), I avoid using          {
3661          // operator!=.  This is because namespace rel_ops also has a template              // NOTE:  When comparing reverse_iterators here (MYRITER), I avoid using
3662          // operator!= which conflicts with the global operator!= already defined              // operator!=.  This is because namespace rel_ops also has a template
3663          // for reverse_iterator in the header <utility>.              // operator!= which conflicts with the global operator!= already defined
3664          // Thanks to John James for alerting me to this.              // for reverse_iterator in the header <utility>.
3665                // Thanks to John James for alerting me to this.
3666          MYRITER it =  
3667              std::find_if(this->rbegin(), this->rend(), NotSpace < CT > ());              MYRITER it =
3668          if (!(this->rend() == it))                  std::find_if(this->rbegin(), this->rend(), NotSpace < CT > ());
3669              this->erase(this->rend() - it);              if (!(this->rend() == it))
3670                    this->erase(this->rend() - it);
3671    
3672          this->erase(!(it == this->rend())? this->find_last_of(*it) + 1 : 0);              this->erase(!(it == this->rend())? this->find_last_of(*it) + 1 : 0);
3673          return *this;              return *this;
3674      }          }
3675    
3676      MYTYPE & TrimRight(CT tTrim) {          MYTYPE & TrimRight(CT tTrim)
3677          MYSIZE nIdx = this->find_last_not_of(tTrim);          {
3678          this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);              MYSIZE nIdx = this->find_last_not_of(tTrim);
3679          return *this;              this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);
3680      }              return *this;
3681            }
3682    
3683      MYTYPE & TrimRight(PCMYSTR szTrimChars) {          MYTYPE & TrimRight(PCMYSTR szTrimChars)
3684          MYSIZE nIdx = this->find_last_not_of(szTrimChars);          {
3685          this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);              MYSIZE nIdx = this->find_last_not_of(szTrimChars);
3686          return *this;              this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx);
3687      }              return *this;
3688            }
3689    
3690      void FreeExtra()          void FreeExtra()
3691      {          {
3692          MYTYPE mt;              MYTYPE mt;
3693          this->swap(mt);              this->swap(mt);
3694          if (!mt.empty())              if (!mt.empty())
3695              this->assign(mt.c_str(), mt.size());                  this->assign(mt.c_str(), mt.size());
3696      }          }
3697    
3698      // I have intentionally not implemented the following CString          // I have intentionally not implemented the following CString
3699      // functions.   You cannot make them work without taking advantage          // functions.   You cannot make them work without taking advantage
3700      // of implementation specific behavior.  However if you absolutely          // of implementation specific behavior.  However if you absolutely
3701      // MUST have them, uncomment out these lines for "sort-of-like"          // MUST have them, uncomment out these lines for "sort-of-like"
3702      // their behavior.  You're on your own.          // their behavior.  You're on your own.
   
 //      CT*                             LockBuffer()    { return GetBuf(); }// won't really lock  
 //      void                    UnlockBuffer(); { }     // why have UnlockBuffer w/o LockBuffer?  
   
     // Array-indexing operators.  Required because we defined an implicit cast  
     // to operator const CT* (Thanks to Julian Selman for pointing this out)  
   
     CT & operator[](int nIdx) {  
         return static_cast < MYBASE * >(this)->operator[](static_cast <  
                                                           MYSIZE > (nIdx));  
     }  
3703    
3704      const CT & operator[] (int nIdx) const          //      CT*                             LockBuffer()    { return GetBuf(); }// won't really lock
3705      {          //      void                    UnlockBuffer(); { }     // why have UnlockBuffer w/o LockBuffer?
         return static_cast < const MYBASE *>(this)->operator[] (static_cast <  
                                                                 MYSIZE >  
                                                                 (nIdx));  
     }  
3706    
3707      CT & operator[] (unsigned int nIdx)          // Array-indexing operators.  Required because we defined an implicit cast
3708      {          // to operator const CT* (Thanks to Julian Selman for pointing this out)
         return static_cast < MYBASE * >(this)->operator[](static_cast <  
                                                           MYSIZE > (nIdx));  
     }  
3709    
3710      const CT & operator[] (unsigned int nIdx) const          CT & operator[](int nIdx)
3711      {          {
3712          return static_cast < const MYBASE *>(this)->operator[] (static_cast <              return static_cast < MYBASE * >(this)->operator[](static_cast <
3713                                                                  MYSIZE >                      MYSIZE > (nIdx));
3714                                                                  (nIdx));          }
3715      }  
3716            const CT & operator[] (int nIdx) const
3717            {
3718                return static_cast < const MYBASE *>(this)->operator[] (static_cast <
3719                        MYSIZE >
3720                        (nIdx));
3721            }
3722    
3723            CT & operator[] (unsigned int nIdx)
3724            {
3725                return static_cast < MYBASE * >(this)->operator[](static_cast <
3726                        MYSIZE > (nIdx));
3727            }
3728    
3729            const CT & operator[] (unsigned int nIdx) const
3730            {
3731                return static_cast < const MYBASE *>(this)->operator[] (static_cast <
3732                        MYSIZE >
3733                        (nIdx));
3734            }
3735    
3736  #ifndef SS_NO_IMPLICIT_CAST  #ifndef SS_NO_IMPLICIT_CAST
3737      operator   const CT *() const          operator     const CT *() const
3738      {          {
3739          return this->c_str();              return this->c_str();
3740      }          }
3741  #endif  #endif
3742    
3743      // IStream related functions.  Useful in IPersistStream implementations          // IStream related functions.  Useful in IPersistStream implementations
3744    
3745  #ifdef SS_INC_COMDEF  #ifdef SS_INC_COMDEF
3746    
3747      // struct SSSHDR - useful for non Std C++ persistence schemes.          // struct SSSHDR - useful for non Std C++ persistence schemes.
3748      typedef struct SSSHDR          typedef struct SSSHDR
3749      {          {
3750          BYTE byCtrl;              BYTE byCtrl;
3751          ULONG nChars;              ULONG nChars;
3752      } SSSHDR;                   // as in "Standard String Stream Header"          }
3753            SSSHDR;                   // as in "Standard String Stream Header"
3754    
3755  #define SSSO_UNICODE    0x01    // the string is a wide string  #define SSSO_UNICODE    0x01    // the string is a wide string
3756  #define SSSO_COMPRESS   0x02    // the string is compressed  #define SSSO_COMPRESS   0x02    // the string is compressed
3757    
3758      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
3759      // FUNCTION: StreamSize          // FUNCTION: StreamSize
3760      // REMARKS:          // REMARKS:
3761      //              Returns how many bytes it will take to StreamSave() this CStdString          //              Returns how many bytes it will take to StreamSave() this CStdString
3762      //              object to an IStream.          //              object to an IStream.
3763      // -------------------------------------------------------------------------          // -------------------------------------------------------------------------
3764      ULONG StreamSize() const          ULONG StreamSize() const
     {  
         // Control header plus string  
         ASSERT(this->size() * sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));  
         return (this->size() * sizeof(CT)) + sizeof(SSSHDR);  
     }  
   
     // -------------------------------------------------------------------------  
     // FUNCTION: StreamSave  
     // REMARKS:  
     //              Saves this CStdString object to a COM IStream.  
     // -------------------------------------------------------------------------  
     HRESULT StreamSave(IStream * pStream) const  
     {  
         ASSERT(this->size() * sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));  
         HRESULT hr = E_FAIL;  
         ASSERT(pStream != 0);  
         SSSHDR hdr;  
         hdr.byCtrl = sizeof(CT) == 2 ? SSSO_UNICODE : 0;  
         hdr.nChars = this->size();  
   
   
         if (FAILED(hr = pStream->Write(&hdr, sizeof(SSSHDR), 0))) {  
             TRACE(_T("StreamSave: Cannot write control header, ERR=0x%X\n"),  
                   hr);  
         }  
         else if (empty())  
3765          {          {
3766              ;                   // nothing to write              // Control header plus string
3767          }              ASSERT(this->size() * sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));
3768          else if (FAILED(hr = pStream->Write(this->c_str(),              return (this->size() * sizeof(CT)) + sizeof(SSSHDR);
                                             this->size() * sizeof(CT), 0))) {  
             TRACE(_T("StreamSave: Cannot write string to stream 0x%X\n"), hr);  
3769          }          }
3770    
3771          return hr;          // -------------------------------------------------------------------------
3772      }          // FUNCTION: StreamSave
3773            // REMARKS:
3774            //              Saves this CStdString object to a COM IStream.
3775            // -------------------------------------------------------------------------
3776            HRESULT StreamSave(IStream * pStream) const
3777            {
3778                ASSERT(this->size() * sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR));
3779                HRESULT hr = E_FAIL;
3780                ASSERT(pStream != 0);
3781                SSSHDR hdr;
3782                hdr.byCtrl = sizeof(CT) == 2 ? SSSO_UNICODE : 0;
3783                hdr.nChars = this->size();
3784    
3785    
3786                if (FAILED(hr = pStream->Write(&hdr, sizeof(SSSHDR), 0))) {
3787                    TRACE(_T("StreamSave: Cannot write control header, ERR=0x%X\n"),
3788                          hr);
3789                } else if (empty()) {
3790                    ;                   // nothing to write
3791                } else if (FAILED(hr = pStream->Write(this->c_str(),
3792                                                      this->size() * sizeof(CT), 0))) {
3793                    TRACE(_T("StreamSave: Cannot write string to stream 0x%X\n"), hr);
3794                }
3795    
3796                return hr;
3797            }
3798    
3799      // -------------------------------------------------------------------------  
3800      // FUNCTION: StreamLoad          // -------------------------------------------------------------------------
3801      // REMARKS:          // FUNCTION: StreamLoad
3802      //              This method loads the object from an IStream.          // REMARKS:
3803      // -------------------------------------------------------------------------          //              This method loads the object from an IStream.
3804      HRESULT StreamLoad(IStream * pStream)          // -------------------------------------------------------------------------
3805      {          HRESULT StreamLoad(IStream * pStream)
3806          ASSERT(pStream != 0);          {
3807          SSSHDR hdr;              ASSERT(pStream != 0);
3808          HRESULT hr = E_FAIL;              SSSHDR hdr;
3809                HRESULT hr = E_FAIL;
3810          if (FAILED(hr = pStream->Read(&hdr, sizeof(SSSHDR), 0))) {  
3811              TRACE(_T("StreamLoad: Cant read control header, ERR=0x%X\n"), hr);              if (FAILED(hr = pStream->Read(&hdr, sizeof(SSSHDR), 0))) {
3812          }                  TRACE(_T("StreamLoad: Cant read control header, ERR=0x%X\n"), hr);
3813          else if (hdr.nChars > 0) {              } else if (hdr.nChars > 0) {
3814              ULONG nRead = 0;                  ULONG nRead = 0;
3815              PMYSTR pMyBuf = BufferSet(hdr.nChars);                  PMYSTR pMyBuf = BufferSet(hdr.nChars);
3816    
3817              // If our character size matches the character size of the string                  // If our character size matches the character size of the string
3818              // we're trying to read, then we can read it directly into our                  // we're trying to read, then we can read it directly into our
3819              // buffer. Otherwise, we have to read into an intermediate buffer                  // buffer. Otherwise, we have to read into an intermediate buffer
3820              // and convert.                  // and convert.
3821    
3822              if ((hdr.byCtrl & SSSO_UNICODE) != 0) {                  if ((hdr.byCtrl & SSSO_UNICODE) != 0) {
3823                  ULONG nBytes = hdr.nChars * sizeof(wchar_t);                      ULONG nBytes = hdr.nChars * sizeof(wchar_t);
3824                  if (sizeof(CT) == sizeof(wchar_t)) {                      if (sizeof(CT) == sizeof(wchar_t)) {
3825                      if (FAILED(hr = pStream->Read(pMyBuf, nBytes, &nRead)))                          if (FAILED(hr = pStream->Read(pMyBuf, nBytes, &nRead)))
3826                          TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"),                              TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"),
3827                                hr);                                    hr);
3828                  }                      } else {
3829                  else {                          PWSTR pBufW =
3830                      PWSTR pBufW =                              reinterpret_cast < PWSTR > (_alloca((nBytes) + 1));
3831                          reinterpret_cast < PWSTR > (_alloca((nBytes) + 1));                          if (FAILED(hr = pStream->Read(pBufW, nBytes, &nRead)))
3832                      if (FAILED(hr = pStream->Read(pBufW, nBytes, &nRead)))                              TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"),
3833                          TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"),                                    hr);
3834                                hr);                          else
3835                      else                              sscpy(pMyBuf, pBufW, hdr.nChars);
3836                          sscpy(pMyBuf, pBufW, hdr.nChars);                      }
3837                  }                  } else {
3838              }                      ULONG nBytes = hdr.nChars * sizeof(char);
3839              else {                      if (sizeof(CT) == sizeof(char)) {
3840                  ULONG nBytes = hdr.nChars * sizeof(char);                          if (FAILED(hr = pStream->Read(pMyBuf, nBytes, &nRead)))
3841                  if (sizeof(CT) == sizeof(char)) {                              TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"),
3842                      if (FAILED(hr = pStream->Read(pMyBuf, nBytes, &nRead)))                                    hr);
3843                          TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"),                      } else {
3844                                hr);                          PSTR pBufA = reinterpret_cast < PSTR > (_alloca(nBytes));
3845                  }                          if (FAILED(hr = pStream->Read(pBufA, hdr.nChars, &nRead)))
3846                  else {                              TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"),
3847                      PSTR pBufA = reinterpret_cast < PSTR > (_alloca(nBytes));                                    hr);
3848                      if (FAILED(hr = pStream->Read(pBufA, hdr.nChars, &nRead)))                          else
3849                          TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"),                              sscpy(pMyBuf, pBufA, hdr.nChars);
3850                                hr);                      }
                     else  
                         sscpy(pMyBuf, pBufA, hdr.nChars);  
3851                  }                  }
3852                } else {
3853                    this->erase();
3854              }              }
3855                return hr;
3856          }          }
         else {  
             this->erase();  
         }  
         return hr;  
     }  
3857  #endif // #ifdef SS_INC_COMDEF  #endif // #ifdef SS_INC_COMDEF
3858    
3859  #ifndef SS_ANSI  #ifndef SS_ANSI
3860    
3861      // SetResourceHandle/GetResourceHandle.  In MFC builds, these map directly          // SetResourceHandle/GetResourceHandle.  In MFC builds, these map directly
3862      // to AfxSetResourceHandle and AfxGetResourceHandle.  In non-MFC builds they          // to AfxSetResourceHandle and AfxGetResourceHandle.  In non-MFC builds they
3863      // point to a single static HINST so that those who call the member          // point to a single static HINST so that those who call the member
3864      // functions that take resource IDs can provide an alternate HINST of a DLL          // functions that take resource IDs can provide an alternate HINST of a DLL
3865      // to search.  This is not exactly the list of HMODULES that MFC provides          // to search.  This is not exactly the list of HMODULES that MFC provides
3866      // but it's better than nothing.          // but it's better than nothing.
3867    
3868  #ifdef _MFC_VER  #ifdef _MFC_VER
3869      static void SetResourceHandle(HMODULE hNew)          static void SetResourceHandle(HMODULE hNew)
3870      {          {
3871          AfxSetResourceHandle(hNew);              AfxSetResourceHandle(hNew);
3872      }          }
3873      static HMODULE GetResourceHandle()          static HMODULE GetResourceHandle()
3874      {          {
3875          return AfxGetResourceHandle();              return AfxGetResourceHandle();
3876      }          }
3877  #else  #else
3878      static void SetResourceHandle(HMODULE hNew)          static void SetResourceHandle(HMODULE hNew)
3879      {          {
3880          SSResourceHandle() = hNew;              SSResourceHandle() = hNew;
3881      }          }
3882      static HMODULE GetResourceHandle()          static HMODULE GetResourceHandle()
3883      {          {
3884          return SSResourceHandle();              return SSResourceHandle();
3885      }          }
3886  #endif  #endif
3887    
3888  #endif  #endif
# Line 3838  template < typename CT > class CStdStr:p Line 3905  template < typename CT > class CStdStr:p
3905  //              SSDLLEXP        (nothing, just #define it)              extern  //              SSDLLEXP        (nothing, just #define it)              extern
3906  //              SSDLLSPEC       __declspec(dllexport)                   __declspec(dllimport)  //              SSDLLSPEC       __declspec(dllexport)                   __declspec(dllimport)
3907  //  //
3908  //              Note that these macros must be available to ALL clients who want to  //              Note that these macros must be available to ALL clients who want to
3909  //              link to the DLL and use the class.  If they  //              link to the DLL and use the class.  If they
3910  //  //
3911  // A word of advice: Don't bother.  // A word of advice: Don't bother.
3912  //  //
# Line 3990  inline CStdStringW operator+(const CStdS Line 4057  inline CStdStringW operator+(const CStdS
4057    
4058  #ifdef SS_SAFE_FORMAT  #ifdef SS_SAFE_FORMAT
4059    
4060  template <> struct FmtArg <CStdStringA >  template <>
4061    struct FmtArg <CStdStringA >
4062  {  {
4063      explicit FmtArg(const CStdStringA & arg):a_(arg)      explicit FmtArg(const CStdStringA & arg):a_(arg)
4064      {      {}
     }  
4065      PCSTR operator() () const      PCSTR operator() () const
4066      {      {
4067          return a_.c_str();          return a_.c_str();
4068      }      }
4069      const CStdStringA & a_;      const CStdStringA & a_;
4070    private:  private:
4071      FmtArg < CStdStringA > &operator=(const FmtArg < CStdStringA > &)      FmtArg < CStdStringA > &operator=(const FmtArg < CStdStringA > &)
4072      {      {
4073          return *this;          return *this;
4074      }      }
4075  };  };
4076  template <> struct FmtArg <CStdStringW >  template <>
4077    struct FmtArg <CStdStringW >
4078  {  {
4079      explicit FmtArg(const CStdStringW & arg):a_(arg)      explicit FmtArg(const CStdStringW & arg):a_(arg)
4080      {      {}
     }  
4081      PCWSTR operator() () const      PCWSTR operator() () const
4082      {      {
4083          return a_.c_str();          return a_.c_str();
4084      }      }
4085      const CStdStringW & a_;      const CStdStringW & a_;
4086    private:  private:
4087      FmtArg < CStdStringW > &operator=(const FmtArg < CStdStringW > &)      FmtArg < CStdStringW > &operator=(const FmtArg < CStdStringW > &)
4088      {      {
4089          return *this;          return *this;
4090      }      }
4091  };  };
4092    
4093  template <> struct FmtArg <std::string >  template <>
4094    struct FmtArg <std::string >
4095  {  {
4096      explicit FmtArg(const std::string & arg):a_(arg)      explicit FmtArg(const std::string & arg):a_(arg)
4097      {      {}
     }  
4098      PCSTR operator() () const      PCSTR operator() () const
4099      {      {
4100          return a_.c_str();          return a_.c_str();
4101      }      }
4102      const std::string & a_;      const std::string & a_;
4103    private:  private:
4104      FmtArg < std::string > &operator=(const FmtArg < std::string > &)      FmtArg < std::string > &operator=(const FmtArg < std::string > &)
4105      {      {
4106          return *this;          return *this;
4107      }      }
4108  };  };
4109  template <> struct FmtArg <std::wstring >  template <>
4110    struct FmtArg <std::wstring >
4111  {  {
4112      explicit FmtArg(const std::wstring & arg):a_(arg)      explicit FmtArg(const std::wstring & arg):a_(arg)
4113      {      {}
     }  
4114      PCWSTR operator() () const      PCWSTR operator() () const
4115      {      {
4116          return a_.c_str();          return a_.c_str();
4117      }      }
4118      const std::wstring & a_;      const std::wstring & a_;
4119    private:  private:
4120      FmtArg < std::wstring > &operator=(const FmtArg < std::wstring > &)      FmtArg < std::wstring > &operator=(const FmtArg < std::wstring > &)
4121      {      {
4122          return *this;          return *this;
# Line 4058  template <> struct FmtArg <std::wstring Line 4125  template <> struct FmtArg <std::wstring
4125  #endif // #ifdef SS_SAFEFORMAT  #endif // #ifdef SS_SAFEFORMAT
4126    
4127  #ifndef SS_ANSI  #ifndef SS_ANSI
4128          // SSResourceHandle: our MFC-like resource handle  // SSResourceHandle: our MFC-like resource handle
4129  inline HMODULE & SSResourceHandle()  inline HMODULE & SSResourceHandle()
4130  {  {
4131      static HMODULE hModuleSS = GetModuleHandle(0);      static HMODULE hModuleSS = GetModuleHandle(0);
# Line 4167  inline CStdStringW WUFormatW(UINT nId, . Line 4234  inline CStdStringW WUFormatW(UINT nId, .
4234    
4235    
4236  #if defined(SS_WIN32) && !defined (SS_ANSI)  #if defined(SS_WIN32) && !defined (SS_ANSI)
4237          // -------------------------------------------------------------------------  // -------------------------------------------------------------------------
4238          // FUNCTION: WUSysMessage  // FUNCTION: WUSysMessage
4239          //       CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);  //       CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);
4240          //       CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);  //       CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID);
4241          //            //
4242          // DESCRIPTION:  // DESCRIPTION:
4243          //       This function simplifies the process of obtaining a string equivalent  //       This function simplifies the process of obtaining a string equivalent
4244          //       of a system error code returned from GetLastError().  You simply  //       of a system error code returned from GetLastError().  You simply
4245          //       supply the value returned by GetLastError() to this function and the  //       supply the value returned by GetLastError() to this function and the
4246          //       corresponding system string is returned in the form of a CStdStringA.  //       corresponding system string is returned in the form of a CStdStringA.
4247          //  //
4248          // PARAMETERS:  // PARAMETERS:
4249          //       dwError - a DWORD value representing the error code to be translated  //       dwError - a DWORD value representing the error code to be translated
4250          //       dwLangId - the language id to use.  defaults to english.  //       dwLangId - the language id to use.  defaults to english.
4251          //  //
4252          // RETURN VALUE:  // RETURN VALUE:
4253          //       a CStdStringA equivalent of the error code.  Currently, this function  //       a CStdStringA equivalent of the error code.  Currently, this function
4254          //       only returns either English of the system default language strings.    //       only returns either English of the system default language strings.
4255          // -------------------------------------------------------------------------  // -------------------------------------------------------------------------
4256  #define SS_DEFLANGID MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT)  #define SS_DEFLANGID MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT)
4257  inline CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId = SS_DEFLANGID)  inline CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId = SS_DEFLANGID)
4258  {  {
# Line 4212  inline CStdStringW WUSysMessageW(DWORD d Line 4279  inline CStdStringW WUSysMessageW(DWORD d
4279  // Define TCHAR based friendly names for some of these functions  // Define TCHAR based friendly names for some of these functions
4280    
4281  #ifdef UNICODE  #ifdef UNICODE
4282          //#define CStdString                            CStdStringW  //#define CStdString                            CStdStringW
4283  typedef CStdStringW CStdString;  typedef CStdStringW CStdString;
4284  #define WUSysMessage                    WUSysMessageW  #define WUSysMessage                    WUSysMessageW
4285  #define WUFormat                                WUFormatW  #define WUFormat                                WUFormatW
4286  #else  #else
4287          //#define CStdString                            CStdStringA  //#define CStdString                            CStdStringA
4288  typedef CStdStringA CStdString;  typedef CStdStringA CStdString;
4289  #define WUSysMessage                    WUSysMessageA  #define WUSysMessage                    WUSysMessageA
4290  #define WUFormat                                WUFormatA  #define WUFormat                                WUFormatA
# Line 4259  typedef CStdStringA CStdString; Line 4326  typedef CStdStringA CStdString;
4326  #endif  #endif
4327    
4328  struct StdStringLessNoCaseW:std::binary_function < CStdStringW, CStdStringW,  struct StdStringLessNoCaseW:std::binary_function < CStdStringW, CStdStringW,
4329      bool >              bool >
4330  {  {
4331      inline      inline
4332          bool operator() (const CStdStringW & sLeft,      bool operator() (const CStdStringW & sLeft,
4333                           const CStdStringW & sRight) const                       const CStdStringW & sRight) const
4334      {      {
4335          return ssicmp(sLeft.c_str(), sRight.c_str()) < 0;          return ssicmp(sLeft.c_str(), sRight.c_str()) < 0;
4336      }      }
4337  };  };
4338  struct StdStringEqualsNoCaseW:std::binary_function < CStdStringW, CStdStringW,  struct StdStringEqualsNoCaseW:std::binary_function < CStdStringW, CStdStringW,
4339      bool >              bool >
4340  {  {
4341      inline      inline
4342          bool operator() (const CStdStringW & sLeft,      bool operator() (const CStdStringW & sLeft,
4343                           const CStdStringW & sRight) const                       const CStdStringW & sRight) const
4344      {      {
4345          return ssicmp(sLeft.c_str(), sRight.c_str()) == 0;          return ssicmp(sLeft.c_str(), sRight.c_str()) == 0;
4346      }      }
4347  };  };
4348  struct StdStringLessNoCaseA:std::binary_function < CStdStringA, CStdStringA,  struct StdStringLessNoCaseA:std::binary_function < CStdStringA, CStdStringA,
4349      bool >              bool >
4350  {  {
4351      inline      inline
4352          bool operator() (const CStdStringA & sLeft,      bool operator() (const CStdStringA & sLeft,
4353                           const CStdStringA & sRight) const                       const CStdStringA & sRight) const
4354      {      {
4355          return ssicmp(sLeft.c_str(), sRight.c_str()) < 0;          return ssicmp(sLeft.c_str(), sRight.c_str()) < 0;
4356      }      }
4357  };  };
4358  struct StdStringEqualsNoCaseA:std::binary_function < CStdStringA, CStdStringA,  struct StdStringEqualsNoCaseA:std::binary_function < CStdStringA, CStdStringA,
4359      bool >              bool >
4360  {  {
4361      inline      inline
4362          bool operator() (const CStdStringA & sLeft,      bool operator() (const CStdStringA & sLeft,
4363                           const CStdStringA & sRight) const                       const CStdStringA & sRight) const
4364      {      {
4365          return ssicmp(sLeft.c_str(), sRight.c_str()) == 0;          return ssicmp(sLeft.c_str(), sRight.c_str()) == 0;
4366      }      }
# Line 4307  struct StdStringEqualsNoCaseA:std::binar Line 4374  struct StdStringEqualsNoCaseA:std::binar
4374  #endif  #endif
4375    
4376    
4377  // These std::swap specializations come courtesy of Mike Crusader.  // These std::swap specializations come courtesy of Mike Crusader.
4378    
4379  //namespace std  //namespace std
4380  //{  //{

Legend:
Removed from v.936  
changed lines
  Added in v.937

  ViewVC Help
Powered by ViewVC 1.1.26