Source code of Windows XP (NT5)
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.

646 lines
17 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 1996-2001 by Microsoft Corp.
  4. //
  5. // FLEXARRY.CPP
  6. //
  7. // CFlexArray implementation (non-arena).
  8. //
  9. // 15-Jul-97 raymcc Created.
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. #include <stdio.h>
  14. #include <flexarry.h>
  15. //***************************************************************************
  16. //
  17. // CFlexArray::CFlexArray
  18. //
  19. // Constructs the array.
  20. //
  21. // Parameters:
  22. // <nSize> The starting preallocated size of the array.
  23. // <nGrowBy> The amount to grow by when the array fills up.
  24. //
  25. // Size() returns the number of elements in use, not the 'true' size.
  26. //
  27. //***************************************************************************
  28. // ok
  29. CFlexArray::CFlexArray(
  30. int nSize,
  31. int nGrowBy
  32. )
  33. {
  34. m_nExtent = nSize;
  35. m_nSize = 0;
  36. m_nGrowBy = nGrowBy;
  37. m_pArray = (void **) LocalAlloc(LMEM_ZEROINIT, sizeof(void *) * nSize);
  38. }
  39. //***************************************************************************
  40. //
  41. // CFlexArray::~CFlexArray
  42. //
  43. //***************************************************************************
  44. // ok
  45. CFlexArray::~CFlexArray()
  46. {
  47. LocalFree(m_pArray);
  48. }
  49. //***************************************************************************
  50. //
  51. // Copy constructor.
  52. //
  53. // Copies the pointers, not their contents.
  54. //
  55. //***************************************************************************
  56. // ok
  57. CFlexArray::CFlexArray(CFlexArray &Src)
  58. {
  59. m_pArray = 0;
  60. m_nSize = 0;
  61. m_nExtent = 0;
  62. m_nGrowBy = 0;
  63. *this = Src;
  64. }
  65. //***************************************************************************
  66. //
  67. // operator =
  68. //
  69. // Assignment operator.
  70. //
  71. // Arenas are not copied. This allows transfer of arrays between arenas.
  72. // Arrays are copied by pointer only.
  73. //
  74. //***************************************************************************
  75. // ok
  76. CFlexArray& CFlexArray::operator=(CFlexArray &Src)
  77. {
  78. m_nSize = Src.m_nSize;
  79. m_nExtent = Src.m_nExtent;
  80. m_nGrowBy = Src.m_nGrowBy;
  81. LocalFree(m_pArray);
  82. m_pArray = (void **) LocalAlloc(LMEM_ZEROINIT, sizeof(void *) * m_nExtent);
  83. memcpy(m_pArray, Src.m_pArray, sizeof(void *) * m_nExtent);
  84. return *this;
  85. }
  86. //***************************************************************************
  87. //
  88. // CFlexArray::RemoveAt
  89. //
  90. // Removes the element at the specified location. Does not
  91. // actually delete the pointer. Shrinks the array over the top of
  92. // the 'doomed' element.
  93. //
  94. // Parameters:
  95. // <nIndex> The location of the element.
  96. //
  97. // Return value:
  98. // range_error The index is not legal.
  99. // no_error Success.
  100. //
  101. //***************************************************************************
  102. // ok
  103. int CFlexArray::RemoveAt(int nIndex)
  104. {
  105. if (nIndex >= m_nSize)
  106. return range_error;
  107. for (int i = nIndex; i < m_nSize - 1; i++)
  108. m_pArray[i] = m_pArray[i + 1];
  109. m_nSize--;
  110. m_pArray[m_nSize] = 0;
  111. return no_error;
  112. }
  113. //***************************************************************************
  114. //
  115. // CFlexArray::InsertAt
  116. //
  117. // Inserts a new element at the specified location. The pointer is copied.
  118. //
  119. // Parameters:
  120. // <nIndex> The 0-origin location at which to insert the new element.
  121. // <pSrc> The pointer to copy. (contents are not copied).
  122. //
  123. // Return value:
  124. // array_full
  125. // out_of_memory
  126. // no_error
  127. //
  128. //***************************************************************************
  129. // ok
  130. int CFlexArray::InsertAt(int nIndex, void *pSrc)
  131. {
  132. // If the array is full, we need to expand it.
  133. // ===========================================
  134. if (m_nSize == m_nExtent)
  135. {
  136. if (m_nGrowBy == 0)
  137. return array_full;
  138. m_nExtent += m_nGrowBy;
  139. void **pTmp = (void **) LocalAlloc(LMEM_ZEROINIT, sizeof(void *) * m_nExtent);
  140. if (!pTmp)
  141. return out_of_memory;
  142. for (int i = 0; i < m_nSize; i++)
  143. pTmp[i] = m_pArray[i];
  144. LocalFree(m_pArray);
  145. m_pArray = pTmp;
  146. }
  147. // Special case of appending. This is so frequent
  148. // compared to true insertion that we want to optimize.
  149. // ====================================================
  150. if (nIndex == m_nSize)
  151. {
  152. m_pArray[m_nSize++] = pSrc;
  153. return no_error;
  154. }
  155. // If here, we are inserting at some random location.
  156. // We start at the end of the array and copy all the elements
  157. // one position farther to the end to make a 'hole' for
  158. // the new element.
  159. // ==========================================================
  160. for (int i = m_nSize; i > nIndex; i--)
  161. m_pArray[i] = m_pArray[i - 1];
  162. m_pArray[nIndex] = pSrc;
  163. m_nSize++;
  164. return no_error;
  165. }
  166. //***************************************************************************
  167. //
  168. // CFlexArray::DebugDump
  169. //
  170. //***************************************************************************
  171. void CFlexArray::DebugDump()
  172. {
  173. printf("----CFlexArray Debug Dump----\n");
  174. printf("m_pArray = 0x%X\n", m_pArray);
  175. printf("m_nSize = %d\n", m_nSize);
  176. printf("m_nExtent = %d\n", m_nExtent);
  177. printf("m_nGrowBy = %d\n", m_nGrowBy);
  178. for (int i = 0; i < m_nExtent; i++)
  179. {
  180. if (i < m_nSize)
  181. printf("![%d] = %X\n", i, m_pArray[i]);
  182. else
  183. printf("?[%d] = %X\n", i, m_pArray[i]);
  184. }
  185. }
  186. //***************************************************************************
  187. //
  188. // CFlexArray::Compress
  189. //
  190. // Removes NULL elements by moving all non-NULL pointers to the beginning
  191. // of the array. The array "Size" changes, but the extent is untouched.
  192. //
  193. //***************************************************************************
  194. // ok
  195. void CFlexArray::Compress()
  196. {
  197. int nLeftCursor = 0, nRightCursor = 0;
  198. while (nLeftCursor < m_nSize - 1) {
  199. if (m_pArray[nLeftCursor]) {
  200. nLeftCursor++;
  201. continue;
  202. }
  203. else {
  204. nRightCursor = nLeftCursor + 1;
  205. while (m_pArray[nRightCursor] == 0 && nRightCursor < m_nSize)
  206. nRightCursor++;
  207. if (nRightCursor == m_nSize)
  208. break; // Short circuit, no more nonzero elements.
  209. m_pArray[nLeftCursor] = m_pArray[nRightCursor];
  210. m_pArray[nRightCursor] = 0;
  211. }
  212. }
  213. while (m_pArray[m_nSize - 1] == 0 && m_nSize > 0) m_nSize--;
  214. }
  215. //***************************************************************************
  216. //
  217. // CFlexArray::Empty
  218. //
  219. // Clears the array of all pointers (does not deallocate them) and sets
  220. // its apparent size to zero.
  221. //
  222. //***************************************************************************
  223. // ok
  224. void CFlexArray::Empty()
  225. {
  226. LocalFree(m_pArray);
  227. m_pArray = (void **) LocalAlloc(LMEM_ZEROINIT, sizeof(void *) * m_nGrowBy);
  228. m_nSize = 0;
  229. m_nExtent = m_nGrowBy;
  230. }
  231. //***************************************************************************
  232. //
  233. // CFlexArray::UnbindPtr
  234. //
  235. // Empties the array and returns the pointer to the data it contained
  236. //
  237. //***************************************************************************
  238. void** CFlexArray::UnbindPtr()
  239. {
  240. void** pp = m_pArray;
  241. Empty();
  242. return pp;
  243. }
  244. //***************************************************************************
  245. //
  246. // CWStringArray::CWStringArray
  247. //
  248. // Constructs a wide-string array.
  249. //
  250. // Parameters:
  251. // <nSize> The starting preallocated size of the array.
  252. // <nGrowBy> The amount to grow by when the array fills up.
  253. //
  254. // Size() returns the number of elements in use, not the 'true' size.
  255. //
  256. //***************************************************************************
  257. CWStringArray::CWStringArray(
  258. int nSize,
  259. int nGrowBy
  260. )
  261. :
  262. m_Array(nSize, nGrowBy)
  263. {
  264. }
  265. //***************************************************************************
  266. //
  267. // Copy constructor.
  268. //
  269. //***************************************************************************
  270. CWStringArray::CWStringArray(CWStringArray &Src)
  271. {
  272. *this = Src;
  273. }
  274. //***************************************************************************
  275. //
  276. // Destructor. Cleans up all the strings.
  277. //
  278. //***************************************************************************
  279. CWStringArray::~CWStringArray()
  280. {
  281. Empty();
  282. }
  283. //***************************************************************************
  284. //
  285. // CWStringArray::DeleteStr
  286. //
  287. // Frees the string at the specified index and sets the element to NULL.
  288. // Does not compress array.
  289. //
  290. // Does not currently do a range check.
  291. //
  292. // Parameters:
  293. // <nIndex> The 0-origin index of the string to remove.
  294. //
  295. // Return values:
  296. // no_error
  297. //
  298. //***************************************************************************
  299. int CWStringArray::DeleteStr(int nIndex)
  300. {
  301. LocalFree(m_Array[nIndex]);
  302. m_Array[nIndex] = 0;
  303. return no_error;
  304. }
  305. //***************************************************************************
  306. //
  307. // CWStringArray::FindStr
  308. //
  309. // Finds the specified string and returns its location.
  310. //
  311. // Parameters:
  312. // <pTarget> The string to find.
  313. // <nFlags> <no_case> or <with_case>
  314. //
  315. // Return value:
  316. // The 0-origin location of the string, or -1 if not found.
  317. //
  318. //***************************************************************************
  319. int CWStringArray::FindStr(wchar_t *pTarget, int nFlags)
  320. {
  321. if (nFlags == no_case)
  322. {
  323. for (int i = 0; i < m_Array.Size(); i++)
  324. if (_wcsicmp((wchar_t *) m_Array[i], pTarget) == 0)
  325. return i;
  326. }
  327. else
  328. {
  329. for (int i = 0; i < m_Array.Size(); i++)
  330. if (wcscmp((wchar_t *) m_Array[i], pTarget) == 0)
  331. return i;
  332. }
  333. return not_found;
  334. }
  335. //***************************************************************************
  336. //
  337. // operator =
  338. //
  339. //***************************************************************************
  340. // Heap handle & allocation functions are not copied. This allows
  341. // transfer of arrays between heaps.
  342. CWStringArray& CWStringArray::operator =(CWStringArray &Src)
  343. {
  344. Empty();
  345. for (int i = 0; i < Src.Size(); i++)
  346. {
  347. wchar_t *pSrc = (wchar_t *) Src.m_Array[i];
  348. wchar_t *pCopy = (wchar_t *) LocalAlloc(LMEM_ZEROINIT, (wcslen(pSrc) + 1) * 2);
  349. wcscpy(pCopy, pSrc);
  350. m_Array.Add(pCopy);
  351. }
  352. return *this;
  353. }
  354. //***************************************************************************
  355. //
  356. // CWStringArray::Add
  357. //
  358. // Appends a new string to the end of the array.
  359. //
  360. // Parameters:
  361. // <pSrc> The string to copy.
  362. //
  363. // Return value:
  364. // The return values of CFlexArray::Add.
  365. //
  366. //***************************************************************************
  367. int CWStringArray::Add(wchar_t *pSrc)
  368. {
  369. wchar_t *pNewStr = (wchar_t *) LocalAlloc(LMEM_ZEROINIT, (wcslen(pSrc) + 1) * 2);
  370. wcscpy(pNewStr, pSrc);
  371. return m_Array.Add(pNewStr);
  372. }
  373. //***************************************************************************
  374. //
  375. // CWStringArray::InsertAt
  376. //
  377. // Inserts a copy of a string in the array.
  378. //
  379. // Parameters:
  380. // <nIndex> The 0-origin location at which to insert the string.
  381. // <pSrc> The string to copy.
  382. //
  383. // Return values:
  384. // The return values of CFlexArray::InsertAt
  385. //
  386. //***************************************************************************
  387. int CWStringArray::InsertAt(int nIndex, wchar_t *pSrc)
  388. {
  389. wchar_t *pNewStr = (wchar_t *) LocalAlloc(LMEM_ZEROINIT, (wcslen(pSrc) + 1) * 2);
  390. wcscpy(pNewStr, pSrc);
  391. return m_Array.InsertAt(nIndex, pNewStr);
  392. }
  393. //***************************************************************************
  394. //
  395. // CWStringArray::RemoveAt
  396. //
  397. // Removes and deallocates the string at the specified location.
  398. // Shrinks the array.
  399. //
  400. // Parameters:
  401. // <nIndex> The 0-origin index of the 'doomed' string.
  402. //
  403. // Return value:
  404. // Same as CFlexArray::RemoveAt.
  405. //
  406. //***************************************************************************
  407. int CWStringArray::RemoveAt(int nIndex)
  408. {
  409. wchar_t *pDoomedString = (wchar_t *) m_Array[nIndex];
  410. LocalFree(pDoomedString);
  411. return m_Array.RemoveAt(nIndex);
  412. }
  413. //***************************************************************************
  414. //
  415. // CWStringArray::SetAt
  416. //
  417. // Replaces the string at the targeted location with the new one.
  418. // The old string at the location is cleaned up.
  419. //
  420. // No range checking or out-of-memory checks at present.
  421. //
  422. // Parameters:
  423. // <nIndex> The 0-origin location at which to replace the string.
  424. // <pSrc> The string to copy.
  425. //
  426. // Return value:
  427. // no_error
  428. //
  429. //***************************************************************************
  430. int CWStringArray::SetAt(int nIndex, wchar_t *pSrc)
  431. {
  432. wchar_t *pDoomedString = (wchar_t *) m_Array[nIndex];
  433. if (pDoomedString)
  434. LocalFree(pDoomedString);
  435. wchar_t *pNewStr = (wchar_t *) LocalAlloc(LMEM_ZEROINIT, (wcslen(pSrc) + 1) * 2);
  436. wcscpy(pNewStr, pSrc);
  437. m_Array[nIndex] = pNewStr;
  438. return no_error;
  439. }
  440. //***************************************************************************
  441. //
  442. // CWStringArray::ReplaceAt
  443. //
  444. // Directly replaces the pointer at the specified location with the
  445. // one in the parameter. No copy or cleanup.
  446. //
  447. // Parameters:
  448. // <nIndex> The 0-origin location at which to replace.
  449. // <pSrc> The new pointer to copy over the old one.
  450. //
  451. // Return value:
  452. // no_error (No checking done at present).
  453. //
  454. //***************************************************************************
  455. int CWStringArray::ReplaceAt(int nIndex, wchar_t *pSrc)
  456. {
  457. m_Array[nIndex] = pSrc;
  458. return no_error;
  459. }
  460. //***************************************************************************
  461. //
  462. // CWStringArray::Empty
  463. //
  464. // Empties the array, deallocates all strings, and sets the apparent
  465. // array size to zero.
  466. //
  467. //***************************************************************************
  468. void CWStringArray::Empty()
  469. {
  470. for (int i = 0; i < m_Array.Size(); i++)
  471. LocalFree(m_Array[i]);
  472. m_Array.Empty();
  473. }
  474. //***************************************************************************
  475. //
  476. // CWStringArray::Sort
  477. //
  478. // Sorts the array according to UNICODE order.
  479. // (Shell sort).
  480. //
  481. //***************************************************************************
  482. void CWStringArray::Sort()
  483. {
  484. for (int nInterval = 1; nInterval < m_Array.Size() / 9; nInterval = nInterval * 3 + 1);
  485. while (nInterval)
  486. {
  487. for (int iCursor = nInterval; iCursor < m_Array.Size(); iCursor++)
  488. {
  489. int iBackscan = iCursor;
  490. while (iBackscan - nInterval >= 0 &&
  491. _wcsicmp((const wchar_t *) m_Array[iBackscan],
  492. (const wchar_t *) m_Array[iBackscan-nInterval]) < 0)
  493. {
  494. wchar_t *pTemp = (wchar_t *) m_Array[iBackscan - nInterval];
  495. m_Array[iBackscan - nInterval] = m_Array[iBackscan];
  496. m_Array[iBackscan] = pTemp;
  497. iBackscan -= nInterval;
  498. }
  499. }
  500. nInterval /= 3;
  501. }
  502. }
  503. //***************************************************************************
  504. //
  505. // CWStringArray::Difference
  506. //
  507. // Set-theoretic difference operation on the arrays.
  508. //
  509. // Parameters:
  510. // <Src1> First array (not modified).
  511. // <Src2> Second array which is 'subtracted' from first (not modified).
  512. // <Diff> Receives the difference. Should be an empty array on entry.
  513. //
  514. //***************************************************************************
  515. void CWStringArray::Difference(
  516. CWStringArray &Src1,
  517. CWStringArray &Src2,
  518. CWStringArray &Diff
  519. )
  520. {
  521. for (int i = 0; i < Src1.Size(); i++)
  522. if (Src2.FindStr(Src1[i], no_case) == -1)
  523. Diff.Add(Src1[i]);
  524. }
  525. //***************************************************************************
  526. //
  527. // CWStringArray::Intersection
  528. //
  529. // Set-theoretic intersection operation on the arrays.
  530. //
  531. // Parameters:
  532. // <Src1> First array (not modified).
  533. // <Src2> Second array (not modified).
  534. // <Diff> Receives the intersection. Should be an empty array on entry.
  535. //***************************************************************************
  536. void CWStringArray::Intersection(
  537. CWStringArray &Src1,
  538. CWStringArray &Src2,
  539. CWStringArray &Output
  540. )
  541. {
  542. for (int i = 0; i < Src1.Size(); i++)
  543. if (Src2.FindStr(Src1[i], no_case) != -1)
  544. Output.Add(Src1[i]);
  545. }
  546. //***************************************************************************
  547. //
  548. // CWStringArray::Union
  549. //
  550. // Set-theoretic union operation on the arrays.
  551. //
  552. // Parameters:
  553. // <Src1> First array (not modified).
  554. // <Src2> Second array (not modified).
  555. // <Diff> Receives the union. Should be an empty array on entry.
  556. //
  557. //***************************************************************************
  558. void CWStringArray::Union(
  559. CWStringArray &Src1,
  560. CWStringArray &Src2,
  561. CWStringArray &Output
  562. )
  563. {
  564. Output = Src1;
  565. for (int i = 0; i < Src2.Size(); i++)
  566. if (Output.FindStr(Src2[i], no_case) == not_found)
  567. Output.Add(Src2[i]);
  568. }