Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

358 lines
9.0 KiB

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