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.

828 lines
22 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMIOLE DB Provider
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // CFlexArray & CWStringArray class implementation - THis implementation is taken
  7. // from Winmgmt\common and modified
  8. //
  9. // Module Name : Flexarry.cpp
  10. ///////////////////////////////////////////////////////////////////////////////////
  11. #include "headers.h"
  12. #include "corex.h"
  13. //***************************************************************************
  14. //
  15. // CFlexArray::CFlexArray
  16. //
  17. // Constructs the array.
  18. //
  19. // Parameters:
  20. // <nSize> The starting preallocated size of the array.
  21. // <nGrowBy> The amount to grow by when the array fills up.
  22. //
  23. // Size() returns the number of elements in use, not the 'true' size.
  24. //
  25. //***************************************************************************
  26. // ok
  27. CFlexArray::CFlexArray(
  28. int nSize,
  29. int nGrowByPercent
  30. )
  31. {
  32. m_nExtent = nSize;
  33. m_nSize = 0;
  34. m_nGrowByPercent = nGrowByPercent;
  35. if(nSize > 0)
  36. {
  37. m_pArray = (void**)g_pIMalloc->Alloc(sizeof(void *) * nSize);
  38. // Check for allocation failures
  39. if ( NULL == m_pArray )
  40. {
  41. throw CX_MemoryException();
  42. }
  43. }
  44. else
  45. m_pArray = NULL;
  46. }
  47. //***************************************************************************
  48. //
  49. // CFlexArray::~CFlexArray
  50. //
  51. //***************************************************************************
  52. // ok
  53. CFlexArray::~CFlexArray()
  54. {
  55. g_pIMalloc->Free(m_pArray);
  56. }
  57. //***************************************************************************
  58. //
  59. // Copy constructor.
  60. //
  61. // Copies the pointers, not their contents.
  62. //
  63. //***************************************************************************
  64. // ok
  65. CFlexArray::CFlexArray(CFlexArray &Src)
  66. {
  67. m_pArray = 0;
  68. m_nSize = 0;
  69. m_nExtent = 0;
  70. m_nGrowByPercent = 0;
  71. *this = Src;
  72. }
  73. //***************************************************************************
  74. //
  75. // operator =
  76. //
  77. // Assignment operator.
  78. //
  79. // Arenas are not copied. This allows transfer of arrays between arenas.
  80. // Arrays are copied by pointer only.
  81. //
  82. //***************************************************************************
  83. // ok
  84. CFlexArray& CFlexArray::operator=(CFlexArray &Src)
  85. {
  86. m_nSize = Src.m_nSize;
  87. m_nExtent = Src.m_nExtent;
  88. m_nGrowByPercent = Src.m_nGrowByPercent;
  89. // CWin32DefaultArena::WbemMemFree(m_pArray);
  90. delete [] m_pArray;
  91. if(m_nExtent > 0)
  92. {
  93. m_pArray = (void**)g_pIMalloc->Alloc(sizeof(void *) * m_nExtent);
  94. // (void**)CWin32DefaultArena::WbemMemAlloc(sizeof(void *) * m_nExtent);
  95. // Check for allocation failures
  96. if ( NULL == m_pArray )
  97. {
  98. throw CX_MemoryException();
  99. }
  100. }
  101. else
  102. m_pArray = NULL;
  103. memcpy(m_pArray, Src.m_pArray, sizeof(void *) * m_nSize);
  104. return *this;
  105. }
  106. //***************************************************************************
  107. //
  108. // CFlexArray::RemoveAt
  109. //
  110. // Removes the element at the specified location. Does not
  111. // actually delete the pointer. Shrinks the array over the top of
  112. // the 'doomed' element.
  113. //
  114. // Parameters:
  115. // <nIndex> The location of the element.
  116. //
  117. // Return value:
  118. // range_error The index is not legal.
  119. // no_error Success.
  120. //
  121. //***************************************************************************
  122. // ok
  123. int CFlexArray::RemoveAt(int nIndex)
  124. {
  125. if (nIndex >= m_nSize)
  126. return range_error;
  127. // Account for the index being 0 based and size being 1 based
  128. MoveMemory( &m_pArray[nIndex], &m_pArray[nIndex+1], ( ( m_nSize - nIndex ) - 1 ) * sizeof(void *) );
  129. m_nSize--;
  130. m_pArray[m_nSize] = 0;
  131. return no_error;
  132. }
  133. int CFlexArray::EnsureExtent(int nExtent)
  134. {
  135. if(m_nExtent < nExtent)
  136. {
  137. m_nExtent = nExtent;
  138. if(m_pArray)
  139. {
  140. register void** pTmp = (void **)g_pIMalloc->Realloc(m_pArray,sizeof(void *) * m_nExtent);
  141. // register void** pTmp = (void **) CWin32DefaultArena::WbemMemReAlloc(m_pArray, sizeof(void *) * m_nExtent);
  142. if (pTmp == 0)
  143. return out_of_memory;
  144. m_pArray = pTmp;
  145. }
  146. else
  147. m_pArray = (void **)g_pIMalloc->Alloc(sizeof(void *) * m_nExtent);
  148. // m_pArray = (void **) CWin32DefaultArena::WbemMemAlloc(sizeof(void *) * m_nExtent);
  149. if (!m_pArray)
  150. return out_of_memory;
  151. }
  152. return no_error;
  153. }
  154. //***************************************************************************
  155. //
  156. // CFlexArray::InsertAt
  157. //
  158. // Inserts a new element at the specified location. The pointer is copied.
  159. //
  160. // Parameters:
  161. // <nIndex> The 0-origin location at which to insert the new element.
  162. // <pSrc> The pointer to copy. (contents are not copied).
  163. //
  164. // Return value:
  165. // array_full
  166. // out_of_memory
  167. // no_error
  168. //
  169. //***************************************************************************
  170. // ok
  171. int CFlexArray::InsertAt(int nIndex, void *pSrc)
  172. {
  173. // TEMP: fix for sparse functionality in stdprov
  174. // =============================================
  175. while(nIndex > m_nSize)
  176. Add(NULL);
  177. // If the array is full, we need to expand it.
  178. // ===========================================
  179. if (m_nSize == m_nExtent) {
  180. if (m_nGrowByPercent == 0)
  181. return array_full;
  182. register nTmpExtent = m_nExtent;
  183. m_nExtent += 1;
  184. m_nExtent *= (100 + m_nGrowByPercent);
  185. m_nExtent /= 100;
  186. if(m_pArray)
  187. {
  188. register void** pTmp = (void **)g_pIMalloc->Realloc(m_pArray,sizeof(void *) * m_nExtent);
  189. // register void** pTmp = (void **) CWin32DefaultArena::WbemMemReAlloc(m_pArray, sizeof(void *) * m_nExtent);
  190. if (pTmp == 0)
  191. {
  192. m_nExtent = nTmpExtent; //Change it back, otherwise the extent could constantly grow even though it keeps failing...
  193. return out_of_memory;
  194. }
  195. m_pArray = pTmp;
  196. }
  197. else
  198. m_pArray = (void **)g_pIMalloc->Alloc(sizeof(void *) * m_nExtent);
  199. // m_pArray = (void **) CWin32DefaultArena::WbemMemAlloc(sizeof(void *) * m_nExtent);
  200. if (!m_pArray)
  201. return out_of_memory;
  202. }
  203. // Special case of appending. This is so frequent
  204. // compared to true insertion that we want to optimize.
  205. // ====================================================
  206. if (nIndex == m_nSize) {
  207. m_pArray[m_nSize++] = pSrc;
  208. return no_error;
  209. }
  210. // If here, we are inserting at some random location.
  211. // We start at the end of the array and copy all the elements
  212. // one position farther to the end to make a 'hole' for
  213. // the new element.
  214. // ==========================================================
  215. // Account for nIndex being 0 based and m_nSize being 1 based
  216. MoveMemory( &m_pArray[nIndex+1], &m_pArray[nIndex], ( m_nSize - nIndex ) * sizeof(void *) );
  217. m_pArray[nIndex] = pSrc;
  218. m_nSize++;
  219. return no_error;
  220. }
  221. void CFlexArray::Sort()
  222. {
  223. if(m_pArray)
  224. qsort((void*)m_pArray, m_nSize, sizeof(void*), CFlexArray::CompareEls);
  225. }
  226. int __cdecl CFlexArray::CompareEls(const void* pelem1, const void* pelem2)
  227. {
  228. return *(int*)pelem1 - *(int*)pelem2;
  229. }
  230. //***************************************************************************
  231. //
  232. // CFlexArray::DebugDump
  233. //
  234. //***************************************************************************
  235. void CFlexArray::DebugDump()
  236. {
  237. printf("----CFlexArray Debug Dump----\n");
  238. printf("m_pArray = 0x%P\n", m_pArray);
  239. printf("m_nSize = %d\n", m_nSize);
  240. printf("m_nExtent = %d\n", m_nExtent);
  241. printf("m_nGrowByPercent = %d\n", m_nGrowByPercent);
  242. for (int i = 0; i < m_nExtent; i++)
  243. {
  244. if (i < m_nSize)
  245. printf("![%P] = %X\n", i, m_pArray[i]);
  246. else
  247. printf("?[%P] = %X\n", i, m_pArray[i]);
  248. }
  249. }
  250. //***************************************************************************
  251. //
  252. // CFlexArray::Compress
  253. //
  254. // Removes NULL elements by moving all non-NULL pointers to the beginning
  255. // of the array. The array "Size" changes, but the extent is untouched.
  256. //
  257. //***************************************************************************
  258. // ok
  259. void CFlexArray::Compress()
  260. {
  261. int nLeftCursor = 0, nRightCursor = 0;
  262. while (nLeftCursor < m_nSize - 1) {
  263. if (m_pArray[nLeftCursor]) {
  264. nLeftCursor++;
  265. continue;
  266. }
  267. else {
  268. nRightCursor = nLeftCursor + 1;
  269. while ( nRightCursor < m_nSize && m_pArray[nRightCursor] == 0 )
  270. nRightCursor++;
  271. if (nRightCursor == m_nSize)
  272. break; // Short circuit, no more nonzero elements.
  273. m_pArray[nLeftCursor] = m_pArray[nRightCursor];
  274. m_pArray[nRightCursor] = 0;
  275. }
  276. }
  277. Trim();
  278. }
  279. void CFlexArray::Trim()
  280. {
  281. while (m_nSize > 0 && m_pArray[m_nSize - 1] == NULL) m_nSize--;
  282. }
  283. //***************************************************************************
  284. //
  285. // CFlexArray::Empty
  286. //
  287. // Clears the array of all pointers (does not deallocate them) and sets
  288. // its apparent size to zero.
  289. //
  290. //***************************************************************************
  291. // ok
  292. void CFlexArray::Empty()
  293. {
  294. g_pIMalloc->Free(m_pArray);
  295. // CWin32DefaultArena::WbemMemFree(m_pArray);
  296. m_pArray = NULL;
  297. m_nSize = 0;
  298. m_nExtent = 0;
  299. }
  300. //***************************************************************************
  301. //
  302. // CFlexArray::UnbindPtr
  303. //
  304. // Empties the array and returns the pointer to the data it contained
  305. //
  306. //***************************************************************************
  307. void** CFlexArray::UnbindPtr()
  308. {
  309. void** pp = m_pArray;
  310. m_pArray = NULL;
  311. Empty();
  312. return pp;
  313. }
  314. //***************************************************************************
  315. //
  316. // CFlexArray::CopyData
  317. //
  318. // Copies the data but not the settings of another flexarray
  319. //
  320. //***************************************************************************
  321. int CFlexArray::CopyDataFrom(const CFlexArray& aOther)
  322. {
  323. // Check if there is enough room
  324. // =============================
  325. if(aOther.m_nSize > m_nExtent)
  326. {
  327. // Extend the array to the requisite size
  328. // ======================================
  329. m_nExtent = aOther.m_nSize;
  330. if(m_pArray)
  331. {
  332. register void** pTmp = (void **)g_pIMalloc->Realloc(m_pArray,sizeof(void *) * m_nExtent);
  333. // register void** pTmp = (void **) CWin32DefaultArena::WbemMemReAlloc(m_pArray, sizeof(void *) * m_nExtent);
  334. if (pTmp == 0)
  335. return out_of_memory;
  336. m_pArray = pTmp;
  337. }
  338. else
  339. m_pArray = (void **)g_pIMalloc->Alloc(sizeof(void *) * m_nExtent);
  340. // m_pArray = (void **) CWin32DefaultArena::WbemMemAlloc(sizeof(void *) * m_nExtent);
  341. if (!m_pArray)
  342. return out_of_memory;
  343. }
  344. // Copy the data
  345. // =============
  346. m_nSize = aOther.m_nSize;
  347. memcpy(m_pArray, aOther.m_pArray, sizeof(void*) * m_nSize);
  348. return no_error;
  349. }
  350. //***************************************************************************
  351. //
  352. // CWStringArray::CWStringArray
  353. //
  354. // Constructs a wide-string array.
  355. //
  356. // Parameters:
  357. // <nSize> The starting preallocated size of the array.
  358. // <nGrowBy> The amount to grow by when the array fills up.
  359. //
  360. // Size() returns the number of elements in use, not the 'true' size.
  361. //
  362. //***************************************************************************
  363. CWStringArray::CWStringArray(
  364. int nSize,
  365. int nGrowBy
  366. )
  367. :
  368. m_Array(nSize, nGrowBy)
  369. {
  370. }
  371. //***************************************************************************
  372. //
  373. // Copy constructor.
  374. //
  375. //***************************************************************************
  376. CWStringArray::CWStringArray(CWStringArray &Src)
  377. {
  378. *this = Src;
  379. }
  380. //***************************************************************************
  381. //
  382. // Destructor. Cleans up all the strings.
  383. //
  384. //***************************************************************************
  385. CWStringArray::~CWStringArray()
  386. {
  387. Empty();
  388. }
  389. //***************************************************************************
  390. //
  391. // CWStringArray::DeleteStr
  392. //
  393. // Frees the string at the specified index and sets the element to NULL.
  394. // Does not compress array.
  395. //
  396. // Does not currently do a range check.
  397. //
  398. // Parameters:
  399. // <nIndex> The 0-origin index of the string to remove.
  400. //
  401. // Return values:
  402. // no_error
  403. //
  404. //***************************************************************************
  405. int CWStringArray::DeleteStr(int nIndex)
  406. {
  407. g_pIMalloc->Free(m_Array[nIndex]);
  408. m_Array[nIndex] = 0;
  409. return no_error;
  410. }
  411. //***************************************************************************
  412. //
  413. // CWStringArray::FindStr
  414. //
  415. // Finds the specified string and returns its location.
  416. //
  417. // Parameters:
  418. // <pTarget> The string to find.
  419. // <nFlags> <no_case> or <with_case>
  420. //
  421. // Return value:
  422. // The 0-origin location of the string, or -1 if not found.
  423. //
  424. //***************************************************************************
  425. int CWStringArray::FindStr(const wchar_t *pTarget, int nFlags)
  426. {
  427. if (nFlags == no_case) {
  428. for (int i = 0; i < m_Array.Size(); i++)
  429. if (wbem_wcsicmp((wchar_t *) m_Array[i], pTarget) == 0)
  430. return i;
  431. }
  432. else {
  433. for (int i = 0; i < m_Array.Size(); i++)
  434. if (wcscmp((wchar_t *) m_Array[i], pTarget) == 0)
  435. return i;
  436. }
  437. return not_found;
  438. }
  439. //***************************************************************************
  440. //
  441. // operator =
  442. //
  443. //***************************************************************************
  444. // Heap handle & allocation functions are not copied. This allows
  445. // transfer of arrays between heaps.
  446. CWStringArray& CWStringArray::operator =(CWStringArray &Src)
  447. {
  448. Empty();
  449. for (int i = 0; i < Src.Size(); i++)
  450. {
  451. wchar_t *pSrc = (wchar_t *) Src.m_Array[i];
  452. wchar_t *pCopy = (wchar_t *) g_pIMalloc->Alloc((wcslen(pSrc) + 1) * 2);
  453. // wchar_t *pCopy = (wchar_t *) CWin32DefaultArena::WbemMemAlloc((wcslen(pSrc) + 1) * 2);
  454. // Check for allocation failures
  455. if ( NULL == pCopy )
  456. {
  457. throw CX_MemoryException();
  458. }
  459. wcscpy(pCopy, pSrc);
  460. if ( m_Array.Add(pCopy) != CFlexArray::no_error )
  461. {
  462. throw CX_MemoryException();
  463. }
  464. }
  465. return *this;
  466. }
  467. //***************************************************************************
  468. //
  469. // CWStringArray::Add
  470. //
  471. // Appends a new string to the end of the array.
  472. //
  473. // Parameters:
  474. // <pSrc> The string to copy.
  475. //
  476. // Return value:
  477. // The return values of CFlexArray::Add.
  478. //
  479. //***************************************************************************
  480. int CWStringArray::Add(const wchar_t *pSrc)
  481. {
  482. wchar_t *pNewStr = (wchar_t *) g_pIMalloc->Alloc((wcslen(pSrc) + 1) * 2);
  483. // wchar_t *pNewStr = (wchar_t *) CWin32DefaultArena::WbemMemAlloc((wcslen(pSrc) + 1) * 2);
  484. // Check for allocation failures
  485. if ( NULL == pNewStr )
  486. {
  487. return out_of_memory;
  488. }
  489. wcscpy(pNewStr, pSrc);
  490. return m_Array.Add(pNewStr);
  491. }
  492. //***************************************************************************
  493. //
  494. // CWStringArray::InsertAt
  495. //
  496. // Inserts a copy of a string in the array.
  497. //
  498. // Parameters:
  499. // <nIndex> The 0-origin location at which to insert the string.
  500. // <pSrc> The string to copy.
  501. //
  502. // Return values:
  503. // The return values of CFlexArray::InsertAt
  504. //
  505. //***************************************************************************
  506. int CWStringArray::InsertAt(int nIndex, const wchar_t *pSrc)
  507. {
  508. wchar_t *pNewStr = (wchar_t *) g_pIMalloc->Alloc((wcslen(pSrc) + 1) * 2);
  509. // wchar_t *pNewStr = (wchar_t *) CWin32DefaultArena::WbemMemAlloc((wcslen(pSrc) + 1) * 2);
  510. // Check for allocation failures
  511. if ( NULL == pNewStr )
  512. {
  513. return out_of_memory;
  514. }
  515. wcscpy(pNewStr, pSrc);
  516. return m_Array.InsertAt(nIndex, pNewStr);
  517. }
  518. //***************************************************************************
  519. //
  520. // CWStringArray::RemoveAt
  521. //
  522. // Removes and deallocates the string at the specified location.
  523. // Shrinks the array.
  524. //
  525. // Parameters:
  526. // <nIndex> The 0-origin index of the 'doomed' string.
  527. //
  528. // Return value:
  529. // Same as CFlexArray::RemoveAt.
  530. //
  531. //***************************************************************************
  532. int CWStringArray::RemoveAt(int nIndex)
  533. {
  534. wchar_t *pDoomedString = (wchar_t *) m_Array[nIndex];
  535. g_pIMalloc->Free(pDoomedString);
  536. // CWin32DefaultArena::WbemMemFree(pDoomedString);
  537. return m_Array.RemoveAt(nIndex);
  538. }
  539. //***************************************************************************
  540. //
  541. // CWStringArray::SetAt
  542. //
  543. // Replaces the string at the targeted location with the new one.
  544. // The old string at the location is cleaned up.
  545. //
  546. // No range checking or out-of-memory checks at present.
  547. //
  548. // Parameters:
  549. // <nIndex> The 0-origin location at which to replace the string.
  550. // <pSrc> The string to copy.
  551. //
  552. // Return value:
  553. // no_error
  554. //
  555. //***************************************************************************
  556. int CWStringArray::SetAt(int nIndex, const wchar_t *pSrc)
  557. {
  558. wchar_t *pNewStr = (wchar_t *) g_pIMalloc->Alloc((wcslen(pSrc) + 1) * 2);
  559. // wchar_t *pNewStr = (wchar_t *) CWin32DefaultArena::WbemMemAlloc((wcslen(pSrc) + 1) * 2);
  560. // Check for allocation failures
  561. if ( NULL == pNewStr )
  562. {
  563. return out_of_memory;
  564. }
  565. wchar_t *pDoomedString = (wchar_t *) m_Array[nIndex];
  566. if (pDoomedString)
  567. g_pIMalloc->Free(pDoomedString);
  568. // CWin32DefaultArena::WbemMemFree(pDoomedString);
  569. wcscpy(pNewStr, pSrc);
  570. m_Array[nIndex] = pNewStr;
  571. return no_error;
  572. }
  573. //***************************************************************************
  574. //
  575. // CWStringArray::ReplaceAt
  576. //
  577. // Directly replaces the pointer at the specified location with the
  578. // one in the parameter. No copy or cleanup.
  579. //
  580. // Parameters:
  581. // <nIndex> The 0-origin location at which to replace.
  582. // <pSrc> The new pointer to copy over the old one.
  583. //
  584. // Return value:
  585. // no_error (No checking done at present).
  586. //
  587. //***************************************************************************
  588. int CWStringArray::ReplaceAt(int nIndex, wchar_t *pSrc)
  589. {
  590. m_Array[nIndex] = pSrc;
  591. return no_error;
  592. }
  593. //***************************************************************************
  594. //
  595. // CWStringArray::Empty
  596. //
  597. // Empties the array, deallocates all strings, and sets the apparent
  598. // array size to zero.
  599. //
  600. //***************************************************************************
  601. void CWStringArray::Empty()
  602. {
  603. for (int i = 0; i < m_Array.Size(); i++)
  604. g_pIMalloc->Free(m_Array[i]);
  605. // CWin32DefaultArena::WbemMemFree(m_Array[i]);
  606. m_Array.Empty();
  607. }
  608. //***************************************************************************
  609. //
  610. // CWStringArray::Sort
  611. //
  612. // Sorts the array according to UNICODE order.
  613. // (Shell sort).
  614. //
  615. //***************************************************************************
  616. void CWStringArray::Sort()
  617. {
  618. for (int nInterval = 1; nInterval < m_Array.Size() / 9; nInterval = nInterval * 3 + 1);
  619. while (nInterval)
  620. {
  621. for (int iCursor = nInterval; iCursor < m_Array.Size(); iCursor++)
  622. {
  623. int iBackscan = iCursor;
  624. while (iBackscan - nInterval >= 0 &&
  625. wbem_wcsicmp((const wchar_t *) m_Array[iBackscan],
  626. (const wchar_t *) m_Array[iBackscan-nInterval]) < 0)
  627. {
  628. wchar_t *pTemp = (wchar_t *) m_Array[iBackscan - nInterval];
  629. m_Array[iBackscan - nInterval] = m_Array[iBackscan];
  630. m_Array[iBackscan] = pTemp;
  631. iBackscan -= nInterval;
  632. }
  633. }
  634. nInterval /= 3;
  635. }
  636. }
  637. //***************************************************************************
  638. //
  639. // CWStringArray::Difference
  640. //
  641. // Set-theoretic difference operation on the arrays.
  642. //
  643. // Parameters:
  644. // <Src1> First array (not modified).
  645. // <Src2> Second array which is 'subtracted' from first (not modified).
  646. // <Diff> Receives the difference. Should be an empty array on entry.
  647. //
  648. //***************************************************************************
  649. void CWStringArray::Difference(
  650. CWStringArray &Src1,
  651. CWStringArray &Src2,
  652. CWStringArray &Diff
  653. )
  654. {
  655. for (int i = 0; i < Src1.Size(); i++)
  656. {
  657. if (Src2.FindStr(Src1[i], no_case) == -1)
  658. {
  659. if ( Diff.Add(Src1[i]) != no_error )
  660. {
  661. throw CX_MemoryException();
  662. }
  663. }
  664. }
  665. }
  666. //***************************************************************************
  667. //
  668. // CWStringArray::Intersection
  669. //
  670. // Set-theoretic intersection operation on the arrays.
  671. //
  672. // Parameters:
  673. // <Src1> First array (not modified).
  674. // <Src2> Second array (not modified).
  675. // <Diff> Receives the intersection. Should be an empty array on entry.
  676. //***************************************************************************
  677. void CWStringArray::Intersection(
  678. CWStringArray &Src1,
  679. CWStringArray &Src2,
  680. CWStringArray &Output
  681. )
  682. {
  683. for (int i = 0; i < Src1.Size(); i++)
  684. {
  685. if (Src2.FindStr(Src1[i], no_case) != -1)
  686. {
  687. if ( Output.Add(Src1[i]) != no_error )
  688. {
  689. throw CX_MemoryException();
  690. }
  691. }
  692. }
  693. }
  694. //***************************************************************************
  695. //
  696. // CWStringArray::Union
  697. //
  698. // Set-theoretic union operation on the arrays.
  699. //
  700. // Parameters:
  701. // <Src1> First array (not modified).
  702. // <Src2> Second array (not modified).
  703. // <Diff> Receives the union. Should be an empty array on entry.
  704. //
  705. //***************************************************************************
  706. void CWStringArray::Union(
  707. CWStringArray &Src1,
  708. CWStringArray &Src2,
  709. CWStringArray &Output
  710. )
  711. {
  712. Output = Src1;
  713. for (int i = 0; i < Src2.Size(); i++)
  714. {
  715. if (Output.FindStr(Src2[i], no_case) == not_found)
  716. {
  717. if ( Output.Add(Src2[i]) != no_error )
  718. {
  719. throw CX_MemoryException();
  720. }
  721. }
  722. }
  723. }