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.

1465 lines
34 KiB

  1. // FauxMFC.cpp
  2. #include "stdafx.h"
  3. #include "FauxMFC.h"
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <limits.h>
  7. const TCHAR afxChNil = '\0';
  8. const /*AFX_STATIC_DATA*/ int _afxInitData[] = { -1, 0, 0, 0 };
  9. const /*AFX_STATIC_DATA*/ CStringData* _afxDataNil = (CStringData*)&_afxInitData;
  10. const LPCTSTR _afxPchNil = (LPCTSTR)(((BYTE*)&_afxInitData)+sizeof(CStringData));
  11. struct _AFX_DOUBLE { BYTE doubleBits[sizeof(double)]; };
  12. #define TCHAR_ARG TCHAR
  13. #define WCHAR_ARG WCHAR
  14. #define CHAR_ARG char
  15. #define DOUBLE_ARG _AFX_DOUBLE
  16. #define FORCE_ANSI 0x10000
  17. #define FORCE_UNICODE 0x20000
  18. #define FORCE_INT64 0x40000
  19. #define IS_DIGIT(c) ((UINT)(c) - (UINT)('0') <= 9)
  20. //////////////////////////////////////////////////////////////////////////////
  21. // Global MFC stuff
  22. HINSTANCE AFXAPI AfxGetResourceHandle(void)
  23. {
  24. return GetModuleHandle(NULL);
  25. }
  26. BOOL AFXAPI AfxIsValidString(LPCSTR lpsz, int nLength = -1)
  27. {
  28. if (lpsz == NULL)
  29. return FALSE;
  30. return ::IsBadStringPtrA(lpsz, nLength) == 0;
  31. }
  32. //////////////////////////////////////////////////////////////////////////////
  33. // CString
  34. CString::CString(LPCTSTR lpsz)
  35. {
  36. Init();
  37. if (lpsz != NULL && HIWORD(lpsz) == NULL)
  38. {
  39. ASSERT(FALSE);
  40. //UINT nID = LOWORD((DWORD)lpsz);
  41. //LoadString(nID);
  42. }
  43. else
  44. {
  45. int nLen = SafeStrlen(lpsz);
  46. if (nLen != 0)
  47. {
  48. AllocBuffer(nLen);
  49. memcpy(m_pchData, lpsz, nLen*sizeof(TCHAR));
  50. }
  51. }
  52. }
  53. CString::CString(const CString& stringSrc)
  54. {
  55. ASSERT(stringSrc.GetData()->nRefs != 0);
  56. if (stringSrc.GetData()->nRefs >= 0)
  57. {
  58. ASSERT(stringSrc.GetData() != _afxDataNil);
  59. m_pchData = stringSrc.m_pchData;
  60. InterlockedIncrement(&GetData()->nRefs);
  61. }
  62. else
  63. {
  64. Init();
  65. *this = stringSrc.m_pchData;
  66. }
  67. }
  68. CString::CString(TCHAR ch, int nLength)
  69. {
  70. Init();
  71. if (nLength >= 1)
  72. {
  73. AllocBuffer(nLength);
  74. #ifdef _UNICODE
  75. for (int i = 0; i < nLength; i++)
  76. m_pchData[i] = ch;
  77. #else
  78. memset(m_pchData, ch, nLength);
  79. #endif
  80. }
  81. }
  82. CString::CString(LPCTSTR lpch, int nLength)
  83. {
  84. Init();
  85. if (nLength != 0)
  86. {
  87. // ASSERT(AfxIsValidAddress(lpch, nLength, FALSE));
  88. AllocBuffer(nLength);
  89. memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));
  90. }
  91. }
  92. CString::~CString()
  93. // free any attached data
  94. {
  95. if (GetData() != _afxDataNil)
  96. {
  97. ASSERT( 0 != GetData()->nRefs );
  98. if (InterlockedDecrement(&GetData()->nRefs) == 0)
  99. {
  100. FreeData(GetData());
  101. }
  102. }
  103. }
  104. CString AFXAPI operator+(const CString& string1, const CString& string2)
  105. {
  106. CString s;
  107. s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData,
  108. string2.GetData()->nDataLength, string2.m_pchData);
  109. return s;
  110. }
  111. CString AFXAPI operator+(const CString& string, LPCTSTR lpsz)
  112. {
  113. ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
  114. CString s;
  115. s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData,
  116. CString::SafeStrlen(lpsz), lpsz);
  117. return s;
  118. }
  119. CString AFXAPI operator+(LPCTSTR lpsz, const CString& string)
  120. {
  121. ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
  122. CString s;
  123. s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength,
  124. string.m_pchData);
  125. return s;
  126. }
  127. BOOL CString::LoadString(UINT nID)
  128. {
  129. HINSTANCE hInst = AfxGetResourceHandle();
  130. int cch;
  131. if (!FindResourceString(hInst, nID, &cch, 0))
  132. return FALSE;
  133. AllocBuffer(cch);
  134. if (cch != 0)
  135. ::LoadString(hInst, nID, this->m_pchData, cch+1);
  136. return TRUE;
  137. }
  138. void CString::FormatV(LPCTSTR lpszFormat, va_list argList)
  139. {
  140. // ASSERT(AfxIsValidString(lpszFormat));
  141. va_list argListSave = argList;
  142. int nMaxLen = 0;
  143. // make a guess at the maximum length of the resulting string
  144. for (LPCTSTR lpsz = lpszFormat; *lpsz != '\0'; ++lpsz)
  145. {
  146. // handle '%' character, but watch out for '%%'
  147. if (*lpsz != '%' || *(++lpsz) == '%')
  148. {
  149. nMaxLen += 2; //_tclen(lpsz);
  150. continue;
  151. }
  152. int nItemLen = 0;
  153. // handle '%' character with format
  154. int nWidth = 0;
  155. for (; *lpsz != '\0'; lpsz = CharNext(lpsz))
  156. {
  157. // check for valid flags
  158. if (*lpsz == '#')
  159. nMaxLen += 2; // for '0x'
  160. else if (*lpsz == '*')
  161. nWidth = va_arg(argList, int);
  162. else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' ||
  163. *lpsz == ' ')
  164. ;
  165. else // hit non-flag character
  166. break;
  167. }
  168. // get width and skip it
  169. if (nWidth == 0)
  170. {
  171. // width indicated by
  172. nWidth = MyAtoi(lpsz); //_ttoi(lpsz);
  173. for (; *lpsz != '\0' && IS_DIGIT(*lpsz); lpsz = CharNext(lpsz))
  174. ;
  175. }
  176. ASSERT(nWidth >= 0);
  177. int nPrecision = 0;
  178. if (*lpsz == '.')
  179. {
  180. // skip past '.' separator (width.precision)
  181. lpsz = CharNext(lpsz);
  182. // get precision and skip it
  183. if (*lpsz == '*')
  184. {
  185. nPrecision = va_arg(argList, int);
  186. lpsz = CharNext(lpsz);
  187. }
  188. else
  189. {
  190. nPrecision = MyAtoi(lpsz); //_ttoi(lpsz);
  191. for (; *lpsz != '\0' && IS_DIGIT(*lpsz); lpsz = CharNext(lpsz))
  192. ;
  193. }
  194. ASSERT(nPrecision >= 0);
  195. }
  196. // should be on type modifier or specifier
  197. int nModifier = 0;
  198. #if 0 // we don't need this code -ks 7/26/1999
  199. if (_tcsncmp(lpsz, _T("I64"), 3) == 0)
  200. {
  201. lpsz += 3;
  202. nModifier = FORCE_INT64;
  203. #if !defined(_X86_) && !defined(_ALPHA_)
  204. // __int64 is only available on X86 and ALPHA platforms
  205. ASSERT(FALSE);
  206. #endif
  207. }
  208. else
  209. #endif
  210. {
  211. switch (*lpsz)
  212. {
  213. // modifiers that affect size
  214. case 'h':
  215. nModifier = FORCE_ANSI;
  216. lpsz = CharNext(lpsz);
  217. break;
  218. case 'l':
  219. nModifier = FORCE_UNICODE;
  220. lpsz = CharNext(lpsz);
  221. break;
  222. // modifiers that do not affect size
  223. case 'F':
  224. case 'N':
  225. case 'L':
  226. lpsz = CharNext(lpsz);
  227. break;
  228. }
  229. }
  230. // now should be on specifier
  231. switch (*lpsz | nModifier)
  232. {
  233. // single characters
  234. case 'c':
  235. case 'C':
  236. nItemLen = 2;
  237. va_arg(argList, TCHAR_ARG);
  238. break;
  239. case 'c'|FORCE_ANSI:
  240. case 'C'|FORCE_ANSI:
  241. nItemLen = 2;
  242. va_arg(argList, CHAR_ARG);
  243. break;
  244. case 'c'|FORCE_UNICODE:
  245. case 'C'|FORCE_UNICODE:
  246. nItemLen = 2;
  247. va_arg(argList, WCHAR_ARG);
  248. break;
  249. // strings
  250. case 's':
  251. {
  252. LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR);
  253. if (pstrNextArg == NULL)
  254. nItemLen = 6; // "(null)"
  255. else
  256. {
  257. nItemLen = lstrlen(pstrNextArg);
  258. nItemLen = max(1, nItemLen);
  259. }
  260. }
  261. break;
  262. case 'S':
  263. {
  264. #ifndef _UNICODE
  265. LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
  266. if (pstrNextArg == NULL)
  267. nItemLen = 6; // "(null)"
  268. else
  269. {
  270. nItemLen = wcslen(pstrNextArg);
  271. nItemLen = max(1, nItemLen);
  272. }
  273. #else
  274. LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
  275. if (pstrNextArg == NULL)
  276. nItemLen = 6; // "(null)"
  277. else
  278. {
  279. nItemLen = lstrlenA(pstrNextArg);
  280. nItemLen = max(1, nItemLen);
  281. }
  282. #endif
  283. }
  284. break;
  285. case 's'|FORCE_ANSI:
  286. case 'S'|FORCE_ANSI:
  287. {
  288. LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
  289. if (pstrNextArg == NULL)
  290. nItemLen = 6; // "(null)"
  291. else
  292. {
  293. nItemLen = lstrlenA(pstrNextArg);
  294. nItemLen = max(1, nItemLen);
  295. }
  296. }
  297. break;
  298. case 's'|FORCE_UNICODE:
  299. case 'S'|FORCE_UNICODE:
  300. {
  301. LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
  302. if (pstrNextArg == NULL)
  303. nItemLen = 6; // "(null)"
  304. else
  305. {
  306. nItemLen = wcslen(pstrNextArg);
  307. nItemLen = max(1, nItemLen);
  308. }
  309. }
  310. break;
  311. }
  312. // adjust nItemLen for strings
  313. if (nItemLen != 0)
  314. {
  315. if (nPrecision != 0)
  316. nItemLen = min(nItemLen, nPrecision);
  317. nItemLen = max(nItemLen, nWidth);
  318. }
  319. else
  320. {
  321. switch (*lpsz)
  322. {
  323. // integers
  324. case 'd':
  325. case 'i':
  326. case 'u':
  327. case 'x':
  328. case 'X':
  329. case 'o':
  330. if (nModifier & FORCE_INT64)
  331. va_arg(argList, __int64);
  332. else
  333. va_arg(argList, int);
  334. nItemLen = 32;
  335. nItemLen = max(nItemLen, nWidth+nPrecision);
  336. break;
  337. case 'e':
  338. case 'g':
  339. case 'G':
  340. va_arg(argList, DOUBLE_ARG);
  341. nItemLen = 128;
  342. nItemLen = max(nItemLen, nWidth+nPrecision);
  343. break;
  344. case 'f':
  345. va_arg(argList, DOUBLE_ARG);
  346. nItemLen = 128; // width isn't truncated
  347. // 312 == strlen("-1+(309 zeroes).")
  348. // 309 zeroes == max precision of a double
  349. nItemLen = max(nItemLen, 312+nPrecision);
  350. break;
  351. case 'p':
  352. va_arg(argList, void*);
  353. nItemLen = 32;
  354. nItemLen = max(nItemLen, nWidth+nPrecision);
  355. break;
  356. // no output
  357. case 'n':
  358. va_arg(argList, int*);
  359. break;
  360. default:
  361. ASSERT(FALSE); // unknown formatting option
  362. }
  363. }
  364. // adjust nMaxLen for output nItemLen
  365. nMaxLen += nItemLen;
  366. }
  367. GetBuffer(nMaxLen);
  368. #ifdef UNICODE
  369. wvnsprintf(m_pchData, ARRAYSIZE(m_pchData), lpszFormat, argListSave);
  370. #else
  371. wvsprintf(m_pchData, lpszFormat, argListSave);
  372. #endif
  373. ReleaseBuffer();
  374. va_end(argListSave);
  375. }
  376. void AFX_CDECL CString::Format(UINT nFormatID, ...)
  377. {
  378. CString strFormat;
  379. strFormat.LoadString(nFormatID);
  380. va_list argList;
  381. va_start(argList, nFormatID);
  382. FormatV(strFormat, argList);
  383. va_end(argList);
  384. }
  385. // formatting (using wsprintf style formatting)
  386. void AFX_CDECL CString::Format(LPCTSTR lpszFormat, ...)
  387. {
  388. ASSERT(AfxIsValidString(lpszFormat));
  389. va_list argList;
  390. va_start(argList, lpszFormat);
  391. FormatV(lpszFormat, argList);
  392. va_end(argList);
  393. }
  394. void CString::Empty()
  395. {
  396. if (GetData()->nDataLength == 0)
  397. return;
  398. if (GetData()->nRefs >= 0)
  399. Release();
  400. else
  401. *this = &afxChNil;
  402. ASSERT(GetData()->nDataLength == 0);
  403. ASSERT(GetData()->nRefs < 0 || GetData()->nAllocLength == 0);
  404. }
  405. const CString& CString::operator=(const CString& stringSrc)
  406. {
  407. if (m_pchData != stringSrc.m_pchData)
  408. {
  409. if ((GetData()->nRefs < 0 && GetData() != _afxDataNil) ||
  410. stringSrc.GetData()->nRefs < 0)
  411. {
  412. // actual copy necessary since one of the strings is locked
  413. AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
  414. }
  415. else
  416. {
  417. // can just copy references around
  418. Release();
  419. ASSERT(stringSrc.GetData() != _afxDataNil);
  420. m_pchData = stringSrc.m_pchData;
  421. InterlockedIncrement(&GetData()->nRefs);
  422. }
  423. }
  424. return *this;
  425. }
  426. const CString& CString::operator=(LPCTSTR lpsz)
  427. {
  428. ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
  429. AssignCopy(SafeStrlen(lpsz), lpsz);
  430. return *this;
  431. }
  432. int AFX_CDECL _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count)
  433. {
  434. if (count == 0 && mbstr != NULL)
  435. return 0;
  436. int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1,
  437. mbstr, count, NULL, NULL);
  438. ASSERT(mbstr == NULL || result <= (int)count);
  439. if (result > 0)
  440. mbstr[result-1] = 0;
  441. return result;
  442. }
  443. const CString& CString::operator=(LPCWSTR lpsz)
  444. {
  445. int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
  446. AllocBeforeWrite(nSrcLen*2);
  447. _wcstombsz(m_pchData, lpsz, (nSrcLen*2)+1);
  448. ReleaseBuffer();
  449. return *this;
  450. }
  451. CString CString::Left(int nCount) const
  452. {
  453. if (nCount < 0)
  454. nCount = 0;
  455. if (nCount >= GetData()->nDataLength)
  456. return *this;
  457. CString dest;
  458. AllocCopy(dest, nCount, 0, 0);
  459. return dest;
  460. }
  461. CString CString::Right(int nCount) const
  462. {
  463. if (nCount < 0)
  464. nCount = 0;
  465. if (nCount >= GetData()->nDataLength)
  466. return *this;
  467. CString dest;
  468. AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);
  469. return dest;
  470. }
  471. // find a sub-string (like strstr)
  472. int CString::Find(LPCTSTR lpszSub) const
  473. {
  474. return Find(lpszSub, 0);
  475. }
  476. int CString::Find(LPCTSTR lpszSub, int nStart) const
  477. {
  478. ASSERT(AfxIsValidString(lpszSub));
  479. int nLength = GetData()->nDataLength;
  480. if (nStart > nLength)
  481. return -1;
  482. // find first matching substring
  483. // LPTSTR lpsz = _tcsstr(m_pchData + nStart, lpszSub);
  484. LPTSTR lpsz = strstr(m_pchData + nStart, lpszSub);
  485. // return -1 for not found, distance from beginning otherwise
  486. return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
  487. }
  488. LPTSTR CString::GetBuffer(int nMinBufLength)
  489. {
  490. ASSERT(nMinBufLength >= 0);
  491. if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
  492. {
  493. // we have to grow the buffer
  494. CStringData* pOldData = GetData();
  495. int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it
  496. if (nMinBufLength < nOldLen)
  497. nMinBufLength = nOldLen;
  498. AllocBuffer(nMinBufLength);
  499. memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));
  500. GetData()->nDataLength = nOldLen;
  501. CString::Release(pOldData);
  502. }
  503. ASSERT(GetData()->nRefs <= 1);
  504. // return a pointer to the character storage for this string
  505. ASSERT(m_pchData != NULL);
  506. return m_pchData;
  507. }
  508. LPTSTR CString::GetBufferSetLength(int nNewLength)
  509. {
  510. ASSERT(nNewLength >= 0);
  511. GetBuffer(nNewLength);
  512. GetData()->nDataLength = nNewLength;
  513. m_pchData[nNewLength] = '\0';
  514. return m_pchData;
  515. }
  516. void CString::Release()
  517. {
  518. if (GetData() != _afxDataNil)
  519. {
  520. ASSERT( 0 != GetData()->nRefs );
  521. if (InterlockedDecrement(&GetData()->nRefs) == 0)
  522. {
  523. FreeData(GetData());
  524. }
  525. Init();
  526. }
  527. }
  528. void CString::AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
  529. {
  530. if (nSrcLen)
  531. {
  532. AllocBeforeWrite(nSrcLen);
  533. memcpy(m_pchData, lpszSrcData, nSrcLen*sizeof(TCHAR));
  534. GetData()->nDataLength = nSrcLen;
  535. m_pchData[nSrcLen] = '\0';
  536. }
  537. }
  538. void CString::AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,
  539. int nExtraLen) const
  540. {
  541. // will clone the data attached to this string
  542. // allocating 'nExtraLen' characters
  543. // Places results in uninitialized string 'dest'
  544. // Will copy the part or all of original data to start of new string
  545. int nNewLen = nCopyLen + nExtraLen;
  546. if (nNewLen == 0)
  547. {
  548. dest.Init();
  549. }
  550. else
  551. {
  552. dest.AllocBuffer(nNewLen);
  553. memcpy(dest.m_pchData, m_pchData+nCopyIndex, nCopyLen*sizeof(TCHAR));
  554. }
  555. }
  556. void CString::AllocBuffer(int nLen)
  557. // always allocate one extra character for '\0' termination
  558. // assumes [optimistically] that data length will equal allocation length
  559. {
  560. ASSERT(nLen >= 0);
  561. ASSERT(nLen <= INT_MAX-1); // max size (enough room for 1 extra)
  562. if (nLen == 0)
  563. Init();
  564. else
  565. {
  566. CStringData* pData;
  567. pData = (CStringData*)new BYTE[sizeof(CStringData) + (nLen+1)*sizeof(TCHAR)];
  568. if (pData)
  569. {
  570. pData->nAllocLength = nLen;
  571. pData->nRefs = 1;
  572. pData->data()[nLen] = '\0';
  573. pData->nDataLength = nLen;
  574. m_pchData = pData->data();
  575. }
  576. }
  577. }
  578. void CString::CopyBeforeWrite()
  579. {
  580. if (GetData()->nRefs > 1)
  581. {
  582. CStringData* pData = GetData();
  583. Release();
  584. AllocBuffer(pData->nDataLength);
  585. memcpy(m_pchData, pData->data(), (pData->nDataLength+1)*sizeof(TCHAR));
  586. }
  587. ASSERT(GetData()->nRefs <= 1);
  588. }
  589. void CString::AllocBeforeWrite(int nLen)
  590. {
  591. if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
  592. {
  593. Release();
  594. AllocBuffer(nLen);
  595. }
  596. ASSERT(GetData()->nRefs <= 1);
  597. }
  598. void PASCAL CString::Release(CStringData* pData)
  599. {
  600. if (pData != _afxDataNil)
  601. {
  602. ASSERT(pData->nRefs != 0);
  603. if (InterlockedDecrement(&pData->nRefs) == 0)
  604. {
  605. FreeData(pData);
  606. }
  607. }
  608. }
  609. void CString::ReleaseBuffer(int nNewLength)
  610. {
  611. CopyBeforeWrite(); // just in case GetBuffer was not called
  612. if (nNewLength == -1)
  613. nNewLength = lstrlen(m_pchData); // zero terminated
  614. ASSERT(nNewLength <= GetData()->nAllocLength);
  615. GetData()->nDataLength = nNewLength;
  616. m_pchData[nNewLength] = '\0';
  617. }
  618. void FASTCALL CString::FreeData(CStringData* pData)
  619. {
  620. //#ifndef _DEBUG
  621. #ifdef TEST
  622. int nLen = pData->nAllocLength;
  623. if (nLen == 64)
  624. _afxAlloc64.Free(pData);
  625. else if (nLen == 128)
  626. _afxAlloc128.Free(pData);
  627. else if (nLen == 256)
  628. _afxAlloc256.Free(pData);
  629. else if (nLen == 512)
  630. _afxAlloc512.Free(pData);
  631. else
  632. {
  633. ASSERT(nLen > 512);
  634. delete[] (BYTE*)pData;
  635. }
  636. #else
  637. delete[] (BYTE*)pData;
  638. #endif
  639. }
  640. void CString::ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data,
  641. int nSrc2Len, LPCTSTR lpszSrc2Data)
  642. {
  643. // -- master concatenation routine
  644. // Concatenate two sources
  645. // -- assume that 'this' is a new CString object
  646. int nNewLen = nSrc1Len + nSrc2Len;
  647. if (nNewLen != 0)
  648. {
  649. AllocBuffer(nNewLen);
  650. memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(TCHAR));
  651. memcpy(m_pchData+nSrc1Len, lpszSrc2Data, nSrc2Len*sizeof(TCHAR));
  652. }
  653. }
  654. void CString::ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
  655. {
  656. // -- the main routine for += operators
  657. // concatenating an empty string is a no-op!
  658. if (nSrcLen == 0)
  659. return;
  660. // if the buffer is too small, or we have a width mis-match, just
  661. // allocate a new buffer (slow but sure)
  662. if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
  663. {
  664. // we have to grow the buffer, use the ConcatCopy routine
  665. CStringData* pOldData = GetData();
  666. ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData);
  667. ASSERT(pOldData != NULL);
  668. CString::Release(pOldData);
  669. }
  670. else
  671. {
  672. // fast concatenation when buffer big enough
  673. memcpy(m_pchData+GetData()->nDataLength, lpszSrcData, nSrcLen*sizeof(TCHAR));
  674. GetData()->nDataLength += nSrcLen;
  675. ASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
  676. m_pchData[GetData()->nDataLength] = '\0';
  677. }
  678. }
  679. const CString& CString::operator+=(LPCTSTR lpsz)
  680. {
  681. ASSERT(lpsz == NULL || AfxIsValidString(lpsz));
  682. ConcatInPlace(SafeStrlen(lpsz), lpsz);
  683. return *this;
  684. }
  685. const CString& CString::operator+=(TCHAR ch)
  686. {
  687. ConcatInPlace(1, &ch);
  688. return *this;
  689. }
  690. const CString& CString::operator+=(const CString& string)
  691. {
  692. ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
  693. return *this;
  694. }
  695. CString CString::Mid(int nFirst) const
  696. {
  697. return Mid(nFirst, GetData()->nDataLength - nFirst);
  698. }
  699. CString CString::Mid(int nFirst, int nCount) const
  700. {
  701. // out-of-bounds requests return sensible things
  702. if (nFirst < 0)
  703. nFirst = 0;
  704. if (nCount < 0)
  705. nCount = 0;
  706. if (nFirst + nCount > GetData()->nDataLength)
  707. nCount = GetData()->nDataLength - nFirst;
  708. if (nFirst > GetData()->nDataLength)
  709. nCount = 0;
  710. ASSERT(nFirst >= 0);
  711. ASSERT(nFirst + nCount <= GetData()->nDataLength);
  712. // optimize case of returning entire string
  713. if (nFirst == 0 && nFirst + nCount == GetData()->nDataLength)
  714. return *this;
  715. CString dest;
  716. AllocCopy(dest, nCount, nFirst, 0);
  717. return dest;
  718. }
  719. //////////////////////////////////////////////////////////////////////////////
  720. // CWinThread
  721. CWinThread::CWinThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam)
  722. {
  723. m_pfnThreadProc = pfnThreadProc;
  724. m_pThreadParams = pParam;
  725. CommonConstruct();
  726. }
  727. CWinThread::CWinThread()
  728. {
  729. m_pThreadParams = NULL;
  730. m_pfnThreadProc = NULL;
  731. CommonConstruct();
  732. }
  733. void CWinThread::CommonConstruct()
  734. {
  735. // no HTHREAD until it is created
  736. m_hThread = NULL;
  737. m_nThreadID = 0;
  738. }
  739. CWinThread::~CWinThread()
  740. {
  741. // free thread object
  742. if (m_hThread != NULL)
  743. CloseHandle(m_hThread);
  744. //TODO:fix
  745. // cleanup module state
  746. // AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
  747. // if (pState->m_pCurrentWinThread == this)
  748. // pState->m_pCurrentWinThread = NULL;
  749. }
  750. CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,
  751. int nPriority, UINT nStackSize, DWORD dwCreateFlags,
  752. LPSECURITY_ATTRIBUTES lpSecurityAttrs)
  753. {
  754. ASSERT(pfnThreadProc != NULL);
  755. CWinThread* pThread = new CWinThread(pfnThreadProc, pParam);
  756. if (pThread)
  757. {
  758. if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize, lpSecurityAttrs))
  759. {
  760. pThread->Delete();
  761. return NULL;
  762. }
  763. pThread->SetThreadPriority(nPriority);
  764. if (!(dwCreateFlags & CREATE_SUSPENDED))
  765. pThread->ResumeThread();
  766. }
  767. return pThread;
  768. }
  769. BOOL CWinThread::SetThreadPriority(int nPriority)
  770. { ASSERT(m_hThread != NULL); return ::SetThreadPriority(m_hThread, nPriority); }
  771. BOOL CWinThread::CreateThread(DWORD dwCreateFlags, UINT nStackSize,
  772. LPSECURITY_ATTRIBUTES lpSecurityAttrs)
  773. {
  774. ASSERT(m_hThread == NULL); // already created?
  775. m_hThread = ::CreateThread(lpSecurityAttrs, nStackSize, m_pfnThreadProc,
  776. m_pThreadParams, dwCreateFlags, &m_nThreadID);
  777. if (m_hThread == NULL)
  778. return FALSE;
  779. return TRUE;
  780. }
  781. DWORD CWinThread::ResumeThread()
  782. { ASSERT(m_hThread != NULL); return ::ResumeThread(m_hThread); }
  783. void CWinThread::Delete()
  784. {
  785. delete this;
  786. }
  787. /////////////////////////////////////////////////////////////////////////////
  788. // CWinThread default implementation
  789. BOOL CWinThread::InitInstance()
  790. {
  791. // ASSERT_VALID(this);
  792. return FALSE; // by default don't enter run loop
  793. }
  794. int CWinThread::ExitInstance()
  795. {
  796. // ASSERT_VALID(this);
  797. // ASSERT(AfxGetApp() != this);
  798. // int nResult = m_msgCur.wParam; // returns the value from PostQuitMessage
  799. return 0;
  800. }
  801. //////////////////////////////////////////////////////////////////////////////
  802. // CStringArray
  803. static inline void ConstructElement(CString* pNewData)
  804. {
  805. memcpy(pNewData, &afxEmptyString, sizeof(CString));
  806. }
  807. static inline void DestructElement(CString* pOldData)
  808. {
  809. pOldData->~CString();
  810. }
  811. static inline void CopyElement(CString* pSrc, CString* pDest)
  812. {
  813. *pSrc = *pDest;
  814. }
  815. static void ConstructElements(CString* pNewData, int nCount)
  816. {
  817. ASSERT(nCount >= 0);
  818. while (nCount--)
  819. {
  820. ConstructElement(pNewData);
  821. pNewData++;
  822. }
  823. }
  824. static void DestructElements(CString* pOldData, int nCount)
  825. {
  826. ASSERT(nCount >= 0);
  827. while (nCount--)
  828. {
  829. DestructElement(pOldData);
  830. pOldData++;
  831. }
  832. }
  833. static void CopyElements(CString* pDest, CString* pSrc, int nCount)
  834. {
  835. ASSERT(nCount >= 0);
  836. while (nCount--)
  837. {
  838. *pDest = *pSrc;
  839. ++pDest;
  840. ++pSrc;
  841. }
  842. }
  843. /////////////////////////////////////////////////////////////////////////////
  844. CStringArray::CStringArray()
  845. {
  846. m_pData = NULL;
  847. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  848. }
  849. CStringArray::~CStringArray()
  850. {
  851. // ASSERT_VALID(this);
  852. DestructElements(m_pData, m_nSize);
  853. delete[] (BYTE*)m_pData;
  854. }
  855. void CStringArray::SetSize(int nNewSize, int nGrowBy)
  856. {
  857. // ASSERT_VALID(this);
  858. ASSERT(nNewSize >= 0);
  859. if (nGrowBy != -1)
  860. m_nGrowBy = nGrowBy; // set new size
  861. if (nNewSize == 0)
  862. {
  863. // shrink to nothing
  864. DestructElements(m_pData, m_nSize);
  865. delete[] (BYTE*)m_pData;
  866. m_pData = NULL;
  867. m_nSize = m_nMaxSize = 0;
  868. }
  869. else if (m_pData == NULL)
  870. {
  871. // create one with exact size
  872. #ifdef SIZE_T_MAX
  873. ASSERT(nNewSize <= SIZE_T_MAX/sizeof(CString)); // no overflow
  874. #endif
  875. m_pData = (CString*) new BYTE[nNewSize * sizeof(CString)];
  876. if (m_pData)
  877. {
  878. ConstructElements(m_pData, nNewSize);
  879. m_nSize = m_nMaxSize = nNewSize;
  880. }
  881. }
  882. else if (nNewSize <= m_nMaxSize)
  883. {
  884. // it fits
  885. if (nNewSize > m_nSize)
  886. {
  887. // initialize the new elements
  888. ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
  889. }
  890. else if (m_nSize > nNewSize) // destroy the old elements
  891. DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
  892. m_nSize = nNewSize;
  893. }
  894. else
  895. {
  896. // otherwise, grow array
  897. int nGrowBy = m_nGrowBy;
  898. if (nGrowBy == 0)
  899. {
  900. // heuristically determine growth when nGrowBy == 0
  901. // (this avoids heap fragmentation in many situations)
  902. nGrowBy = min(1024, max(4, m_nSize / 8));
  903. }
  904. int nNewMax;
  905. if (nNewSize < m_nMaxSize + nGrowBy)
  906. nNewMax = m_nMaxSize + nGrowBy; // granularity
  907. else
  908. nNewMax = nNewSize; // no slush
  909. ASSERT(nNewMax >= m_nMaxSize); // no wrap around
  910. #ifdef SIZE_T_MAX
  911. ASSERT(nNewMax <= SIZE_T_MAX/sizeof(CString)); // no overflow
  912. #endif
  913. CString* pNewData = (CString*) new BYTE[nNewMax * sizeof(CString)];
  914. if (pNewData)
  915. {
  916. // copy new data from old
  917. memcpy(pNewData, m_pData, m_nSize * sizeof(CString));
  918. // construct remaining elements
  919. ASSERT(nNewSize > m_nSize);
  920. ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
  921. // get rid of old stuff (note: no destructors called)
  922. delete[] (BYTE*)m_pData;
  923. m_pData = pNewData;
  924. m_nSize = nNewSize;
  925. m_nMaxSize = nNewMax;
  926. }
  927. }
  928. }
  929. int CStringArray::Append(const CStringArray& src)
  930. {
  931. // ASSERT_VALID(this);
  932. ASSERT(this != &src); // cannot append to itself
  933. int nOldSize = m_nSize;
  934. SetSize(m_nSize + src.m_nSize);
  935. CopyElements(m_pData + nOldSize, src.m_pData, src.m_nSize);
  936. return nOldSize;
  937. }
  938. void CStringArray::Copy(const CStringArray& src)
  939. {
  940. // ASSERT_VALID(this);
  941. ASSERT(this != &src); // cannot append to itself
  942. SetSize(src.m_nSize);
  943. CopyElements(m_pData, src.m_pData, src.m_nSize);
  944. }
  945. void CStringArray::FreeExtra()
  946. {
  947. // ASSERT_VALID(this);
  948. if (m_nSize != m_nMaxSize)
  949. {
  950. // shrink to desired size
  951. #ifdef SIZE_T_MAX
  952. ASSERT(m_nSize <= SIZE_T_MAX/sizeof(CString)); // no overflow
  953. #endif
  954. CString* pNewData = NULL;
  955. if (m_nSize != 0)
  956. {
  957. pNewData = (CString*) new BYTE[m_nSize * sizeof(CString)];
  958. if (pNewData)
  959. {
  960. // copy new data from old
  961. memcpy(pNewData, m_pData, m_nSize * sizeof(CString));
  962. }
  963. }
  964. // get rid of old stuff (note: no destructors called)
  965. delete[] (BYTE*)m_pData;
  966. m_pData = pNewData;
  967. m_nMaxSize = m_nSize;
  968. }
  969. }
  970. void CStringArray::SetAtGrow(int nIndex, LPCTSTR newElement)
  971. {
  972. // ASSERT_VALID(this);
  973. ASSERT(nIndex >= 0);
  974. if (nIndex >= m_nSize)
  975. SetSize(nIndex+1);
  976. m_pData[nIndex] = newElement;
  977. }
  978. void CStringArray::SetAtGrow(int nIndex, const CString& newElement)
  979. {
  980. // ASSERT_VALID(this);
  981. ASSERT(nIndex >= 0);
  982. if (nIndex >= m_nSize)
  983. SetSize(nIndex+1);
  984. m_pData[nIndex] = newElement;
  985. }
  986. void CStringArray::InsertEmpty(int nIndex, int nCount)
  987. {
  988. // ASSERT_VALID(this);
  989. ASSERT(nIndex >= 0); // will expand to meet need
  990. ASSERT(nCount > 0); // zero or negative size not allowed
  991. if (nIndex >= m_nSize)
  992. {
  993. // adding after the end of the array
  994. SetSize(nIndex + nCount); // grow so nIndex is valid
  995. }
  996. else
  997. {
  998. // inserting in the middle of the array
  999. int nOldSize = m_nSize;
  1000. SetSize(m_nSize + nCount); // grow it to new size
  1001. // shift old data up to fill gap
  1002. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  1003. (nOldSize-nIndex) * sizeof(CString));
  1004. // re-init slots we copied from
  1005. ConstructElements(&m_pData[nIndex], nCount);
  1006. }
  1007. // insert new value in the gap
  1008. ASSERT(nIndex + nCount <= m_nSize);
  1009. }
  1010. void CStringArray::InsertAt(int nIndex, LPCTSTR newElement, int nCount)
  1011. {
  1012. // make room for new elements
  1013. InsertEmpty(nIndex, nCount);
  1014. // copy elements into the empty space
  1015. CString temp = newElement;
  1016. while (nCount--)
  1017. m_pData[nIndex++] = temp;
  1018. }
  1019. void CStringArray::InsertAt(int nIndex, const CString& newElement, int nCount)
  1020. {
  1021. // make room for new elements
  1022. InsertEmpty(nIndex, nCount);
  1023. // copy elements into the empty space
  1024. while (nCount--)
  1025. m_pData[nIndex++] = newElement;
  1026. }
  1027. void CStringArray::RemoveAt(int nIndex, int nCount)
  1028. {
  1029. // ASSERT_VALID(this);
  1030. ASSERT(nIndex >= 0);
  1031. ASSERT(nCount >= 0);
  1032. ASSERT(nIndex + nCount <= m_nSize);
  1033. // just remove a range
  1034. int nMoveCount = m_nSize - (nIndex + nCount);
  1035. DestructElements(&m_pData[nIndex], nCount);
  1036. if (nMoveCount)
  1037. memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
  1038. nMoveCount * sizeof(CString));
  1039. m_nSize -= nCount;
  1040. }
  1041. void CStringArray::InsertAt(int nStartIndex, CStringArray* pNewArray)
  1042. {
  1043. // ASSERT_VALID(this);
  1044. ASSERT(pNewArray != NULL);
  1045. // ASSERT_KINDOF(CStringArray, pNewArray);
  1046. // ASSERT_VALID(pNewArray);
  1047. ASSERT(nStartIndex >= 0);
  1048. if (pNewArray->GetSize() > 0)
  1049. {
  1050. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  1051. for (int i = 0; i < pNewArray->GetSize(); i++)
  1052. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  1053. }
  1054. }
  1055. //////////////////////////////////////////////////////////////////////////////
  1056. // CPtrArray
  1057. /////////////////////////////////////////////////////////////////////////////
  1058. CPtrArray::CPtrArray()
  1059. {
  1060. m_pData = NULL;
  1061. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  1062. }
  1063. CPtrArray::~CPtrArray()
  1064. {
  1065. // ASSERT_VALID(this);
  1066. delete[] (BYTE*)m_pData;
  1067. }
  1068. void CPtrArray::SetSize(int nNewSize, int nGrowBy)
  1069. {
  1070. // ASSERT_VALID(this);
  1071. ASSERT(nNewSize >= 0);
  1072. if (nGrowBy != -1)
  1073. m_nGrowBy = nGrowBy; // set new size
  1074. if (nNewSize == 0)
  1075. {
  1076. // shrink to nothing
  1077. delete[] (BYTE*)m_pData;
  1078. m_pData = NULL;
  1079. m_nSize = m_nMaxSize = 0;
  1080. }
  1081. else if (m_pData == NULL)
  1082. {
  1083. // create one with exact size
  1084. #ifdef SIZE_T_MAX
  1085. ASSERT(nNewSize <= SIZE_T_MAX/sizeof(void*)); // no overflow
  1086. #endif
  1087. m_pData = (void**) new BYTE[nNewSize * sizeof(void*)];
  1088. if (m_pData)
  1089. {
  1090. memset(m_pData, 0, nNewSize * sizeof(void*)); // zero fill
  1091. m_nSize = m_nMaxSize = nNewSize;
  1092. }
  1093. }
  1094. else if (nNewSize <= m_nMaxSize)
  1095. {
  1096. // it fits
  1097. if (nNewSize > m_nSize)
  1098. {
  1099. // initialize the new elements
  1100. memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*));
  1101. }
  1102. m_nSize = nNewSize;
  1103. }
  1104. else
  1105. {
  1106. // otherwise, grow array
  1107. int nGrowBy = m_nGrowBy;
  1108. if (nGrowBy == 0)
  1109. {
  1110. // heuristically determine growth when nGrowBy == 0
  1111. // (this avoids heap fragmentation in many situations)
  1112. nGrowBy = min(1024, max(4, m_nSize / 8));
  1113. }
  1114. int nNewMax;
  1115. if (nNewSize < m_nMaxSize + nGrowBy)
  1116. nNewMax = m_nMaxSize + nGrowBy; // granularity
  1117. else
  1118. nNewMax = nNewSize; // no slush
  1119. ASSERT(nNewMax >= m_nMaxSize); // no wrap around
  1120. #ifdef SIZE_T_MAX
  1121. ASSERT(nNewMax <= SIZE_T_MAX/sizeof(void*)); // no overflow
  1122. #endif
  1123. void** pNewData = (void**) new BYTE[nNewMax * sizeof(void*)];
  1124. if (pNewData)
  1125. {
  1126. // copy new data from old
  1127. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  1128. // construct remaining elements
  1129. ASSERT(nNewSize > m_nSize);
  1130. memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(void*));
  1131. // get rid of old stuff (note: no destructors called)
  1132. delete[] (BYTE*)m_pData;
  1133. m_pData = pNewData;
  1134. m_nSize = nNewSize;
  1135. m_nMaxSize = nNewMax;
  1136. }
  1137. }
  1138. }
  1139. int CPtrArray::Append(const CPtrArray& src)
  1140. {
  1141. // ASSERT_VALID(this);
  1142. ASSERT(this != &src); // cannot append to itself
  1143. int nOldSize = m_nSize;
  1144. SetSize(m_nSize + src.m_nSize);
  1145. memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(void*));
  1146. return nOldSize;
  1147. }
  1148. void CPtrArray::Copy(const CPtrArray& src)
  1149. {
  1150. // ASSERT_VALID(this);
  1151. ASSERT(this != &src); // cannot append to itself
  1152. SetSize(src.m_nSize);
  1153. memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(void*));
  1154. }
  1155. void CPtrArray::FreeExtra()
  1156. {
  1157. // ASSERT_VALID(this);
  1158. if (m_nSize != m_nMaxSize)
  1159. {
  1160. // shrink to desired size
  1161. #ifdef SIZE_T_MAX
  1162. ASSERT(m_nSize <= SIZE_T_MAX/sizeof(void*)); // no overflow
  1163. #endif
  1164. void** pNewData = NULL;
  1165. if (m_nSize != 0)
  1166. {
  1167. pNewData = (void**) new BYTE[m_nSize * sizeof(void*)];
  1168. if (pNewData)
  1169. {
  1170. // copy new data from old
  1171. memcpy(pNewData, m_pData, m_nSize * sizeof(void*));
  1172. }
  1173. }
  1174. // get rid of old stuff (note: no destructors called)
  1175. delete[] (BYTE*)m_pData;
  1176. m_pData = pNewData;
  1177. m_nMaxSize = m_nSize;
  1178. }
  1179. }
  1180. /////////////////////////////////////////////////////////////////////////////
  1181. void CPtrArray::SetAtGrow(int nIndex, void* newElement)
  1182. {
  1183. // ASSERT_VALID(this);
  1184. ASSERT(nIndex >= 0);
  1185. if (nIndex >= m_nSize)
  1186. SetSize(nIndex+1);
  1187. m_pData[nIndex] = newElement;
  1188. }
  1189. void CPtrArray::InsertAt(int nIndex, void* newElement, int nCount)
  1190. {
  1191. // ASSERT_VALID(this);
  1192. ASSERT(nIndex >= 0); // will expand to meet need
  1193. ASSERT(nCount > 0); // zero or negative size not allowed
  1194. if (nIndex >= m_nSize)
  1195. {
  1196. // adding after the end of the array
  1197. SetSize(nIndex + nCount); // grow so nIndex is valid
  1198. }
  1199. else
  1200. {
  1201. // inserting in the middle of the array
  1202. int nOldSize = m_nSize;
  1203. SetSize(m_nSize + nCount); // grow it to new size
  1204. // shift old data up to fill gap
  1205. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  1206. (nOldSize-nIndex) * sizeof(void*));
  1207. // re-init slots we copied from
  1208. memset(&m_pData[nIndex], 0, nCount * sizeof(void*));
  1209. }
  1210. // insert new value in the gap
  1211. ASSERT(nIndex + nCount <= m_nSize);
  1212. // copy elements into the empty space
  1213. while (nCount--)
  1214. m_pData[nIndex++] = newElement;
  1215. }
  1216. void CPtrArray::RemoveAt(int nIndex, int nCount)
  1217. {
  1218. // ASSERT_VALID(this);
  1219. ASSERT(nIndex >= 0);
  1220. ASSERT(nCount >= 0);
  1221. ASSERT(nIndex + nCount <= m_nSize);
  1222. // just remove a range
  1223. int nMoveCount = m_nSize - (nIndex + nCount);
  1224. if (nMoveCount)
  1225. memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
  1226. nMoveCount * sizeof(void*));
  1227. m_nSize -= nCount;
  1228. }
  1229. void CPtrArray::InsertAt(int nStartIndex, CPtrArray* pNewArray)
  1230. {
  1231. // ASSERT_VALID(this);
  1232. ASSERT(pNewArray != NULL);
  1233. // ASSERT_KINDOF(CPtrArray, pNewArray);
  1234. // ASSERT_VALID(pNewArray);
  1235. ASSERT(nStartIndex >= 0);
  1236. if (pNewArray->GetSize() > 0)
  1237. {
  1238. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  1239. for (int i = 0; i < pNewArray->GetSize(); i++)
  1240. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  1241. }
  1242. }
  1243. /////////////////////////////////////////////////////////////////////////////