home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 19.ddi / MFC / SRC / STRCORE.CP_ / STRCORE.CP
Encoding:
Text File  |  1993-02-08  |  9.1 KB  |  381 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 and/or WinHelp documentation provided with the library. 
  8. // See these sources for detailed information regarding the 
  9. // Microsoft Foundation Classes product. 
  10.  
  11. #include "stdafx.h"
  12. #include <limits.h>
  13.  
  14. #ifdef AFX_CORE1_SEG
  15. #pragma code_seg(AFX_CORE1_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char BASED_CODE THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #define new DEBUG_NEW
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26. // static class data, special inlines
  27.  
  28. char NEAR _afxChNil = '\0';
  29.  
  30. // For an empty string, m_???Data will point here
  31. // (note: avoids a lot of NULL pointer tests when we call standard
  32. //  C runtime libraries
  33.  
  34. extern const CString NEAR afxEmptyString;   
  35.         // for creating empty key strings
  36. const CString NEAR afxEmptyString;
  37.  
  38. void CString::Init()
  39. {
  40.     m_nDataLength = m_nAllocLength = 0;
  41.     m_pchData = (char*)&_afxChNil;
  42. }
  43.  
  44. static void NEAR PASCAL SafeDelete(char* pch)
  45. {
  46.     if (pch != NULL && pch != (char*)&_afxChNil)
  47.         delete [] pch;
  48. }
  49.  
  50. //////////////////////////////////////////////////////////////////////////////
  51. // Construction/Destruction
  52.  
  53. CString::CString()
  54. {
  55.     Init();
  56. }
  57.  
  58. CString::CString(const CString& stringSrc)
  59. {
  60.     // if constructing a CString from another CString, we make a copy of the
  61.     // original string data to enforce value semantics (i.e. each string
  62.     // gets a copy of it's own
  63.  
  64.     stringSrc.AllocCopy(*this, stringSrc.m_nDataLength, 0, 0);
  65. }
  66.  
  67. void CString::AllocBuffer(int nLen)
  68.  // always allocate one extra character for '\0' termination
  69.  // assumes [optimistically] that data length will equal allocation length
  70. {
  71.     ASSERT(nLen >= 0);
  72.     ASSERT(nLen <= INT_MAX - 1);    // max size (enough room for 1 extra)
  73.  
  74.     if (nLen == 0)
  75.     {
  76.         Init();
  77.     }
  78.     else
  79.     {
  80.         m_pchData = new char[nLen+1];       // may throw an exception
  81.         m_pchData[nLen] = '\0';
  82.         m_nDataLength = nLen;
  83.         m_nAllocLength = nLen;
  84.     }
  85. }
  86.  
  87. void CString::Empty()
  88. {
  89.     SafeDelete(m_pchData);
  90.     Init();
  91.     ASSERT(m_nDataLength == 0);
  92.     ASSERT(m_nAllocLength == 0);
  93. }
  94.  
  95. CString::~CString()
  96.  //  free any attached data
  97. {
  98.     SafeDelete(m_pchData);
  99. }
  100.  
  101. //////////////////////////////////////////////////////////////////////////////
  102. // Helpers for the rest of the implementation
  103.  
  104. static inline int SafeStrlen(const char* psz)
  105.     { return (psz == NULL) ? NULL : strlen(psz); }
  106.  
  107. void CString::AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,
  108.      int nExtraLen) const
  109. {
  110.     // will clone the data attached to this string
  111.     // allocating 'nExtraLen' characters
  112.     // Places results in uninitialized string 'dest'
  113.     // Will copy the part or all of original data to start of new string
  114.  
  115.     int nNewLen = nCopyLen + nExtraLen;
  116.  
  117.     if (nNewLen == 0)
  118.     {
  119.         dest.Init();
  120.     }
  121.     else
  122.     {
  123.         dest.AllocBuffer(nNewLen);
  124.         memcpy(dest.m_pchData, &m_pchData[nCopyIndex], nCopyLen);
  125.     }
  126. }
  127.  
  128. //////////////////////////////////////////////////////////////////////////////
  129. // More sophisticated construction
  130.  
  131. CString::CString(const char* psz)
  132. {
  133.     int nLen;
  134.     if ((nLen = SafeStrlen(psz)) == 0)
  135.         Init();
  136.     else
  137.     {
  138.         AllocBuffer(nLen);
  139.         memcpy(m_pchData, psz, nLen);
  140.     }
  141. }
  142.  
  143. //////////////////////////////////////////////////////////////////////////////
  144. // Diagnostic support
  145.  
  146. #ifdef _DEBUG 
  147.  
  148. CDumpContext&
  149. AFXAPI operator <<(CDumpContext& dc, const CString& string)
  150. {
  151.     dc << string.m_pchData;
  152.     return dc;
  153. }
  154.  
  155. #endif //_DEBUG
  156.  
  157. //////////////////////////////////////////////////////////////////////////////
  158. // Assignment operators
  159. //  All assign a new value to the string
  160. //      (a) first see if the buffer is big enough
  161. //      (b) if enough room, copy on top of old buffer, set size and type
  162. //      (c) otherwise free old string data, and create a new one
  163. //
  164. //  All routines return the new string (but as a 'const CString&' so that
  165. //      assigning it again will cause a copy, eg: s1 = s2 = "hi there".
  166. //
  167.  
  168. void CString::AssignCopy(int nSrcLen, const char* pszSrcData)
  169. {
  170.     // check if it will fit
  171.     if (nSrcLen > m_nAllocLength)
  172.     {
  173.         // it won't fit, allocate another one
  174.         Empty();
  175.         AllocBuffer(nSrcLen);
  176.     }
  177.     if (nSrcLen != 0)
  178.         memcpy(m_pchData, pszSrcData, nSrcLen);
  179.     m_nDataLength = nSrcLen;
  180.     m_pchData[nSrcLen] = '\0';
  181. }
  182.  
  183. const CString&
  184. CString::operator =(const CString& stringSrc)
  185. {
  186.     AssignCopy(stringSrc.m_nDataLength, stringSrc.m_pchData);
  187.     return *this;
  188. }
  189.  
  190. const CString&
  191. CString::operator =(const char* psz)
  192. {
  193.     AssignCopy(SafeStrlen(psz), psz);
  194.     return *this;
  195. }
  196.  
  197.  
  198. //////////////////////////////////////////////////////////////////////////////
  199. // concatenation
  200.  
  201. // NOTE: "operator +" is done as friend functions for simplicity
  202. //      There are three variants:
  203. //          CString + CString
  204. // and for ? = char, const char*
  205. //          CString + ?
  206. //          ? + CString
  207.  
  208. void
  209. CString::ConcatCopy(int nSrc1Len, const char* pszSrc1Data,
  210.         int nSrc2Len, const char* pszSrc2Data)
  211. {
  212.   // -- master concatenation routine
  213.   // Concatenate two sources
  214.   // -- assume that 'this' is a new CString object
  215.  
  216.     int nNewLen = nSrc1Len + nSrc2Len;
  217.     AllocBuffer(nNewLen);
  218.     memcpy(m_pchData, pszSrc1Data, nSrc1Len);
  219.     memcpy(&m_pchData[nSrc1Len], pszSrc2Data, nSrc2Len);
  220. }
  221.  
  222. CString
  223. AFXAPI operator +(const CString& string1, const CString& string2)
  224. {
  225.     CString s;
  226.     s.ConcatCopy(string1.m_nDataLength, string1.m_pchData,
  227.         string2.m_nDataLength, string2.m_pchData);
  228.     return s;
  229. }
  230.  
  231. CString
  232. AFXAPI operator +(const CString& string, const char* psz)
  233. {
  234.     CString s;
  235.     s.ConcatCopy(string.m_nDataLength, string.m_pchData, SafeStrlen(psz), psz);
  236.     return s;
  237. }
  238.  
  239.  
  240. CString
  241. AFXAPI operator +(const char* psz, const CString& string)
  242. {
  243.     CString s;
  244.     s.ConcatCopy(SafeStrlen(psz), psz, string.m_nDataLength, string.m_pchData);
  245.     return s;
  246. }
  247.  
  248. //////////////////////////////////////////////////////////////////////////////
  249. // concatenate in place
  250.  
  251. void
  252. CString::ConcatInPlace(int nSrcLen, const char* pszSrcData)
  253. {
  254.     //  -- the main routine for += operators
  255.  
  256.     // if the buffer is too small, or we have a width mis-match, just
  257.     //   allocate a new buffer (slow but sure)
  258.     if (m_nDataLength + nSrcLen > m_nAllocLength)
  259.     {
  260.         // we have to grow the buffer, use the Concat in place routine
  261.         char* pszOldData = m_pchData;
  262.         ConcatCopy(m_nDataLength, pszOldData, nSrcLen, pszSrcData);
  263.         ASSERT(pszOldData != NULL);
  264.         SafeDelete(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 +=(char ch)
  285. {
  286.     ConcatInPlace(1, &ch);
  287.     return *this;
  288. }
  289.  
  290. const CString&
  291. CString::operator +=(const CString& string)
  292. {
  293.     ConcatInPlace(string.m_nDataLength, string.m_pchData);
  294.     return *this;
  295. }
  296.  
  297.  
  298. ///////////////////////////////////////////////////////////////////////////////
  299. // Advanced direct buffer access
  300.  
  301. char* CString::GetBuffer(int nMinBufLength)
  302. {
  303.     ASSERT(nMinBufLength >= 0);
  304.  
  305.     if (nMinBufLength > m_nAllocLength)
  306.     {
  307.         // we have to grow the buffer
  308.         char* pszOldData = m_pchData;
  309.         int nOldLen = m_nDataLength;        // AllocBuffer will tromp it
  310.  
  311.         AllocBuffer(nMinBufLength);
  312.         memcpy(m_pchData, pszOldData, nOldLen);
  313.         m_nDataLength = nOldLen;
  314.         m_pchData[m_nDataLength] = '\0';
  315.  
  316.         SafeDelete(pszOldData);
  317.     }
  318.  
  319.     // return a pointer to the character storage for this string
  320.     ASSERT(m_pchData != NULL);
  321.     return m_pchData;
  322. }
  323.  
  324. void CString::ReleaseBuffer(int nNewLength)
  325. {
  326.     if (nNewLength == -1)
  327.         nNewLength = strlen(m_pchData); // zero terminated
  328.  
  329.     ASSERT(nNewLength <= m_nAllocLength);
  330.     m_nDataLength = nNewLength;
  331.     m_pchData[m_nDataLength] = '\0';
  332. }
  333.  
  334. char* CString::GetBufferSetLength(int nNewLength)
  335. {
  336.     ASSERT(nNewLength >= 0);
  337.  
  338.     GetBuffer(nNewLength);
  339.     m_nDataLength = nNewLength;
  340.     m_pchData[m_nDataLength] = '\0';
  341.     return m_pchData;
  342. }
  343.  
  344. ///////////////////////////////////////////////////////////////////////////////
  345. // Commonly used routines (rarely used routines in STREX.CPP)
  346.  
  347. int CString::Find(char ch) const
  348. {
  349.     // find a single character (strchr)
  350.     char* psz = strchr(m_pchData, ch);
  351.     return (psz == NULL) ? -1 : (int)(psz - m_pchData);
  352. }
  353.  
  354. int CString::FindOneOf(const char* pszCharSet) const
  355. {
  356.     ASSERT(pszCharSet != NULL);
  357.     char* psz = (char*) strpbrk(m_pchData, pszCharSet);
  358.     return (psz == NULL) ? -1 : (int)(psz - m_pchData);
  359. }
  360.  
  361. ///////////////////////////////////////////////////////////////////////////////
  362. // Additional constructors for far string data
  363.  
  364. #ifdef _NEARDATA
  365. CString::CString(LPCSTR lpsz)
  366. {
  367.     int nLen;
  368.     if (lpsz == NULL || (nLen = lstrlen(lpsz)) == 0)
  369.     {
  370.         Init();
  371.     }
  372.     else
  373.     {
  374.         AllocBuffer(nLen);
  375.         _fmemcpy(m_pchData, lpsz, nLen);
  376.     }
  377. }
  378. #endif //_NEARDATA
  379.  
  380. ///////////////////////////////////////////////////////////////////////////////
  381.