Исходник. Реализация CString без MFC.
От: SeregaLBN Украина  
Дата: 29.10.04 12:41
Оценка: 3 (1) :)
Может кому понадобиться...
////////////////////////////////////////////////////////////////////////////////
// File name: CStringKS.h
// Author: Sergey Krivulya (Ceргей Кpивуля) - KSerg
// e-mail: Sergey_Krivulya@UkrPost.Net
// Date: 22 08 2004
//
// Description: Класс для работы со строками.
//   Реализует почти весь интерфейс CString из MFC.
// Для чего это было написано? Лично моё мнение - если есть выбор между
// использованием CString и std::string я всегда предпочитаю CString.
// В основном из-за метода CString::Format(). А с кем небывало след.
// случаев - пишется некий модулёк с применением CString из MFC, а потом
// вы хотите перенести его в др. проект. А проект -  на чистом Win32 API,
// где нет CString. Приходиться его переделывать - избавляться от CString,
// и вместо него использовать, например, str::string.
// Так вот, для этого и придуман мой класс CStringKS.
// Класс CStringKS - это обёртка std:string, которая предоставляет
// пользователю привычный интерфейс CString.
//  При использовании MFC, CString и CStringKS - это 2 разных класса.
// А при использовании только Win32 API - это один и тот же класс CStringKS.
//
// !!! Особенности:
// 1. Если в MFC можно было так писать:
//   CString str1("qwerty");
//   CString str2;
//   str2.Format(TEXT("str1 = %s"), str1);
// То при использовании CStringKS надо писать так:
//   CStringKS str1("qwerty");
//   CStringKS str2;
//   str2.Format(TEXT("str1 = %s"), (LPCTSTR)str1);
//
// 2. Нереализованные методы:
//   friend CArchive& operator<<(CArchive& ar, const CString& string);
//   friend CArchive& operator>>(CArchive& ar, CString& string);
//   LPTSTR LockBuffer();
//   void UnlockBuffer();
//
////////////////////////////////////////////////////////////////////////////////

#ifndef __FILE__CSTRINGKS__
#define __FILE__CSTRINGKS__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <TChar.H>
#include <ComDef.h>
#pragma warning(disable:4786) // identifier was truncated to '255' characters in the debug information
#include <string>
#include <crtdbg.h>
#include <ATLConv.H>

#ifdef CSTRINGKS_DLL_EXPORT
      #define CSTRINGKS_API __declspec(dllexport)
#else
   #ifdef CSTRINGKS_DLL_IMPORT
      #define CSTRINGKS_API __declspec(dllimport)
   #else
      #define CSTRINGKS_API
   #endif
#endif

class CSTRINGKS_API CStringKS {
private:
   #ifdef UNICODE
      typedef std::wstring tstring;
   #else
      typedef std:: string tstring;
   #endif // UNICODE
   tstring m_str;
public:

// Constructors

   // constructs empty CStringKS
   CStringKS() {}
   // copy constructor
   CStringKS(const CStringKS& stringSrc) : m_str((LPCTSTR)stringSrc) {}
   // from a single character
   CStringKS(TCHAR ch, int nRepeat = 1) : m_str(tstring(nRepeat, ch)) {}
   // from an ANSI string (converts to TCHAR)
   CStringKS(LPCSTR  lpsz) {if (lpsz!=NULL) {USES_CONVERSION; m_str = A2CT(lpsz);}}
   // from a UNICODE string (converts to TCHAR)
   CStringKS(LPCWSTR lpsz) {if (lpsz!=NULL) {USES_CONVERSION; m_str = W2CT(lpsz);}}
   // subset of characters from an ANSI string (converts to TCHAR)
   CStringKS(LPCSTR lpch, int nLength)  : m_str((LPCTSTR)(CStringKS(lpch).Left(nLength))) {}
   // subset of characters from a UNICODE string (converts to TCHAR)
   CStringKS(LPCWSTR lpch, int nLength) : m_str((LPCTSTR)(CStringKS(lpch).Left(nLength))) {}
   // from unsigned characters
   CStringKS(const unsigned char* psz) {this->operator=(psz);}

// Attributes & Operations

   // get data length
   int GetLength() const {return m_str.length();}
   // TRUE if zero length
   BOOL IsEmpty() const {return m_str.empty();}
   // clear contents to empty
   void Empty() {m_str.erase();}

   // return single character at zero-based index
   TCHAR GetAt(int nIndex) const {return m_str[nIndex];}
   // return single character at zero-based index
   TCHAR operator[](int nIndex) const {return m_str[nIndex];}
   // set a single character at zero-based index
   void SetAt(int nIndex, TCHAR ch) {m_str[nIndex] = ch;}
   // return pointer to const string
   operator LPCTSTR() const {return m_str.c_str();}

   // overloaded assignment

   // ref-counted copy from another CStringKS
   const CStringKS& operator=(const CStringKS& stringSrc) { if (&stringSrc != this) {m_str = (LPCTSTR)stringSrc;} return *this;}
   // set string content to single character
   const CStringKS& operator=(TCHAR ch) {m_str = ch; return *this;}
#ifdef _UNICODE
   const CStringKS& operator=(char ch) {TCHAR tCh = ch; m_str = tCh; return *this;}
#endif
   // copy string content from ANSI string (converts to TCHAR)
   const CStringKS& operator=(LPCSTR  lpsz) {m_str = (LPCTSTR)CStringKS(lpsz); return *this;}
   // copy string content from UNICODE string (converts to TCHAR)
   const CStringKS& operator=(LPCWSTR lpsz) {m_str = (LPCTSTR)CStringKS(lpsz); return *this;}
   // copy string content from unsigned chars
   const CStringKS& operator=(const unsigned char* psz) {USES_CONVERSION; m_str = A2CT((const char*)psz); return *this;}

   // string concatenation

   // concatenate from another CStringKS
   const CStringKS& operator+=(const CStringKS& string) {m_str += (LPCTSTR)string; return *this;}

   // concatenate a single character
   const CStringKS& operator+=(TCHAR ch) {m_str += ch; return *this;}
#ifdef _UNICODE
   // concatenate an ANSI character after converting it to TCHAR
   const CStringKS& operator+=(char ch) {TCHAR tCh = ch; m_str += tCh; return *this;}
#endif
   // concatenate a UNICODE character after converting it to TCHAR
   const CStringKS& operator+=(LPCTSTR lpsz) {m_str += lpsz; return *this;}

   friend CStringKS operator+(const CStringKS& string1, const CStringKS& string2) {CStringKS str(string1); return (str += string2);}
   friend CStringKS operator+(const CStringKS& string, TCHAR ch) {CStringKS str(string); return (str += ch    );}
   friend CStringKS operator+(TCHAR ch, const CStringKS& string) {CStringKS str(ch    ); return (str += string);}
#ifdef _UNICODE
   friend CStringKS operator+(const CStringKS& string, char ch) {CStringKS str(string); TCHAR tCh = ch; return (str += tCh);}
   friend CStringKS operator+(char ch, const CStringKS& string) {TCHAR tCh = ch; CStringKS str(tCh); return (str += string);}
#endif
   friend CStringKS operator+(const CStringKS& string, LPCTSTR lpsz) {CStringKS str(string); return (str += lpsz  );}
   friend CStringKS operator+(LPCTSTR lpsz, const CStringKS& string) {CStringKS str(lpsz  ); return (str += string);}

   // string comparison

   // straight character comparison
   int Compare      (LPCTSTR lpsz) const {return _tcscmp  (this->operator LPCTSTR(), lpsz);}
   // compare ignoring case
   int CompareNoCase(LPCTSTR lpsz) const {return _tcsicmp (this->operator LPCTSTR(), lpsz);}
   // NLS aware comparison, case sensitive
   int Collate      (LPCTSTR lpsz) const {return _tcscoll (this->operator LPCTSTR(), lpsz);}
   // NLS aware comparison, case insensitive
   int CollateNoCase(LPCTSTR lpsz) const {return _tcsicoll(this->operator LPCTSTR(), lpsz);}

   // simple sub-string extraction

   // return nCount characters starting at zero-based nFirst
   CStringKS Mid(int nFirst, int nCount) const {return Mid(nFirst).Left(nCount);}
   // return all characters starting at zero-based nFirst
   CStringKS Mid(int nFirst) const {return CStringKS(this->operator LPCTSTR()+max(0,nFirst));}
   // return first nCount characters in string
   CStringKS Left(int nCount) const {CStringKS str; for (int i=0; i<nCount; i++) str += GetAt(i); return str;}
   // return nCount characters from end of string
   CStringKS Right(int nCount) const {return Mid(GetLength()-max(0,nCount));}

   //  characters from beginning that are also in passed string
   CStringKS SpanIncluding(LPCTSTR lpszCharSet) const {CStringKS str; for (int i=0; i<GetLength(); i++) if(_tcschr(lpszCharSet, GetAt(i)) != NULL) str += GetAt(i); else break; return str;}
   // characters from beginning that are not also in passed string
   CStringKS SpanExcluding(LPCTSTR lpszCharSet) const {CStringKS str; for (int i=0; i<GetLength(); i++) if(_tcschr(lpszCharSet, GetAt(i)) == NULL) str += GetAt(i); else break; return str;}

   // upper/lower/reverse conversion

   // NLS aware conversion to uppercase
   void MakeUpper() {
      //TCHAR *szStr = new TCHAR[1+GetLength()];
      //_tcscpy(szStr, this->operator LPCTSTR());
      ::CharUpper((LPTSTR)this->operator LPCTSTR());//::CharUpper(szStr);
      //m_str = szStr;
      //delete szStr;
   }
   // NLS aware conversion to lowercase
   void MakeLower() {
      //TCHAR *szStr = new TCHAR[1+GetLength()];
      //_tcscpy(szStr, this->operator LPCTSTR());
      ::CharLower((LPTSTR)this->operator LPCTSTR());//::CharLower(szStr);
      //m_str = szStr;
      //delete szStr;
   }
   // reverse string right-to-left
   void MakeReverse() {
      int len = GetLength();
      for (int i=0; i<len/2; i++) {
         TCHAR ch = GetAt(i);
         SetAt(i, GetAt(len-i-1));
         SetAt(len-i-1, ch);
      }
   }

   // trimming whitespace (either side)

   // remove whitespace starting from right edge
   void TrimRight() {TrimRight(TEXT(' '));}
   // remove whitespace starting from left side
   void TrimLeft () {TrimLeft (TEXT(' '));}

   // trimming anything (either side)

   // remove continuous occurrences of chTarget starting from right
   void TrimRight(TCHAR chTarget) {
      for (int i=GetLength()-1; i>=0; i--) {
         if (GetAt(i) != chTarget) {
            operator =(Left(i+1));
            break;
         }
      }
   }
   // remove continuous occcurrences of characters in passed string,
   // starting from right
   void TrimRight(LPCTSTR lpszTargets) {
      int pos = -1;
      CStringKS strTargets(lpszTargets);
      for (int i=GetLength()-1; i>=0; i--) {
         if (strTargets.Find(GetAt(i)) != -1) {
            pos = i;
         } else {
            break;
         }
      }
      if (pos >= 0) {
         operator =(Left(pos));
      }
   }
   // remove continuous occurrences of chTarget starting from left
   void TrimLeft(TCHAR chTarget) {
      for (int i=0; i<GetLength(); i++) {
         if (GetAt(i) != chTarget) {
            operator =(Mid(i));
            break;
         }
      }
   }
   // remove continuous occcurrences of characters in
   // passed string, starting from left
   void TrimLeft(LPCTSTR lpszTargets) {
      int pos = -1;
      CStringKS strTargets(lpszTargets);
      for (int i=0; i<GetLength(); i++) {
         if (strTargets.Find(GetAt(i)) != -1) {
            pos = i;
         } else {
            break;
         }
      }
      if (pos >= 0) {
         operator =(Mid(i));
      }
   }

   // advanced manipulation

   // replace occurrences of chOld with chNew
   int Replace(TCHAR chOld, TCHAR chNew) {
      int count = 0;
      for (int i=0; i<GetLength(); i++) {
         if (GetAt(i) == chOld) {
            SetAt(i, chNew);
            count++;
         }
      }
      return count;
   }

   // replace occurrences of substring lpszOld with lpszNew;
   // empty lpszNew removes instances of lpszOld
   int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew) {
      int count = 0;
      if (lpszOld) {
         int pos = 0;
         size_t len = _tcslen(lpszOld);
         do {
            pos = Find(lpszOld, pos);
            if (pos == -1) break;
            count++;
            if (lpszNew) {
               m_str.replace(pos, len, lpszNew);
            } else {
               m_str.erase(pos, len);
            }
         } while (true);
      }
      return count;
   }
   // remove occurrences of chRemove
   int Remove(TCHAR chRemove) {
      int count = 0;
      int i=0;
      while (i<GetLength()) {
         if (GetAt(i) == chRemove) {
            Delete(i);
            count++;
         } else {
            i++;
         }
      }
      return count;
   }
   // insert character at zero-based index; concatenates
   // if index is past end of string
   int Insert(int nIndex, TCHAR ch) {
      m_str.insert(max(0, min(nIndex, GetLength())), 1, ch);
      return GetLength();
   }
   // insert substring at zero-based index; concatenates
   // if index is past end of string
   int Insert(int nIndex, LPCTSTR pstr) {
      if (pstr) {
         m_str.insert(max(0, min(nIndex, GetLength())), pstr);
      }
      return GetLength();
   }
   // delete nCount characters starting at zero-based index
   int Delete(int nIndex, int nCount = 1) {
      const int iRes = GetLength();
      if (nCount > 0) {
         nIndex = max(0, nIndex);
         nCount = min(nCount, GetLength()-nIndex);
         m_str.erase(nIndex, nCount);
      }
      return iRes;
   }

   // searching

   // find character starting at left, -1 if not found
   int Find(TCHAR ch) const {return m_str.find(ch);}
   // find character starting at right
   int ReverseFind(TCHAR ch) const {return m_str.rfind(ch);}
   // find character starting at zero-based index and going right
   int Find(TCHAR ch, int nStart) const {return m_str.find(ch, nStart);}
   // find first instance of any character in passed string
   int FindOneOf(LPCTSTR lpszCharSet) const {return m_str.find_first_of(lpszCharSet);}
   // find first instance of substring
   int Find(LPCTSTR lpszSub) const {return m_str.find(lpszSub);}
   // find first instance of substring starting at zero-based index
   int Find(LPCTSTR lpszSub, int nStart) const {return m_str.find(lpszSub, nStart);}

   // simple formatting

   // printf-like formatting using passed string
   void Format(LPCTSTR lpszFormat, ...) {
      va_list arglist;
      va_start(arglist, lpszFormat);
      FormatV(lpszFormat, arglist);
      va_end(arglist);
   }
   // printf-like formatting using referenced string resource
   void Format(UINT nFormatID, ...) {
      va_list arglist;
      va_start(arglist, nFormatID);
      CStringKS strLoad;
      BOOL bRes = strLoad.LoadString(nFormatID);
      if (bRes) {
         FormatV(strLoad, arglist);
      } else {
         Empty();
      }
      va_end(arglist);
   }
   // printf-like formatting using variable arguments parameter
   void FormatV(LPCTSTR lpszFormat, va_list argList) {
      size_t sizeBuff = 512;
      TCHAR *szFormat = NULL;
      int write = -1;
      do {
         szFormat = new TCHAR[sizeBuff*=2];
         write = _vsntprintf(szFormat, sizeBuff-1, lpszFormat, argList);
         if (write >= 0) {
            m_str = szFormat;
         }
         delete [] szFormat;
      } while (write < 0);
   }

   // formatting for localization (uses FormatMessage API)

   // format using FormatMessage API on passed string
   void FormatMessage(LPCTSTR lpszFormat, ...) {
      va_list argList;
      va_start(argList, lpszFormat);
      LPTSTR lpszTemp;
      if ((::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0) &&
          (lpszTemp == NULL))
      {
         *this = lpszTemp;
         LocalFree(lpszTemp);
      }
      va_end(argList);
   }
   // format using FormatMessage API on referenced string resource
   void FormatMessage(UINT nFormatID, ...) {
      CStringKS strFormat;
      if (strFormat.LoadString(nFormatID)) {
         va_list argList;
         va_start(argList, nFormatID);
         LPTSTR lpszTemp;
         if ((::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0) &&
             (lpszTemp == NULL))
         {
            *this = lpszTemp;
            LocalFree(lpszTemp);
         }
         va_end(argList);
      }
   }

   // input and output
   //friend CArchive& operator<<(CArchive& ar, const CStringKS& string);
   //friend CArchive& operator>>(CArchive& ar, CStringKS& string);

   // load from string resource
   BOOL LoadString(UINT nID) {
      size_t sizeBuff = 512;
      bool bRepeat;
      int iRes = 0;
      TCHAR *szFormat = NULL;
      do {
         szFormat = new TCHAR[sizeBuff*=2];
         iRes = ::LoadString(::GetModuleHandle(NULL), nID, szFormat, sizeBuff);
         bRepeat = (iRes+1 >= sizeBuff);
         if (!bRepeat)
            m_str = szFormat;
         delete [] szFormat;
      } while (bRepeat);
      return (iRes > 0);
   }

#ifndef _UNICODE
   // ANSI <-> OEM support (convert string in place)

   // convert string from ANSI to OEM in-place
   void AnsiToOem() {::CharToOem((LPCTSTR)this->operator LPCTSTR(), (LPSTR) this->operator LPCTSTR());}
   // convert string from OEM to ANSI in-place
   void OemToAnsi() {::OemToChar((LPCSTR) this->operator LPCTSTR(), (LPTSTR)this->operator LPCTSTR());}
#endif

#ifndef _AFX_NO_BSTR_SUPPORT
   // OLE BSTR support (use for OLE automation)

   // return a BSTR initialized with this CStringKS's data
   BSTR AllocSysString() const {USES_CONVERSION; return SysAllocString(T2COLE(m_str.c_str()));}
   // reallocates the passed BSTR, copies content of this CStringKS to it
   BSTR SetSysString(BSTR* pbstr) const {BSTR szRes = AllocSysString(); if (pbstr) {::SysFreeString(*pbstr); *pbstr=szRes;} return szRes;}
#endif

   // Access to string implementation buffer as "C" character array

   // get pointer to modifiable buffer at least as long as nMinBufLength
   LPTSTR GetBuffer(int nMinBufLength) {
      if (GetLength() < nMinBufLength) {
         m_str.resize(nMinBufLength);
      }
      return (LPTSTR)this->operator LPCTSTR();
   }
   // release buffer, setting length to nNewLength (or to first nul if -1)
   void ReleaseBuffer(int nNewLength = -1) {
      if (nNewLength != -1) {
         nNewLength = max(0, nNewLength);
         m_str.resize(nNewLength);
      }
      FreeExtra();
   }
   // get pointer to modifiable buffer exactly as long as nNewLength
   LPTSTR GetBufferSetLength(int nNewLength) { return GetBuffer(nNewLength);}
   // release memory allocated to but unused by string
   void FreeExtra() {
      int pos = Find(TEXT('\0'));
      if (pos != -1) {
         m_str.resize(pos);
      }
   }

   // Use LockBuffer/UnlockBuffer to turn refcounting off

   // turn refcounting back on
   LPTSTR LockBuffer();
   // turn refcounting off
   void UnlockBuffer();

// Implementation
public:
   ~CStringKS() {}
   int GetAllocLength() const {return GetLength();};
};

#ifndef __AFX_H__
typedef CStringKS CString;
#endif

#endif // __FILE__CSTRINGKS__



29.10.04 17:43: Перенесено из 'WIN API'
Серёга, любит баранью ногу.
Re: Исходник. Реализация CString без MFC.
От: sercher Украина  
Дата: 29.10.04 13:20
Оценка:
Нету синхронизации и подсчёта ссылок. (зависит от реализации stl). Так что я бы не рискнул слепо использовать этот класс...
Re[2]: Исходник. Реализация CString без MFC.
От: AndrewJD США  
Дата: 29.10.04 13:53
Оценка:
Здравствуйте, sercher, Вы писали:


S> Нету синхронизации и подсчёта ссылок. (зависит от реализации stl). Так что я бы не рискнул слепо использовать этот класс...


А зачем там синхронихация?
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re: Исходник. Реализация CString без MFC.
От: _nn_ www.nemerleweb.com
Дата: 30.10.04 09:13
Оценка:
Здравствуйте, SeregaLBN, Вы писали:

Для VC 7 и выше лучше пользоваться CAtlString(atlstr.h).

P.S.
Пока что лучше чем wnd_string
Автор: _nn_
Дата: 08.08.04
ничего не нахожу.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Добавлены ф-ции сравнения
От: SeregaLBN Украина  
Дата: 01.03.06 08:18
Оценка: 3 (1)
Добавлены ф-ции сравнения:
////////////////////////////////////////////////////////////////////////////////
// File name: CStringKS.h
// Author: Sergey Krivulya (Ceргей Кpивуля) - KSerg (SeregaLBN)
// e-mail: Sergey_Krivulya@UkrPost.Net
// Date: 2006 02 28
//
// Description: Класс для работы со строками.
//     Реализует почти весь интерфейс CString из MFC.
// Для чего это было написано? Для облегчения переноса MFC модулей на Win32 API.
// Класс CStringKS - это обёртка std::string, которая предоставляет
// пользователю привычный интерфейс CString.
//    При использовании MFC, CString и CStringKS - это 2 разных класса.
// А при использовании только Win32 API - это один и тот же класс CStringKS.
//
// Особенности:
// 1. Если в MFC можно было так писать:
//   CString str1(_T("qwerty"));
//   CString str2;
//   str2.Format(_T("str1 = %s"), str1);
// То при использовании CStringKS надо писать так:
//   CStringKS str1(_T("qwerty"));
//   CStringKS str2;
//   str2.Format(_T("str1 = %s"), (LPCTSTR)str1);
//
// 2. Нереализованные методы:
//   friend CArchive& operator<<(CArchive& ar, const CString& string);
//   friend CArchive& operator>>(CArchive& ar, CString& string);
//   LPTSTR LockBuffer();
//   void UnlockBuffer();
//
////////////////////////////////////////////////////////////////////////////////

#ifndef __FILE__CSTRINGKS__
#define __FILE__CSTRINGKS__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <TChar.H>
#include <ComDef.h>
#pragma warning(disable:4786) // identifier was truncated to '255' characters in the debug information
#include <string>
#include <crtdbg.h>
#include <ATLConv.H>

class CStringKS {
private:
   #ifdef UNICODE
      typedef std::wstring tstring;
   #else
      typedef std:: string tstring;
   #endif // UNICODE
   tstring m_str;
public:

// Constructors

   // constructs empty CStringKS
   CStringKS() {}
   // copy constructor
   CStringKS(const CStringKS& stringSrc) : m_str((LPCTSTR)stringSrc) {}
   // from a single character
   CStringKS(TCHAR ch, int nRepeat = 1) : m_str(tstring(nRepeat, ch)) {}
   // from an ANSI string (converts to TCHAR)
   CStringKS(LPCSTR  lpsz) {if (lpsz!=NULL) {USES_CONVERSION; m_str = A2CT(lpsz);}}
   // from a UNICODE string (converts to TCHAR)
   CStringKS(LPCWSTR lpsz) {if (lpsz!=NULL) {USES_CONVERSION; m_str = W2CT(lpsz);}}
   // subset of characters from an ANSI string (converts to TCHAR)
   CStringKS(LPCSTR lpch, int nLength)  : m_str((LPCTSTR)(CStringKS(lpch).Left(nLength))) {}
   // subset of characters from a UNICODE string (converts to TCHAR)
   CStringKS(LPCWSTR lpch, int nLength) : m_str((LPCTSTR)(CStringKS(lpch).Left(nLength))) {}
   // from unsigned characters
   CStringKS(const unsigned char* psz) {this->operator=(psz);}

// Attributes & Operations

   // get data length
   int GetLength() const {return m_str.length();}
   // TRUE if zero length
   BOOL IsEmpty() const {return m_str.empty();}
   // clear contents to empty
   void Empty() {m_str.erase();}

   // return single character at zero-based index
   TCHAR GetAt(int nIndex) const {return m_str[nIndex];}
   // return single character at zero-based index
   TCHAR operator[](int nIndex) const {return m_str[nIndex];}
   // set a single character at zero-based index
   void SetAt(int nIndex, TCHAR ch) {m_str[nIndex] = ch;}
   // return pointer to const string
   operator LPCTSTR() const {return m_str.c_str();}

   // overloaded assignment

   // ref-counted copy from another CStringKS
   const CStringKS& operator=(const CStringKS& stringSrc) { if (&stringSrc != this) {m_str = (LPCTSTR)stringSrc;} return *this;}
   // set string content to single character
   const CStringKS& operator=(TCHAR ch) {m_str = ch; return *this;}
#ifdef _UNICODE
   const CStringKS& operator=(char ch) {TCHAR tCh = ch; m_str = tCh; return *this;}
#endif
   // copy string content from ANSI string (converts to TCHAR)
   const CStringKS& operator=(LPCSTR  lpsz) {m_str = (LPCTSTR)CStringKS(lpsz); return *this;}
   // copy string content from UNICODE string (converts to TCHAR)
   const CStringKS& operator=(LPCWSTR lpsz) {m_str = (LPCTSTR)CStringKS(lpsz); return *this;}
   // copy string content from unsigned chars
   const CStringKS& operator=(const unsigned char* psz) {USES_CONVERSION; m_str = A2CT((const char*)psz); return *this;}

   // string concatenation

   // concatenate from another CStringKS
   const CStringKS& operator+=(const CStringKS& string) {m_str += (LPCTSTR)string; return *this;}

   // concatenate a single character
   const CStringKS& operator+=(TCHAR ch) {m_str += ch; return *this;}
#ifdef _UNICODE
   // concatenate an ANSI character after converting it to TCHAR
   const CStringKS& operator+=(char ch) {TCHAR tCh = ch; m_str += tCh; return *this;}
#endif
   // concatenate a UNICODE character after converting it to TCHAR
   const CStringKS& operator+=(LPCTSTR lpsz) {m_str += lpsz; return *this;}

   friend CStringKS operator+(const CStringKS& string1, const CStringKS& string2) {CStringKS str(string1); return (str += string2);}
   friend CStringKS operator+(const CStringKS& string, TCHAR ch) {CStringKS str(string); return (str += ch    );}
   friend CStringKS operator+(TCHAR ch, const CStringKS& string) {CStringKS str(ch    ); return (str += string);}
#ifdef _UNICODE
   friend CStringKS operator+(const CStringKS& string, char ch) {CStringKS str(string); TCHAR tCh = ch; return (str += tCh);}
   friend CStringKS operator+(char ch, const CStringKS& string) {TCHAR tCh = ch; CStringKS str(tCh); return (str += string);}
#endif
   friend CStringKS operator+(const CStringKS& string, LPCTSTR lpsz) {CStringKS str(string); return (str += lpsz  );}
   friend CStringKS operator+(LPCTSTR lpsz, const CStringKS& string) {CStringKS str(lpsz  ); return (str += string);}

   // string comparison

   // straight character comparison
   int Compare      (LPCTSTR lpsz) const {return _tcscmp  (this->operator LPCTSTR(), lpsz);}
   // compare ignoring case
   int CompareNoCase(LPCTSTR lpsz) const {return _tcsicmp (this->operator LPCTSTR(), lpsz);}
   // NLS aware comparison, case sensitive
   int Collate      (LPCTSTR lpsz) const {return _tcscoll (this->operator LPCTSTR(), lpsz);}
   // NLS aware comparison, case insensitive
   int CollateNoCase(LPCTSTR lpsz) const {return _tcsicoll(this->operator LPCTSTR(), lpsz);}

   // simple sub-string extraction

   // return nCount characters starting at zero-based nFirst
   CStringKS Mid(int nFirst, int nCount) const {return Mid(nFirst).Left(nCount);}
   // return all characters starting at zero-based nFirst
   CStringKS Mid(int nFirst) const {return CStringKS(this->operator LPCTSTR()+max(0,nFirst));}
   // return first nCount characters in string
   CStringKS Left(int nCount) const {CStringKS str; for (int i=0; i<nCount; i++) str += GetAt(i); return str;}
   // return nCount characters from end of string
   CStringKS Right(int nCount) const {return Mid(GetLength()-max(0,nCount));}

   //  characters from beginning that are also in passed string
   CStringKS SpanIncluding(LPCTSTR lpszCharSet) const {CStringKS str; for (int i=0; i<GetLength(); i++) if(_tcschr(lpszCharSet, GetAt(i)) != NULL) str += GetAt(i); else break; return str;}
   // characters from beginning that are not also in passed string
   CStringKS SpanExcluding(LPCTSTR lpszCharSet) const {CStringKS str; for (int i=0; i<GetLength(); i++) if(_tcschr(lpszCharSet, GetAt(i)) == NULL) str += GetAt(i); else break; return str;}

   // upper/lower/reverse conversion

   // NLS aware conversion to uppercase
   void MakeUpper() {
      //TCHAR *szStr = new TCHAR[1+GetLength()];
      //_tcscpy(szStr, this->operator LPCTSTR());
      ::CharUpper((LPTSTR)this->operator LPCTSTR());//::CharUpper(szStr);
      //m_str = szStr;
      //delete szStr;
   }
   // NLS aware conversion to lowercase
   void MakeLower() {
      //TCHAR *szStr = new TCHAR[1+GetLength()];
      //_tcscpy(szStr, this->operator LPCTSTR());
      ::CharLower((LPTSTR)this->operator LPCTSTR());//::CharLower(szStr);
      //m_str = szStr;
      //delete szStr;
   }
   // reverse string right-to-left
   void MakeReverse() {
      int len = GetLength();
      for (int i=0; i<(len>>1); i++) {
         TCHAR ch = GetAt(i);
         SetAt(i, GetAt(len-i-1));
         SetAt(len-i-1, ch);
      }
   }

   // trimming whitespace (either side)

   // remove whitespace starting from right edge
   void TrimRight() {TrimRight(_T(' '));}
   // remove whitespace starting from left side
   void TrimLeft () {TrimLeft (_T(' '));}

   // trimming anything (either side)

   // remove continuous occurrences of chTarget starting from right
   void TrimRight(TCHAR chTarget) {
      for (int i=GetLength()-1; i>=0; i--) {
         if (GetAt(i) != chTarget) {
            operator =(Left(i+1));
            break;
         }
      }
   }
   // remove continuous occcurrences of characters in passed string,
   // starting from right
   void TrimRight(LPCTSTR lpszTargets) {
      int pos = -1;
      CStringKS strTargets(lpszTargets);
      for (int i=GetLength()-1; i>=0; i--) {
         if (strTargets.Find(GetAt(i)) != -1) {
            pos = i;
         } else {
            break;
         }
      }
      if (pos >= 0) {
         operator =(Left(pos));
      }
   }
   // remove continuous occurrences of chTarget starting from left
   void TrimLeft(TCHAR chTarget) {
      for (int i=0; i<GetLength(); i++) {
         if (GetAt(i) != chTarget) {
            operator =(Mid(i));
            break;
         }
      }
   }
   // remove continuous occcurrences of characters in
   // passed string, starting from left
   void TrimLeft(LPCTSTR lpszTargets) {
      int pos = -1;
      CStringKS strTargets(lpszTargets);
      for (int i=0; i<GetLength(); i++) {
         if (strTargets.Find(GetAt(i)) != -1) {
            pos = i;
         } else {
            break;
         }
      }
      if (pos >= 0) {
         operator =(Mid(i));
      }
   }

   // advanced manipulation

   // replace occurrences of chOld with chNew
   int Replace(TCHAR chOld, TCHAR chNew) {
      int count = 0;
      for (int i=0; i<GetLength(); i++) {
         if (GetAt(i) == chOld) {
            SetAt(i, chNew);
            count++;
         }
      }
      return count;
   }

   // replace occurrences of substring lpszOld with lpszNew;
   // empty lpszNew removes instances of lpszOld
   int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew) {
      int count = 0;
      if (lpszOld) {
         int pos = 0;
         size_t len = _tcslen(lpszOld);
         do {
            pos = Find(lpszOld, pos);
            if (pos == -1) break;
            count++;
            if (lpszNew) {
               m_str.replace(pos, len, lpszNew);
            } else {
               m_str.erase(pos, len);
            }
         } while (true);
      }
      return count;
   }
   // remove occurrences of chRemove
   int Remove(TCHAR chRemove) {
      int count = 0;
      int i=0;
      while (i<GetLength()) {
         if (GetAt(i) == chRemove) {
            Delete(i);
            count++;
         } else {
            i++;
         }
      }
      return count;
   }
   // insert character at zero-based index; concatenates
   // if index is past end of string
   int Insert(int nIndex, TCHAR ch) {
      m_str.insert(max(0, min(nIndex, GetLength())), 1, ch);
      return GetLength();
   }
   // insert substring at zero-based index; concatenates
   // if index is past end of string
   int Insert(int nIndex, LPCTSTR pstr) {
      if (pstr) {
         m_str.insert(max(0, min(nIndex, GetLength())), pstr);
      }
      return GetLength();
   }
   // delete nCount characters starting at zero-based index
   int Delete(int nIndex, int nCount = 1) {
      const int iRes = GetLength();
      if (nCount > 0) {
         nIndex = max(0, nIndex);
         nCount = min(nCount, GetLength()-nIndex);
         m_str.erase(nIndex, nCount);
      }
      return iRes;
   }

   // searching

   // find character starting at left, -1 if not found
   int Find(TCHAR ch) const {return m_str.find(ch);}
   // find character starting at right
   int ReverseFind(TCHAR ch) const {return m_str.rfind(ch);}
   // find character starting at zero-based index and going right
   int Find(TCHAR ch, int nStart) const {return m_str.find(ch, nStart);}
   // find first instance of any character in passed string
   int FindOneOf(LPCTSTR lpszCharSet) const {return m_str.find_first_of(lpszCharSet);}
   // find first instance of substring
   int Find(LPCTSTR lpszSub) const {return m_str.find(lpszSub);}
   // find first instance of substring starting at zero-based index
   int Find(LPCTSTR lpszSub, int nStart) const {return m_str.find(lpszSub, nStart);}

   // simple formatting

   // printf-like formatting using passed string
   void Format(LPCTSTR lpszFormat, ...) {
      va_list arglist;
      va_start(arglist, lpszFormat);
      FormatV(lpszFormat, arglist);
      va_end(arglist);
   }
   // printf-like formatting using referenced string resource
   void Format(UINT nFormatID, ...) {
      va_list arglist;
      va_start(arglist, nFormatID);
      CStringKS strLoad;
      BOOL bRes = strLoad.LoadString(nFormatID);
      if (bRes) {
         FormatV(strLoad, arglist);
      } else {
         Empty();
      }
      va_end(arglist);
   }
   // printf-like formatting using variable arguments parameter
   void FormatV(LPCTSTR lpszFormat, va_list argList) {
      size_t sizeBuff = 512;
      TCHAR *szFormat = NULL;
      int write = -1;
      do {
         sizeBuff = sizeBuff<<1;
         szFormat = new TCHAR[sizeBuff];
         if (szFormat) {
            szFormat[0] = 0;
            write = _vsntprintf(szFormat, sizeBuff-1, lpszFormat, argList);
            if (write >= 0) {
               m_str = szFormat;
            }
            delete [] szFormat;
         } else {
            break;
         }
      } while (write < 0);
   }

   // formatting for localization (uses FormatMessage API)

   // format using FormatMessage API on passed string
   void FormatMessage(LPCTSTR lpszFormat, ...) {
      va_list argList;
      va_start(argList, lpszFormat);
      LPTSTR lpszTemp;
      if ((::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0) &&
          (lpszTemp == NULL))
      {
         *this = lpszTemp;
         LocalFree(lpszTemp);
      }
      va_end(argList);
   }
   // format using FormatMessage API on referenced string resource
   void FormatMessage(UINT nFormatID, ...) {
      CStringKS strFormat;
      if (strFormat.LoadString(nFormatID)) {
         va_list argList;
         va_start(argList, nFormatID);
         LPTSTR lpszTemp;
         if ((::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0) &&
             (lpszTemp == NULL))
         {
            *this = lpszTemp;
            LocalFree(lpszTemp);
         }
         va_end(argList);
      }
   }

   // input and output
   //friend CArchive& operator<<(CArchive& ar, const CStringKS& string);
   //friend CArchive& operator>>(CArchive& ar, CStringKS& string);

   // load from string resource
   BOOL LoadString(UINT nID) {
      size_t sizeBuff = 512;
      bool bRepeat;
      int iRes = 0;
      TCHAR *szFormat = NULL;
      do {
         sizeBuff = sizeBuff<<1;
         szFormat = new TCHAR[sizeBuff];
         if (szFormat) {
            szFormat[0] = 0;
            iRes = ::LoadString(::GetModuleHandle(NULL), nID, szFormat, sizeBuff);
            bRepeat = (iRes+1 >= sizeBuff);
            if (!bRepeat) {
               m_str = szFormat;
            }
            delete [] szFormat;
         } else {
            break;
         }
      } while (bRepeat);
      return (iRes > 0);
   }

#ifndef _UNICODE
   // ANSI <-> OEM support (convert string in place)

   // convert string from ANSI to OEM in-place
   void AnsiToOem() {::CharToOem((LPCTSTR)this->operator LPCTSTR(), (LPSTR) this->operator LPCTSTR());}
   // convert string from OEM to ANSI in-place
   void OemToAnsi() {::OemToChar((LPCSTR) this->operator LPCTSTR(), (LPTSTR)this->operator LPCTSTR());}
#endif

#ifndef _AFX_NO_BSTR_SUPPORT
   // OLE BSTR support (use for OLE automation)

   // return a BSTR initialized with this CStringKS's data
   BSTR AllocSysString() const {USES_CONVERSION; return SysAllocString(T2COLE(m_str.c_str()));}
   // reallocates the passed BSTR, copies content of this CStringKS to it
   BSTR SetSysString(BSTR* pbstr) const {BSTR szRes = AllocSysString(); if (pbstr) {::SysFreeString(*pbstr); *pbstr=szRes;} return szRes;}
#endif

   // Access to string implementation buffer as "C" character array

   // get pointer to modifiable buffer at least as long as nMinBufLength
   LPTSTR GetBuffer(int nMinBufLength) {
      if (GetLength() < nMinBufLength) {
         m_str.resize(nMinBufLength);
      }
      return (LPTSTR)this->operator LPCTSTR();
   }
   // release buffer, setting length to nNewLength (or to first nul if -1)
   void ReleaseBuffer(int nNewLength = -1) {
      if (nNewLength != -1) {
         nNewLength = max(0, nNewLength);
         m_str.resize(nNewLength);
      }
      FreeExtra();
   }
   // get pointer to modifiable buffer exactly as long as nNewLength
   LPTSTR GetBufferSetLength(int nNewLength) { return GetBuffer(nNewLength);}
   // release memory allocated to but unused by string
   void FreeExtra() {
      int pos = Find(_T('\0'));
      if (pos != -1) {
         m_str.resize(pos);
      }
   }

   // Use LockBuffer/UnlockBuffer to turn refcounting off

   // turn refcounting back on
   LPTSTR LockBuffer();
   // turn refcounting off
   void UnlockBuffer();

// Implementation
public:
   ~CStringKS() {}
   int GetAllocLength() const {return GetLength();};
};

// Compare helpers
bool operator==(const CStringKS& s1, const CStringKS& s2) { return (s1.Compare(s2) == 0); }
bool operator==(const CStringKS& s1, LPCTSTR s2)          { return (s1.Compare(s2) == 0); }
bool operator==(LPCTSTR s1, const CStringKS& s2)          { return (s2.Compare(s1) == 0); }
bool operator!=(const CStringKS& s1, const CStringKS& s2) { return (s1.Compare(s2) != 0); }
bool operator!=(const CStringKS& s1, LPCTSTR s2)          { return (s1.Compare(s2) != 0); }
bool operator!=(LPCTSTR s1, const CStringKS& s2)          { return (s2.Compare(s1) != 0); }
bool operator<(const CStringKS& s1, const CStringKS& s2)  { return (s1.Compare(s2) <  0); }
bool operator<(const CStringKS& s1, LPCTSTR s2)           { return (s1.Compare(s2) <  0); }
bool operator<(LPCTSTR s1, const CStringKS& s2)           { return (s2.Compare(s1) >  0); }
bool operator>(const CStringKS& s1, const CStringKS& s2)  { return (s1.Compare(s2) >  0); }
bool operator>(const CStringKS& s1, LPCTSTR s2)           { return (s1.Compare(s2) >  0); }
bool operator>(LPCTSTR s1, const CStringKS& s2)           { return (s2.Compare(s1) <  0); }
bool operator<=(const CStringKS& s1, const CStringKS& s2) { return (s1.Compare(s2) <= 0); }
bool operator<=(const CStringKS& s1, LPCTSTR s2)          { return (s1.Compare(s2) <= 0); }
bool operator<=(LPCTSTR s1, const CStringKS& s2)          { return (s2.Compare(s1) >= 0); }
bool operator>=(const CStringKS& s1, const CStringKS& s2) { return (s1.Compare(s2) >= 0); }
bool operator>=(const CStringKS& s1, LPCTSTR s2)          { return (s1.Compare(s2) >= 0); }
bool operator>=(LPCTSTR s1, const CStringKS& s2)          { return (s2.Compare(s1) <= 0); }

#ifndef __AFX_H__
   typedef CStringKS CString;
#endif

#endif // __FILE__CSTRINGKS__
Серёга, любит баранью ногу.
Re[2]: Добавлены ф-ции сравнения
От: Vlads  
Дата: 08.09.06 17:47
Оценка:
Еще бы этот клас обернуть в шаблонный клас — цены бы ему не было...
Re[3]: Добавлены ф-ции сравнения
От: EqWu Россия  
Дата: 12.09.06 13:55
Оценка: 14 (1)
Здравствуйте, Vlads, Вы писали:

V>Еще бы этот клас обернуть в шаблонный клас — цены бы ему не было...


http://home.earthlink.net/~jmoleary/stdstring.htm
Re: Исходник. Реализация CString без MFC.
От: WoldemaR Россия  
Дата: 15.09.06 14:15
Оценка:
SLB>// Для чего это было написано? Лично моё мнение — если есть выбор между
SLB>// использованием CString и std::string я всегда предпочитаю CString.
SLB>// В основном из-за метода CString::Format(). [...]

Для любителей метода Format готовлю одноимённую функцию.
очень полезную. экономит строчку (а иногда 2) кода.
CString Format(LPCTSTR s, ...)
{
    va_list args;
    va_start(args, s);

    CString str;
    str.FormatV(s, args);
    return str;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.