home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK10 / MFC / SRC / STRING.CP$ / string
Encoding:
Text File  |  1992-03-10  |  7.0 KB  |  292 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library. 
  2. // Copyright (C) 1992 Microsoft Corporation 
  3. // All rights reserved. 
  4. //  
  5. // This source code is only intended as a supplement to the 
  6. // Microsoft Foundation Classes Reference and Microsoft 
  7. // QuickHelp documentation provided with the library. 
  8. // See these sources for detailed information regarding the 
  9. // Microsoft Foundation Classes product. 
  10.  
  11.  
  12. #include "afx.h"
  13. #pragma hdrstop
  14. #include <limits.h>
  15.  
  16. #ifdef AFX_CORE_SEG
  17. #pragma code_seg(AFX_CORE_SEG)
  18. #endif
  19.  
  20. #ifdef _DEBUG
  21. #undef THIS_FILE
  22. static char BASED_CODE THIS_FILE[] = __FILE__;
  23. #endif
  24.  
  25. #define new DEBUG_NEW
  26.  
  27. /////////////////////////////////////////////////////////////////////////////
  28. // static class data, special inlines
  29.  
  30. char _afxChNil = '\0';
  31.  
  32. // For an empty string, m_???Data will point here
  33. // (note: avoids a lot of NULL pointer tests when we call standard
  34. //  C runtime libraries
  35.  
  36. extern const CString NEAR afxEmptyString;
  37. const CString NEAR afxEmptyString;
  38.  
  39. void CString::Init()
  40. {
  41.     m_nDataLength = m_nAllocLength = 0;
  42.     m_pchData = &_afxChNil;
  43. }
  44.  
  45. //////////////////////////////////////////////////////////////////////////////
  46. // Construction/Destruction
  47.  
  48. CString::CString()
  49. {
  50.     Init();
  51. }
  52.  
  53. CString::CString(const CString& stringSrc)
  54. {
  55.     // if constructing a CString from another CString, we make a copy of the
  56.     // original string data to enforce value semantics (i.e. each string
  57.     // gets a copy of it's own
  58.  
  59.     stringSrc.AllocCopy(*this, stringSrc.m_nDataLength, 0, 0);
  60. }
  61.  
  62. void CString::AllocBuffer(int nLen)
  63.  // always allocate one extra character for '\0' termination
  64.  // assumes [optimistically] that data length will equal allocation length
  65. {
  66.     ASSERT(nLen >= 0);
  67.     ASSERT(nLen < INT_MAX - 1); // max size (enough room for 1 extra)
  68.  
  69.     if (nLen == 0)
  70.     {
  71.         Init();
  72.     }
  73.     else
  74.     {
  75.         m_pchData = new char[nLen+1];       // may throw an exception
  76.         m_pchData[nLen] = '\0';
  77.         m_nDataLength = nLen;
  78.         m_nAllocLength = nLen;
  79.     }
  80. }
  81.  
  82. void CString::Empty()
  83. {
  84.     if (m_pchData != &_afxChNil)
  85.     {
  86.         delete [] m_pchData;
  87.         Init();
  88.     }
  89.     ASSERT(m_nDataLength == 0);
  90.     ASSERT(m_nAllocLength == 0);
  91. }
  92.  
  93. CString::~CString()
  94.  //  free any attached data
  95. {
  96.     if (m_pchData != &_afxChNil)
  97.         delete [] m_pchData;        // NOTE: not type safe
  98. }
  99.  
  100. //////////////////////////////////////////////////////////////////////////////
  101. // Helpers for the rest of the implementation
  102.  
  103. static inline int SafeStrlen(const char* psz)
  104.     { return (psz == NULL) ? NULL : strlen(psz); }
  105.  
  106. void CString::AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,
  107.      int nExtraLen) const
  108. {
  109.     // will clone the data attached to this string
  110.     // allocating 'nExtraLen' characters
  111.     // Places results in uninitialized string 'dest'
  112.     // Will copy the part or all of original data to start of new string
  113.  
  114.     int nNewLen = nCopyLen + nExtraLen;
  115.  
  116.     if (nNewLen == 0)
  117.     {
  118.         dest.Init();
  119.     }
  120.     else
  121.     {
  122.         dest.AllocBuffer(nNewLen);
  123.         memcpy(dest.m_pchData, &m_pchData[nCopyIndex], nCopyLen);
  124.     }
  125. }
  126.  
  127. //////////////////////////////////////////////////////////////////////////////
  128. // More sophisticated construction
  129.  
  130. CString::CString(const char* psz)
  131. {
  132.     int nLen;
  133.     if ((nLen = SafeStrlen(psz)) == 0)
  134.         Init();
  135.     else
  136.     {
  137.         AllocBuffer(nLen);
  138.         memcpy(m_pchData, psz, nLen);
  139.     }
  140. }
  141.  
  142. //////////////////////////////////////////////////////////////////////////////
  143. // Diagnostic support
  144.  
  145. #ifdef _DEBUG 
  146.  
  147. CDumpContext&
  148. operator <<(CDumpContext& dc, const CString& string)
  149. {
  150.     dc << string.m_pchData;
  151.     return dc;
  152. }
  153.  
  154. #endif //_DEBUG
  155.  
  156. //////////////////////////////////////////////////////////////////////////////
  157. // Assignment operators
  158. //  All assign a new value to the string
  159. //      (a) first see if the buffer is big enough
  160. //      (b) if enough room, copy on top of old buffer, set size and type
  161. //      (c) otherwise free old string data, and create a new one
  162. //
  163. //  All routines return the new string (but as a 'const CString&' so that
  164. //      assigning it again will cause a copy, eg: s1 = s2 = "hi there".
  165. //
  166.  
  167. void CString::AssignCopy(int nSrcLen, const char* pszSrcData)
  168. {
  169.     // check if it will fit
  170.     if (nSrcLen > m_nAllocLength)
  171.     {
  172.         // it won't fit, allocate another one
  173.         Empty();
  174.         AllocBuffer(nSrcLen);
  175.     }
  176.     if (nSrcLen != 0)
  177.         memcpy(m_pchData, pszSrcData, nSrcLen);
  178.     m_nDataLength = nSrcLen;
  179.     m_pchData[nSrcLen] = '\0';
  180. }
  181.  
  182. const CString&
  183. CString::operator =(const CString& stringSrc)
  184. {
  185.     AssignCopy(stringSrc.m_nDataLength, stringSrc.m_pchData);
  186.     return *this;
  187. }
  188.  
  189. const CString&
  190. CString::operator =(const char* psz)
  191. {
  192.     AssignCopy(SafeStrlen(psz), psz);
  193.     return *this;
  194. }
  195.  
  196.  
  197. //////////////////////////////////////////////////////////////////////////////
  198. // concatenation
  199.  
  200. // NOTE: "operator +" is done as friend functions for simplicity
  201. //      There are three variants:
  202. //          CString + CString
  203. // and for ? = char, const char*
  204. //          CString + ?
  205. //          ? + CString
  206.  
  207. void
  208. CString::ConcatCopy(int nSrc1Len, const char* pszSrc1Data,
  209.         int nSrc2Len, const char* pszSrc2Data)
  210. {
  211.   // -- master concatenation routine
  212.   // Concatenate two sources
  213.   // -- assume that 'this' is a new CString object
  214.  
  215.     int nNewLen = nSrc1Len + nSrc2Len;
  216.     AllocBuffer(nNewLen);
  217.     memcpy(m_pchData, pszSrc1Data, nSrc1Len);
  218.     memcpy(&m_pchData[nSrc1Len], pszSrc2Data, nSrc2Len);
  219. }
  220.  
  221. CString
  222. operator +(const CString& string1, const CString& string2)
  223. {
  224.     CString s;
  225.     s.ConcatCopy(string1.m_nDataLength, string1.m_pchData,
  226.         string2.m_nDataLength, string2.m_pchData);
  227.     return s;
  228. }
  229.  
  230. CString
  231. operator +(const CString& string, const char* psz)
  232. {
  233.     CString s;
  234.     s.ConcatCopy(string.m_nDataLength, string.m_pchData, SafeStrlen(psz), psz);
  235.     return s;
  236. }
  237.  
  238.  
  239. CString
  240. operator +(const char* psz, const CString& string)
  241. {
  242.     CString s;
  243.     s.ConcatCopy(SafeStrlen(psz), psz, string.m_nDataLength, string.m_pchData);
  244.     return s;
  245. }
  246.  
  247. //////////////////////////////////////////////////////////////////////////////
  248. // concatenate in place
  249.  
  250. void
  251. CString::ConcatInPlace(int nSrcLen, const char* pszSrcData)
  252. {
  253.     //  -- the main routine for += operators
  254.  
  255.     // if the buffer is too small, or we have a width mis-match, just
  256.     //   allocate a new buffer (slow but sure)
  257.     if (m_nDataLength + nSrcLen > m_nAllocLength)
  258.     {
  259.         // we have to grow the buffer, use the Concat in place routine
  260.         char* pszOldData = m_pchData;
  261.         ConcatCopy(m_nDataLength, pszOldData, nSrcLen, pszSrcData);
  262.         ASSERT(pszOldData != NULL);
  263.         if (pszOldData != &_afxChNil)
  264.             delete [] pszOldData;
  265.     }
  266.     else
  267.     {
  268.         // fast concatenation when buffer big enough
  269.         memcpy(&m_pchData[m_nDataLength], pszSrcData, nSrcLen);
  270.         m_nDataLength += nSrcLen;
  271.     }
  272.     ASSERT(m_nDataLength <= m_nAllocLength);
  273.     m_pchData[m_nDataLength] = '\0';
  274. }
  275.  
  276. const CString&
  277. CString::operator +=(const char* psz)
  278. {
  279.     ConcatInPlace(SafeStrlen(psz), psz);
  280.     return *this;
  281. }
  282.  
  283. const CString&
  284. CString::operator +=(const CString& string)
  285. {
  286.     ConcatInPlace(string.m_nDataLength, string.m_pchData);
  287.     return *this;
  288. }
  289.  
  290.  
  291. ///////////////////////////////////////////////////////////////////////////////
  292.